New upstream version 1.13.0+dfsg1

This commit is contained in:
Sylvestre Ledru 2016-11-11 13:34:06 +01:00
parent c4e45e28a7
commit 9e0c209edc
1585 changed files with 50279 additions and 47838 deletions

View File

@ -151,6 +151,10 @@ Some common make targets are:
command above as we only build the stage1 compiler, not the entire thing).
You can also leave off the `-rpass` to run all stage1 test types.
- `make check-stage1-coretest` - Run stage1 tests in `libcore`.
- `make tidy` - Check that the source code is in compliance with Rust's style
guidelines. There is no official document describing Rust's full guidelines
as of yet, but basic rules like 4 spaces for indentation and no more than 99
characters in a single line should be kept in mind when writing code.
## Pull Requests
@ -177,6 +181,15 @@ youre adding something to the standard library, try
This will not rebuild the compiler, but will run the tests.
Please make sure your pull request is in compliance with Rust's style
guidelines by running
$ make tidy
Make this check before every pull request (and every new commit in a pull
request) ; you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
before every push to make sure you never forget to make this check.
All pull requests are reviewed by another person. We have a bot,
@rust-highfive, that will automatically assign a random person to review your
request.
@ -230,7 +243,7 @@ To find documentation-related issues, sort by the [A-docs label][adocs].
In many cases, you don't need a full `make doc`. You can use `rustdoc` directly
to check small fixes. For example, `rustdoc src/doc/reference.md` will render
reference to `doc/reference.html`. The CSS might be messed up, but you can
verify that HTML is right.
verify that the HTML is right.
## Issue Triage

View File

@ -19,7 +19,7 @@ Read ["Installing Rust"] from [The Book].
* `g++` 4.7 or later or `clang++` 3.x
* `python` 2.7 (but not 3.x)
* GNU `make` 3.81 or later
* `cmake` 2.8.8 or later
* `cmake` 3.4.3 or later
* `curl`
* `git`
@ -170,7 +170,7 @@ fetch snapshots, and an OS that can execute the available snapshot binaries.
Snapshot binaries are currently built and tested on several platforms:
| Platform \ Architecture | x86 | x86_64 |
| Platform / Architecture | x86 | x86_64 |
|--------------------------------|-----|--------|
| Windows (7, 8, Server 2008 R2) | ✓ | ✓ |
| Linux (2.6.18 or later) | ✓ | ✓ |

View File

@ -1,3 +1,287 @@
Version 1.13.0 (2016-11-10)
===========================
Language
--------
* [Stabilize the `?` operator][36995]. `?` is a simple way to propagate
errors, like the `try!` macro, described in [RFC 0243].
* [Stabilize macros in type position][36014]. Described in [RFC 873].
* [Stabilize attributes on statements][36995]. Described in [RFC 0016].
* [Fix `#[derive]` for empty tuple structs/variants][35728]
* [Fix lifetime rules for 'if' conditions][36029]
* [Avoid loading and parsing unconfigured non-inline modules][36482]
Compiler
--------
* [Add the `-C link-arg` argument][36574]
* [Remove the old AST-based backend from rustc_trans][35764]
* [Don't enable NEON by default on armv7 Linux][35814]
* [Fix debug line number info for macro expansions][35238]
* [Do not emit "class method" debuginfo for types that are not
DICompositeType][36008]
* [Warn about multiple conflicting #[repr] hints][34623]
* [When sizing DST, don't double-count nested struct prefixes][36351]
* [Default RUST_MIN_STACK to 16MiB for now][36505]
* [Improve rlib metadata format][36551]. Reduces rlib size significantly.
* [Reject macros with empty repetitions to avoid infinite loop][36721]
* [Expand macros without recursing to avoid stack overflows][36214]
Diagnostics
-----------
* [Replace macro backtraces with labeled local uses][35702]
* [Improve error message for missplaced doc comments][33922]
* [Buffer unix and lock windows to prevent message interleaving][35975]
* [Update lifetime errors to specifically note temporaries][36171]
* [Special case a few colors for Windows][36178]
* [Suggest `use self` when such an import resolves][36289]
* [Be more specific when type parameter shadows primitive type][36338]
* Many minor improvements
Compile-time Optimizations
--------------------------
* [Compute and cache HIR hashes at beginning][35854]
* [Don't hash types in loan paths][36004]
* [Cache projections in trans][35761]
* [Optimize the parser's last token handling][36527]
* [Only instantiate #[inline] functions in codegen units referencing
them][36524]. This leads to big improvements in cases where crates export
define many inline functions without using them directly.
* [Lazily allocate TypedArena's first chunk][36592]
* [Don't allocate during default HashSet creation][36734]
Stabilized APIs
---------------
* [`checked_abs`]
* [`wrapping_abs`]
* [`overflowing_abs`]
* [`RefCell::try_borrow`]
* [`RefCell::try_borrow_mut`]
Libraries
---------
* [Add `assert_ne!` and `debug_assert_ne!`][35074]
* [Make `vec_deque::Drain`, `hash_map::Drain`, and `hash_set::Drain`
covariant][35354]
* [Implement `AsRef<[T]>` for `std::slice::Iter`][35559]
* [Implement `Debug` for `std::vec::IntoIter`][35707]
* [`CString`: avoid excessive growth just to 0-terminate][35871]
* [Implement `CoerceUnsized` for `{Cell, RefCell, UnsafeCell}`][35627]
* [Use arc4rand on FreeBSD][35884]
* [memrchr: Correct aligned offset computation][35969]
* [Improve Demangling of Rust Symbols][36059]
* [Use monotonic time in condition variables][35048]
* [Implement `Debug` for `std::path::{Components,Iter}`][36101]
* [Implement conversion traits for `char`][35755]
* [Fix illegal instruction caused by overflow in channel cloning][36104]
* [Zero first byte of CString on drop][36264]
* [Inherit overflow checks for sum and product][36372]
* [Add missing Eq implementations][36423]
* [Implement `Debug` for `DirEntry`][36631]
* [When `getaddrinfo` returns `EAI_SYSTEM` retrieve actual error from
`errno`][36754]
* [`SipHasher`] is deprecated. Use [`DefaultHasher`].
* [Implement more traits for `std::io::ErrorKind`][35911]
* [Optimize BinaryHeap bounds checking][36072]
* [Work around pointer aliasing issue in `Vec::extend_from_slice`,
`extend_with_element`][36355]
* [Fix overflow checking in unsigned pow()][34942]
Cargo
-----
* This release includes security fixes to both curl and OpenSSL.
* [Fix transitive doctests when panic=abort][cargo/3021]
* [Add --all-features flag to cargo][cargo/3038]
* [Reject path-based dependencies in `cargo package`][cargo/3060]
* [Don't parse the home directory more than once][cargo/3078]
* [Don't try to generate Cargo.lock on empty workspaces][cargo/3092]
* [Update OpenSSL to 1.0.2j][cargo/3121]
* [Add license and license_file to cargo metadata output][cargo/3110]
* [Make crates-io registry URL optional in config; ignore all changes to
source.crates-io][cargo/3089]
* [Don't download dependencies from other platforms][cargo/3123]
* [Build transitive dev-dependencies when needed][cargo/3125]
* [Add support for per-target rustflags in .cargo/config][cargo/3157]
* [Avoid updating registry when adding existing deps][cargo/3144]
* [Warn about path overrides that won't work][cargo/3136]
* [Use workspaces during `cargo install`][cargo/3146]
* [Leak mspdbsrv.exe processes on Windows][cargo/3162]
* [Add --message-format flag][cargo/3000]
* [Pass target environment for rustdoc][cargo/3205]
* [Use `CommandExt::exec` for `cargo run` on Unix][cargo/2818]
* [Update curl and curl-sys][cargo/3241]
* [Call rustdoc test with the correct cfg flags of a package][cargo/3242]
Tooling
-------
* [rustdoc: Add the `--sysroot` argument][36586]
* [rustdoc: Fix a couple of issues with the search results][35655]
* [rustdoc: remove the `!` from macro URLs and titles][35234]
* [gdb: Fix pretty-printing special-cased Rust types][35585]
* [rustdoc: Filter more incorrect methods inherited through Deref][36266]
Misc
----
* [Remove unmaintained style guide][35124]
* [Add s390x support][36369]
* [Initial work at Haiku OS support][36727]
* [Add mips-uclibc targets][35734]
* [Crate-ify compiler-rt into compiler-builtins][35021]
* [Add rustc version info (git hash + date) to dist tarball][36213]
* Many documentation improvements
Compatibility Notes
-------------------
* [`SipHasher`] is deprecated. Use [`DefaultHasher`].
* [Deny (by default) transmuting from fn item types to pointer-sized
types][34923]. Continuing the long transition to zero-sized fn items,
per [RFC 401].
* [Fix `#[derive]` for empty tuple structs/variants][35728].
Part of [RFC 1506].
* [Issue deprecation warnings for safe accesses to extern statics][36173]
* [Fix lifetime rules for 'if' conditions][36029].
* [Inherit overflow checks for sum and product][36372].
* [Forbid user-defined macros named "macro_rules"][36730].
[33922]: https://github.com/rust-lang/rust/pull/33922
[34623]: https://github.com/rust-lang/rust/pull/34623
[34923]: https://github.com/rust-lang/rust/pull/34923
[34942]: https://github.com/rust-lang/rust/pull/34942
[34982]: https://github.com/rust-lang/rust/pull/34982
[35021]: https://github.com/rust-lang/rust/pull/35021
[35048]: https://github.com/rust-lang/rust/pull/35048
[35074]: https://github.com/rust-lang/rust/pull/35074
[35124]: https://github.com/rust-lang/rust/pull/35124
[35234]: https://github.com/rust-lang/rust/pull/35234
[35238]: https://github.com/rust-lang/rust/pull/35238
[35354]: https://github.com/rust-lang/rust/pull/35354
[35559]: https://github.com/rust-lang/rust/pull/35559
[35585]: https://github.com/rust-lang/rust/pull/35585
[35627]: https://github.com/rust-lang/rust/pull/35627
[35655]: https://github.com/rust-lang/rust/pull/35655
[35702]: https://github.com/rust-lang/rust/pull/35702
[35707]: https://github.com/rust-lang/rust/pull/35707
[35728]: https://github.com/rust-lang/rust/pull/35728
[35734]: https://github.com/rust-lang/rust/pull/35734
[35755]: https://github.com/rust-lang/rust/pull/35755
[35761]: https://github.com/rust-lang/rust/pull/35761
[35764]: https://github.com/rust-lang/rust/pull/35764
[35814]: https://github.com/rust-lang/rust/pull/35814
[35854]: https://github.com/rust-lang/rust/pull/35854
[35871]: https://github.com/rust-lang/rust/pull/35871
[35884]: https://github.com/rust-lang/rust/pull/35884
[35911]: https://github.com/rust-lang/rust/pull/35911
[35969]: https://github.com/rust-lang/rust/pull/35969
[35975]: https://github.com/rust-lang/rust/pull/35975
[36004]: https://github.com/rust-lang/rust/pull/36004
[36008]: https://github.com/rust-lang/rust/pull/36008
[36014]: https://github.com/rust-lang/rust/pull/36014
[36029]: https://github.com/rust-lang/rust/pull/36029
[36059]: https://github.com/rust-lang/rust/pull/36059
[36072]: https://github.com/rust-lang/rust/pull/36072
[36101]: https://github.com/rust-lang/rust/pull/36101
[36104]: https://github.com/rust-lang/rust/pull/36104
[36171]: https://github.com/rust-lang/rust/pull/36171
[36173]: https://github.com/rust-lang/rust/pull/36173
[36178]: https://github.com/rust-lang/rust/pull/36178
[36213]: https://github.com/rust-lang/rust/pull/36213
[36214]: https://github.com/rust-lang/rust/pull/36214
[36264]: https://github.com/rust-lang/rust/pull/36264
[36266]: https://github.com/rust-lang/rust/pull/36266
[36289]: https://github.com/rust-lang/rust/pull/36289
[36338]: https://github.com/rust-lang/rust/pull/36338
[36351]: https://github.com/rust-lang/rust/pull/36351
[36355]: https://github.com/rust-lang/rust/pull/36355
[36369]: https://github.com/rust-lang/rust/pull/36369
[36372]: https://github.com/rust-lang/rust/pull/36372
[36423]: https://github.com/rust-lang/rust/pull/36423
[36482]: https://github.com/rust-lang/rust/pull/36482
[36505]: https://github.com/rust-lang/rust/pull/36505
[36524]: https://github.com/rust-lang/rust/pull/36524
[36527]: https://github.com/rust-lang/rust/pull/36527
[36551]: https://github.com/rust-lang/rust/pull/36551
[36574]: https://github.com/rust-lang/rust/pull/36574
[36586]: https://github.com/rust-lang/rust/pull/36586
[36592]: https://github.com/rust-lang/rust/pull/36592
[36631]: https://github.com/rust-lang/rust/pull/36631
[36639]: https://github.com/rust-lang/rust/pull/36639
[36721]: https://github.com/rust-lang/rust/pull/36721
[36727]: https://github.com/rust-lang/rust/pull/36727
[36730]: https://github.com/rust-lang/rust/pull/36730
[36734]: https://github.com/rust-lang/rust/pull/36734
[36754]: https://github.com/rust-lang/rust/pull/36754
[36995]: https://github.com/rust-lang/rust/pull/36995
[RFC 0016]: https://github.com/rust-lang/rfcs/blob/master/text/0016-more-attributes.md
[RFC 0243]: https://github.com/rust-lang/rfcs/blob/master/text/0243-trait-based-exception-handling.md
[RFC 1506]: https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md
[RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
[RFC 873]: https://github.com/rust-lang/rfcs/blob/master/text/0873-type-macros.md
[cargo/2818]: https://github.com/rust-lang/cargo/pull/2818
[cargo/3000]: https://github.com/rust-lang/cargo/pull/3000
[cargo/3021]: https://github.com/rust-lang/cargo/pull/3021
[cargo/3038]: https://github.com/rust-lang/cargo/pull/3038
[cargo/3060]: https://github.com/rust-lang/cargo/pull/3060
[cargo/3078]: https://github.com/rust-lang/cargo/pull/3078
[cargo/3089]: https://github.com/rust-lang/cargo/pull/3089
[cargo/3092]: https://github.com/rust-lang/cargo/pull/3092
[cargo/3110]: https://github.com/rust-lang/cargo/pull/3110
[cargo/3121]: https://github.com/rust-lang/cargo/pull/3121
[cargo/3123]: https://github.com/rust-lang/cargo/pull/3123
[cargo/3125]: https://github.com/rust-lang/cargo/pull/3125
[cargo/3136]: https://github.com/rust-lang/cargo/pull/3136
[cargo/3144]: https://github.com/rust-lang/cargo/pull/3144
[cargo/3146]: https://github.com/rust-lang/cargo/pull/3146
[cargo/3157]: https://github.com/rust-lang/cargo/pull/3157
[cargo/3162]: https://github.com/rust-lang/cargo/pull/3162
[cargo/3205]: https://github.com/rust-lang/cargo/pull/3205
[cargo/3241]: https://github.com/rust-lang/cargo/pull/3241
[cargo/3242]: https://github.com/rust-lang/cargo/pull/3242
[rustup]: https://www.rustup.rs
[`checked_abs`]: https://doc.rust-lang.org/std/primitive.i32.html#method.checked_abs
[`wrapping_abs`]: https://doc.rust-lang.org/std/primitive.i32.html#method.wrapping_abs
[`overflowing_abs`]: https://doc.rust-lang.org/std/primitive.i32.html#method.overflowing_abs
[`RefCell::try_borrow`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.try_borrow
[`RefCell::try_borrow_mut`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.try_borrow_mut
[`SipHasher`]: https://doc.rust-lang.org/std/hash/struct.SipHasher.html
[`DefaultHasher`]: https://doc.rust-lang.org/std/collections/hash_map/struct.DefaultHasher.html
Version 1.12.1 (2016-10-20)
===========================
Regression Fixes
----------------
* [ICE: 'rustc' panicked at 'assertion failed: concrete_substs.is_normalized_for_trans()' #36381][36381]
* [Confusion with double negation and booleans][36856]
* [rustc 1.12.0 fails with SIGSEGV in release mode (syn crate 0.8.0)][36875]
* [Rustc 1.12.0 Windows build of `ethcore` crate fails with LLVM error][36924]
* [1.12.0: High memory usage when linking in release mode with debug info][36926]
* [Corrupted memory after updated to 1.12][36936]
* ["Let NullaryConstructor = something;" causes internal compiler error: "tried to overwrite interned AdtDef"][37026]
* [Fix ICE: inject bitcast if types mismatch for invokes/calls/stores][37112]
* [debuginfo: Handle spread_arg case in MIR-trans in a more stable way.][37153]
[36381]: https://github.com/rust-lang/rust/issues/36381
[36856]: https://github.com/rust-lang/rust/issues/36856
[36875]: https://github.com/rust-lang/rust/issues/36875
[36924]: https://github.com/rust-lang/rust/issues/36924
[36926]: https://github.com/rust-lang/rust/issues/36926
[36936]: https://github.com/rust-lang/rust/issues/36936
[37026]: https://github.com/rust-lang/rust/issues/37026
[37112]: https://github.com/rust-lang/rust/issues/37112
[37153]: https://github.com/rust-lang/rust/issues/37153
Version 1.12.0 (2016-09-29)
===========================
@ -27,7 +311,7 @@ Compiler
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`]
`--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]
@ -74,7 +358,7 @@ Language
useful]
(https://github.com/rust-lang/rust/pull/34908)
* [`macro_rules!` `stmt` matchers correctly consume the entire contents when
insider non-braces invocations]
inside non-braces invocations]
(https://github.com/rust-lang/rust/pull/34886)
* [Semicolons are properly required as statement delimeters inside
`macro_rules!` invocations]
@ -208,9 +492,6 @@ Cargo
Performance
-----------
* [`rustc` produces more compact code by more precisely identifying the live
ranges of variables]
(https://github.com/rust-lang/rust/pull/35409)
* [`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]

38
configure vendored
View File

@ -360,6 +360,13 @@ abs_path() {
(unset CDPATH && cd "$_path" > /dev/null && pwd)
}
HELP=0
for arg; do
case "$arg" in
--help) HELP=1;;
esac
done
msg "looking for configure programs"
need_cmd cmp
need_cmd mkdir
@ -430,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`:
@ -517,10 +528,18 @@ case $CFG_CPUTYPE in
CFG_CPUTYPE=powerpc64le
;;
s390x)
CFG_CPUTYPE=s390x
;;
x86_64 | x86-64 | x64 | amd64)
CFG_CPUTYPE=x86_64
;;
BePC)
CFG_CPUTYPE=i686
;;
*)
err "unknown CPU type: $CFG_CPUTYPE"
esac
@ -566,11 +585,8 @@ esac
OPTIONS=""
HELP=0
if [ "$1" = "--help" ]
if [ "$HELP" -eq 1 ]
then
HELP=1
shift
echo
echo "Usage: $CFG_SELF [options]"
echo
@ -609,7 +625,6 @@ opt dist-host-only 0 "only install bins for the host architecture"
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
opt rustbuild 0 "use the rust and cargo based build system"
opt orbit 1 "get MIR where it belongs - everywhere; most importantly, in orbit"
opt codegen-tests 1 "run the src/test/codegen tests"
opt option-checking 1 "complain about unrecognized options in this configure script"
opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)"
@ -630,6 +645,7 @@ 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)"
@ -668,6 +684,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 documentation in PATH"
# On Windows this determines root of the subtree for target libraries.
# Host runtime libs always go to 'bin'.
@ -733,8 +750,6 @@ if [ -n "$CFG_ENABLE_DEBUG_ASSERTIONS" ]; then putvar CFG_ENABLE_DEBUG_ASSERTION
if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi
if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi
if [ -n "$CFG_DISABLE_ORBIT" ]; then putvar CFG_DISABLE_ORBIT; fi
step_msg "looking for build programs"
probe_need CFG_CURL curl
@ -747,6 +762,9 @@ 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 ]
@ -899,7 +917,7 @@ then
fi
CMD="${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF}"
LRV=`$CMD --version`
LRV=`LD_LIBRARY_PATH=${CFG_LOCAL_RUST_ROOT}/lib $CMD --version`
if [ $? -ne 0 ]
then
step_msg "failure while running $CMD --version"
@ -1115,6 +1133,7 @@ putvar CFG_STDCPP_NAME
# a little post-processing of various config values
CFG_PREFIX=${CFG_PREFIX%/}
CFG_MANDIR=${CFG_MANDIR%/}
CFG_DOCDIR=${CFG_DOCDIR%/}
CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')"
CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')"
CFG_SUPPORTED_TARGET=""
@ -1749,7 +1768,7 @@ do
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON"
fi
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC'"
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ'"
CMAKE_ARGS="$CMAKE_ARGS -G '$CFG_CMAKE_GENERATOR'"
CMAKE_ARGS="$CMAKE_ARGS $CFG_LLVM_SRC_DIR"
@ -1796,6 +1815,7 @@ putvar CFG_ARMV7_LINUX_ANDROIDEABI_NDK
putvar CFG_I686_LINUX_ANDROID_NDK
putvar CFG_NACL_CROSS_PATH
putvar CFG_MANDIR
putvar CFG_DOCDIR
putvar CFG_USING_LIBCPP
# Avoid spurious warnings from clang by feeding it original source on

View File

@ -1,4 +1,4 @@
.TH RUSTC "1" "August 2016" "rustc 1.12.0" "User Commands"
.TH RUSTC "1" "September 2016" "rustc 1.13.0" "User Commands"
.SH NAME
rustc \- The Rust compiler
.SH SYNOPSIS

View File

@ -1,4 +1,4 @@
.TH RUSTDOC "1" "August 2016" "rustdoc 1.12.0" "User Commands"
.TH RUSTDOC "1" "September 2016" "rustdoc 1.13.0" "User Commands"
.SH NAME
rustdoc \- generate documentation from Rust source code
.SH SYNOPSIS

View File

@ -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

View File

@ -0,0 +1 @@
# rustbuild-only target

View File

@ -0,0 +1 @@
# rustbuild-only target

View File

@ -0,0 +1 @@
# rustbuild-only target

View File

@ -0,0 +1 @@
# rustbuild-only target

View File

@ -0,0 +1,24 @@
# s390x-unknown-linux-gnu configuration
CROSS_PREFIX_s390x-unknown-linux-gnu=s390x-linux-gnu-
CC_s390x-unknown-linux-gnu=$(CC)
CXX_s390x-unknown-linux-gnu=$(CXX)
CPP_s390x-unknown-linux-gnu=$(CPP)
AR_s390x-unknown-linux-gnu=$(AR)
CFG_LIB_NAME_s390x-unknown-linux-gnu=lib$(1).so
CFG_STATIC_LIB_NAME_s390x-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_s390x-unknown-linux-gnu=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_s390x-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_s390x-unknown-linux-gnu := -m64 $(CFLAGS)
CFG_GCCISH_CFLAGS_s390x-unknown-linux-gnu := -g -fPIC -m64 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_s390x-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_s390x-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
CFG_GCCISH_DEF_FLAG_s390x-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
CFG_LLC_FLAGS_s390x-unknown-linux-gnu :=
CFG_INSTALL_NAME_s390x-unknown-linux-gnu =
CFG_EXE_SUFFIX_s390x-unknown-linux-gnu =
CFG_WINDOWSY_s390x-unknown-linux-gnu :=
CFG_UNIXY_s390x-unknown-linux-gnu := 1
CFG_LDPATH_s390x-unknown-linux-gnu :=
CFG_RUN_s390x-unknown-linux-gnu=$(2)
CFG_RUN_TARG_s390x-unknown-linux-gnu=$(call CFG_RUN_s390x-unknown-linux-gnu,,$(2))
CFG_GNU_TRIPLE_s390x-unknown-linux-gnu := s390x-unknown-linux-gnu

View File

@ -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

View File

@ -102,7 +102,6 @@ define CLEAN_TARGET_STAGE_N
clean$(1)_T_$(2)_H_$(3): \
$$(foreach crate,$$(CRATES),clean$(1)_T_$(2)_H_$(3)-lib-$$(crate)) \
$$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS_ALL),clean$(1)_T_$(2)_H_$(3)-tool-$$(tool))
$$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/librun_pass_stage* # For unix
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/run_pass_stage* # For windows

View File

@ -51,7 +51,7 @@
TARGET_CRATES := libc std term \
getopts collections test rand \
core alloc \
compiler_builtins core alloc \
rustc_unicode rustc_bitflags \
alloc_system alloc_jemalloc \
panic_abort panic_unwind unwind
@ -59,12 +59,13 @@ 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
HOST_CRATES := syntax syntax_ext syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \
flate arena graphviz rbml log serialize
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 log serialize
TOOLS := compiletest rustdoc rustc rustbook error_index_generator
DEPS_core :=
DEPS_compiler_builtins := core
DEPS_alloc := core libc alloc_system
DEPS_alloc_system := core libc
DEPS_alloc_jemalloc := core libc native:jemalloc
@ -77,12 +78,14 @@ DEPS_panic_abort := libc alloc
DEPS_panic_unwind := libc alloc unwind
DEPS_unwind := libc
RUSTFLAGS_compiler_builtins := -lstatic=compiler-rt
# FIXME(stage0): change this to just `RUSTFLAGS_panic_abort := ...`
RUSTFLAGS1_panic_abort := -C panic=abort
RUSTFLAGS2_panic_abort := -C panic=abort
RUSTFLAGS3_panic_abort := -C panic=abort
DEPS_std := core libc rand alloc collections rustc_unicode \
DEPS_std := core libc rand alloc collections compiler_builtins rustc_unicode \
native:backtrace \
alloc_system panic_abort panic_unwind unwind
DEPS_arena := std
@ -93,34 +96,37 @@ 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
DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros rustc_macro
DEPS_proc_macro := syntax syntax_pos rustc_plugin log
DEPS_syntax_pos := serialize
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
DEPS_rustc_borrowck := rustc log graphviz syntax syntax_pos rustc_errors rustc_mir
DEPS_rustc_data_structures := std log serialize
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 rustc_passes rustc_save_analysis rustc_const_eval \
rustc_incremental syntax_pos rustc_errors
rustc_trans rustc_privacy rustc_lint rustc_plugin \
rustc_metadata syntax_ext proc_macro \
rustc_passes rustc_save_analysis rustc_const_eval \
rustc_incremental syntax_pos rustc_errors rustc_macro
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_metadata := rustc syntax syntax_pos rustc_errors rbml rustc_const_math
DEPS_rustc_macro := std syntax
DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \
rustc_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
@ -130,14 +136,13 @@ 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
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
test rustc_lint rustc_const_eval syntax_pos
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts test \
rustc_lint rustc_const_eval syntax_pos rustc_data_structures
TOOL_DEPS_compiletest := test getopts log serialize
TOOL_DEPS_rustdoc := rustdoc
@ -150,6 +155,7 @@ TOOL_SOURCE_rustc := $(S)src/driver/driver.rs
TOOL_SOURCE_rustbook := $(S)src/tools/rustbook/main.rs
TOOL_SOURCE_error_index_generator := $(S)src/tools/error_index_generator/main.rs
ONLY_RLIB_compiler_builtins := 1
ONLY_RLIB_core := 1
ONLY_RLIB_libc := 1
ONLY_RLIB_alloc := 1

View File

@ -76,6 +76,7 @@ tmp/dist/$$(SRC_PKG_NAME)-image: $(PKG_FILES)
@$(call E, making src image)
$(Q)rm -Rf tmp/dist/$(SRC_PKG_NAME)-image
$(Q)mkdir -p tmp/dist/$(SRC_PKG_NAME)-image/lib/rustlib/src/rust
$(Q)echo "$(CFG_VERSION)" > tmp/dist/$(SRC_PKG_NAME)-image/lib/rustlib/src/rust/version
$(Q)tar \
-C $(S) \
-f - \

View File

@ -66,7 +66,7 @@ ERR_IDX_GEN_MD = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(ERR_IDX_GEN_EXE)
D := $(S)src/doc
DOC_TARGETS := book nomicon style error-index
DOC_TARGETS := book nomicon error-index
COMPILER_DOC_TARGETS :=
DOC_L10N_TARGETS :=
@ -209,13 +209,6 @@ doc/nomicon/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/nomicon/*.md) |
$(Q)rm -rf doc/nomicon
$(Q)$(RUSTBOOK) build $(S)src/doc/nomicon doc/nomicon
style: doc/style/index.html
doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/
@$(call E, rustbook: $@)
$(Q)rm -rf doc/style
$(Q)$(RUSTBOOK) build $(S)src/doc/style doc/style
error-index: doc/error-index.html
# Metadata used to generate the index is created as a side effect of

View File

@ -12,7 +12,8 @@ RUN_INSTALLER = cd tmp/empty_dir && \
sh ../../tmp/dist/$(1)/install.sh \
--prefix="$(DESTDIR)$(CFG_PREFIX)" \
--libdir="$(DESTDIR)$(CFG_LIBDIR)" \
--mandir="$(DESTDIR)$(CFG_MANDIR)"
--mandir="$(DESTDIR)$(CFG_MANDIR)" \
--docdir="$(DESTDIR)$(CFG_DOCDIR)"
install:
ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))

View File

@ -13,12 +13,12 @@
######################################################################
# The version number
CFG_RELEASE_NUM=1.12.1
CFG_RELEASE_NUM=1.13.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
# versions (section 9)
CFG_PRERELEASE_VERSION=.6
CFG_PRERELEASE_VERSION=.3
ifeq ($(CFG_RELEASE_CHANNEL),stable)
# This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly"
@ -53,17 +53,6 @@ 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
ifdef CFG_ENABLE_LOCAL_RUST
ifeq ($(CFG_RELEASE),\
@ -73,14 +62,6 @@ ifeq ($(CFG_RELEASE),\
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)
@ -162,12 +143,6 @@ ifdef CFG_ENABLE_DEBUGINFO
CFG_RUSTC_FLAGS += -g
endif
ifdef CFG_DISABLE_ORBIT
$(info cfg: HOLD HOLD HOLD (CFG_DISABLE_ORBIT))
RUSTFLAGS_STAGE1 += -Z orbit=off
RUSTFLAGS_STAGE2 += -Z orbit=off
endif
ifdef SAVE_TEMPS
CFG_RUSTC_FLAGS += -C save-temps
endif
@ -306,7 +281,7 @@ endif
# LLVM macros
######################################################################
LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl
LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz
LLVM_REQUIRED_COMPONENTS=ipo bitreader bitwriter linker asmparser mcjit \
interpreter instrumentation
@ -354,6 +329,7 @@ LLVM_AS_$(1)=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-as$$(X_$(1))
LLC_$(1)=$$(CFG_LLVM_INST_DIR_$(1))/bin/llc$$(X_$(1))
LLVM_ALL_COMPONENTS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --components)
LLVM_VERSION_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --version)
endef
@ -392,13 +368,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=1
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=5c6cf767
######################################################################
# Per-stage targets and runner
######################################################################
@ -460,7 +439,10 @@ endif
TSREQ$(1)_T_$(2)_H_$(3) = \
$$(HSREQ$(1)_H_$(3)) \
$$(foreach obj,$$(REQUIRED_OBJECTS_$(2)),\
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(obj))
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(obj)) \
$$(TLIB0_T_$(2)_H_$(3))/$$(call CFG_STATIC_LIB_NAME_$(2),compiler-rt)
# ^ This copies `libcompiler-rt.a` to the stage0 sysroot
# ^ TODO(stage0) update this to not copy `libcompiler-rt.a` to stage0
# Prerequisites for a working stageN compiler and libraries, for a specific
# target
@ -514,10 +496,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
@ -635,7 +621,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

View File

@ -102,8 +102,6 @@ include $(wildcard $(CFG_SRC_DIR)mk/cfg/*.mk)
define ADD_INSTALLED_OBJECTS
INSTALLED_OBJECTS_$(1) += $$(CFG_INSTALLED_OBJECTS_$(1))
REQUIRED_OBJECTS_$(1) += $$(CFG_THIRD_PARTY_OBJECTS_$(1))
INSTALLED_OBJECTS_$(1) += $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
REQUIRED_OBJECTS_$(1) += $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
endef
$(foreach target,$(CFG_TARGET), \

338
mk/rt.mk
View File

@ -37,6 +37,16 @@
################################################################################
NATIVE_LIBS := hoedown miniz rust_test_helpers
# A macro to add a generic implementation of intrinsics iff a arch optimized implementation is not
# already in the list.
# $(1) is the target
# $(2) is the intrinsic
define ADD_INTRINSIC
ifeq ($$(findstring X,$$(foreach intrinsic,$$(COMPRT_OBJS_$(1)),$$(if $$(findstring $(2),$$(intrinsic)),X,))),)
COMPRT_OBJS_$(1) += $(2)
endif
endef
# $(1) is the target triple
define NATIVE_LIBRARIES
@ -230,167 +240,15 @@ COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1))
COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt
# GENERIC_SOURCES in CMakeLists.txt
COMPRT_OBJS_$(1) := \
absvdi2.o \
absvsi2.o \
adddf3.o \
addsf3.o \
addvdi3.o \
addvsi3.o \
apple_versioning.o \
ashldi3.o \
ashrdi3.o \
clear_cache.o \
clzdi2.o \
clzsi2.o \
cmpdi2.o \
comparedf2.o \
comparesf2.o \
ctzdi2.o \
ctzsi2.o \
divdc3.o \
divdf3.o \
divdi3.o \
divmoddi4.o \
divmodsi4.o \
divsc3.o \
divsf3.o \
divsi3.o \
divxc3.o \
extendsfdf2.o \
extendhfsf2.o \
ffsdi2.o \
fixdfdi.o \
fixdfsi.o \
fixsfdi.o \
fixsfsi.o \
fixunsdfdi.o \
fixunsdfsi.o \
fixunssfdi.o \
fixunssfsi.o \
fixunsxfdi.o \
fixunsxfsi.o \
fixxfdi.o \
floatdidf.o \
floatdisf.o \
floatdixf.o \
floatsidf.o \
floatsisf.o \
floatundidf.o \
floatundisf.o \
floatundixf.o \
floatunsidf.o \
floatunsisf.o \
int_util.o \
lshrdi3.o \
moddi3.o \
modsi3.o \
muldc3.o \
muldf3.o \
muldi3.o \
mulodi4.o \
mulosi4.o \
muloti4.o \
mulsc3.o \
mulsf3.o \
mulvdi3.o \
mulvsi3.o \
mulxc3.o \
negdf2.o \
negdi2.o \
negsf2.o \
negvdi2.o \
negvsi2.o \
paritydi2.o \
paritysi2.o \
popcountdi2.o \
popcountsi2.o \
powidf2.o \
powisf2.o \
powixf2.o \
subdf3.o \
subsf3.o \
subvdi3.o \
subvsi3.o \
truncdfhf2.o \
truncdfsf2.o \
truncsfhf2.o \
ucmpdi2.o \
udivdi3.o \
udivmoddi4.o \
udivmodsi4.o \
udivsi3.o \
umoddi3.o \
umodsi3.o
# We must avoid compiling both a generic implementation (e.g. `floatdidf.c) and an arch optimized
# implementation (e.g. `x86_64/floatdidf.S) of the same symbol (e.g. `floatdidf) because that causes
# linker errors. To avoid that, we first add all the arch optimized implementations and then add the
# generic implementations if and only if its arch optimized version is not already in the list. This
# last part is handled by the ADD_INTRINSIC macro.
ifeq ($$(findstring ios,$(1)),)
COMPRT_OBJS_$(1) += \
absvti2.o \
addtf3.o \
addvti3.o \
ashlti3.o \
ashrti3.o \
clzti2.o \
cmpti2.o \
ctzti2.o \
divtf3.o \
divti3.o \
ffsti2.o \
fixdfti.o \
fixsfti.o \
fixunsdfti.o \
fixunssfti.o \
fixunsxfti.o \
fixxfti.o \
floattidf.o \
floattisf.o \
floattixf.o \
floatuntidf.o \
floatuntisf.o \
floatuntixf.o \
lshrti3.o \
modti3.o \
multf3.o \
multi3.o \
mulvti3.o \
negti2.o \
negvti2.o \
parityti2.o \
popcountti2.o \
powitf2.o \
subtf3.o \
subvti3.o \
trampoline_setup.o \
ucmpti2.o \
udivmodti4.o \
udivti3.o \
umodti3.o
endif
ifeq ($$(findstring apple,$(1)),apple)
COMPRT_OBJS_$(1) += \
atomic_flag_clear.o \
atomic_flag_clear_explicit.o \
atomic_flag_test_and_set.o \
atomic_flag_test_and_set_explicit.o \
atomic_signal_fence.o \
atomic_thread_fence.o
endif
ifeq ($$(findstring windows,$(1)),)
COMPRT_OBJS_$(1) += emutls.o
endif
COMPRT_OBJS_$(1) :=
ifeq ($$(findstring msvc,$(1)),)
ifeq ($$(findstring freebsd,$(1)),)
COMPRT_OBJS_$(1) += gcc_personality_v0.o
endif
COMPRT_OBJS_$(1) += emutls.o
ifeq ($$(findstring x86_64,$(1)),x86_64)
COMPRT_OBJS_$(1) += \
x86_64/chkstk.o \
@ -540,9 +398,166 @@ COMPRT_OBJS_$(1) += \
arm/unordsf2vfp.o
endif
$(foreach intrinsic,absvdi2.o \
absvsi2.o \
adddf3.o \
addsf3.o \
addvdi3.o \
addvsi3.o \
apple_versioning.o \
ashldi3.o \
ashrdi3.o \
clear_cache.o \
clzdi2.o \
clzsi2.o \
cmpdi2.o \
comparedf2.o \
comparesf2.o \
ctzdi2.o \
ctzsi2.o \
divdc3.o \
divdf3.o \
divdi3.o \
divmoddi4.o \
divmodsi4.o \
divsc3.o \
divsf3.o \
divsi3.o \
divxc3.o \
extendsfdf2.o \
extendhfsf2.o \
ffsdi2.o \
fixdfdi.o \
fixdfsi.o \
fixsfdi.o \
fixsfsi.o \
fixunsdfdi.o \
fixunsdfsi.o \
fixunssfdi.o \
fixunssfsi.o \
fixunsxfdi.o \
fixunsxfsi.o \
fixxfdi.o \
floatdidf.o \
floatdisf.o \
floatdixf.o \
floatsidf.o \
floatsisf.o \
floatundidf.o \
floatundisf.o \
floatundixf.o \
floatunsidf.o \
floatunsisf.o \
int_util.o \
lshrdi3.o \
moddi3.o \
modsi3.o \
muldc3.o \
muldf3.o \
muldi3.o \
mulodi4.o \
mulosi4.o \
muloti4.o \
mulsc3.o \
mulsf3.o \
mulvdi3.o \
mulvsi3.o \
mulxc3.o \
negdf2.o \
negdi2.o \
negsf2.o \
negvdi2.o \
negvsi2.o \
paritydi2.o \
paritysi2.o \
popcountdi2.o \
popcountsi2.o \
powidf2.o \
powisf2.o \
powixf2.o \
subdf3.o \
subsf3.o \
subvdi3.o \
subvsi3.o \
truncdfhf2.o \
truncdfsf2.o \
truncsfhf2.o \
ucmpdi2.o \
udivdi3.o \
udivmoddi4.o \
udivmodsi4.o \
udivsi3.o \
umoddi3.o \
umodsi3.o,
$(call ADD_INTRINSIC,$(1),$(intrinsic)))
ifeq ($$(findstring ios,$(1)),)
$(foreach intrinsic,absvti2.o \
addtf3.o \
addvti3.o \
ashlti3.o \
ashrti3.o \
clzti2.o \
cmpti2.o \
ctzti2.o \
divtf3.o \
divti3.o \
ffsti2.o \
fixdfti.o \
fixsfti.o \
fixunsdfti.o \
fixunssfti.o \
fixunsxfti.o \
fixxfti.o \
floattidf.o \
floattisf.o \
floattixf.o \
floatuntidf.o \
floatuntisf.o \
floatuntixf.o \
lshrti3.o \
modti3.o \
multf3.o \
multi3.o \
mulvti3.o \
negti2.o \
negvti2.o \
parityti2.o \
popcountti2.o \
powitf2.o \
subtf3.o \
subvti3.o \
trampoline_setup.o \
ucmpti2.o \
udivmodti4.o \
udivti3.o \
umodti3.o,
$(call ADD_INTRINSIC,$(1),$(intrinsic)))
endif
ifeq ($$(findstring apple,$(1)),apple)
$(foreach intrinsic,atomic_flag_clear.o \
atomic_flag_clear_explicit.o \
atomic_flag_test_and_set.o \
atomic_flag_test_and_set_explicit.o \
atomic_signal_fence.o \
atomic_thread_fence.o,
$(call ADD_INTRINSIC,$(1),$(intrinsic)))
endif
ifeq ($$(findstring windows,$(1)),)
$(call ADD_INTRINSIC,$(1),emutls.o)
endif
ifeq ($$(findstring msvc,$(1)),)
ifeq ($$(findstring freebsd,$(1)),)
$(call ADD_INTRINSIC,$(1),gcc_personality_v0.o)
endif
endif
ifeq ($$(findstring aarch64,$(1)),aarch64)
COMPRT_OBJS_$(1) += \
comparetf2.o \
$(foreach intrinsic,comparetf2.o \
extenddftf2.o \
extendsftf2.o \
fixtfdi.o \
@ -557,7 +572,8 @@ COMPRT_OBJS_$(1) += \
floatunsitf.o \
multc3.o \
trunctfdf2.o \
trunctfsf2.o
trunctfsf2.o,
$(call ADD_INTRINSIC,$(1),$(intrinsic)))
endif
ifeq ($$(findstring msvc,$(1)),msvc)

View File

@ -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)) \

View File

@ -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))
@ -649,6 +649,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) = \
--lldb-python $$(CFG_LLDB_PYTHON) \
--gdb-version="$(CFG_GDB_VERSION)" \
--lldb-version="$(CFG_LLDB_VERSION)" \
--llvm-version="$$(LLVM_VERSION_$(3))" \
--android-cross-path=$(CFG_ARM_LINUX_ANDROIDEABI_NDK) \
--adb-path=$(CFG_ADB) \
--adb-test-dir=$(CFG_ADB_TEST_DIR) \

View File

@ -157,3 +157,24 @@ 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)" = "<none>"
"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"

View File

@ -38,21 +38,27 @@ fn main() {
// is passed (a bit janky...)
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
// able to produce an executable, whereas intermediate compilers may not
// have the standard library built yet and may not be able to produce an
// executable. Otherwise we just use the standard compiler we're
// bootstrapping with.
let (rustc, libdir) = if target.is_none() {
//
// Also note that cargo will detect the version of the compiler to trigger
// a rebuild when the compiler changes. If this happens, we want to make
// sure to use the actual compiler instead of the snapshot compiler becase
// that's the one that's actually changing.
let (rustc, libdir) = if target.is_none() && version.is_none() {
("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
} 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));
@ -65,7 +71,7 @@ fn main() {
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

View File

@ -20,15 +20,16 @@ use std::path::PathBuf;
fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
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(format!("stage{}", stage))
.arg("--cfg").arg("dox")
.env(bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap());
@ -37,4 +38,3 @@ fn main() {
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
})
}

View File

@ -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 @@ class RustBuild:
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 @@ class RustBuild:
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 @@ class RustBuild:
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 @@ class RustBuild:
sys.exit(ret)
def build_triple(self):
default_encoding = sys.getdefaultencoding()
config = self.get_toml('build')
if config:
return config
@ -276,8 +278,8 @@ class RustBuild:
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 @@ class RustBuild:
# 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'

View File

@ -148,6 +148,9 @@ pub fn compiletest(build: &Build,
if let Some(ref dir) = build.lldb_python_dir {
cmd.arg("--lldb-python-dir").arg(dir);
}
let llvm_config = build.llvm_config(target);
let llvm_version = output(Command::new(&llvm_config).arg("--version"));
cmd.arg("--llvm-version").arg(llvm_version);
cmd.args(&build.flags.args);
@ -158,7 +161,6 @@ pub fn compiletest(build: &Build,
// Only pass correct values for these flags for the `run-make` suite as it
// requires that a C++ compiler was configured which isn't always the case.
if suite == "run-make" {
let llvm_config = build.llvm_config(target);
let llvm_components = output(Command::new(&llvm_config).arg("--components"));
let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
cmd.arg("--cc").arg(build.cc(target))
@ -183,7 +185,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);

View File

@ -28,7 +28,6 @@ pub fn clean(build: &Build) {
let out = build.out.join(host);
rm_rf(build, &out.join("compiler-rt"));
rm_rf(build, &out.join("doc"));
for stage in 0..4 {

View File

@ -16,12 +16,14 @@
//! compiler. This module is also responsible for assembling the sysroot as it
//! goes along from the output of the previous stage.
use std::cmp;
use std::collections::HashMap;
use std::fs;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::process::Command;
use build_helper::output;
use filetime::FileTime;
use util::{exe, staticlib, libdir, mtime, is_dylib, copy};
use {Build, Compiler, Mode};
@ -35,13 +37,23 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
compiler.host, target);
// Move compiler-rt into place as it'll be required by the compiler when
// building the standard library to link the dylib of libstd
let libdir = build.sysroot_libdir(compiler, target);
let _ = fs::remove_dir_all(&libdir);
t!(fs::create_dir_all(&libdir));
copy(&build.compiler_rt_built.borrow()[target],
&libdir.join(staticlib("compiler-rt", target)));
// 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.
@ -59,13 +71,14 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
cargo.env("JEMALLOC_OVERRIDE", jemalloc);
}
}
if let Some(ref p) = build.config.musl_root {
if target.contains("musl") {
if target.contains("musl") {
if let Some(p) = build.musl_root(target) {
cargo.env("MUSL_ROOT", p);
}
}
build.run(&mut cargo);
update_mtime(&libstd_stamp(build, compiler, target));
std_link(build, target, compiler, compiler.host);
}
@ -83,26 +96,24 @@ pub fn std_link(build: &Build,
// If we're linking one compiler host's output into another, then we weren't
// called from the `std` method above. In that case we clean out what's
// already there and then also link compiler-rt into place.
// already there.
if host != compiler.host {
let _ = fs::remove_dir_all(&libdir);
t!(fs::create_dir_all(&libdir));
copy(&build.compiler_rt_built.borrow()[target],
&libdir.join(staticlib("compiler-rt", target)));
}
add_to_sysroot(&out_dir, &libdir);
if target.contains("musl") && !target.contains("mips") {
copy_third_party_objects(build, target, &libdir);
copy_musl_third_party_objects(build, &libdir);
}
}
/// Copies the crt(1,i,n).o startup objects
///
/// Only required for musl targets that statically link to libc
fn copy_third_party_objects(build: &Build, target: &str, into: &Path) {
fn copy_musl_third_party_objects(build: &Build, into: &Path) {
for &obj in &["crt1.o", "crti.o", "crtn.o"] {
copy(&compiler_file(build.cc(target), obj), &into.join(obj));
copy(&build.config.musl_root.as_ref().unwrap().join("lib").join(obj), &into.join(obj));
}
}
@ -117,14 +128,16 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
return
}
let compiler = Compiler::new(0, &build.config.build);
let compiler = build.compiler_path(&compiler);
let compiler_path = build.compiler_path(&compiler);
for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) {
let file = t!(file);
build.run(Command::new(&compiler)
.arg("--emit=obj")
.arg("--out-dir").arg(into)
.arg(file.path()));
let mut cmd = Command::new(&compiler_path);
build.add_bootstrap_key(&mut cmd);
build.run(cmd.arg("--target").arg(target)
.arg("--emit=obj")
.arg("--out-dir").arg(into)
.arg(file.path()));
}
for obj in ["crt2.o", "dllcrt2.o"].iter() {
@ -141,11 +154,12 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
compiler.host, target);
let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
build.clear_if_dirty(&out_dir, &libstd_shim(build, compiler, target));
build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build");
cargo.arg("--manifest-path")
.arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
build.run(&mut cargo);
update_mtime(&libtest_stamp(build, compiler, target));
test_link(build, target, compiler, compiler.host);
}
@ -173,7 +187,7 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
compiler.stage, compiler.host, target);
let out_dir = build.cargo_out(compiler, Mode::Librustc, target);
build.clear_if_dirty(&out_dir, &libtest_shim(build, compiler, target));
build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target));
let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build");
cargo.arg("--features").arg(build.rustc_features())
@ -185,7 +199,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");
@ -203,6 +216,10 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
cargo.env("LLVM_RUSTLLVM", "1");
}
cargo.env("LLVM_CONFIG", build.llvm_config(target));
let target_config = build.config.target_config.get(target);
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
cargo.env("CFG_LLVM_ROOT", s);
}
if build.config.llvm_static_stdcpp {
cargo.env("LLVM_STATIC_STDCPP",
compiler_file(build.cxx(target), "libstdc++.a"));
@ -234,14 +251,14 @@ pub fn rustc_link(build: &Build,
/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
fn libstd_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
build.cargo_out(compiler, Mode::Libstd, target).join("libstd_shim.rlib")
fn libstd_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
}
/// Cargo's output path for libtest in a given stage, compiled by a particular
/// compiler for the specified target.
fn libtest_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
build.cargo_out(compiler, Mode::Libtest, target).join("libtest_shim.rlib")
fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
}
fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
@ -354,10 +371,35 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
// Maybe when libstd is compiled it should clear out the rustc of the
// corresponding stage?
// let out_dir = build.cargo_out(stage, &host, Mode::Librustc, target);
// build.clear_if_dirty(&out_dir, &libstd_shim(build, stage, &host, target));
// build.clear_if_dirty(&out_dir, &libstd_stamp(build, stage, &host, target));
let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build");
cargo.arg("--manifest-path")
.arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool)));
build.run(&mut cargo);
}
/// Updates the mtime of a stamp file if necessary, only changing it if it's
/// older than some other file in the same directory.
///
/// We don't know what file Cargo is going to output (because there's a hash in
/// the file name) but we know where it's going to put it. We use this helper to
/// detect changes to that output file by looking at the modification time for
/// all files in a directory and updating the stamp if any are newer.
fn update_mtime(path: &Path) {
let mut max = None;
if let Ok(entries) = path.parent().unwrap().read_dir() {
for entry in entries.map(|e| t!(e)) {
if t!(entry.file_type()).is_file() {
let meta = t!(entry.metadata());
let time = FileTime::from_last_modification_time(&meta);
max = cmp::max(max, Some(time));
}
}
}
if !max.is_none() && max <= Some(mtime(path)) {
return
}
t!(File::create(path));
}

View File

@ -76,8 +76,11 @@ pub struct Config {
// misc
pub channel: String,
// Fallback musl-root for all targets
pub musl_root: Option<PathBuf>,
pub prefix: Option<String>,
pub codegen_tests: bool,
pub nodejs: Option<PathBuf>,
}
/// Per-target configuration stored in the global configuration structure.
@ -88,6 +91,7 @@ pub struct Target {
pub cc: Option<PathBuf>,
pub cxx: Option<PathBuf>,
pub ndk: Option<PathBuf>,
pub musl_root: Option<PathBuf>,
}
/// Structure of the `config.toml` file that configuration is read from.
@ -143,6 +147,7 @@ struct Rust {
rpath: Option<bool>,
optimize_tests: Option<bool>,
debuginfo_tests: Option<bool>,
codegen_tests: Option<bool>,
}
/// TOML representation of how each build target is configured.
@ -169,6 +174,7 @@ impl Config {
config.rust_codegen_units = 1;
config.build = build.to_string();
config.channel = "dev".to_string();
config.codegen_tests = true;
let toml = file.map(|file| {
let mut f = t!(File::open(&file));
@ -230,6 +236,7 @@ impl Config {
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);
set(&mut config.codegen_tests, rust.codegen_tests);
set(&mut config.rust_rpath, rust.rpath);
set(&mut config.debug_jemalloc, rust.debug_jemalloc);
set(&mut config.use_jemalloc, rust.use_jemalloc);
@ -322,6 +329,7 @@ impl Config {
("DEBUGINFO_TESTS", self.rust_debuginfo_tests),
("LOCAL_REBUILD", self.local_rebuild),
("NINJA", self.ninja),
("CODEGEN_TESTS", self.codegen_tests),
}
match key {
@ -388,6 +396,9 @@ 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));
}
_ => {}
}
}

View File

@ -1,5 +1,8 @@
# Sample TOML configuration file for building Rust.
#
# To configure rustbuild, copy this file to the directory from which you will be
# running the build, and name it config.toml.
#
# All options are commented out by default in this file, and they're commented
# out with their default values. The build system by default looks for
# `config.toml` in the current directory of a build for build configuration, but
@ -115,10 +118,6 @@
# nightly features
#channel = "dev"
# The root location of the MUSL installation directory. The library directory
# will also need to contain libunwind.a for an unwinding implementation.
#musl-root = "..."
# By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix
# platforms to ensure that the compiler is usable by default from the build
# directory (as it links to a number of dynamic libraries). This may not be
@ -130,6 +129,10 @@
#optimize-tests = true
#debuginfo-tests = true
# Flag indicating whether codegen tests will be run or not. If you get an error
# saying that the FileCheck executable is missing, you may want to disable this.
#codegen-tests = true
# =============================================================================
# Options for specific targets
#
@ -160,3 +163,9 @@
# the NDK for the target lives. This is used to find the C compiler to link and
# build native code.
#android-ndk = "/path/to/ndk"
# The root location of the MUSL installation directory. The library directory
# will also need to contain libunwind.a for an unwinding implementation. Note
# that this option only makes sense for MUSL targets that produce statically
# linked binaries
#musl-root = "..."

View File

@ -388,6 +388,9 @@ pub fn rust_src(build: &Build) {
// Rename directory, so that root folder of tarball has the correct name
t!(fs::rename(&dst_src, &plain_dst_src));
// Create the version file
write_file(&plain_dst_src.join("version"), build.version.as_bytes());
// Create plain source tarball
let mut cmd = Command::new("tar");
cmd.arg("-czf").arg(sanitize_sh(&distdir(build).join(&format!("{}.tar.gz", plain_name))))
@ -431,3 +434,8 @@ fn sanitize_sh(path: &Path) -> String {
Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
}
}
fn write_file(path: &Path, data: &[u8]) {
let mut vf = t!(fs::File::create(path));
t!(vf.write_all(data));
}

View File

@ -28,11 +28,10 @@ extern crate rustc_serialize;
extern crate toml;
extern crate regex;
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::fs::{self, File};
use std::path::{PathBuf, Path};
use std::path::{Component, PathBuf, Path};
use std::process::Command;
use build_helper::{run_silent, output};
@ -46,7 +45,7 @@ use util::{exe, mtime, libdir, add_lib_path};
/// * The error itself
///
/// This is currently used judiciously throughout the build system rather than
/// using a `Result` with `try!`, but this may change on day...
/// using a `Result` with `try!`, but this may change one day...
macro_rules! t {
($e:expr) => (match $e {
Ok(e) => e,
@ -131,7 +130,6 @@ pub struct Build {
// Runtime state filled in later on
cc: HashMap<String, (gcc::Tool, Option<PathBuf>)>,
cxx: HashMap<String, gcc::Tool>,
compiler_rt_built: RefCell<HashMap<String, PathBuf>>,
}
/// The various "modes" of invoking Cargo.
@ -198,7 +196,6 @@ impl Build {
package_vers: String::new(),
cc: HashMap::new(),
cxx: HashMap::new(),
compiler_rt_built: RefCell::new(HashMap::new()),
gdb_version: None,
lldb_version: None,
lldb_python_dir: None,
@ -246,15 +243,19 @@ 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 } => {
native::llvm(self, target.target);
}
CompilerRt { _dummy } => {
native::compiler_rt(self, target.target);
}
TestHelpers { _dummy } => {
native::test_helpers(self, target.target);
}
@ -308,10 +309,6 @@ impl Build {
doc::rustbook(self, stage, target.target, "nomicon",
&doc_out);
}
DocStyle { stage } => {
doc::rustbook(self, stage, target.target, "style",
&doc_out);
}
DocStandalone { stage } => {
doc::standalone(self, stage, target.target, &doc_out);
}
@ -394,8 +391,10 @@ impl Build {
"mir-opt", "mir-opt");
}
CheckCodegen { compiler } => {
check::compiletest(self, &compiler, target.target,
"codegen", "codegen");
if self.config.codegen_tests {
check::compiletest(self, &compiler, target.target,
"codegen", "codegen");
}
}
CheckCodegenUnits { compiler } => {
check::compiletest(self, &compiler, target.target,
@ -479,12 +478,32 @@ impl Build {
/// This will detect if any submodules are out of date an run the necessary
/// commands to sync them all with upstream.
fn update_submodules(&self) {
struct Submodule<'a> {
path: &'a Path,
state: State,
}
enum State {
// The submodule may have staged/unstaged changes
MaybeDirty,
// Or could be initialized but never updated
NotInitialized,
// The submodule, itself, has extra commits but those changes haven't been commited to
// the (outer) git repository
OutOfSync,
}
if !self.config.submodules {
return
}
if fs::metadata(self.src.join(".git")).is_err() {
return
}
let git = || {
let mut cmd = Command::new("git");
cmd.current_dir(&self.src);
return cmd
};
let git_submodule = || {
let mut cmd = Command::new("git");
cmd.current_dir(&self.src).arg("submodule");
@ -496,19 +515,67 @@ impl Build {
// of detecting whether we need to run all the submodule commands
// below.
let out = output(git_submodule().arg("status"));
if !out.lines().any(|l| l.starts_with("+") || l.starts_with("-")) {
return
let mut submodules = vec![];
for line in out.lines() {
// NOTE `git submodule status` output looks like this:
//
// -5066b7dcab7e700844b0e2ba71b8af9dc627a59b src/liblibc
// +b37ef24aa82d2be3a3cc0fe89bf82292f4ca181c src/compiler-rt (remotes/origin/..)
// e058ca661692a8d01f8cf9d35939dfe3105ce968 src/jemalloc (3.6.0-533-ge058ca6)
//
// The first character can be '-', '+' or ' ' and denotes the `State` of the submodule
// Right next to this character is the SHA-1 of the submodule HEAD
// And after that comes the path to the submodule
let path = Path::new(line[1..].split(' ').skip(1).next().unwrap());
let state = if line.starts_with('-') {
State::NotInitialized
} else if line.starts_with('+') {
State::OutOfSync
} else if line.starts_with(' ') {
State::MaybeDirty
} else {
panic!("unexpected git submodule state: {:?}", line.chars().next());
};
submodules.push(Submodule { path: path, state: state })
}
self.run(git_submodule().arg("sync"));
self.run(git_submodule().arg("init"));
self.run(git_submodule().arg("update"));
self.run(git_submodule().arg("update").arg("--recursive"));
self.run(git_submodule().arg("status").arg("--recursive"));
self.run(git_submodule().arg("foreach").arg("--recursive")
.arg("git").arg("clean").arg("-fdx"));
self.run(git_submodule().arg("foreach").arg("--recursive")
.arg("git").arg("checkout").arg("."));
for submodule in submodules {
// If using llvm-root then don't touch the llvm submodule.
if submodule.path.components().any(|c| c == Component::Normal("llvm".as_ref())) &&
self.config.target_config.get(&self.config.build)
.and_then(|c| c.llvm_config.as_ref()).is_some()
{
continue
}
if submodule.path.components().any(|c| c == Component::Normal("jemalloc".as_ref())) &&
!self.config.use_jemalloc
{
continue
}
match submodule.state {
State::MaybeDirty => {
// drop staged changes
self.run(git().arg("-C").arg(submodule.path).args(&["reset", "--hard"]));
// drops unstaged changes
self.run(git().arg("-C").arg(submodule.path).args(&["clean", "-fdx"]));
},
State::NotInitialized => {
self.run(git_submodule().arg("init").arg(submodule.path));
self.run(git_submodule().arg("update").arg(submodule.path));
},
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"]));
},
}
}
}
/// Clear out `dir` if `input` is newer.
@ -519,6 +586,8 @@ impl Build {
if mtime(&stamp) < mtime(input) {
self.verbose(&format!("Dirty - {}", dir.display()));
let _ = fs::remove_dir_all(dir);
} else if stamp.exists() {
return
}
t!(fs::create_dir_all(dir));
t!(File::create(stamp));
@ -543,6 +612,10 @@ impl Build {
.arg("-j").arg(self.jobs().to_string())
.arg("--target").arg(target);
// FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005
// Force cargo to output binaries with disambiguating hashes in the name
cargo.env("__CARGO_DEFAULT_LIB_METADATA", "1");
let stage;
if compiler.stage == 0 && self.local_rebuild {
// Assume the local-rebuild rustc already has stage1 features.
@ -574,7 +647,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.
@ -769,11 +842,6 @@ impl Build {
}
}
/// Root output directory for compiler-rt compiled for `target`
fn compiler_rt_out(&self, target: &str) -> PathBuf {
self.out.join(target).join("compiler-rt")
}
/// Root output directory for rust_test_helpers library compiled for
/// `target`
fn test_helpers_out(&self, target: &str) -> PathBuf {
@ -794,16 +862,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", "1");
// 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", "5c6cf767");
}
/// Returns the compiler's libdir where it stores the dynamic libraries that
@ -889,7 +952,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`.
@ -907,6 +974,13 @@ impl Build {
}
return base
}
/// 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()
.or(self.config.musl_root.as_ref())
.map(|p| &**p)
}
}
impl<'a> Compiler<'a> {

View File

@ -22,6 +22,10 @@ BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py $(BOOTSTRAP_
all:
$(Q)$(BOOTSTRAP)
# Dont use $(Q) here, always show how to invoke the bootstrap script directly
help:
$(BOOTSTRAP) --help
clean:
$(Q)$(BOOTSTRAP) --clean

View File

@ -27,7 +27,7 @@ use cmake;
use gcc;
use Build;
use util::{staticlib, up_to_date};
use util::up_to_date;
/// Compile LLVM for `target`.
pub fn llvm(build: &Build, target: &str) {
@ -65,7 +65,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")
.define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC;SystemZ")
.define("LLVM_INCLUDE_EXAMPLES", "OFF")
.define("LLVM_INCLUDE_TESTS", "OFF")
.define("LLVM_INCLUDE_DOCS", "OFF")
@ -131,401 +131,6 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version)
}
/// Compiles the `compiler-rt` library, or at least the builtins part of it.
///
/// Note that while compiler-rt has a build system associated with it, we
/// specifically don't use it here. The compiler-rt build system, written in
/// CMake, is actually *very* difficult to work with in terms of getting it to
/// compile on all the relevant platforms we want it to compile on. In the end
/// it became so much pain to work with local patches, work around the oddities
/// of the build system, etc, that we're just building everything by hand now.
///
/// In general compiler-rt is just a bunch of intrinsics that are in practice
/// *very* stable. We just need to make sure that all the relevant functions and
/// such are compiled somewhere and placed in an object file somewhere.
/// Eventually, these should all be written in Rust!
///
/// So below you'll find a listing of every single file in the compiler-rt repo
/// that we're compiling. We just reach in and compile with the `gcc` crate
/// which should have all the relevant flags and such already configured.
///
/// The risk here is that if we update compiler-rt we may need to compile some
/// new intrinsics, but to be honest we surely don't use all of the intrinsics
/// listed below today so the likelihood of us actually needing a new intrinsic
/// is quite low. The failure case is also just that someone reports a link
/// error (if any) and then we just add it to the list. Overall, that cost is
/// far far less than working with compiler-rt's build system over time.
pub fn compiler_rt(build: &Build, target: &str) {
let build_dir = build.compiler_rt_out(target);
let output = build_dir.join(staticlib("compiler-rt", target));
build.compiler_rt_built.borrow_mut().insert(target.to_string(),
output.clone());
t!(fs::create_dir_all(&build_dir));
let mut cfg = gcc::Config::new();
cfg.cargo_metadata(false)
.out_dir(&build_dir)
.target(target)
.host(&build.config.build)
.opt_level(2)
.debug(false);
if target.contains("msvc") {
// Don't pull in extra libraries on MSVC
cfg.flag("/Zl");
// Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
cfg.define("__func__", Some("__FUNCTION__"));
} else {
// Turn off various features of gcc and such, mostly copying
// compiler-rt's build system already
cfg.flag("-fno-builtin");
cfg.flag("-fvisibility=hidden");
cfg.flag("-fomit-frame-pointer");
cfg.flag("-ffreestanding");
}
let mut sources = vec![
"absvdi2.c",
"absvsi2.c",
"adddf3.c",
"addsf3.c",
"addvdi3.c",
"addvsi3.c",
"apple_versioning.c",
"ashldi3.c",
"ashrdi3.c",
"clear_cache.c",
"clzdi2.c",
"clzsi2.c",
"cmpdi2.c",
"comparedf2.c",
"comparesf2.c",
"ctzdi2.c",
"ctzsi2.c",
"divdc3.c",
"divdf3.c",
"divdi3.c",
"divmoddi4.c",
"divmodsi4.c",
"divsc3.c",
"divsf3.c",
"divsi3.c",
"divxc3.c",
"extendsfdf2.c",
"extendhfsf2.c",
"ffsdi2.c",
"fixdfdi.c",
"fixdfsi.c",
"fixsfdi.c",
"fixsfsi.c",
"fixunsdfdi.c",
"fixunsdfsi.c",
"fixunssfdi.c",
"fixunssfsi.c",
"fixunsxfdi.c",
"fixunsxfsi.c",
"fixxfdi.c",
"floatdidf.c",
"floatdisf.c",
"floatdixf.c",
"floatsidf.c",
"floatsisf.c",
"floatundidf.c",
"floatundisf.c",
"floatundixf.c",
"floatunsidf.c",
"floatunsisf.c",
"int_util.c",
"lshrdi3.c",
"moddi3.c",
"modsi3.c",
"muldc3.c",
"muldf3.c",
"muldi3.c",
"mulodi4.c",
"mulosi4.c",
"muloti4.c",
"mulsc3.c",
"mulsf3.c",
"mulvdi3.c",
"mulvsi3.c",
"mulxc3.c",
"negdf2.c",
"negdi2.c",
"negsf2.c",
"negvdi2.c",
"negvsi2.c",
"paritydi2.c",
"paritysi2.c",
"popcountdi2.c",
"popcountsi2.c",
"powidf2.c",
"powisf2.c",
"powixf2.c",
"subdf3.c",
"subsf3.c",
"subvdi3.c",
"subvsi3.c",
"truncdfhf2.c",
"truncdfsf2.c",
"truncsfhf2.c",
"ucmpdi2.c",
"udivdi3.c",
"udivmoddi4.c",
"udivmodsi4.c",
"udivsi3.c",
"umoddi3.c",
"umodsi3.c",
];
if !target.contains("ios") {
sources.extend(vec![
"absvti2.c",
"addtf3.c",
"addvti3.c",
"ashlti3.c",
"ashrti3.c",
"clzti2.c",
"cmpti2.c",
"ctzti2.c",
"divtf3.c",
"divti3.c",
"ffsti2.c",
"fixdfti.c",
"fixsfti.c",
"fixunsdfti.c",
"fixunssfti.c",
"fixunsxfti.c",
"fixxfti.c",
"floattidf.c",
"floattisf.c",
"floattixf.c",
"floatuntidf.c",
"floatuntisf.c",
"floatuntixf.c",
"lshrti3.c",
"modti3.c",
"multf3.c",
"multi3.c",
"mulvti3.c",
"negti2.c",
"negvti2.c",
"parityti2.c",
"popcountti2.c",
"powitf2.c",
"subtf3.c",
"subvti3.c",
"trampoline_setup.c",
"ucmpti2.c",
"udivmodti4.c",
"udivti3.c",
"umodti3.c",
]);
}
if target.contains("apple") {
sources.extend(vec![
"atomic_flag_clear.c",
"atomic_flag_clear_explicit.c",
"atomic_flag_test_and_set.c",
"atomic_flag_test_and_set_explicit.c",
"atomic_signal_fence.c",
"atomic_thread_fence.c",
]);
}
if !target.contains("windows") {
sources.push("emutls.c");
}
if target.contains("msvc") {
if target.contains("x86_64") {
sources.extend(vec![
"x86_64/floatdidf.c",
"x86_64/floatdisf.c",
"x86_64/floatdixf.c",
]);
}
} else {
if !target.contains("freebsd") {
sources.push("gcc_personality_v0.c");
}
if target.contains("x86_64") {
sources.extend(vec![
"x86_64/chkstk.S",
"x86_64/chkstk2.S",
"x86_64/floatdidf.c",
"x86_64/floatdisf.c",
"x86_64/floatdixf.c",
"x86_64/floatundidf.S",
"x86_64/floatundisf.S",
"x86_64/floatundixf.S",
]);
}
if target.contains("i386") ||
target.contains("i586") ||
target.contains("i686") {
sources.extend(vec![
"i386/ashldi3.S",
"i386/ashrdi3.S",
"i386/chkstk.S",
"i386/chkstk2.S",
"i386/divdi3.S",
"i386/floatdidf.S",
"i386/floatdisf.S",
"i386/floatdixf.S",
"i386/floatundidf.S",
"i386/floatundisf.S",
"i386/floatundixf.S",
"i386/lshrdi3.S",
"i386/moddi3.S",
"i386/muldi3.S",
"i386/udivdi3.S",
"i386/umoddi3.S",
]);
}
}
if target.contains("arm") && !target.contains("ios") {
sources.extend(vec![
"arm/aeabi_cdcmp.S",
"arm/aeabi_cdcmpeq_check_nan.c",
"arm/aeabi_cfcmp.S",
"arm/aeabi_cfcmpeq_check_nan.c",
"arm/aeabi_dcmp.S",
"arm/aeabi_div0.c",
"arm/aeabi_drsub.c",
"arm/aeabi_fcmp.S",
"arm/aeabi_frsub.c",
"arm/aeabi_idivmod.S",
"arm/aeabi_ldivmod.S",
"arm/aeabi_memcmp.S",
"arm/aeabi_memcpy.S",
"arm/aeabi_memmove.S",
"arm/aeabi_memset.S",
"arm/aeabi_uidivmod.S",
"arm/aeabi_uldivmod.S",
"arm/bswapdi2.S",
"arm/bswapsi2.S",
"arm/clzdi2.S",
"arm/clzsi2.S",
"arm/comparesf2.S",
"arm/divmodsi4.S",
"arm/divsi3.S",
"arm/modsi3.S",
"arm/switch16.S",
"arm/switch32.S",
"arm/switch8.S",
"arm/switchu8.S",
"arm/sync_synchronize.S",
"arm/udivmodsi4.S",
"arm/udivsi3.S",
"arm/umodsi3.S",
]);
}
if target.contains("armv7") {
sources.extend(vec![
"arm/sync_fetch_and_add_4.S",
"arm/sync_fetch_and_add_8.S",
"arm/sync_fetch_and_and_4.S",
"arm/sync_fetch_and_and_8.S",
"arm/sync_fetch_and_max_4.S",
"arm/sync_fetch_and_max_8.S",
"arm/sync_fetch_and_min_4.S",
"arm/sync_fetch_and_min_8.S",
"arm/sync_fetch_and_nand_4.S",
"arm/sync_fetch_and_nand_8.S",
"arm/sync_fetch_and_or_4.S",
"arm/sync_fetch_and_or_8.S",
"arm/sync_fetch_and_sub_4.S",
"arm/sync_fetch_and_sub_8.S",
"arm/sync_fetch_and_umax_4.S",
"arm/sync_fetch_and_umax_8.S",
"arm/sync_fetch_and_umin_4.S",
"arm/sync_fetch_and_umin_8.S",
"arm/sync_fetch_and_xor_4.S",
"arm/sync_fetch_and_xor_8.S",
]);
}
if target.contains("eabihf") {
sources.extend(vec![
"arm/adddf3vfp.S",
"arm/addsf3vfp.S",
"arm/divdf3vfp.S",
"arm/divsf3vfp.S",
"arm/eqdf2vfp.S",
"arm/eqsf2vfp.S",
"arm/extendsfdf2vfp.S",
"arm/fixdfsivfp.S",
"arm/fixsfsivfp.S",
"arm/fixunsdfsivfp.S",
"arm/fixunssfsivfp.S",
"arm/floatsidfvfp.S",
"arm/floatsisfvfp.S",
"arm/floatunssidfvfp.S",
"arm/floatunssisfvfp.S",
"arm/gedf2vfp.S",
"arm/gesf2vfp.S",
"arm/gtdf2vfp.S",
"arm/gtsf2vfp.S",
"arm/ledf2vfp.S",
"arm/lesf2vfp.S",
"arm/ltdf2vfp.S",
"arm/ltsf2vfp.S",
"arm/muldf3vfp.S",
"arm/mulsf3vfp.S",
"arm/negdf2vfp.S",
"arm/negsf2vfp.S",
"arm/nedf2vfp.S",
"arm/nesf2vfp.S",
"arm/restore_vfp_d8_d15_regs.S",
"arm/save_vfp_d8_d15_regs.S",
"arm/subdf3vfp.S",
"arm/subsf3vfp.S",
"arm/truncdfsf2vfp.S",
"arm/unorddf2vfp.S",
"arm/unordsf2vfp.S",
]);
}
if target.contains("aarch64") {
sources.extend(vec![
"comparetf2.c",
"extenddftf2.c",
"extendsftf2.c",
"fixtfdi.c",
"fixtfsi.c",
"fixtfti.c",
"fixunstfdi.c",
"fixunstfsi.c",
"fixunstfti.c",
"floatditf.c",
"floatsitf.c",
"floatunditf.c",
"floatunsitf.c",
"multc3.c",
"trunctfdf2.c",
"trunctfsf2.c",
]);
}
let mut out_of_date = false;
for src in sources {
let src = build.src.join("src/compiler-rt/lib/builtins").join(src);
out_of_date = out_of_date || !up_to_date(&src, &output);
cfg.file(src);
}
if !out_of_date {
return
}
cfg.compile("libcompiler-rt.a");
}
/// Compiles the `rust_test_helpers.c` library which we used in various
/// `run-pass` test suites for ABI testing.
pub fn test_helpers(build: &Build, target: &str) {

View File

@ -75,6 +75,12 @@ 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.
if let Some(ref s) = build.config.nodejs {
need_cmd(s.as_ref());
}
// 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() {
@ -89,7 +95,7 @@ pub fn check(build: &mut Build) {
// Externally configured LLVM requires FileCheck to exist
let filecheck = build.llvm_filecheck(&build.config.build);
if !filecheck.starts_with(&build.out) && !filecheck.exists() {
if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
panic!("filecheck executable {:?} does not exist", filecheck);
}
@ -111,8 +117,8 @@ pub fn check(build: &mut Build) {
// Make sure musl-root is valid if specified
if target.contains("musl") && !target.contains("mips") {
match build.config.musl_root {
Some(ref root) => {
match build.musl_root(target) {
Some(root) => {
if fs::metadata(root.join("lib/libc.a")).is_err() {
panic!("couldn't find libc.a in musl dir: {}",
root.join("lib").display());
@ -123,8 +129,9 @@ pub fn check(build: &mut Build) {
}
}
None => {
panic!("when targeting MUSL the build.musl-root option \
must be specified in config.toml")
panic!("when targeting MUSL either the build.musl-root \
option or the target.$TARGET.musl-root one must \
be specified in config.toml")
}
}
}

View File

@ -82,7 +82,6 @@ macro_rules! targets {
// There aren't really any parameters to this, but empty structs
// with braces are unstable so we just pick something that works.
(llvm, Llvm { _dummy: () }),
(compiler_rt, CompilerRt { _dummy: () }),
(test_helpers, TestHelpers { _dummy: () }),
(debugger_scripts, DebuggerScripts { stage: u32 }),
@ -92,7 +91,6 @@ macro_rules! targets {
(doc, Doc { stage: u32 }),
(doc_book, DocBook { stage: u32 }),
(doc_nomicon, DocNomicon { stage: u32 }),
(doc_style, DocStyle { stage: u32 }),
(doc_standalone, DocStandalone { stage: u32 }),
(doc_std, DocStd { stage: u32 }),
(doc_test, DocTest { stage: u32 }),
@ -173,6 +171,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<Step> {
build.verbose("inferred build steps:");
let mut ret = Vec::new();
let mut all = HashSet::new();
for target in top_level(build) {
@ -186,6 +186,7 @@ pub fn all(build: &Build) -> Vec<Step> {
set: &mut HashSet<Step<'a>>) {
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());
@ -335,8 +336,7 @@ impl<'a> Step<'a> {
vec![self.libstd(compiler)]
}
Source::Libstd { compiler } => {
vec![self.compiler_rt(()),
self.rustc(compiler.stage).target(compiler.host)]
vec![self.rustc(compiler.stage).target(compiler.host)]
}
Source::LibrustcLink { compiler, host } => {
vec![self.librustc(compiler),
@ -349,7 +349,6 @@ impl<'a> Step<'a> {
vec![self.libstd(compiler),
self.target(host).rustc(compiler.stage)]
}
Source::CompilerRt { _dummy } => Vec::new(),
Source::Llvm { _dummy } => Vec::new(),
Source::TestHelpers { _dummy } => Vec::new(),
Source::DebuggerScripts { stage: _ } => Vec::new(),
@ -366,8 +365,7 @@ impl<'a> Step<'a> {
vec![self.libtest(compiler)]
}
Source::DocBook { stage } |
Source::DocNomicon { stage } |
Source::DocStyle { stage } => {
Source::DocNomicon { stage } => {
vec![self.target(&build.config.build).tool_rustbook(stage)]
}
Source::DocErrorIndex { stage } => {
@ -382,8 +380,7 @@ impl<'a> Step<'a> {
Source::Doc { stage } => {
let mut deps = vec![
self.doc_book(stage), self.doc_nomicon(stage),
self.doc_style(stage), self.doc_standalone(stage),
self.doc_std(stage),
self.doc_standalone(stage), self.doc_std(stage),
self.doc_error_index(stage),
];

View File

@ -23,7 +23,7 @@ use filetime::FileTime;
/// Returns the `name` as the filename of a static library for `target`.
pub fn staticlib(name: &str, target: &str) -> String {
if target.contains("windows-msvc") {
if target.contains("windows") {
format!("{}.lib", name)
} else {
format!("lib{}.a", name)

View File

@ -24,27 +24,26 @@ COMPILER_RT_ABI fp_t
__floatsidf(int a) {
const int aWidth = sizeof a * CHAR_BIT;
// Handle zero as a special case to protect clz
if (a == 0)
return fromRep(0);
// All other cases begin by extracting the sign and absolute value of a
rep_t sign = 0;
unsigned aAbs = (unsigned)a;
if (a < 0) {
sign = signBit;
a = -a;
aAbs = ~(unsigned)a + 1U;
}
// Exponent of (fp_t)a is the width of abs(a).
const int exponent = (aWidth - 1) - __builtin_clz(a);
const int exponent = (aWidth - 1) - __builtin_clz(aAbs);
rep_t result;
// Shift a into the significand field and clear the implicit bit. Extra
// cast to unsigned int is necessary to get the correct behavior for
// the input INT_MIN.
// Shift a into the significand field and clear the implicit bit.
const int shift = significandBits - exponent;
result = (rep_t)(unsigned int)a << shift ^ implicitBit;
result = (rep_t)aAbs << shift ^ implicitBit;
// Insert the exponent
result += (rep_t)(exponent + exponentBias) << significandBits;

View File

@ -24,30 +24,31 @@ COMPILER_RT_ABI fp_t
__floatsisf(int a) {
const int aWidth = sizeof a * CHAR_BIT;
// Handle zero as a special case to protect clz
if (a == 0)
return fromRep(0);
// All other cases begin by extracting the sign and absolute value of a
rep_t sign = 0;
unsigned aAbs = (unsigned)a;
if (a < 0) {
sign = signBit;
a = -a;
aAbs = ~(unsigned)a + 1U;
}
// Exponent of (fp_t)a is the width of abs(a).
const int exponent = (aWidth - 1) - __builtin_clz(a);
const int exponent = (aWidth - 1) - __builtin_clz(aAbs);
rep_t result;
// Shift a into the significand field, rounding if it is a right-shift
if (exponent <= significandBits) {
const int shift = significandBits - exponent;
result = (rep_t)a << shift ^ implicitBit;
result = (rep_t)aAbs << shift ^ implicitBit;
} else {
const int shift = exponent - significandBits;
result = (rep_t)a >> shift ^ implicitBit;
rep_t round = (rep_t)a << (typeWidth - shift);
result = (rep_t)aAbs >> shift ^ implicitBit;
rep_t round = (rep_t)aAbs << (typeWidth - shift);
if (round > signBit) result++;
if (round == signBit) result += result & 1;
}

View File

@ -32,7 +32,7 @@
#if __ARM_EABI__
# define ARM_EABI_FNALIAS(aeabi_name, name) \
void __aeabi_##aeabi_name() __attribute__((alias("__" #name)));
# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
# define COMPILER_RT_ABI
#else
# define ARM_EABI_FNALIAS(aeabi_name, name)
# define COMPILER_RT_ABI

View File

@ -67,7 +67,7 @@ trait Graph {
Simple enough. Associated types use the `type` keyword, and go inside the body
of the trait, with the functions.
These `type` declarations can have all the same thing as functions do. For example,
These type declarations work the same way as those for functions. For example,
if we wanted our `N` type to implement `Display`, so we can print the nodes out,
we could do this:

View File

@ -8,7 +8,7 @@ different. Heres a quick refresher on what these two traits mean.
# Borrow
The `Borrow` trait is used when youre writing a datastructure, and you want to
The `Borrow` trait is used when youre writing a data structure, and you want to
use either an owned or borrowed type as synonymous for some purpose.
For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`:
@ -86,7 +86,7 @@ We can see how theyre kind of the same: they both deal with owned and borrowe
versions of some type. However, theyre a bit different.
Choose `Borrow` when you want to abstract over different kinds of borrowing, or
when youre building a datastructure that treats owned and borrowed values in
when youre building a data structure that treats owned and borrowed values in
equivalent ways, such as hashing and comparison.
Choose `AsRef` when you want to convert something to a reference directly, and

View File

@ -262,7 +262,7 @@ the result:
```rust
fn call_with_one<F>(some_closure: F) -> i32
where F : Fn(i32) -> i32 {
where F: Fn(i32) -> i32 {
some_closure(1)
}
@ -279,7 +279,7 @@ Lets examine the signature of `call_with_one` in more depth:
```rust
fn call_with_one<F>(some_closure: F) -> i32
# where F : Fn(i32) -> i32 {
# where F: Fn(i32) -> i32 {
# some_closure(1) }
```
@ -288,7 +288,7 @@ isnt interesting. The next part is:
```rust
# fn call_with_one<F>(some_closure: F) -> i32
where F : Fn(i32) -> i32 {
where F: Fn(i32) -> i32 {
# some_closure(1) }
```
@ -340,7 +340,7 @@ fn call_with_ref<'a, F>(some_closure:F) -> i32
where F: Fn(&'a i32) -> i32 {
```
However this presents a problem with in our case. When you specify the explicit
However this presents a problem in our case. When you specify the explicit
lifetime on a function it binds that lifetime to the *entire* scope of the function
instead of just the invocation scope of our closure. This means that the borrow checker
will see a mutable reference in the same lifetime as our immutable reference and fail

View File

@ -46,10 +46,10 @@ extern crate rustc;
extern crate rustc_plugin;
use syntax::parse::token;
use syntax::ast::TokenTree;
use syntax::tokenstream::TokenTree;
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::build::AstBuilder; // trait for expr_usize
use syntax_pos::Span;
use syntax::ext::quote::rt::Span;
use rustc_plugin::Registry;
fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
@ -69,7 +69,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
}
let text = match args[0] {
TokenTree::Token(_, token::Ident(s, _)) => s.to_string(),
TokenTree::Token(_, token::Ident(s)) => s.to_string(),
_ => {
cx.span_err(sp, "argument should be a single identifier");
return DummyResult::any(sp);

View File

@ -59,7 +59,7 @@ handling is reducing the amount of explicit case analysis the programmer has to
do while keeping code composable.
Keeping code composable is important, because without that requirement, we
could [`panic`](../std/macro.panic!.html) whenever we
could [`panic`](../std/macro.panic.html) whenever we
come across something unexpected. (`panic` causes the current task to unwind,
and in most cases, the entire program aborts.) Here's an example:
@ -944,7 +944,7 @@ macro_rules! try {
}
```
(The [real definition](../std/macro.try!.html) is a bit more
(The [real definition](../std/macro.try.html) is a bit more
sophisticated. We will address that later.)
Using the `try!` macro makes it very easy to simplify our last example. Since
@ -1271,7 +1271,7 @@ macro_rules! try {
```
This is not its real definition. Its real definition is
[in the standard library](../std/macro.try!.html):
[in the standard library](../std/macro.try.html):
<span id="code-try-def"></span>
@ -2178,7 +2178,7 @@ heuristics!
[`From`](../std/convert/trait.From.html)
and
[`Error`](../std/error/trait.Error.html)
impls to make the [`try!`](../std/macro.try!.html)
impls to make the [`try!`](../std/macro.try.html)
macro more ergonomic.
* If you're writing a library and your code can produce errors, define your own
error type and implement the

View File

@ -471,7 +471,7 @@ extern {
fn main() {
println!("You have readline version {} installed.",
rl_readline_version as i32);
unsafe { rl_readline_version as i32 });
}
```
@ -539,6 +539,7 @@ This is currently hidden behind the `abi_vectorcall` gate and is subject to chan
* `system`
* `C`
* `win64`
* `sysv64`
Most of the abis in this list are self-explanatory, but the `system` abi may
seem a little odd. This constraint selects whatever the appropriate ABI is for

View File

@ -230,12 +230,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 youre 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() {

View File

@ -57,8 +57,8 @@ fn main(argc: isize, argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
#[lang = "eh_personality"] extern fn rust_eh_personality() {}
#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { loop {} }
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
# #[no_mangle] pub extern fn rust_eh_register_frames () {}
# #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
@ -73,8 +73,8 @@ Other features provided by lang items include:
`==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
marked with lang items; those specific four are `eq`, `ord`,
`deref`, and `add` respectively.
- stack unwinding and general failure; the `eh_personality`, `fail`
and `fail_bounds_checks` lang items.
- stack unwinding and general failure; the `eh_personality`,
`eh_unwind_resume`, `fail` and `fail_bounds_checks` lang items.
- the traits in `std::marker` used to indicate types of
various kinds; lang items `send`, `sync` and `copy`.
- the marker types and variance indicators found in

View File

@ -662,7 +662,7 @@ Here are some common macros youll see in Rust code.
This macro causes the current thread to panic. You can give it a message
to panic with:
```rust,no_run
```rust,should_panic
panic!("oh no!");
```
@ -688,7 +688,7 @@ These two macros are used in tests. `assert!` takes a boolean. `assert_eq!`
takes two values and checks them for equality. `true` passes, `false` `panic!`s.
Like this:
```rust,no_run
```rust,should_panic
// A-ok!
assert!(true);

View File

@ -54,7 +54,7 @@ binary downloads][install-page].
Oh, we should also mention the officially supported platforms:
* Windows (7, 8, Server 2008 R2)
* Windows (7+)
* Linux (2.6.18 or later, various distributions), x86 and x86-64
* OSX 10.7 (Lion) or greater, x86 and x86-64

View File

@ -55,7 +55,13 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
// provided by libstd.
#[lang = "eh_personality"]
#[no_mangle]
pub extern fn eh_personality() {
pub extern fn rust_eh_personality() {
}
// This function may be needed based on the compilation target.
#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {
}
#[lang = "panic_fmt"]
@ -87,12 +93,18 @@ pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
0
}
// These functions and traits are used by the compiler, but not
// These functions are used by the compiler, but not
// for a bare-bones hello world. These are normally
// provided by libstd.
#[lang = "eh_personality"]
#[no_mangle]
pub extern fn eh_personality() {
pub extern fn rust_eh_personality() {
}
// This function may be needed based on the compilation target.
#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {
}
#[lang = "panic_fmt"]
@ -104,7 +116,7 @@ pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
}
```
## More about the langauge items
## More about the language items
The compiler currently makes a few assumptions about symbols which are
available in the executable to call. Normally these functions are provided by
@ -112,15 +124,20 @@ the standard library, but without it you must define your own. These symbols
are called "language items", and they each have an internal name, and then a
signature that an implementation must conform to.
The first of these two functions, `eh_personality`, is used by the failure
The first of these functions, `rust_eh_personality`, is used by the failure
mechanisms of the compiler. This is often mapped to GCC's personality function
(see the [libstd implementation][unwind] for more information), but crates
which do not trigger a panic can be assured that this function is never
called. Both the language item and the symbol name are `eh_personality`.
called. The language item's name is `eh_personality`.
[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs
The second function, `panic_fmt`, is also used by the failure mechanisms of the
The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
compiler. When a panic happens, this controls the message that's displayed on
the screen. While the language item's name is `panic_fmt`, the symbol name is
`rust_begin_panic`.
A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume`
flag is set in the options of the compilation target. It allows customizing the
process of resuming unwind at the end of the landing pads. The language item's name
is `eh_unwind_resume`.

View File

@ -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<T>`, so in this example `v` will have type
`Vec<i32>`. We'll cover generics in detail later in this chapter.
`Vec<i32>`. We'll cover [generics] in detail in a later chapter.
[arrays]: primitive-types.html#arrays
[vectors]: vectors.html

View File

@ -152,7 +152,7 @@ the thing `y` points at. Youll notice that `x` had to be marked `mut` as well
If it wasnt, we couldnt take a mutable borrow to an immutable value.
You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`,
this is because `y` is a `&mut` reference. You'll need to use astrisks to
this is because `y` is a `&mut` reference. You'll need to use asterisks to
access the contents of a reference as well.
Otherwise, `&mut` references are like references. There _is_ a large

View File

@ -47,6 +47,34 @@ As you can see, the `trait` block looks very similar to the `impl` block,
but we dont define a body, only a type signature. When we `impl` a trait,
we use `impl Trait for Item`, rather than only `impl Item`.
`Self` may be used in a type annotation to refer to an instance of the type
implementing this trait passed as a parameter. `Self`, `&Self` or `&mut Self`
may be used depending on the level of ownership required.
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
trait HasArea {
fn area(&self) -> f64;
fn is_larger(&self, &Self) -> bool;
}
impl HasArea for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
fn is_larger(&self, other: &Self) -> bool {
self.area() > other.area()
}
}
```
## Trait bounds on generic functions
Traits are useful because they allow a type to make certain promises about its
@ -247,7 +275,7 @@ wont have its methods:
[write]: ../std/io/trait.Write.html
```rust,ignore
let mut f = std::fs::File::open("foo.txt").expect("Couldnt open foo.txt");
let mut f = std::fs::File::create("foo.txt").expect("Couldnt create foo.txt");
let buf = b"whatever"; // byte string literal. buf: &[u8; 8]
let result = f.write(buf);
# result.unwrap(); // ignore the error
@ -263,10 +291,10 @@ 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::open("foo.txt").expect("Couldnt open foo.txt");
let mut f = std::fs::File::create("foo.txt").expect("Couldnt create foo.txt");
let buf = b"whatever";
let result = f.write(buf);
# result.unwrap(); // ignore the error

View File

@ -172,6 +172,11 @@ token : simple_token | ident | literal | symbol | whitespace token ;
Each of these keywords has special meaning in its grammar, and all of them are
excluded from the `ident` rule.
Not all of these keywords are used by the language. Some of them were used
before Rust 1.0, and were left reserved once their implementations were
removed. Some of them were reserved before 1.0 to make space for possible
future features.
### Literals
```antlr

View File

@ -52,7 +52,7 @@ let mut data = vec![1, 2, 3];
let x = &data[0];
// OH NO! `push` causes the backing storage of `data` to be reallocated.
// Dangling pointer! User after free! Alas!
// Dangling pointer! Use after free! Alas!
// (this does not compile in Rust)
data.push(4);

View File

@ -26,10 +26,6 @@ can therefore be trusted. You can use `unsafe` on a trait implementation
to declare that the implementation of that trait has adhered to whatever
contracts the trait's documentation requires.
There is also the `#[unsafe_no_drop_flag]` attribute, which exists for
historic reasons and is being phased out. See the section on [drop flags]
for details.
The standard library has a number of unsafe functions, including:
* `slice::get_unchecked`, which performs unchecked indexing, allowing

View File

@ -1677,6 +1677,7 @@ There are also some platform-specific ABI strings:
* `extern "cdecl"` -- The default for x86\_32 C code.
* `extern "stdcall"` -- The default for the Win32 API on x86\_32.
* `extern "win64"` -- The default for C code on x86\_64 Windows.
* `extern "sysv64"` -- The default for C code on non-Windows x86\_64.
* `extern "aapcs"` -- The default for ARM.
* `extern "fastcall"` -- The `fastcall` ABI -- corresponds to MSVC's
`__fastcall` and GCC and clang's `__attribute__((fastcall))`
@ -2058,10 +2059,6 @@ macro scope.
outside of its dynamic extent), and thus this attribute has the word
"unsafe" in its name. To use this, the
`unsafe_destructor_blind_to_params` feature gate must be enabled.
- `unsafe_no_drop_flag` - on structs, remove the flag that prevents
destructors from being run twice. Destructors might be run multiple times on
the same object with this attribute. To use this, the `unsafe_no_drop_flag` feature
gate must be enabled.
- `doc` - Doc comments such as `/// foo` are equivalent to `#[doc = "foo"]`.
- `rustc_on_unimplemented` - Write a custom note to be shown along with the error
when the trait is found to be unimplemented on a type.
@ -2070,6 +2067,9 @@ macro scope.
trait of the same name. `{Self}` will be replaced with the type that is supposed
to implement the trait but doesn't. To use this, the `on_unimplemented` feature gate
must be enabled.
- `must_use` - on structs and enums, will warn if a value of this type isn't used or
assigned to a variable. You may also include an optional message by using
`#[must_use = "message"]` which will be given alongside the warning.
### Conditional compilation
@ -2283,7 +2283,7 @@ the `PartialEq` or `Clone` constraints for the appropriate `impl`:
#[derive(PartialEq, Clone)]
struct Foo<T> {
a: i32,
b: T
b: T,
}
```
@ -2441,6 +2441,9 @@ The currently implemented features of the reference compiler are:
into a Rust program. This capability, especially the signature for the
annotated function, is subject to change.
* `static_in_const` - Enables lifetime elision with a `'static` default for
`const` and `static` item declarations.
* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
and should be seen as unstable. This attribute is used to
declare a `static` as being unique per-thread leveraging
@ -2454,12 +2457,6 @@ The currently implemented features of the reference compiler are:
* `unboxed_closures` - Rust's new closure design, which is currently a work in
progress feature with many known bugs.
* `unsafe_no_drop_flag` - Allows use of the `#[unsafe_no_drop_flag]` attribute,
which removes hidden flag added to a type that
implements the `Drop` trait. The design for the
`Drop` flag is subject to change, and this feature
may be removed in the future.
* `unmarked_api` - Allows use of items within a `#![staged_api]` crate
which have not been marked with a stability marker.
Such items should not be allowed by the compiler to exist,
@ -2475,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`.
@ -2485,6 +2481,9 @@ The currently implemented features of the reference compiler are:
* - `dotdot_in_tuple_patterns` - Allows `..` in tuple (struct) patterns.
* - `abi_sysv64` - Allows the usage of the system V AMD64 calling convention
(e.g. `extern "sysv64" func fn_();`)
If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about `#![feature]` directives which enabled
the new feature (because the directive is no longer necessary). However, if a
@ -3896,7 +3895,7 @@ Coercion is allowed between the following types:
use std::ops::Deref;
struct CharContainer {
value: char
value: char,
}
impl Deref for CharContainer {

View File

@ -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;

View File

@ -1,64 +0,0 @@
% Style Guidelines
This document collects the emerging principles, conventions, abstractions, and
best practices for writing Rust code.
Since Rust is evolving at a rapid pace, these guidelines are
preliminary. The hope is that writing them down explicitly will help
drive discussion, consensus and adoption.
Whenever feasible, guidelines provide specific examples from Rust's standard
libraries.
### Guideline statuses
Every guideline has a status:
* **[FIXME]**: Marks places where there is more work to be done. In
some cases, that just means going through the RFC process.
* **[FIXME #NNNNN]**: Like **[FIXME]**, but links to the issue tracker.
* **[RFC #NNNN]**: Marks accepted guidelines, linking to the rust-lang
RFC establishing them.
### Guideline stabilization
One purpose of these guidelines is to reach decisions on a number of
cross-cutting API and stylistic choices. Discussion and development of
the guidelines will happen primarily on https://internals.rust-lang.org/,
using the Guidelines category. Discussion can also occur on the
[guidelines issue tracker](https://github.com/rust-lang/rust-guidelines).
Guidelines that are under development or discussion will be marked with the
status **[FIXME]**, with a link to the issue tracker when appropriate.
Once a concrete guideline is ready to be proposed, it should be filed
as an [FIXME: needs RFC](https://github.com/rust-lang/rfcs). If the RFC is
accepted, the official guidelines will be updated to match, and will
include the tag **[RFC #NNNN]** linking to the RFC document.
### What's in this document
This document is broken into four parts:
* **[Style](style/README.md)** provides a set of rules governing naming conventions,
whitespace, and other stylistic issues.
* **[Guidelines by Rust feature](features/README.md)** places the focus on each of
Rust's features, starting from expressions and working the way out toward
crates, dispensing guidelines relevant to each.
* **Topical guidelines and patterns**. The rest of the document proceeds by
cross-cutting topic, starting with
[Ownership and resources](ownership/README.md).
* **APIs for a changing Rust**
discusses the forward-compatibility hazards, especially those that interact
with the pre-1.0 library stabilization process.
> **[FIXME]** Add cross-references throughout this document to the tutorial,
> reference manual, and other guides.
> **[FIXME]** What are some _non_-goals, _non_-principles, or _anti_-patterns that
> we should document?

View File

@ -1,50 +0,0 @@
# Summary
* [Style](style/README.md)
* [Whitespace](style/whitespace.md)
* [Comments](style/comments.md)
* [Braces, semicolons, commas](style/braces.md)
* [Naming](style/naming/README.md)
* [Ownership variants](style/naming/ownership.md)
* [Containers/wrappers](style/naming/containers.md)
* [Conversions](style/naming/conversions.md)
* [Iterators](style/naming/iterators.md)
* [Imports](style/imports.md)
* [Organization](style/organization.md)
* [Guidelines by Rust feature](features/README.md)
* [Let binding](features/let.md)
* [Pattern matching](features/match.md)
* [Loops](features/loops.md)
* [Functions and methods](features/functions-and-methods/README.md)
* [Input](features/functions-and-methods/input.md)
* [Output](features/functions-and-methods/output.md)
* [For convenience](features/functions-and-methods/convenience.md)
* [Types](features/types/README.md)
* [Conversions](features/types/conversions.md)
* [The newtype pattern](features/types/newtype.md)
* [Traits](features/traits/README.md)
* [For generics](features/traits/generics.md)
* [For objects](features/traits/objects.md)
* [For overloading](features/traits/overloading.md)
* [For extensions](features/traits/extensions.md)
* [For reuse](features/traits/reuse.md)
* [Common traits](features/traits/common.md)
* [Modules](features/modules.md)
* [Crates](features/crates.md)
* [Ownership and resources](ownership/README.md)
* [Constructors](ownership/constructors.md)
* [Builders](ownership/builders.md)
* [Destructors](ownership/destructors.md)
* [RAII](ownership/raii.md)
* [Cells and smart pointers](ownership/cell-smart.md)
* [Errors](errors/README.md)
* [Signaling](errors/signaling.md)
* [Handling](errors/handling.md)
* [Propagation](errors/propagation.md)
* [Ergonomics](errors/ergonomics.md)
* [Safety and guarantees](safety/README.md)
* [Using unsafe](safety/unsafe.md)
* [Library guarantees](safety/lib-guarantees.md)
* [Testing](testing/README.md)
* [Unit testing](testing/unit.md)
* [FFI, platform-specific code](platform.md)

View File

@ -1,3 +0,0 @@
% Errors
> **[FIXME]** Add some general text here.

View File

@ -1,66 +0,0 @@
% Ergonomic error handling
Error propagation with raw `Result`s can require tedious matching and
repackaging. This tedium is largely alleviated by the `try!` macro,
and can be completely removed (in some cases) by the "`Result`-`impl`"
pattern.
### The `try!` macro
Prefer
```rust,ignore
use std::io::{File, Open, Write, IoError};
struct Info {
name: String,
age: i32,
rating: i32
}
fn write_info(info: &Info) -> Result<(), IoError> {
let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
Open, Write);
// Early return on error
try!(file.write_line(&format!("name: {}", info.name)));
try!(file.write_line(&format!("age: {}", info.age)));
try!(file.write_line(&format!("rating: {}", info.rating)));
return Ok(());
}
```
over
```rust,ignore
use std::io::{File, Open, Write, IoError};
struct Info {
name: String,
age: i32,
rating: i32
}
fn write_info(info: &Info) -> Result<(), IoError> {
let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
Open, Write);
// Early return on error
match file.write_line(&format!("name: {}", info.name)) {
Ok(_) => (),
Err(e) => return Err(e)
}
match file.write_line(&format!("age: {}", info.age)) {
Ok(_) => (),
Err(e) => return Err(e)
}
return file.write_line(&format!("rating: {}", info.rating));
}
```
See
[the `result` module documentation](https://doc.rust-lang.org/stable/std/result/index.html#the-try-macro)
for more details.
### The `Result`-`impl` pattern [FIXME]
> **[FIXME]** Document the way that the `io` module uses trait impls
> on `std::io::Result` to painlessly propagate errors.

View File

@ -1,7 +0,0 @@
% Handling errors
### Use thread isolation to cope with failure. [FIXME]
> **[FIXME]** Explain how to isolate threads and detect thread failure for recovery.
### Consuming `Result` [FIXME]

View File

@ -1,8 +0,0 @@
% Propagation
> **[FIXME]** We need guidelines on how to layer error information up a stack of
> abstractions.
### Error interoperation [FIXME]
> **[FIXME]** Document the `FromError` infrastructure.

View File

@ -1,125 +0,0 @@
% Signaling errors [RFC #236]
> The guidelines below were approved by [RFC #236](https://github.com/rust-lang/rfcs/pull/236).
Errors fall into one of three categories:
* Catastrophic errors, e.g. out-of-memory.
* Contract violations, e.g. wrong input encoding, index out of bounds.
* Obstructions, e.g. file not found, parse error.
The basic principle of the convention is that:
* Catastrophic errors and programming errors (bugs) can and should only be
recovered at a *coarse grain*, i.e. a thread boundary.
* Obstructions preventing an operation should be reported at a maximally *fine
grain* -- to the immediate invoker of the operation.
## Catastrophic errors
An error is _catastrophic_ if there is no meaningful way for the current thread to
continue after the error occurs.
Catastrophic errors are _extremely_ rare, especially outside of `libstd`.
**Canonical examples**: out of memory, stack overflow.
### For catastrophic errors, panic
For errors like stack overflow, Rust currently aborts the process, but
could in principle panic, which (in the best case) would allow
reporting and recovery from a supervisory thread.
## Contract violations
An API may define a contract that goes beyond the type checking enforced by the
compiler. For example, slices support an indexing operation, with the contract
that the supplied index must be in bounds.
Contracts can be complex and involve more than a single function invocation. For
example, the `RefCell` type requires that `borrow_mut` not be called until all
existing borrows have been relinquished.
### For contract violations, panic
A contract violation is always a bug, and for bugs we follow the Erlang
philosophy of "let it crash": we assume that software *will* have bugs, and we
design coarse-grained thread boundaries to report, and perhaps recover, from these
bugs.
### Contract design
One subtle aspect of these guidelines is that the contract for a function is
chosen by an API designer -- and so the designer also determines what counts as
a violation.
This RFC does not attempt to give hard-and-fast rules for designing
contracts. However, here are some rough guidelines:
* Prefer expressing contracts through static types whenever possible.
* It *must* be possible to write code that uses the API without violating the
contract.
* Contracts are most justified when violations are *inarguably* bugs -- but this
is surprisingly rare.
* Consider whether the API client could benefit from the contract-checking
logic. The checks may be expensive. Or there may be useful programming
patterns where the client does not want to check inputs before hand, but would
rather attempt the operation and then find out whether the inputs were invalid.
* When a contract violation is the *only* kind of error a function may encounter
-- i.e., there are no obstructions to its success other than "bad" inputs --
using `Result` or `Option` instead is especially warranted. Clients can then use
`unwrap` to assert that they have passed valid input, or re-use the error
checking done by the API for their own purposes.
* When in doubt, use loose contracts and instead return a `Result` or `Option`.
## Obstructions
An operation is *obstructed* if it cannot be completed for some reason, even
though the operation's contract has been satisfied. Obstructed operations may
have (documented!) side effects -- they are not required to roll back after
encountering an obstruction. However, they should leave the data structures in
a "coherent" state (satisfying their invariants, continuing to guarantee safety,
etc.).
Obstructions may involve external conditions (e.g., I/O), or they may involve
aspects of the input that are not covered by the contract.
**Canonical examples**: file not found, parse error.
### For obstructions, use `Result`
The
[`Result<T,E>` type](https://doc.rust-lang.org/stable/std/result/index.html)
represents either a success (yielding `T`) or failure (yielding `E`). By
returning a `Result`, a function allows its clients to discover and react to
obstructions in a fine-grained way.
#### What about `Option`?
The `Option` type should not be used for "obstructed" operations; it
should only be used when a `None` return value could be considered a
"successful" execution of the operation.
This is of course a somewhat subjective question, but a good litmus
test is: would a reasonable client ever ignore the result? The
`Result` type provides a lint that ensures the result is actually
inspected, while `Option` does not, and this difference of behavior
can help when deciding between the two types.
Another litmus test: can the operation be understood as asking a
question (possibly with sideeffects)? Operations like `pop` on a
vector can be viewed as asking for the contents of the first element,
with the side effect of removing it if it exists -- with an `Option`
return value.
## Do not provide both `Result` and `panic!` variants.
An API should not provide both `Result`-producing and `panic`king versions of an
operation. It should provide just the `Result` version, allowing clients to use
`try!` or `unwrap` instead as needed. This is part of the general pattern of
cutting down on redundant variants by instead using method chaining.

View File

@ -1,9 +0,0 @@
% Guidelines by language feature
Rust provides a unique combination of language features, some new and some
old. This section gives guidance on when and how to use Rust's features, and
brings attention to some of the tradeoffs between different features.
Notably missing from this section is an in-depth discussion of Rust's pointer
types (both built-in and in the library). The topic of pointers is discussed at
length in a [separate section on ownership](../ownership/README.md).

View File

@ -1,6 +0,0 @@
% Crates
> **[FIXME]** What general guidelines should we provide for crate design?
> Possible topics: facades; per-crate preludes (to be imported as globs);
> "lib.rs"

View File

@ -1,44 +0,0 @@
% Functions and methods
### Prefer methods to functions if there is a clear receiver. **[FIXME: needs RFC]**
Prefer
```rust,ignore
impl Foo {
pub fn frob(&self, w: widget) { ... }
}
```
over
```rust,ignore
pub fn frob(foo: &Foo, w: widget) { ... }
```
for any operation that is clearly associated with a particular
type.
Methods have numerous advantages over functions:
* They do not need to be imported or qualified to be used: all you
need is a value of the appropriate type.
* Their invocation performs autoborrowing (including mutable borrows).
* They make it easy to answer the question "what can I do with a value
of type `T`" (especially when using rustdoc).
* They provide `self` notation, which is more concise and often more
clearly conveys ownership distinctions.
> **[FIXME]** Revisit these guidelines with
> [UFCS](https://github.com/nick29581/rfcs/blob/ufcs/0000-ufcs.md) and
> conventions developing around it.
### Guidelines for inherent methods. **[FIXME]**
> **[FIXME]** We need guidelines for when to provide inherent methods on a type,
> versus methods through a trait or functions.
> **NOTE**: Rules for method resolution around inherent methods are in flux,
> which may impact the guidelines.

View File

@ -1,43 +0,0 @@
% Convenience methods
### Provide small, coherent sets of convenience methods. **[FIXME: needs RFC]**
_Convenience methods_ wrap up existing functionality in a more convenient
way. The work done by a convenience method varies widely:
* _Re-providing functions as methods_. For example, the `std::path::Path` type
provides methods like `stat` on `Path`s that simply invoke the corresponding
function in `std::io::fs`.
* _Skipping through conversions_. For example, the `str` type provides a
`.len()` convenience method which is also expressible as `.as_bytes().len()`.
Sometimes the conversion is more complex: the `str` module also provides
`from_chars`, which encapsulates a simple use of iterators.
* _Encapsulating common arguments_. For example, vectors of `&str`s
provide a `connect` as well as a special case, `concat`, that is expressible
using `connect` with a fixed separator of `""`.
* _Providing more efficient special cases_. The `connect` and `concat` example
also applies here: singling out `concat` as a special case allows for a more
efficient implementation.
Note, however, that the `connect` method actually detects the special case
internally and invokes `concat`. Usually, it is not necessary to add a public
convenience method just for efficiency gains; there should also be a
_conceptual_ reason to add it, e.g. because it is such a common special case.
It is tempting to add convenience methods in a one-off, haphazard way as
common use patterns emerge. Avoid this temptation, and instead _design_ small,
coherent sets of convenience methods that are easy to remember:
* _Small_: Avoid combinatorial explosions of convenience methods. For example,
instead of adding `_str` variants of methods that provide a `str` output,
instead ensure that the normal output type of methods is easily convertible to
`str`.
* _Coherent_: Look for small groups of convenience methods that make sense to
include together. For example, the `Path` API mentioned above includes a small
selection of the most common filesystem operations that take a `Path`
argument. If one convenience method strongly suggests the existence of others,
consider adding the whole group.
* _Memorable_: It is not worth saving a few characters of typing if you have to
look up the name of a convenience method every time you use it. Add
convenience methods with names that are obvious and easy to remember, and add
them for the most common or painful use cases.

View File

@ -1,203 +0,0 @@
% Input to functions and methods
### Let the client decide when to copy and where to place data. [FIXME: needs RFC]
#### Copying:
Prefer
```rust,ignore
fn foo(b: Bar) {
// use b as owned, directly
}
```
over
```rust,ignore
fn foo(b: &Bar) {
let b = b.clone();
// use b as owned after cloning
}
```
If a function requires ownership of a value of unknown type `T`, but does not
otherwise need to make copies, the function should take ownership of the
argument (pass by value `T`) rather than using `.clone()`. That way, the caller
can decide whether to relinquish ownership or to `clone`.
Similarly, the `Copy` trait bound should only be demanded it when absolutely
needed, not as a way of signaling that copies should be cheap to make.
#### Placement:
Prefer
```rust,ignore
fn foo(b: Bar) -> Bar { ... }
```
over
```rust,ignore
fn foo(b: Box<Bar>) -> Box<Bar> { ... }
```
for concrete types `Bar` (as opposed to trait objects). This way, the caller can
decide whether to place data on the stack or heap. No overhead is imposed by
letting the caller determine the placement.
### Minimize assumptions about parameters. [FIXME: needs RFC]
The fewer assumptions a function makes about its inputs, the more widely usable
it becomes.
#### Minimizing assumptions through generics:
Prefer
```rust,ignore
fn foo<T: Iterator<i32>>(c: T) { ... }
```
over any of
```rust,ignore
fn foo(c: &[i32]) { ... }
fn foo(c: &Vec<i32>) { ... }
fn foo(c: &SomeOtherCollection<i32>) { ... }
```
if the function only needs to iterate over the data.
More generally, consider using generics to pinpoint the assumptions a function
needs to make about its arguments.
On the other hand, generics can make it more difficult to read and understand a
function's signature. Aim for "natural" parameter types that a neither overly
concrete nor overly abstract. See the discussion on
[traits](../traits/README.md) for more guidance.
#### Minimizing ownership assumptions:
Prefer either of
```rust,ignore
fn foo(b: &Bar) { ... }
fn foo(b: &mut Bar) { ... }
```
over
```rust,ignore
fn foo(b: Bar) { ... }
```
That is, prefer borrowing arguments rather than transferring ownership, unless
ownership is actually needed.
### Prefer compound return types to out-parameters. [FIXME: needs RFC]
Prefer
```rust,ignore
fn foo() -> (Bar, Bar)
```
over
```rust,ignore
fn foo(output: &mut Bar) -> Bar
```
for returning multiple `Bar` values.
Compound return types like tuples and structs are efficiently compiled
and do not require heap allocation. If a function needs to return
multiple values, it should do so via one of these types.
The primary exception: sometimes a function is meant to modify data
that the caller already owns, for example to re-use a buffer:
```rust,ignore
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize>
```
(From the [Read trait](https://doc.rust-lang.org/stable/std/io/trait.Read.html#tymethod.read).)
### Consider validating arguments, statically or dynamically. [FIXME: needs RFC]
_Note: this material is closely related to
[library-level guarantees](../../safety/lib-guarantees.md)._
Rust APIs do _not_ generally follow the
[robustness principle](https://en.wikipedia.org/wiki/Robustness_principle): "be
conservative in what you send; be liberal in what you accept".
Instead, Rust code should _enforce_ the validity of input whenever practical.
Enforcement can be achieved through the following mechanisms (listed
in order of preference).
#### Static enforcement:
Choose an argument type that rules out bad inputs.
For example, prefer
```rust,ignore
enum FooMode {
Mode1,
Mode2,
Mode3,
}
fn foo(mode: FooMode) { ... }
```
over
```rust,ignore
fn foo(mode2: bool, mode3: bool) {
assert!(!mode2 || !mode3);
...
}
```
Static enforcement usually comes at little run-time cost: it pushes the
costs to the boundaries. It also catches bugs early, during compilation,
rather than through run-time failures.
On the other hand, some properties are difficult or impossible to
express using types.
#### Dynamic enforcement:
Validate the input as it is processed (or ahead of time, if necessary). Dynamic
checking is often easier to implement than static checking, but has several
downsides:
1. Runtime overhead (unless checking can be done as part of processing the input).
2. Delayed detection of bugs.
3. Introduces failure cases, either via `panic!` or `Result`/`Option` types (see
the [error handling guidelines](../../errors/README.md)), which must then be
dealt with by client code.
#### Dynamic enforcement with `debug_assert!`:
Same as dynamic enforcement, but with the possibility of easily turning off
expensive checks for production builds.
#### Dynamic enforcement with opt-out:
Same as dynamic enforcement, but adds sibling functions that opt out of the
checking.
The convention is to mark these opt-out functions with a suffix like
`_unchecked` or by placing them in a `raw` submodule.
The unchecked functions can be used judiciously in cases where (1) performance
dictates avoiding checks and (2) the client is otherwise confident that the
inputs are valid.
> **[FIXME]** Should opt-out functions be marked `unsafe`?

View File

@ -1,56 +0,0 @@
% Output from functions and methods
### Don't overpromise. [FIXME]
> **[FIXME]** Add discussion of overly-specific return types,
> e.g. returning a compound iterator type rather than hiding it behind
> a use of newtype.
### Let clients choose what to throw away. [FIXME: needs RFC]
#### Return useful intermediate results:
Many functions that answer a question also compute interesting related data. If
this data is potentially of interest to the client, consider exposing it in the
API.
Prefer
```rust,ignore
struct SearchResult {
found: bool, // item in container?
expected_index: usize // what would the item's index be?
}
fn binary_search(&self, k: Key) -> SearchResult
```
or
```rust,ignore
fn binary_search(&self, k: Key) -> (bool, usize)
```
over
```rust,ignore
fn binary_search(&self, k: Key) -> bool
```
#### Yield back ownership:
Prefer
```rust,ignore
fn from_utf8_owned(vv: Vec<u8>) -> Result<String, Vec<u8>>
```
over
```rust,ignore
fn from_utf8_owned(vv: Vec<u8>) -> Option<String>
```
The `from_utf8_owned` function gains ownership of a vector. In the successful
case, the function consumes its input, returning an owned string without
allocating or copying. In the unsuccessful case, however, the function returns
back ownership of the original slice.

View File

@ -1,103 +0,0 @@
% Let binding
### Always separately bind RAII guards. [FIXME: needs RFC]
Prefer
```rust,ignore
fn use_mutex(m: sync::mutex::Mutex<i32>) {
let guard = m.lock();
do_work(guard);
drop(guard); // unlock the lock
// do other work
}
```
over
```rust,ignore
fn use_mutex(m: sync::mutex::Mutex<i32>) {
do_work(m.lock());
// do other work
}
```
As explained in the [RAII guide](../ownership/raii.md), RAII guards are values
that represent ownership of some resource and whose destructor releases the
resource. Because the lifetime of guards are significant, they should always be
explicitly `let`-bound to make the lifetime clear. Consider using an explicit
`drop` to release the resource early.
### Prefer conditional expressions to deferred initialization. [FIXME: needs RFC]
Prefer
```rust,ignore
let foo = match bar {
Baz => 0,
Quux => 1
};
```
over
```rust,ignore
let foo;
match bar {
Baz => {
foo = 0;
}
Quux => {
foo = 1;
}
}
```
unless the conditions for initialization are too complex to fit into a simple
conditional expression.
### Use type annotations for clarification; prefer explicit generics when inference fails. [FIXME: needs RFC]
Prefer
```rust,ignore
let v = s.iter().map(|x| x * 2)
.collect::<Vec<_>>();
```
over
```rust,ignore
let v: Vec<_> = s.iter().map(|x| x * 2)
.collect();
```
When the type of a value might be unclear to the _reader_ of the code, consider
explicitly annotating it in a `let`.
On the other hand, when the type is unclear to the _compiler_, prefer to specify
the type by explicit generics instantiation, which is usually more clear.
### Shadowing [FIXME]
> **[FIXME]** Repeatedly shadowing a binding is somewhat common in Rust code. We
> need to articulate a guideline on when it is appropriate/useful and when not.
### Prefer immutable bindings. [FIXME: needs RFC]
Use `mut` bindings to signal the span during which a value is mutated:
```rust,ignore
let mut v = Vec::new();
// push things onto v
let v = v;
// use v immutably henceforth
```
### Prefer to bind all `struct` or tuple fields. [FIXME: needs RFC]
When consuming a `struct` or tuple via a `let`, bind all of the fields rather
than using `..` to elide the ones you don't need. The benefit is that when
fields are added, the compiler will pinpoint all of the places where that type
of value was consumed, which will often need to be adjusted to take the new
field properly into account.

View File

@ -1,13 +0,0 @@
% Loops
### Prefer `for` to `while`. [FIXME: needs RFC]
A `for` loop is preferable to a `while` loop, unless the loop counts in a
non-uniform way (making it difficult to express using `for`).
### Guidelines for `loop`. [FIXME]
> **[FIXME]** When is `loop` recommended? Some possibilities:
> * For optimistic retry algorithms
> * For servers
> * To avoid mutating local variables sometimes needed to fit `while`

View File

@ -1,26 +0,0 @@
% Pattern matching
### Dereference `match` targets when possible. [FIXME: needs RFC]
Prefer
~~~~ignore
match *foo {
X(...) => ...
Y(...) => ...
}
~~~~
over
~~~~ignore
match foo {
box X(...) => ...
box Y(...) => ...
}
~~~~
<!-- ### Clearly indicate important scopes. **[FIXME: needs RFC]** -->
<!-- If it is important that the destructor for a value be executed at a specific -->
<!-- time, clearly bind that value using a standalone `let` -->

View File

@ -1,133 +0,0 @@
% Modules
> **[FIXME]** What general guidelines should we provide for module design?
> We should discuss visibility, nesting, `mod.rs`, and any interesting patterns
> around modules.
### Headers [FIXME: needs RFC]
Organize module headers as follows:
1. [Imports](../style/imports.md).
1. `mod` declarations.
1. `pub mod` declarations.
### Avoid `path` directives. [FIXME: needs RFC]
Avoid using `#[path="..."]` directives; make the file system and
module hierarchy match, instead.
### Use the module hierarchy to organize APIs into coherent sections. [FIXME]
> **[FIXME]** Flesh this out with examples; explain what a "coherent
> section" is with examples.
>
> The module hierarchy defines both the public and internal API of your module.
> Breaking related functionality into submodules makes it understandable to both
> users and contributors to the module.
### Place modules in their own file. [FIXME: needs RFC]
> **[FIXME]**
> - "<100 lines" is arbitrary, but it's a clearer recommendation
> than "~1 page" or similar suggestions that vary by screen size, etc.
For all except very short modules (<100 lines) and [tests](../testing/README.md),
place the module `foo` in a separate file, as in:
```rust,ignore
pub mod foo;
// in foo.rs or foo/mod.rs
pub fn bar() { println!("..."); }
/* ... */
```
rather than declaring it inline:
```rust,ignore
pub mod foo {
pub fn bar() { println!("..."); }
/* ... */
}
```
#### Use subdirectories for modules with children. [FIXME: needs RFC]
For modules that themselves have submodules, place the module in a separate
directory (e.g., `bar/mod.rs` for a module `bar`) rather than the same directory.
Note the structure of
[`std::io`](https://doc.rust-lang.org/std/io/). Many of the submodules lack
children, like
[`io::fs`](https://doc.rust-lang.org/std/io/fs/)
and
[`io::stdio`](https://doc.rust-lang.org/std/io/stdio/).
On the other hand,
[`io::net`](https://doc.rust-lang.org/std/io/net/)
contains submodules, so it lives in a separate directory:
```text
io/mod.rs
io/extensions.rs
io/fs.rs
io/net/mod.rs
io/net/addrinfo.rs
io/net/ip.rs
io/net/tcp.rs
io/net/udp.rs
io/net/unix.rs
io/pipe.rs
...
```
While it is possible to define all of `io` within a single directory,
mirroring the module hierarchy in the directory structure makes
submodules of `io::net` easier to find.
### Consider top-level definitions or reexports. [FIXME: needs RFC]
For modules with submodules,
define or [reexport](https://doc.rust-lang.org/std/io/#reexports) commonly used
definitions at the top level:
* Functionality relevant to the module itself or to many of its
children should be defined in `mod.rs`.
* Functionality specific to a submodule should live in that
submodule. Reexport at the top level for the most important or
common definitions.
For example,
[`IoError`](https://doc.rust-lang.org/std/io/struct.IoError.html)
is defined in `io/mod.rs`, since it pertains to the entirety of `io`,
while
[`TcpStream`](https://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
is defined in `io/net/tcp.rs` and reexported in the `io` module.
### Use internal module hierarchies for organization. [FIXME: needs RFC]
> **[FIXME]**
> - Referencing internal modules from the standard library is subject to
> becoming outdated.
Internal module hierarchies (i.e., private submodules) may be used to
hide implementation details that are not part of the module's API.
For example, in [`std::io`](https://doc.rust-lang.org/std/io/), `mod mem`
provides implementations for
[`BufReader`](https://doc.rust-lang.org/std/io/struct.BufReader.html)
and
[`BufWriter`](https://doc.rust-lang.org/std/io/struct.BufWriter.html),
but these are re-exported in `io/mod.rs` at the top level of the module:
```rust,ignore
// libstd/io/mod.rs
pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter};
/* ... */
mod mem;
```
This hides the detail that there even exists a `mod mem` in `io`, and
helps keep code organized while offering freedom to change the
implementation.

View File

@ -1,22 +0,0 @@
% Traits
Traits are probably Rust's most complex feature, supporting a wide range of use
cases and design tradeoffs. Patterns of trait usage are still emerging.
### Know whether a trait will be used as an object. [FIXME: needs RFC]
Trait objects have some [significant limitations](objects.md): methods
invoked through a trait object cannot use generics, and cannot use
`Self` except in receiver position.
When designing a trait, decide early on whether the trait will be used
as an [object](objects.md) or as a [bound on generics](generics.md);
the tradeoffs are discussed in each of the linked sections.
If a trait is meant to be used as an object, its methods should take
and return trait objects rather than use generics.
### Default methods [FIXME]
> **[FIXME]** Guidelines for default methods.

View File

@ -1,71 +0,0 @@
% Common traits
### Eagerly implement common traits. [FIXME: needs RFC]
Rust's trait system does not allow _orphans_: roughly, every `impl` must live
either in the crate that defines the trait or the implementing
type. Consequently, crates that define new types should eagerly implement all
applicable, common traits.
To see why, consider the following situation:
* Crate `std` defines trait `Debug`.
* Crate `url` defines type `Url`, without implementing `Debug`.
* Crate `webapp` imports from both `std` and `url`,
There is no way for `webapp` to add `Debug` to `url`, since it defines neither.
(Note: the newtype pattern can provide an efficient, but inconvenient
workaround; see [newtype for views](../types/newtype.md))
The most important common traits to implement from `std` are:
```text
Clone, Debug, Hash, Eq
```
#### When safe, derive or otherwise implement `Send` and `Share`. [FIXME]
> **[FIXME]**. This guideline is in flux while the "opt-in" nature of
> built-in traits is being decided. See https://github.com/rust-lang/rfcs/pull/127
### Prefer to derive, rather than implement. [FIXME: needs RFC]
Deriving saves implementation effort, makes correctness trivial, and
automatically adapts to upstream changes.
### Do not overload operators in surprising ways. [FIXME: needs RFC]
Operators with built in syntax (`*`, `|`, and so on) can be provided for a type
by implementing the traits in `core::ops`. These operators come with strong
expectations: implement `Mul` only for an operation that bears some resemblance
to multiplication (and shares the expected properties, e.g. associativity), and
so on for the other traits.
### The `Drop` trait
The `Drop` trait is treated specially by the compiler as a way of
associating destructors with types. See
[the section on destructors](../../ownership/destructors.md) for
guidance.
### The `Deref`/`DerefMut` traits
#### Use `Deref`/`DerefMut` only for smart pointers. [FIXME: needs RFC]
The `Deref` traits are used implicitly by the compiler in many circumstances,
and interact with method resolution. The relevant rules are designed
specifically to accommodate smart pointers, and so the traits should be used
only for that purpose.
#### Do not fail within a `Deref`/`DerefMut` implementation. [FIXME: needs RFC]
Because the `Deref` traits are invoked implicitly by the compiler in sometimes
subtle ways, failure during dereferencing can be extremely confusing. If a
dereference might not succeed, target the `Deref` trait as a `Result` or
`Option` type instead.
#### Avoid inherent methods when implementing `Deref`/`DerefMut` [FIXME: needs RFC]
The rules around method resolution and `Deref` are in flux, but inherent methods
on a type implementing `Deref` are likely to shadow any methods of the referent
with the same name.

View File

@ -1,7 +0,0 @@
% Using traits to add extension methods
> **[FIXME]** Elaborate.
### Consider using default methods rather than extension traits **[FIXME]**
> **[FIXME]** Elaborate.

View File

@ -1,67 +0,0 @@
% Using traits for bounds on generics
The most widespread use of traits is for writing generic functions or types. For
example, the following signature describes a function for consuming any iterator
yielding items of type `A` to produce a collection of `A`:
```rust,ignore
fn from_iter<T: Iterator<A>>(iterator: T) -> SomeCollection<A>
```
Here, the `Iterator` trait specifies an interface that a type `T` must
explicitly implement to be used by this generic function.
**Pros**:
* _Reusability_. Generic functions can be applied to an open-ended collection of
types, while giving a clear contract for the functionality those types must
provide.
* _Static dispatch and optimization_. Each use of a generic function is
specialized ("monomorphized") to the particular types implementing the trait
bounds, which means that (1) invocations of trait methods are static, direct
calls to the implementation and (2) the compiler can inline and otherwise
optimize these calls.
* _Inline layout_. If a `struct` and `enum` type is generic over some type
parameter `T`, values of type `T` will be laid out _inline_ in the
`struct`/`enum`, without any indirection.
* _Inference_. Since the type parameters to generic functions can usually be
inferred, generic functions can help cut down on verbosity in code where
explicit conversions or other method calls would usually be necessary. See the
overloading/implicits use case below.
* _Precise types_. Because generics give a _name_ to the specific type
implementing a trait, it is possible to be precise about places where that
exact type is required or produced. For example, a function
```rust,ignore
fn binary<T: Trait>(x: T, y: T) -> T
```
is guaranteed to consume and produce elements of exactly the same type `T`; it
cannot be invoked with parameters of different types that both implement
`Trait`.
**Cons**:
* _Code size_. Specializing generic functions means that the function body is
duplicated. The increase in code size must be weighed against the performance
benefits of static dispatch.
* _Homogeneous types_. This is the other side of the "precise types" coin: if
`T` is a type parameter, it stands for a _single_ actual type. So for example
a `Vec<T>` contains elements of a single concrete type (and, indeed, the
vector representation is specialized to lay these out in line). Sometimes
heterogeneous collections are useful; see
trait objects below.
* _Signature verbosity_. Heavy use of generics can bloat function signatures.
**[Ed. note]** This problem may be mitigated by some language improvements; stay tuned.
### Favor widespread traits. **[FIXME: needs RFC]**
Generic types are a form of abstraction, which entails a mental indirection: if
a function takes an argument of type `T` bounded by `Trait`, clients must first
think about the concrete types that implement `Trait` to understand how and when
the function is callable.
To keep the cost of abstraction low, favor widely-known traits. Whenever
possible, implement and use traits provided as part of the standard library. Do
not introduce new traits for generics lightly; wait until there are a wide range
of types that can implement the type.

View File

@ -1,49 +0,0 @@
% Using trait objects
> **[FIXME]** What are uses of trait objects other than heterogeneous collections?
Trait objects are useful primarily when _heterogeneous_ collections of objects
need to be treated uniformly; it is the closest that Rust comes to
object-oriented programming.
```rust,ignore
struct Frame { ... }
struct Button { ... }
struct Label { ... }
trait Widget { ... }
impl Widget for Frame { ... }
impl Widget for Button { ... }
impl Widget for Label { ... }
impl Frame {
fn new(contents: &[Box<Widget>]) -> Frame {
...
}
}
fn make_gui() -> Box<Widget> {
let b: Box<Widget> = box Button::new(...);
let l: Box<Widget> = box Label::new(...);
box Frame::new([b, l]) as Box<Widget>
}
```
By using trait objects, we can set up a GUI framework with a `Frame` widget that
contains a heterogeneous collection of children widgets.
**Pros**:
* _Heterogeneity_. When you need it, you really need it.
* _Code size_. Unlike generics, trait objects do not generate specialized
(monomorphized) versions of code, which can greatly reduce code size.
**Cons**:
* _No generic methods_. Trait objects cannot currently provide generic methods.
* _Dynamic dispatch and fat pointers_. Trait objects inherently involve
indirection and vtable dispatch, which can carry a performance penalty.
* _No Self_. Except for the method receiver argument, methods on trait objects
cannot use the `Self` type.

View File

@ -1,7 +0,0 @@
% Using traits for overloading
> **[FIXME]** Elaborate.
> **[FIXME]** We need to decide on guidelines for this use case. There are a few
> patterns emerging in current Rust code, but it's not clear how widespread they
> should be.

View File

@ -1,30 +0,0 @@
% Using traits to share implementations
> **[FIXME]** Elaborate.
> **[FIXME]** We probably want to discourage this, at least when used in a way
> that is publicly exposed.
Traits that provide default implementations for function can provide code reuse
across types. For example, a `print` method can be defined across multiple
types as follows:
``` Rust
trait Printable {
// Default method implementation
fn print(&self) { println!("{:?}", *self) }
}
impl Printable for i32 {}
impl Printable for String {
fn print(&self) { println!("{}", *self) }
}
impl Printable for bool {}
impl Printable for f32 {}
```
This allows the implementation of `print` to be shared across types, yet
overridden where needed, as seen in the `impl` for `String`.

View File

@ -1,68 +0,0 @@
% Data types
### Use custom types to imbue meaning; do not abuse `bool`, `Option` or other core types. **[FIXME: needs RFC]**
Prefer
```rust,ignore
let w = Widget::new(Small, Round)
```
over
```rust,ignore
let w = Widget::new(true, false)
```
Core types like `bool`, `u8` and `Option` have many possible interpretations.
Use custom types (whether `enum`s, `struct`, or tuples) to convey
interpretation and invariants. In the above example,
it is not immediately clear what `true` and `false` are conveying without
looking up the argument names, but `Small` and `Round` are more suggestive.
Using custom types makes it easier to expand the
options later on, for example by adding an `ExtraLarge` variant.
See [the newtype pattern](newtype.md) for a no-cost way to wrap
existing types with a distinguished name.
### Prefer private fields, except for passive data. **[FIXME: needs RFC]**
Making a field public is a strong commitment: it pins down a representation
choice, _and_ prevents the type from providing any validation or maintaining any
invariants on the contents of the field, since clients can mutate it arbitrarily.
Public fields are most appropriate for `struct` types in the C spirit: compound,
passive data structures. Otherwise, consider providing getter/setter methods
and hiding fields instead.
> **[FIXME]** Cross-reference validation for function arguments.
### Use custom `enum`s for alternatives, `bitflags` for C-style flags. **[FIXME: needs RFC]**
Rust supports `enum` types with "custom discriminants":
~~~~
enum Color {
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff
}
~~~~
Custom discriminants are useful when an `enum` type needs to be serialized to an
integer value compatibly with some other system/language. They support
"typesafe" APIs: by taking a `Color`, rather than an integer, a function is
guaranteed to get well-formed inputs, even if it later views those inputs as
integers.
An `enum` allows an API to request exactly one choice from among many. Sometimes
an API's input is instead the presence or absence of a set of flags. In C code,
this is often done by having each flag correspond to a particular bit, allowing
a single integer to represent, say, 32 or 64 flags. Rust's `std::bitflags`
module provides a typesafe way for doing so.
### Phantom types. [FIXME]
> **[FIXME]** Add some material on phantom types (https://blog.mozilla.org/research/2014/06/23/static-checking-of-units-in-servo/)

View File

@ -1,22 +0,0 @@
% Conversions between types
### Associate conversions with the most specific type involved. **[FIXME: needs RFC]**
When in doubt, prefer `to_`/`as_`/`into_` to `from_`, because they are
more ergonomic to use (and can be chained with other methods).
For many conversions between two types, one of the types is clearly more
"specific": it provides some additional invariant or interpretation that is not
present in the other type. For example, `str` is more specific than `&[u8]`,
since it is a utf-8 encoded sequence of bytes.
Conversions should live with the more specific of the involved types. Thus,
`str` provides both the `as_bytes` method and the `from_utf8` constructor for
converting to and from `&[u8]` values. Besides being intuitive, this convention
avoids polluting concrete types like `&[u8]` with endless conversion methods.
### Explicitly mark lossy conversions, or do not label them as conversions. **[FIXME: needs RFC]**
If a function's name implies that it is a conversion (prefix `from_`, `as_`,
`to_` or `into_`), but the function loses information, add a suffix `_lossy` or
otherwise indicate the lossyness. Consider avoiding the conversion name prefix.

View File

@ -1,69 +0,0 @@
% The newtype pattern
A "newtype" is a tuple or `struct` with a single field. The terminology is borrowed from Haskell.
Newtypes are a zero-cost abstraction: they introduce a new, distinct name for an
existing type, with no runtime overhead when converting between the two types.
### Use newtypes to provide static distinctions. [FIXME: needs RFC]
Newtypes can statically distinguish between different interpretations of an
underlying type.
For example, a `f64` value might be used to represent a quantity in miles or in
kilometers. Using newtypes, we can keep track of the intended interpretation:
```rust,ignore
struct Miles(pub f64);
struct Kilometers(pub f64);
impl Miles {
fn as_kilometers(&self) -> Kilometers { ... }
}
impl Kilometers {
fn as_miles(&self) -> Miles { ... }
}
```
Once we have separated these two types, we can statically ensure that we do not
confuse them. For example, the function
```rust,ignore
fn are_we_there_yet(distance_travelled: Miles) -> bool { ... }
```
cannot accidentally be called with a `Kilometers` value. The compiler will
remind us to perform the conversion, thus averting certain
[catastrophic bugs](http://en.wikipedia.org/wiki/Mars_Climate_Orbiter).
### Use newtypes with private fields for hiding. [FIXME: needs RFC]
A newtype can be used to hide representation details while making precise
promises to the client.
For example, consider a function `my_transform` that returns a compound iterator
type `Enumerate<Skip<vec::MoveItems<T>>>`. We wish to hide this type from the
client, so that the client's view of the return type is roughly `Iterator<(usize,
T)>`. We can do so using the newtype pattern:
```rust,ignore
struct MyTransformResult<T>(Enumerate<Skip<vec::MoveItems<T>>>);
impl<T> Iterator<(usize, T)> for MyTransformResult<T> { ... }
fn my_transform<T, Iter: Iterator<T>>(iter: Iter) -> MyTransformResult<T> {
...
}
```
Aside from simplifying the signature, this use of newtypes allows us to make a
expose and promise less to the client. The client does not know _how_ the result
iterator is constructed or represented, which means the representation can
change in the future without breaking client code.
> **[FIXME]** Interaction with auto-deref.
### Use newtypes to provide cost-free _views_ of another type. **[FIXME]**
> **[FIXME]** Describe the pattern of using newtypes to provide a new set of
> inherent or trait methods, providing a different perspective on the underlying
> type.

View File

@ -1,3 +0,0 @@
% Ownership and resource management
> **[FIXME]** Add general remarks about ownership/resources here.

View File

@ -1,176 +0,0 @@
% The builder pattern
Some data structures are complicated to construct, due to their construction needing:
* a large number of inputs
* compound data (e.g. slices)
* optional configuration data
* choice between several flavors
which can easily lead to a large number of distinct constructors with
many arguments each.
If `T` is such a data structure, consider introducing a `T` _builder_:
1. Introduce a separate data type `TBuilder` for incrementally configuring a `T`
value. When possible, choose a better name: e.g. `Command` is the builder for
`Process`.
2. The builder constructor should take as parameters only the data _required_ to
make a `T`.
3. The builder should offer a suite of convenient methods for configuration,
including setting up compound inputs (like slices) incrementally.
These methods should return `self` to allow chaining.
4. The builder should provide one or more "_terminal_" methods for actually building a `T`.
The builder pattern is especially appropriate when building a `T` involves side
effects, such as spawning a thread or launching a process.
In Rust, there are two variants of the builder pattern, differing in the
treatment of ownership, as described below.
### Non-consuming builders (preferred):
In some cases, constructing the final `T` does not require the builder itself to
be consumed. The follow variant on
[`std::process::Command`](https://doc.rust-lang.org/stable/std/process/struct.Command.html)
is one example:
```rust,ignore
// NOTE: the actual Command API does not use owned Strings;
// this is a simplified version.
pub struct Command {
program: String,
args: Vec<String>,
cwd: Option<String>,
// etc
}
impl Command {
pub fn new(program: String) -> Command {
Command {
program: program,
args: Vec::new(),
cwd: None,
}
}
/// Add an argument to pass to the program.
pub fn arg<'a>(&'a mut self, arg: String) -> &'a mut Command {
self.args.push(arg);
self
}
/// Add multiple arguments to pass to the program.
pub fn args<'a>(&'a mut self, args: &[String])
-> &'a mut Command {
self.args.push_all(args);
self
}
/// Set the working directory for the child process.
pub fn cwd<'a>(&'a mut self, dir: String) -> &'a mut Command {
self.cwd = Some(dir);
self
}
/// Executes the command as a child process, which is returned.
pub fn spawn(&self) -> std::io::Result<Process> {
...
}
}
```
Note that the `spawn` method, which actually uses the builder configuration to
spawn a process, takes the builder by immutable reference. This is possible
because spawning the process does not require ownership of the configuration
data.
Because the terminal `spawn` method only needs a reference, the configuration
methods take and return a mutable borrow of `self`.
#### The benefit
By using borrows throughout, `Command` can be used conveniently for both
one-liner and more complex constructions:
```rust,ignore
// One-liners
Command::new("/bin/cat").arg("file.txt").spawn();
// Complex configuration
let mut cmd = Command::new("/bin/ls");
cmd.arg(".");
if size_sorted {
cmd.arg("-S");
}
cmd.spawn();
```
### Consuming builders:
Sometimes builders must transfer ownership when constructing the final type
`T`, meaning that the terminal methods must take `self` rather than `&self`:
```rust,ignore
// A simplified excerpt from std::thread::Builder
impl ThreadBuilder {
/// Name the thread-to-be. Currently the name is used for identification
/// only in failure messages.
pub fn named(mut self, name: String) -> ThreadBuilder {
self.name = Some(name);
self
}
/// Redirect thread-local stdout.
pub fn stdout(mut self, stdout: Box<Writer + Send>) -> ThreadBuilder {
self.stdout = Some(stdout);
// ^~~~~~ this is owned and cannot be cloned/re-used
self
}
/// Creates and executes a new child thread.
pub fn spawn(self, f: proc():Send) {
// consume self
...
}
}
```
Here, the `stdout` configuration involves passing ownership of a `Writer`,
which must be transferred to the thread upon construction (in `spawn`).
When the terminal methods of the builder require ownership, there is a basic tradeoff:
* If the other builder methods take/return a mutable borrow, the complex
configuration case will work well, but one-liner configuration becomes
_impossible_.
* If the other builder methods take/return an owned `self`, one-liners
continue to work well but complex configuration is less convenient.
Under the rubric of making easy things easy and hard things possible, _all_
builder methods for a consuming builder should take and returned an owned
`self`. Then client code works as follows:
```rust,ignore
// One-liners
ThreadBuilder::new().named("my_thread").spawn(proc() { ... });
// Complex configuration
let mut thread = ThreadBuilder::new();
thread = thread.named("my_thread_2"); // must re-assign to retain ownership
if reroute {
thread = thread.stdout(mywriter);
}
thread.spawn(proc() { ... });
```
One-liners work as before, because ownership is threaded through each of the
builder methods until being consumed by `spawn`. Complex configuration,
however, is more verbose: it requires re-assigning the builder at each step.

View File

@ -1,4 +0,0 @@
% Cells and smart pointers
> **[FIXME]** Add guidelines about when to use Cell, RefCell, Rc and
> Arc (and how to use them together).

View File

@ -1,62 +0,0 @@
% Constructors
### Define constructors as static, inherent methods. [FIXME: needs RFC]
In Rust, "constructors" are just a convention:
```rust,ignore
impl<T> Vec<T> {
pub fn new() -> Vec<T> { ... }
}
```
Constructors are static (no `self`) inherent methods for the type that they
construct. Combined with the practice of
[fully importing type names](../style/imports.md), this convention leads to
informative but concise construction:
```rust,ignore
use vec::Vec;
// construct a new vector
let mut v = Vec::new();
```
This convention also applied to conversion constructors (prefix `from` rather
than `new`).
### Provide constructors for passive `struct`s with defaults. [FIXME: needs RFC]
Given the `struct`
```rust,ignore
pub struct Config {
pub color: Color,
pub size: Size,
pub shape: Shape,
}
```
provide a constructor if there are sensible defaults:
```rust,ignore
impl Config {
pub fn new() -> Config {
Config {
color: Brown,
size: Medium,
shape: Square,
}
}
}
```
which then allows clients to concisely override using `struct` update syntax:
```rust,ignore
Config { color: Red, .. Config::new() };
```
See the [guideline for field privacy](../features/types/README.md) for
discussion on when to create such "passive" `struct`s with public
fields.

View File

@ -1,22 +0,0 @@
% Destructors
Unlike constructors, destructors in Rust have a special status: they are added
by implementing `Drop` for a type, and they are automatically invoked as values
go out of scope.
> **[FIXME]** This section needs to be expanded.
### Destructors should not fail. [FIXME: needs RFC]
Destructors are executed on thread failure, and in that context a failing
destructor causes the program to abort.
Instead of failing in a destructor, provide a separate method for checking for
clean teardown, e.g. a `close` method, that returns a `Result` to signal
problems.
### Destructors should not block. [FIXME: needs RFC]
Similarly, destructors should not invoke blocking operations, which can make
debugging much more difficult. Again, consider providing a separate method for
preparing for an infallible, nonblocking teardown.

View File

@ -1,12 +0,0 @@
% RAII
Resource Acquisition is Initialization
> **[FIXME]** Explain the RAII pattern and give best practices.
### Whenever possible, tie resource access to guard scopes [FIXME]
> **[FIXME]** Example: Mutex guards guarantee that access to the
> protected resource only happens when the guard is in scope.
`must_use`

View File

@ -1,7 +0,0 @@
% FFI and platform-specific code **[FIXME]**
> **[FIXME]** Not sure where this should live.
When writing cross-platform code, group platform-specific code into a
module called `platform`. Avoid `#[cfg]` directives outside this
`platform` module.

View File

@ -1,19 +0,0 @@
% Safety and guarantees
> **[FIXME]** Is there a better phrase than "strong guarantees" that encompasses
> both e.g. memory safety and e.g. data structure invariants?
A _guarantee_ is a property that holds no matter what client code does, unless
the client explicitly opts out:
* Rust guarantees memory safety and data-race freedom, with `unsafe`
blocks as an opt-out mechanism.
* APIs in Rust often provide their own guarantees. For example, `std::str`
guarantees that its underlying buffer is valid utf-8. The `std::path::Path` type
guarantees no interior nulls. Both strings and paths provide `unsafe` mechanisms
for opting out of these guarantees (and thereby avoiding runtime checks).
Thinking about guarantees is an essential part of writing good Rust code. The
rest of this subsection outlines some cross-cutting principles around
guarantees.

View File

@ -1,81 +0,0 @@
% Library-level guarantees
Most libraries rely on internal invariants, e.g. about their data, resource
ownership, or protocol states. In Rust, broken invariants cannot produce
segfaults, but they can still lead to wrong answers.
### Provide library-level guarantees whenever practical. **[FIXME: needs RFC]**
Library-level invariants should be turned into guarantees whenever
practical. They should hold no matter what the client does, modulo
explicit opt-outs. Depending on the kind of invariant, this can be
achieved through a combination of static and dynamic enforcement, as
described below.
#### Static enforcement:
Guaranteeing invariants almost always requires _hiding_,
i.e. preventing the client from directly accessing or modifying
internal data.
For example, the representation of the `str` type is hidden,
which means that any value of type `str` must have been produced
through an API under the control of the `str` module, and these
APIs in turn ensure valid utf-8 encoding.
Rust's type system makes it possible to provide guarantees even while
revealing more of the representation than usual. For example, the
`as_bytes()` method on `&str` gives a _read-only_ view into the
underlying buffer, which cannot be used to violate the utf-8 property.
#### Dynamic enforcement:
Malformed inputs from the client are hazards to library-level
guarantees, so library APIs should validate their input.
For example, `std::str::from_utf8_owned` attempts to convert a `u8`
slice into an owned string, but dynamically checks that the slice is
valid utf-8 and returns `Err` if not.
See
[the discussion on input validation](../features/functions-and-methods/input.md)
for more detail.
### Prefer static enforcement of guarantees. **[FIXME: needs RFC]**
Static enforcement provides two strong benefits over dynamic enforcement:
* Bugs are caught at compile time.
* There is no runtime cost.
Sometimes purely static enforcement is impossible or impractical. In these
cases, a library should check as much as possible statically, but defer to
dynamic checks where needed.
For example, the `std::string` module exports a `String` type with the guarantee
that all instances are valid utf-8:
* Any _consumer_ of a `String` is statically guaranteed utf-8 contents. For example,
the `append` method can push a `&str` onto the end of a `String` without
checking anything dynamically, since the existing `String` and `&str` are
statically guaranteed to be in utf-8.
* Some _producers_ of a `String` must perform dynamic checks. For example, the
`from_utf8` function attempts to convert a `Vec<u8>` into a `String`, but
dynamically checks that the contents are utf-8.
### Provide opt-outs with caution; make them explicit. **[FIXME: needs RFC]**
Providing library-level guarantees sometimes entails inconvenience (for static
checks) or overhead (for dynamic checks). So it is sometimes desirable to allow
clients to sidestep this checking, while promising to use the API in a way that
still provides the guarantee. Such escape hatches should only be introduced when
there is a demonstrated need for them.
It should be trivial for clients to audit their use of the library for
escape hatches.
See
[the discussion on input validation](../features/functions-and-methods/input.md)
for conventions on marking opt-out functions.

View File

@ -1,22 +0,0 @@
% Using `unsafe`
### Unconditionally guarantee safety, or mark API as `unsafe`. **[FIXME: needs RFC]**
Memory safety, type safety, and data race freedom are basic assumptions for all
Rust code.
APIs that use `unsafe` blocks internally thus have two choices:
* They can guarantee safety _unconditionally_ (i.e., regardless of client
behavior or inputs) and be exported as safe code. Any safety violation is then
the library's fault, not the client's fault.
* They can export potentially unsafe functions with the `unsafe` qualifier. In
this case, the documentation should make very clear the conditions under which
safety is guaranteed.
The result is that a client program can never violate safety merely by having a
bug; it must have explicitly opted out by using an `unsafe` block.
Of the two options for using `unsafe`, creating such safe abstractions (the
first option above) is strongly preferred.

View File

@ -1,5 +0,0 @@
% Style
This section gives a set of strict rules for styling Rust code.
> **[FIXME]** General remarks about the style guidelines

View File

@ -1,77 +0,0 @@
% Braces, semicolons, and commas [FIXME: needs RFC]
### Opening braces always go on the same line.
```rust,ignore
fn foo() {
...
}
fn frobnicate(a: Bar, b: Bar,
c: Bar, d: Bar)
-> Bar {
...
}
trait Bar {
fn baz(&self);
}
impl Bar for Baz {
fn baz(&self) {
...
}
}
frob(|x| {
x.transpose()
})
```
### `match` arms get braces, except for single-line expressions.
```rust,ignore
match foo {
bar => baz,
quux => {
do_something();
do_something_else()
}
}
```
### `return` statements get semicolons.
```rust,ignore
fn foo() {
do_something();
if condition() {
return;
}
do_something_else();
}
```
### Trailing commas
> **[FIXME]** We should have a guideline for when to include trailing
> commas in `struct`s, `match`es, function calls, etc.
>
> One possible rule: a trailing comma should be included whenever the
> closing delimiter appears on a separate line:
```rust,ignore
Foo { bar: 0, baz: 1 }
Foo {
bar: 0,
baz: 1,
}
match a_thing {
None => 0,
Some(x) => 1,
}
```

Some files were not shown because too many files have changed in this diff Show More