Merge branch 'master' into escape-reason-docs
This commit is contained in:
commit
e766c465d2
601 changed files with 19295 additions and 10334 deletions
27
.travis.yml
27
.travis.yml
|
@ -8,6 +8,8 @@ git:
|
|||
depth: 1
|
||||
submodules: false
|
||||
|
||||
osx_image: xcode8.2
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# Linux builders, all docker images
|
||||
|
@ -27,28 +29,37 @@ matrix:
|
|||
# OSX builders
|
||||
- env: >
|
||||
RUST_CHECK_TARGET=check
|
||||
RUST_CONFIGURE_ARGS=--target=x86_64-apple-darwin
|
||||
RUST_CONFIGURE_ARGS=--build=x86_64-apple-darwin
|
||||
SRC=.
|
||||
os: osx
|
||||
install: brew install ccache
|
||||
install: &osx_install_sccache >
|
||||
curl -L https://api.pub.build.mozilla.org/tooltool/sha512/d0025b286468cc5ada83b23d3fafbc936b9f190eaa7d4a981715b18e8e3bf720a7bcee7bfe758cfdeb8268857f6098fd52dcdd8818232692a30ce91039936596 |
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
- env: >
|
||||
RUST_CHECK_TARGET=check
|
||||
RUST_CONFIGURE_ARGS=--target=i686-apple-darwin
|
||||
RUST_CONFIGURE_ARGS=--build=i686-apple-darwin
|
||||
SRC=.
|
||||
os: osx
|
||||
install: brew install ccache
|
||||
install: *osx_install_sccache
|
||||
- env: >
|
||||
RUST_CHECK_TARGET=check
|
||||
RUST_CONFIGURE_ARGS=--target=x86_64-apple-darwin --disable-rustbuild
|
||||
RUST_CONFIGURE_ARGS=--build=x86_64-apple-darwin --disable-rustbuild
|
||||
SRC=.
|
||||
os: osx
|
||||
install: brew install ccache
|
||||
install: *osx_install_sccache
|
||||
- env: >
|
||||
RUST_CHECK_TARGET=
|
||||
RUST_CONFIGURE_ARGS=--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios
|
||||
SRC=.
|
||||
os: osx
|
||||
install: brew install ccache
|
||||
install: *osx_install_sccache
|
||||
|
||||
env:
|
||||
global:
|
||||
- SCCACHE_BUCKET=rust-lang-ci-sccache
|
||||
- AWS_ACCESS_KEY_ID=AKIAIMX7VLAS3PZAVLUQ
|
||||
# AWS_SECRET_ACCESS_KEY=...
|
||||
- secure: "Pixhh0hXDqGCdOyLtGFjli3J2AtDWIpyb2btIrLe956nCBDRutRoMm6rv5DI9sFZN07Mms7VzNNvhc9wCW1y63JAm414d2Co7Ob8kWMZlz9l9t7ACHuktUiis8yr+S4Quq1Vqd6pqi7pf2J++UxC8R/uLeqVrubzr6+X7AbmEFE="
|
||||
|
||||
script:
|
||||
- >
|
||||
|
@ -77,5 +88,3 @@ notifications:
|
|||
cache:
|
||||
directories:
|
||||
- $HOME/docker
|
||||
- $HOME/.ccache
|
||||
- $HOME/.cargo
|
||||
|
|
|
@ -212,12 +212,13 @@ Some common invocations of `x.py` are:
|
|||
& everything builds in the correct manner.
|
||||
- `x.py test src/libstd --stage 1` - test the standard library without
|
||||
recompiling stage 2.
|
||||
- `x.py test src/test/run-pass --filter TESTNAME` - Run a matching set of tests.
|
||||
- `x.py test src/test/run-pass --test-args TESTNAME` - Run a matching set of
|
||||
tests.
|
||||
- `TESTNAME` should be a substring of the tests to match against e.g. it could
|
||||
be the fully qualified test name, or just a part of it.
|
||||
`TESTNAME=collections::hash::map::test_map::test_capacity_not_less_than_len`
|
||||
or `TESTNAME=test_capacity_not_less_than_len`.
|
||||
- `x.py test src/test/run-pass --stage 1 --filter <substring-of-test-name>` -
|
||||
- `x.py test src/test/run-pass --stage 1 --test-args <substring-of-test-name>` -
|
||||
Run a single rpass test with the stage1 compiler (this will be quicker than
|
||||
running the command above as we only build the stage1 compiler, not the entire
|
||||
thing). You can also leave off the directory argument to run all stage1 test
|
||||
|
@ -284,7 +285,7 @@ been approved. The PR then enters the [merge queue][merge-queue], where @bors
|
|||
will run all the tests on every platform we support. If it all works out,
|
||||
@bors will merge your code into `master` and close the pull request.
|
||||
|
||||
[merge-queue]: http://buildbot.rust-lang.org/homu/queue/rust
|
||||
[merge-queue]: https://buildbot.rust-lang.org/homu/queue/rust
|
||||
|
||||
Speaking of tests, Rust has a comprehensive test suite. More information about
|
||||
it can be found
|
||||
|
@ -403,4 +404,4 @@ are:
|
|||
[tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/
|
||||
[ro]: http://www.rustaceans.org/
|
||||
[rctd]: ./COMPILER_TESTS.md
|
||||
[cheatsheet]: http://buildbot.rust-lang.org/homu/
|
||||
[cheatsheet]: https://buildbot.rust-lang.org/homu/
|
||||
|
|
219
RELEASES.md
219
RELEASES.md
|
@ -1,3 +1,222 @@
|
|||
Version 1.14.0 (2016-12-22)
|
||||
===========================
|
||||
|
||||
Language
|
||||
--------
|
||||
|
||||
* [`..` matches multiple tuple fields in enum variants, structs
|
||||
and tuples][36843]. [RFC 1492].
|
||||
* [Safe `fn` items can be coerced to `unsafe fn` pointers][37389]
|
||||
* [`use *` and `use ::*` both glob-import from the crate root][37367]
|
||||
* [It's now possible to call a `Vec<Box<Fn()>>` without explicit
|
||||
dereferencing][36822]
|
||||
|
||||
Compiler
|
||||
--------
|
||||
|
||||
* [Mark enums with non-zero discriminant as non-zero][37224]
|
||||
* [Lower-case `static mut` names are linted like other
|
||||
statics and consts][37162]
|
||||
* [Fix ICE on some macros in const integer positions
|
||||
(e.g. `[u8; m!()]`)][36819]
|
||||
* [Improve error message and snippet for "did you mean `x`"][36798]
|
||||
* [Add a panic-strategy field to the target specification][36794]
|
||||
* [Include LLVM version in `--version --verbose`][37200]
|
||||
|
||||
Compile-time Optimizations
|
||||
--------------------------
|
||||
|
||||
* [Improve macro expansion performance][37569]
|
||||
* [Shrink `Expr_::ExprInlineAsm`][37445]
|
||||
* [Replace all uses of SHA-256 with BLAKE2b][37439]
|
||||
* [Reduce the number of bytes hashed by `IchHasher`][37427]
|
||||
* [Avoid more allocations when compiling html5ever][37373]
|
||||
* [Use `SmallVector` in `CombineFields::instantiate`][37322]
|
||||
* [Avoid some allocations in the macro parser][37318]
|
||||
* [Use a faster deflate setting][37298]
|
||||
* [Add `ArrayVec` and `AccumulateVec` to reduce heap allocations
|
||||
during interning of slices][37270]
|
||||
* [Optimize `write_metadata`][37267]
|
||||
* [Don't process obligation forest cycles when stalled][37231]
|
||||
* [Avoid many `CrateConfig` clones][37161]
|
||||
* [Optimize `Substs::super_fold_with`][37108]
|
||||
* [Optimize `ObligationForest`'s `NodeState` handling][36993]
|
||||
* [Speed up `plug_leaks`][36917]
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
||||
* [`println!()`, with no arguments, prints newline][36825].
|
||||
Previously, an empty string was required to achieve the same.
|
||||
* [`Wrapping` impls standard binary and unary operators, as well as
|
||||
the `Sum` and `Product` iterators][37356]
|
||||
* [Implement `From<Cow<str>> for String` and `From<Cow<[T]>> for
|
||||
Vec<T>`][37326]
|
||||
* [Improve `fold` performance for `chain`, `cloned`, `map`, and
|
||||
`VecDeque` iterators][37315]
|
||||
* [Improve `SipHasher` performance on small values][37312]
|
||||
* [Add Iterator trait TrustedLen to enable better FromIterator /
|
||||
Extend][37306]
|
||||
* [Expand `.zip()` specialization to `.map()` and `.cloned()`][37230]
|
||||
* [`ReadDir` implements `Debug`][37221]
|
||||
* [Implement `RefUnwindSafe` for atomic types][37178]
|
||||
* [Specialize `Vec::extend` to `Vec::extend_from_slice`][37094]
|
||||
* [Avoid allocations in `Decoder::read_str`][37064]
|
||||
* [`io::Error` implements `From<io::ErrorKind>`][37037]
|
||||
* [Impl `Debug` for raw pointers to unsized data][36880]
|
||||
* [Don't reuse `HashMap` random seeds][37470]
|
||||
* [The internal memory layout of `HashMap` is more cache-friendly, for
|
||||
significant improvements in some operations][36692]
|
||||
* [`HashMap` uses less memory on 32-bit architectures][36595]
|
||||
* [Impl `Add<{str, Cow<str>}>` for `Cow<str>`][36430]
|
||||
|
||||
Cargo
|
||||
-----
|
||||
|
||||
* [Expose rustc cfg values to build scripts][cargo/3243]
|
||||
* [Allow cargo to work with read-only `CARGO_HOME`][cargo/3259]
|
||||
* [Fix passing --features when testing multiple packages][cargo/3280]
|
||||
* [Use a single profile set per workspace][cargo/3249]
|
||||
* [Load `replace` sections from lock files][cargo/3220]
|
||||
* [Ignore `panic` configuration for test/bench profiles][cargo/3175]
|
||||
|
||||
Tooling
|
||||
-------
|
||||
|
||||
* [rustup is the recommended Rust installation method][1.14rustup]
|
||||
* This release includes host (rustc) builds for Linux on MIPS, PowerPC, and
|
||||
S390x. These are [tier 2] platforms and may have major defects. Follow the
|
||||
instructions on the website to install, or add the targets to an existing
|
||||
installation with `rustup target add`. The new target triples are:
|
||||
- `mips-unknown-linux-gnu`
|
||||
- `mipsel-unknown-linux-gnu`
|
||||
- `mips64-unknown-linux-gnuabi64`
|
||||
- `mips64el-unknown-linux-gnuabi64 `
|
||||
- `powerpc-unknown-linux-gnu`
|
||||
- `powerpc64-unknown-linux-gnu`
|
||||
- `powerpc64le-unknown-linux-gnu`
|
||||
- `s390x-unknown-linux-gnu `
|
||||
* This release includes target (std) builds for ARM Linux running MUSL
|
||||
libc. These are [tier 2] platforms and may have major defects. Add the
|
||||
following triples to an existing rustup installation with `rustup target add`:
|
||||
- `arm-unknown-linux-musleabi`
|
||||
- `arm-unknown-linux-musleabihf`
|
||||
- `armv7-unknown-linux-musleabihf`
|
||||
* This release includes [experimental support for WebAssembly][1.14wasm], via
|
||||
the `wasm32-unknown-emscripten` target. This target is known to have major
|
||||
defects. Please test, report, and fix.
|
||||
* rustup no longer installs documentation by default. Run `rustup
|
||||
component add rust-docs` to install.
|
||||
* [Fix line stepping in debugger][37310]
|
||||
* [Enable line number debuginfo in releases][37280]
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
* [Disable jemalloc on aarch64/powerpc/mips][37392]
|
||||
* [Add support for Fuchsia OS][37313]
|
||||
* [Detect local-rebuild by only MAJOR.MINOR version][37273]
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
|
||||
* [A number of forward-compatibility lints used by the compiler
|
||||
to gradually introduce language changes have been converted
|
||||
to deny by default][36894]:
|
||||
- ["use of inaccessible extern crate erroneously allowed"][36886]
|
||||
- ["type parameter default erroneously allowed in invalid location"][36887]
|
||||
- ["detects super or self keywords at the beginning of global path"][36888]
|
||||
- ["two overlapping inherent impls define an item with the same name
|
||||
were erroneously allowed"][36889]
|
||||
- ["floating-point constants cannot be used in patterns"][36890]
|
||||
- ["constants of struct or enum type can only be used in a pattern if
|
||||
the struct or enum has `#[derive(PartialEq, Eq)]`"][36891]
|
||||
- ["lifetimes or labels named `'_` were erroneously allowed"][36892]
|
||||
* [Prohibit patterns in trait methods without bodies][37378]
|
||||
* [The atomic `Ordering` enum may not be matched exhaustively][37351]
|
||||
* [Future-proofing `#[no_link]` breaks some obscure cases][37247]
|
||||
* [The `$crate` macro variable is accepted in fewer locations][37213]
|
||||
* [Impls specifying extra region requirements beyond the trait
|
||||
they implement are rejected][37167]
|
||||
* [Enums may not be unsized][37111]. Unsized enums are intended to
|
||||
work but never have. For now they are forbidden.
|
||||
* [Enforce the shadowing restrictions from RFC 1560 for today's macros][36767]
|
||||
|
||||
[tier 2]: https://forge.rust-lang.org/platform-support.html
|
||||
[1.14rustup]: https://internals.rust-lang.org/t/beta-testing-rustup-rs/3316/204
|
||||
[1.14wasm]: https://users.rust-lang.org/t/compiling-to-the-web-with-rust-and-emscripten/7627
|
||||
[36430]: https://github.com/rust-lang/rust/pull/36430
|
||||
[36595]: https://github.com/rust-lang/rust/pull/36595
|
||||
[36595]: https://github.com/rust-lang/rust/pull/36595
|
||||
[36692]: https://github.com/rust-lang/rust/pull/36692
|
||||
[36767]: https://github.com/rust-lang/rust/pull/36767
|
||||
[36794]: https://github.com/rust-lang/rust/pull/36794
|
||||
[36798]: https://github.com/rust-lang/rust/pull/36798
|
||||
[36819]: https://github.com/rust-lang/rust/pull/36819
|
||||
[36822]: https://github.com/rust-lang/rust/pull/36822
|
||||
[36825]: https://github.com/rust-lang/rust/pull/36825
|
||||
[36843]: https://github.com/rust-lang/rust/pull/36843
|
||||
[36880]: https://github.com/rust-lang/rust/pull/36880
|
||||
[36886]: https://github.com/rust-lang/rust/issues/36886
|
||||
[36887]: https://github.com/rust-lang/rust/issues/36887
|
||||
[36888]: https://github.com/rust-lang/rust/issues/36888
|
||||
[36889]: https://github.com/rust-lang/rust/issues/36889
|
||||
[36890]: https://github.com/rust-lang/rust/issues/36890
|
||||
[36891]: https://github.com/rust-lang/rust/issues/36891
|
||||
[36892]: https://github.com/rust-lang/rust/issues/36892
|
||||
[36894]: https://github.com/rust-lang/rust/pull/36894
|
||||
[36917]: https://github.com/rust-lang/rust/pull/36917
|
||||
[36993]: https://github.com/rust-lang/rust/pull/36993
|
||||
[37037]: https://github.com/rust-lang/rust/pull/37037
|
||||
[37064]: https://github.com/rust-lang/rust/pull/37064
|
||||
[37094]: https://github.com/rust-lang/rust/pull/37094
|
||||
[37108]: https://github.com/rust-lang/rust/pull/37108
|
||||
[37111]: https://github.com/rust-lang/rust/pull/37111
|
||||
[37161]: https://github.com/rust-lang/rust/pull/37161
|
||||
[37162]: https://github.com/rust-lang/rust/pull/37162
|
||||
[37167]: https://github.com/rust-lang/rust/pull/37167
|
||||
[37178]: https://github.com/rust-lang/rust/pull/37178
|
||||
[37200]: https://github.com/rust-lang/rust/pull/37200
|
||||
[37213]: https://github.com/rust-lang/rust/pull/37213
|
||||
[37221]: https://github.com/rust-lang/rust/pull/37221
|
||||
[37224]: https://github.com/rust-lang/rust/pull/37224
|
||||
[37230]: https://github.com/rust-lang/rust/pull/37230
|
||||
[37231]: https://github.com/rust-lang/rust/pull/37231
|
||||
[37247]: https://github.com/rust-lang/rust/pull/37247
|
||||
[37267]: https://github.com/rust-lang/rust/pull/37267
|
||||
[37270]: https://github.com/rust-lang/rust/pull/37270
|
||||
[37273]: https://github.com/rust-lang/rust/pull/37273
|
||||
[37280]: https://github.com/rust-lang/rust/pull/37280
|
||||
[37298]: https://github.com/rust-lang/rust/pull/37298
|
||||
[37306]: https://github.com/rust-lang/rust/pull/37306
|
||||
[37310]: https://github.com/rust-lang/rust/pull/37310
|
||||
[37312]: https://github.com/rust-lang/rust/pull/37312
|
||||
[37313]: https://github.com/rust-lang/rust/pull/37313
|
||||
[37315]: https://github.com/rust-lang/rust/pull/37315
|
||||
[37318]: https://github.com/rust-lang/rust/pull/37318
|
||||
[37322]: https://github.com/rust-lang/rust/pull/37322
|
||||
[37326]: https://github.com/rust-lang/rust/pull/37326
|
||||
[37351]: https://github.com/rust-lang/rust/pull/37351
|
||||
[37356]: https://github.com/rust-lang/rust/pull/37356
|
||||
[37367]: https://github.com/rust-lang/rust/pull/37367
|
||||
[37373]: https://github.com/rust-lang/rust/pull/37373
|
||||
[37378]: https://github.com/rust-lang/rust/pull/37378
|
||||
[37389]: https://github.com/rust-lang/rust/pull/37389
|
||||
[37392]: https://github.com/rust-lang/rust/pull/37392
|
||||
[37427]: https://github.com/rust-lang/rust/pull/37427
|
||||
[37439]: https://github.com/rust-lang/rust/pull/37439
|
||||
[37445]: https://github.com/rust-lang/rust/pull/37445
|
||||
[37470]: https://github.com/rust-lang/rust/pull/37470
|
||||
[37569]: https://github.com/rust-lang/rust/pull/37569
|
||||
[RFC 1492]: https://github.com/rust-lang/rfcs/blob/master/text/1492-dotdot-in-patterns.md
|
||||
[cargo/3175]: https://github.com/rust-lang/cargo/pull/3175
|
||||
[cargo/3220]: https://github.com/rust-lang/cargo/pull/3220
|
||||
[cargo/3243]: https://github.com/rust-lang/cargo/pull/3243
|
||||
[cargo/3249]: https://github.com/rust-lang/cargo/pull/3249
|
||||
[cargo/3259]: https://github.com/rust-lang/cargo/pull/3259
|
||||
[cargo/3280]: https://github.com/rust-lang/cargo/pull/3280
|
||||
|
||||
|
||||
Version 1.13.0 (2016-11-10)
|
||||
===========================
|
||||
|
||||
|
|
12
appveyor.yml
12
appveyor.yml
|
@ -1,4 +1,9 @@
|
|||
environment:
|
||||
SCCACHE_BUCKET: rust-lang-ci-sccache
|
||||
AWS_ACCESS_KEY_ID: AKIAIMX7VLAS3PZAVLUQ
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
secure: 1UkmbiDd15tWtYbMm5O2Uqm0b0Ur8v1MoSlydxl4ojcroPeerRMlUges0l57py8c
|
||||
SCCACHE_DIGEST: f808afabb4a4eb1d7112bcb3fa6be03b61e93412890c88e177c667eb37f46353d7ec294e559b16f9f4b5e894f2185fe7670a0df15fd064889ecbd80f0c34166c
|
||||
matrix:
|
||||
# 32/64 bit MSVC
|
||||
- MSYS_BITS: 64
|
||||
|
@ -84,6 +89,13 @@ install:
|
|||
# Otherwise pull in the MinGW installed on appveyor
|
||||
- if NOT defined MINGW_URL set PATH=C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin;%PATH%
|
||||
|
||||
# Download and install sccache
|
||||
- appveyor DownloadFile https://api.pub.build.mozilla.org/tooltool/sha512/%SCCACHE_DIGEST%
|
||||
- mv %SCCACHE_DIGEST% sccache.tar.bz2
|
||||
- 7z x -y sccache.tar.bz2 > nul
|
||||
- 7z x -y sccache.tar > nul
|
||||
- set PATH=%PATH%;%CD%\sccache2
|
||||
|
||||
test_script:
|
||||
- git submodule update --init
|
||||
- set SRC=.
|
||||
|
|
33
configure
vendored
33
configure
vendored
|
@ -621,6 +621,7 @@ opt llvm-assertions 0 "build LLVM with assertions"
|
|||
opt debug-assertions 0 "build with debugging assertions"
|
||||
opt fast-make 0 "use .gitmodules as timestamp for submodule deps"
|
||||
opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
|
||||
opt sccache 0 "invoke gcc/clang via sccache to reuse object files between builds"
|
||||
opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
|
||||
opt local-rebuild 0 "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version"
|
||||
opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
|
||||
|
@ -916,6 +917,18 @@ case $CFG_BUILD in
|
|||
esac
|
||||
putvar CFG_LLDB_PYTHON
|
||||
|
||||
# Do some sanity checks if running on buildbot
|
||||
# (these env vars are set by rust-buildbot)
|
||||
if [ -n "$RUST_DIST_SERVER" -a -n "$ALLOW_NONZERO_RLIMIT_CORE" ]; then
|
||||
# Frequently the llvm submodule directory is broken by the build
|
||||
# being killed
|
||||
llvm_lock="${CFG_SRC_DIR}/.git/modules/src/llvm/index.lock"
|
||||
if [ -e "$llvm_lock" ]; then
|
||||
step_msg "removing $llvm_lock"
|
||||
rm -f "$llvm_lock"
|
||||
fi
|
||||
fi
|
||||
|
||||
step_msg "looking for target specific programs"
|
||||
|
||||
probe CFG_ADB adb
|
||||
|
@ -1677,11 +1690,23 @@ do
|
|||
LLVM_CC_64_ARG1="gcc"
|
||||
;;
|
||||
("gcc")
|
||||
LLVM_CXX_32="g++"
|
||||
LLVM_CC_32="gcc"
|
||||
if [ -z "$CFG_ENABLE_SCCACHE" ]; then
|
||||
LLVM_CXX_32="g++"
|
||||
LLVM_CC_32="gcc"
|
||||
|
||||
LLVM_CXX_64="g++"
|
||||
LLVM_CC_64="gcc"
|
||||
LLVM_CXX_64="g++"
|
||||
LLVM_CC_64="gcc"
|
||||
else
|
||||
LLVM_CXX_32="sccache"
|
||||
LLVM_CC_32="sccache"
|
||||
LLVM_CXX_32_ARG1="g++"
|
||||
LLVM_CC_32_ARG1="gcc"
|
||||
|
||||
LLVM_CXX_64="sccache"
|
||||
LLVM_CC_64="sccache"
|
||||
LLVM_CXX_64_ARG1="g++"
|
||||
LLVM_CC_64_ARG1="gcc"
|
||||
fi
|
||||
;;
|
||||
|
||||
(*)
|
||||
|
|
1
mk/cfg/x86_64-unknown-redox.mk
Normal file
1
mk/cfg/x86_64-unknown-redox.mk
Normal file
|
@ -0,0 +1 @@
|
|||
# rustbuild-only target
|
|
@ -13,7 +13,7 @@
|
|||
######################################################################
|
||||
|
||||
# The version number
|
||||
CFG_RELEASE_NUM=1.15.0
|
||||
CFG_RELEASE_NUM=1.16.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
|
||||
|
|
|
@ -22,7 +22,7 @@ $(eval $(call RUST_CRATE,coretest))
|
|||
DEPS_collectionstest :=
|
||||
$(eval $(call RUST_CRATE,collectionstest))
|
||||
|
||||
TEST_TARGET_CRATES = $(filter-out core rustc_unicode alloc_system libc \
|
||||
TEST_TARGET_CRATES = $(filter-out core std_unicode alloc_system libc \
|
||||
alloc_jemalloc panic_unwind \
|
||||
panic_abort,$(TARGET_CRATES)) \
|
||||
collectionstest coretest
|
||||
|
|
20
src/Cargo.lock
generated
20
src/Cargo.lock
generated
|
@ -19,7 +19,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.0.0",
|
||||
]
|
||||
|
||||
|
@ -42,7 +42,7 @@ dependencies = [
|
|||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -63,7 +63,7 @@ name = "cmake"
|
|||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -80,7 +80,7 @@ name = "compiler_builtins"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -121,7 +121,7 @@ name = "flate"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -130,7 +130,7 @@ version = "0.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.38"
|
||||
version = "0.3.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -402,7 +402,7 @@ name = "rustc_llvm"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_bitflags 0.0.0",
|
||||
]
|
||||
|
||||
|
@ -551,7 +551,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"arena 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.0.0",
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
|
@ -587,7 +587,7 @@ dependencies = [
|
|||
"collections 0.0.0",
|
||||
"compiler_builtins 0.0.0",
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.0.0",
|
||||
"panic_abort 0.0.0",
|
||||
"panic_unwind 0.0.0",
|
||||
|
@ -677,7 +677,7 @@ dependencies = [
|
|||
"checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283"
|
||||
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
|
||||
"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
|
||||
"checksum gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5"
|
||||
"checksum gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950"
|
||||
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
|
||||
"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
|
||||
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
|
||||
|
|
|
@ -22,7 +22,7 @@ Note that if you're on Unix you should be able to execute the script directly:
|
|||
./x.py build
|
||||
```
|
||||
|
||||
The script accepts commands, flags, and filters to determine what to do:
|
||||
The script accepts commands, flags, and arguments to determine what to do:
|
||||
|
||||
* `build` - a general purpose command for compiling code. Alone `build` will
|
||||
bootstrap the entire compiler, and otherwise arguments passed indicate what to
|
||||
|
@ -42,6 +42,15 @@ The script accepts commands, flags, and filters to determine what to do:
|
|||
./x.py build --stage 0 src/libtest
|
||||
```
|
||||
|
||||
If files are dirty that would normally be rebuilt from stage 0, that can be
|
||||
overidden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps
|
||||
that belong to stage n or earlier:
|
||||
|
||||
```
|
||||
# keep old build products for stage 0 and build stage 1
|
||||
./x.py build --keep-stage 0 --stage 1
|
||||
```
|
||||
|
||||
* `test` - a command for executing unit tests. Like the `build` command this
|
||||
will execute the entire test suite by default, and otherwise it can be used to
|
||||
select which test suite is run:
|
||||
|
@ -54,7 +63,7 @@ The script accepts commands, flags, and filters to determine what to do:
|
|||
./x.py test src/test/run-pass
|
||||
|
||||
# execute only some tests in the run-pass test suite
|
||||
./x.py test src/test/run-pass --filter my-filter
|
||||
./x.py test src/test/run-pass --test-args substring-of-test-name
|
||||
|
||||
# execute tests in the standard library in stage0
|
||||
./x.py test --stage 0 src/libstd
|
||||
|
@ -107,6 +116,42 @@ compiler. What actually happens when you invoke rustbuild is:
|
|||
The goal of each stage is to (a) leverage Cargo as much as possible and failing
|
||||
that (b) leverage Rust as much as possible!
|
||||
|
||||
## Incremental builds
|
||||
|
||||
You can configure rustbuild to use incremental compilation. Because
|
||||
incremental is new and evolving rapidly, if you want to use it, it is
|
||||
recommended that you replace the snapshot with a locally installed
|
||||
nightly build of rustc. You will want to keep this up to date.
|
||||
|
||||
To follow this course of action, first thing you will want to do is to
|
||||
install a nightly, presumably using `rustup`. You will then want to
|
||||
configure your directory to use this build, like so:
|
||||
|
||||
```
|
||||
# configure to use local rust instead of downloding a beta.
|
||||
# `--local-rust-root` is optional here. If elided, we will
|
||||
# use whatever rustc we find on your PATH.
|
||||
> configure --enable-rustbuild --local-rust-root=~/.cargo/ --enable-local-rebuild
|
||||
```
|
||||
|
||||
After that, you can use the `--incremental` flag to actually do
|
||||
incremental builds:
|
||||
|
||||
```
|
||||
> ../x.py build --incremental
|
||||
```
|
||||
|
||||
The `--incremental` flag will store incremental compilation artifacts
|
||||
in `build/<host>/stage0-incremental`. Note that we only use incremental
|
||||
compilation for the stage0 -> stage1 compilation -- this is because
|
||||
the stage1 compiler is changing, and we don't try to cache and reuse
|
||||
incremental artifacts across different versions of the compiler. For
|
||||
this reason, `--incremental` defaults to `--stage 1` (though you can
|
||||
manually select a higher stage, if you prefer).
|
||||
|
||||
You can always drop the `--incremental` to build as normal (but you
|
||||
will still be using the local nightly as your bootstrap).
|
||||
|
||||
## Directory Layout
|
||||
|
||||
This build system houses all output under the `build` directory, which looks
|
||||
|
|
|
@ -25,12 +25,17 @@
|
|||
//! switching compilers for the bootstrap and for build scripts will probably
|
||||
//! never get replaced.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate bootstrap;
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::str::FromStr;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::process::{Command, ExitStatus};
|
||||
|
||||
fn main() {
|
||||
let args = env::args_os().skip(1).collect::<Vec<_>>();
|
||||
|
@ -41,6 +46,11 @@ fn main() {
|
|||
.and_then(|w| w[1].to_str());
|
||||
let version = args.iter().find(|w| &**w == "-vV");
|
||||
|
||||
let verbose = match env::var("RUSTC_VERBOSE") {
|
||||
Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
|
||||
Err(_) => 0,
|
||||
};
|
||||
|
||||
// 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
|
||||
|
@ -95,6 +105,15 @@ fn main() {
|
|||
cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
// Pass down incremental directory, if any.
|
||||
if let Ok(dir) = env::var("RUSTC_INCREMENTAL") {
|
||||
cmd.arg(format!("-Zincremental={}", dir));
|
||||
|
||||
if verbose > 0 {
|
||||
cmd.arg("-Zincremental-info");
|
||||
}
|
||||
}
|
||||
|
||||
// If we're compiling specifically the `panic_abort` crate then we pass
|
||||
// the `-C panic=abort` option. Note that we do not do this for any
|
||||
// other crate intentionally as this is the only crate for now that we
|
||||
|
@ -158,6 +177,15 @@ fn main() {
|
|||
// to change a flag in a binary?
|
||||
if env::var("RUSTC_RPATH") == Ok("true".to_string()) {
|
||||
let rpath = if target.contains("apple") {
|
||||
|
||||
// Note that we need to take one extra step on OSX to also pass
|
||||
// `-Wl,-instal_name,@rpath/...` to get things to work right. To
|
||||
// do that we pass a weird flag to the compiler to get it to do
|
||||
// so. Note that this is definitely a hack, and we should likely
|
||||
// flesh out rpath support more fully in the future.
|
||||
if stage != "0" {
|
||||
cmd.arg("-Z").arg("osx-rpath-install-name");
|
||||
}
|
||||
Some("-Wl,-rpath,@loader_path/../lib")
|
||||
} else if !target.contains("windows") {
|
||||
Some("-Wl,-rpath,$ORIGIN/../lib")
|
||||
|
@ -167,12 +195,33 @@ fn main() {
|
|||
if let Some(rpath) = rpath {
|
||||
cmd.arg("-C").arg(format!("link-args={}", rpath));
|
||||
}
|
||||
|
||||
if let Ok(s) = env::var("RUSTFLAGS") {
|
||||
for flag in s.split_whitespace() {
|
||||
cmd.arg(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if verbose > 1 {
|
||||
writeln!(&mut io::stderr(), "rustc command: {:?}", cmd).unwrap();
|
||||
}
|
||||
|
||||
// Actually run the compiler!
|
||||
std::process::exit(match cmd.status() {
|
||||
Ok(s) => s.code().unwrap_or(1),
|
||||
std::process::exit(match exec_cmd(&mut cmd) {
|
||||
Ok(s) => s.code().unwrap_or(0xfe),
|
||||
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn exec_cmd(cmd: &mut Command) -> ::std::io::Result<ExitStatus> {
|
||||
use std::os::unix::process::CommandExt;
|
||||
Err(cmd.exec())
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn exec_cmd(cmd: &mut Command) -> ::std::io::Result<ExitStatus> {
|
||||
cmd.status()
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
//!
|
||||
//! See comments in `src/bootstrap/rustc.rs` for more information.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate bootstrap;
|
||||
|
||||
use std::env;
|
||||
|
|
|
@ -81,7 +81,7 @@ def verify(path, sha_path, verbose):
|
|||
with open(path, "rb") as f:
|
||||
found = hashlib.sha256(f.read()).hexdigest()
|
||||
with open(sha_path, "r") as f:
|
||||
expected, _ = f.readline().split()
|
||||
expected = f.readline().split()[0]
|
||||
verified = found == expected
|
||||
if not verified:
|
||||
print("invalid checksum:\n"
|
||||
|
@ -146,7 +146,7 @@ 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())
|
||||
cargo_cache = os.path.join(cache_dst, self.stage0_cargo_date())
|
||||
cargo_cache = os.path.join(cache_dst, self.stage0_cargo_rev())
|
||||
if not os.path.exists(rustc_cache):
|
||||
os.makedirs(rustc_cache)
|
||||
if not os.path.exists(cargo_cache):
|
||||
|
@ -179,21 +179,17 @@ class RustBuild(object):
|
|||
if self.cargo().startswith(self.bin_root()) and \
|
||||
(not os.path.exists(self.cargo()) or self.cargo_out_of_date()):
|
||||
self.print_what_it_means_to_bootstrap()
|
||||
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()
|
||||
filename = "cargo-nightly-{}.tar.gz".format(self.build)
|
||||
url = "https://s3.amazonaws.com/rust-lang-ci/cargo-builds/" + self.stage0_cargo_rev()
|
||||
tarball = os.path.join(cargo_cache, filename)
|
||||
if not os.path.exists(tarball):
|
||||
get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
|
||||
unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose)
|
||||
with open(self.cargo_stamp(), 'w') as f:
|
||||
f.write(self.stage0_cargo_date())
|
||||
f.write(self.stage0_cargo_rev())
|
||||
|
||||
def stage0_cargo_date(self):
|
||||
return self._cargo_date
|
||||
|
||||
def stage0_cargo_channel(self):
|
||||
return self._cargo_channel
|
||||
def stage0_cargo_rev(self):
|
||||
return self._cargo_rev
|
||||
|
||||
def stage0_rustc_date(self):
|
||||
return self._rustc_date
|
||||
|
@ -217,7 +213,7 @@ class RustBuild(object):
|
|||
if not os.path.exists(self.cargo_stamp()) or self.clean:
|
||||
return True
|
||||
with open(self.cargo_stamp(), 'r') as f:
|
||||
return self.stage0_cargo_date() != f.read()
|
||||
return self.stage0_cargo_rev() != f.read()
|
||||
|
||||
def bin_root(self):
|
||||
return os.path.join(self.build_dir, self.build, "stage0")
|
||||
|
@ -294,6 +290,8 @@ class RustBuild(object):
|
|||
env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib")
|
||||
env["PATH"] = os.path.join(self.bin_root(), "bin") + \
|
||||
os.pathsep + env["PATH"]
|
||||
if not os.path.isfile(self.cargo()):
|
||||
raise Exception("no cargo executable found at `%s`" % self.cargo())
|
||||
args = [self.cargo(), "build", "--manifest-path",
|
||||
os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")]
|
||||
if self.use_vendored_sources:
|
||||
|
@ -467,7 +465,7 @@ def main():
|
|||
|
||||
data = stage0_data(rb.rust_root)
|
||||
rb._rustc_channel, rb._rustc_date = data['rustc'].split('-', 1)
|
||||
rb._cargo_channel, rb._cargo_date = data['cargo'].split('-', 1)
|
||||
rb._cargo_rev = data['cargo']
|
||||
|
||||
start_time = time()
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
//! `package_vers`, and otherwise indicating to the compiler what it should
|
||||
//! print out as part of its version information.
|
||||
|
||||
use std::fs::{self, File};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::process::Command;
|
||||
|
||||
|
@ -69,7 +69,7 @@ pub fn collect(build: &mut Build) {
|
|||
|
||||
// If we have a git directory, add in some various SHA information of what
|
||||
// commit this compiler was compiled from.
|
||||
if fs::metadata(build.src.join(".git")).is_ok() {
|
||||
if build.src.join(".git").is_dir() {
|
||||
let ver_date = output(Command::new("git").current_dir(&build.src)
|
||||
.arg("log").arg("-1")
|
||||
.arg("--date=short")
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
//! This file implements the various regression test suites that we execute on
|
||||
//! our CI.
|
||||
|
||||
extern crate build_helper;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
|
@ -190,7 +192,7 @@ pub fn compiletest(build: &Build,
|
|||
|
||||
cmd.args(&build.flags.cmd.test_args());
|
||||
|
||||
if build.config.verbose || build.flags.verbose {
|
||||
if build.config.verbose() || build.flags.verbose() {
|
||||
cmd.arg("--verbose");
|
||||
}
|
||||
|
||||
|
@ -299,6 +301,7 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
|
|||
build.add_rust_test_threads(&mut cmd);
|
||||
cmd.arg("--test");
|
||||
cmd.arg(markdown);
|
||||
cmd.env("RUSTC_BOOTSTRAP", "1");
|
||||
|
||||
let mut test_args = build.flags.cmd.test_args().join(" ");
|
||||
if build.config.quiet_tests {
|
||||
|
@ -542,7 +545,7 @@ pub fn distcheck(build: &Build) {
|
|||
build.run(&mut cmd);
|
||||
build.run(Command::new("./configure")
|
||||
.current_dir(&dir));
|
||||
build.run(Command::new("make")
|
||||
build.run(Command::new(build_helper::make(&build.config.build))
|
||||
.arg("check")
|
||||
.current_dir(&dir));
|
||||
}
|
||||
|
|
|
@ -38,9 +38,9 @@ use util::push_exe_path;
|
|||
/// `src/bootstrap/config.toml.example`.
|
||||
#[derive(Default)]
|
||||
pub struct Config {
|
||||
pub ccache: bool,
|
||||
pub ccache: Option<String>,
|
||||
pub ninja: bool,
|
||||
pub verbose: bool,
|
||||
pub verbose: usize,
|
||||
pub submodules: bool,
|
||||
pub compiler_docs: bool,
|
||||
pub docs: bool,
|
||||
|
@ -113,6 +113,7 @@ pub struct Target {
|
|||
#[derive(RustcDecodable, Default)]
|
||||
struct TomlConfig {
|
||||
build: Option<Build>,
|
||||
install: Option<Install>,
|
||||
llvm: Option<Llvm>,
|
||||
rust: Option<Rust>,
|
||||
target: Option<HashMap<String, TomlTarget>>,
|
||||
|
@ -135,10 +136,16 @@ struct Build {
|
|||
python: Option<String>,
|
||||
}
|
||||
|
||||
/// TOML representation of various global install decisions.
|
||||
#[derive(RustcDecodable, Default, Clone)]
|
||||
struct Install {
|
||||
prefix: Option<String>,
|
||||
}
|
||||
|
||||
/// TOML representation of how the LLVM build is configured.
|
||||
#[derive(RustcDecodable, Default)]
|
||||
struct Llvm {
|
||||
ccache: Option<bool>,
|
||||
ccache: Option<StringOrBool>,
|
||||
ninja: Option<bool>,
|
||||
assertions: Option<bool>,
|
||||
optimize: Option<bool>,
|
||||
|
@ -147,6 +154,18 @@ struct Llvm {
|
|||
static_libstdcpp: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(RustcDecodable)]
|
||||
enum StringOrBool {
|
||||
String(String),
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
impl Default for StringOrBool {
|
||||
fn default() -> StringOrBool {
|
||||
StringOrBool::Bool(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// TOML representation of how the Rust build is configured.
|
||||
#[derive(RustcDecodable, Default)]
|
||||
struct Rust {
|
||||
|
@ -246,8 +265,20 @@ impl Config {
|
|||
set(&mut config.submodules, build.submodules);
|
||||
set(&mut config.vendor, build.vendor);
|
||||
|
||||
if let Some(ref install) = toml.install {
|
||||
config.prefix = install.prefix.clone();
|
||||
}
|
||||
|
||||
if let Some(ref llvm) = toml.llvm {
|
||||
set(&mut config.ccache, llvm.ccache);
|
||||
match llvm.ccache {
|
||||
Some(StringOrBool::String(ref s)) => {
|
||||
config.ccache = Some(s.to_string())
|
||||
}
|
||||
Some(StringOrBool::Bool(true)) => {
|
||||
config.ccache = Some("ccache".to_string());
|
||||
}
|
||||
Some(StringOrBool::Bool(false)) | None => {}
|
||||
}
|
||||
set(&mut config.ninja, llvm.ninja);
|
||||
set(&mut config.llvm_assertions, llvm.assertions);
|
||||
set(&mut config.llvm_optimize, llvm.optimize);
|
||||
|
@ -255,6 +286,7 @@ impl Config {
|
|||
set(&mut config.llvm_version_check, llvm.version_check);
|
||||
set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
|
||||
}
|
||||
|
||||
if let Some(ref rust) = toml.rust {
|
||||
set(&mut config.rust_debug_assertions, rust.debug_assertions);
|
||||
set(&mut config.rust_debuginfo, rust.debuginfo);
|
||||
|
@ -338,7 +370,6 @@ impl Config {
|
|||
}
|
||||
|
||||
check! {
|
||||
("CCACHE", self.ccache),
|
||||
("MANAGE_SUBMODULES", self.submodules),
|
||||
("COMPILER_DOCS", self.compiler_docs),
|
||||
("DOCS", self.docs),
|
||||
|
@ -475,10 +506,24 @@ impl Config {
|
|||
let path = parse_configure_path(value);
|
||||
self.python = Some(path);
|
||||
}
|
||||
"CFG_ENABLE_CCACHE" if value == "1" => {
|
||||
self.ccache = Some("ccache".to_string());
|
||||
}
|
||||
"CFG_ENABLE_SCCACHE" if value == "1" => {
|
||||
self.ccache = Some("sccache".to_string());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verbose(&self) -> bool {
|
||||
self.verbose > 0
|
||||
}
|
||||
|
||||
pub fn very_verbose(&self) -> bool {
|
||||
self.verbose > 1
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
# Indicates whether ccache is used when building LLVM
|
||||
#ccache = false
|
||||
# or alternatively ...
|
||||
#ccache = "/path/to/ccache"
|
||||
|
||||
# If an external LLVM root is specified, we automatically check the version by
|
||||
# default to make sure it's within the range that we're expecting, but setting
|
||||
|
@ -98,6 +100,14 @@
|
|||
# Indicate whether the vendored sources are used for Rust dependencies or not
|
||||
#vendor = false
|
||||
|
||||
# =============================================================================
|
||||
# General install configuration options
|
||||
# =============================================================================
|
||||
[install]
|
||||
|
||||
# Instead of installing to /usr/local, install to this path instead.
|
||||
#prefix = "/path/to/install"
|
||||
|
||||
# =============================================================================
|
||||
# Options for compiling Rust code itself
|
||||
# =============================================================================
|
||||
|
|
|
@ -48,6 +48,11 @@ pub fn tmpdir(build: &Build) -> PathBuf {
|
|||
/// Slurps up documentation from the `stage`'s `host`.
|
||||
pub fn docs(build: &Build, stage: u32, host: &str) {
|
||||
println!("Dist docs stage{} ({})", stage, host);
|
||||
if !build.config.docs {
|
||||
println!("\tskipping - docs disabled");
|
||||
return
|
||||
}
|
||||
|
||||
let name = format!("rust-docs-{}", package_vers(build));
|
||||
let image = tmpdir(build).join(format!("{}-{}-image", name, name));
|
||||
let _ = fs::remove_dir_all(&image);
|
||||
|
@ -92,6 +97,7 @@ pub fn mingw(build: &Build, host: &str) {
|
|||
let name = format!("rust-mingw-{}", package_vers(build));
|
||||
let image = tmpdir(build).join(format!("{}-{}-image", name, host));
|
||||
let _ = fs::remove_dir_all(&image);
|
||||
t!(fs::create_dir_all(&image));
|
||||
|
||||
// The first argument to the script is a "temporary directory" which is just
|
||||
// thrown away (this contains the runtime DLLs included in the rustc package
|
||||
|
@ -260,6 +266,14 @@ pub fn debugger_scripts(build: &Build,
|
|||
pub fn std(build: &Build, compiler: &Compiler, target: &str) {
|
||||
println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host,
|
||||
target);
|
||||
|
||||
// The only true set of target libraries came from the build triple, so
|
||||
// let's reduce redundant work by only producing archives from that host.
|
||||
if compiler.host != build.config.build {
|
||||
println!("\tskipping, not a build host");
|
||||
return
|
||||
}
|
||||
|
||||
let name = format!("rust-std-{}", package_vers(build));
|
||||
let image = tmpdir(build).join(format!("{}-{}-image", name, target));
|
||||
let _ = fs::remove_dir_all(&image);
|
||||
|
@ -294,10 +308,15 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
|
|||
println!("Dist analysis");
|
||||
|
||||
if build.config.channel != "nightly" {
|
||||
println!("Skipping dist-analysis - not on nightly channel");
|
||||
println!("\tskipping - not on nightly channel");
|
||||
return;
|
||||
}
|
||||
if compiler.host != build.config.build {
|
||||
println!("\tskipping - not a build host");
|
||||
return
|
||||
}
|
||||
if compiler.stage != 2 {
|
||||
println!("\tskipping - not stage2");
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -324,18 +343,17 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
|
|||
.arg("--legacy-manifest-dirs=rustlib,cargo");
|
||||
build.run(&mut cmd);
|
||||
t!(fs::remove_dir_all(&image));
|
||||
|
||||
// Create plain source tarball
|
||||
let mut cmd = Command::new("tar");
|
||||
cmd.arg("-czf").arg(sanitize_sh(&distdir(build).join(&format!("{}.tar.gz", name))))
|
||||
.arg("analysis")
|
||||
.current_dir(&src);
|
||||
build.run(&mut cmd);
|
||||
}
|
||||
|
||||
/// Creates the `rust-src` installer component and the plain source tarball
|
||||
pub fn rust_src(build: &Build) {
|
||||
pub fn rust_src(build: &Build, host: &str) {
|
||||
println!("Dist src");
|
||||
|
||||
if host != build.config.build {
|
||||
println!("\tskipping, not a build host");
|
||||
return
|
||||
}
|
||||
|
||||
let plain_name = format!("rustc-{}-src", package_vers(build));
|
||||
let name = format!("rust-src-{}", package_vers(build));
|
||||
let image = tmpdir(build).join(format!("{}-image", name));
|
||||
|
|
|
@ -27,8 +27,9 @@ use step;
|
|||
|
||||
/// Deserialized version of all flags for this compile.
|
||||
pub struct Flags {
|
||||
pub verbose: bool,
|
||||
pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
|
||||
pub stage: Option<u32>,
|
||||
pub keep_stage: Option<u32>,
|
||||
pub build: String,
|
||||
pub host: Vec<String>,
|
||||
pub target: Vec<String>,
|
||||
|
@ -36,6 +37,17 @@ pub struct Flags {
|
|||
pub src: Option<PathBuf>,
|
||||
pub jobs: Option<u32>,
|
||||
pub cmd: Subcommand,
|
||||
pub incremental: bool,
|
||||
}
|
||||
|
||||
impl Flags {
|
||||
pub fn verbose(&self) -> bool {
|
||||
self.verbose > 0
|
||||
}
|
||||
|
||||
pub fn very_verbose(&self) -> bool {
|
||||
self.verbose > 1
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Subcommand {
|
||||
|
@ -62,12 +74,14 @@ pub enum Subcommand {
|
|||
impl Flags {
|
||||
pub fn parse(args: &[String]) -> Flags {
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("v", "verbose", "use verbose output");
|
||||
opts.optflagmulti("v", "verbose", "use verbose output (-vv for very verbose)");
|
||||
opts.optflag("i", "incremental", "use incremental compilation");
|
||||
opts.optopt("", "config", "TOML configuration file for build", "FILE");
|
||||
opts.optopt("", "build", "build target of the stage0 compiler", "BUILD");
|
||||
opts.optmulti("", "host", "host targets to build", "HOST");
|
||||
opts.optmulti("", "target", "target targets to build", "TARGET");
|
||||
opts.optopt("", "stage", "stage to build", "N");
|
||||
opts.optopt("", "keep-stage", "stage to keep without recompiling", "N");
|
||||
opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
|
||||
opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
|
||||
opts.optflag("h", "help", "print this help message");
|
||||
|
@ -108,7 +122,6 @@ Arguments:
|
|||
tests that should be compiled and run. For example:
|
||||
|
||||
./x.py test src/test/run-pass
|
||||
./x.py test src/test/run-pass/assert-*
|
||||
./x.py test src/libstd --test-args hash_map
|
||||
./x.py test src/libstd --stage 0
|
||||
|
||||
|
@ -255,9 +268,20 @@ To learn more about a subcommand, run `./x.py <command> -h`
|
|||
}
|
||||
});
|
||||
|
||||
let mut stage = m.opt_str("stage").map(|j| j.parse().unwrap());
|
||||
|
||||
let incremental = m.opt_present("i");
|
||||
|
||||
if incremental {
|
||||
if stage.is_none() {
|
||||
stage = Some(1);
|
||||
}
|
||||
}
|
||||
|
||||
Flags {
|
||||
verbose: m.opt_present("v"),
|
||||
stage: m.opt_str("stage").map(|j| j.parse().unwrap()),
|
||||
verbose: m.opt_count("v"),
|
||||
stage: stage,
|
||||
keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()),
|
||||
build: m.opt_str("build").unwrap_or_else(|| {
|
||||
env::var("BUILD").unwrap()
|
||||
}),
|
||||
|
@ -267,6 +291,7 @@ To learn more about a subcommand, run `./x.py <command> -h`
|
|||
src: m.opt_str("src").map(PathBuf::from),
|
||||
jobs: m.opt_str("jobs").map(|j| j.parse().unwrap()),
|
||||
cmd: cmd,
|
||||
incremental: incremental,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,8 @@
|
|||
//! More documentation can be found in each respective module below, and you can
|
||||
//! also check out the `src/bootstrap/README.md` file for more information.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate build_helper;
|
||||
extern crate cmake;
|
||||
extern crate filetime;
|
||||
|
@ -74,6 +76,7 @@ extern crate rustc_serialize;
|
|||
extern crate toml;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::cmp;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::{self, File};
|
||||
|
@ -497,6 +500,17 @@ impl Build {
|
|||
cargo.env("RUSTC_BOOTSTRAP", "1");
|
||||
self.add_rust_test_threads(&mut cargo);
|
||||
|
||||
// Ignore incremental modes except for stage0, since we're
|
||||
// not guaranteeing correctness acros builds if the compiler
|
||||
// is changing under your feet.`
|
||||
if self.flags.incremental && compiler.stage == 0 {
|
||||
let incr_dir = self.incremental_dir(compiler);
|
||||
cargo.env("RUSTC_INCREMENTAL", incr_dir);
|
||||
}
|
||||
|
||||
let verbose = cmp::max(self.config.verbose, self.flags.verbose);
|
||||
cargo.env("RUSTC_VERBOSE", format!("{}", verbose));
|
||||
|
||||
// Specify some various options for build scripts used throughout
|
||||
// the build.
|
||||
//
|
||||
|
@ -516,7 +530,7 @@ impl Build {
|
|||
// FIXME: should update code to not require this env var
|
||||
cargo.env("CFG_COMPILER_HOST_TRIPLE", target);
|
||||
|
||||
if self.config.verbose || self.flags.verbose {
|
||||
if self.config.verbose() || self.flags.verbose() {
|
||||
cargo.arg("-v");
|
||||
}
|
||||
// FIXME: cargo bench does not accept `--release`
|
||||
|
@ -630,6 +644,12 @@ impl Build {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the directory for incremental by-products when using the
|
||||
/// given compiler.
|
||||
fn incremental_dir(&self, compiler: &Compiler) -> PathBuf {
|
||||
self.out.join(compiler.host).join(format!("stage{}-incremental", compiler.stage))
|
||||
}
|
||||
|
||||
/// Returns the libdir where the standard library and other artifacts are
|
||||
/// found for a compiler's sysroot.
|
||||
fn sysroot_libdir(&self, compiler: &Compiler, target: &str) -> PathBuf {
|
||||
|
@ -703,7 +723,8 @@ impl Build {
|
|||
fn llvm_filecheck(&self, target: &str) -> PathBuf {
|
||||
let target_config = self.config.target_config.get(target);
|
||||
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
|
||||
s.parent().unwrap().join(exe("FileCheck", target))
|
||||
let llvm_bindir = output(Command::new(s).arg("--bindir"));
|
||||
Path::new(llvm_bindir.trim()).join(exe("FileCheck", target))
|
||||
} else {
|
||||
let base = self.llvm_out(&self.config.build).join("build");
|
||||
let exe = exe("FileCheck", target);
|
||||
|
@ -768,7 +789,7 @@ impl Build {
|
|||
|
||||
/// Prints a message if this build is configured in verbose mode.
|
||||
fn verbose(&self, msg: &str) {
|
||||
if self.flags.verbose || self.config.verbose {
|
||||
if self.flags.verbose() || self.config.verbose() {
|
||||
println!("{}", msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,8 @@ check-cargotest:
|
|||
dist:
|
||||
$(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
|
||||
distcheck:
|
||||
$(Q)$(BOOTSTRAP) test distcheck
|
||||
$(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
|
||||
$(Q)$(BOOTSTRAP) test distcheck $(BOOTSTRAP_ARGS)
|
||||
install:
|
||||
$(Q)$(BOOTSTRAP) dist --install $(BOOTSTRAP_ARGS)
|
||||
tidy:
|
||||
|
@ -65,7 +66,7 @@ tidy:
|
|||
check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu:
|
||||
$(Q)$(BOOTSTRAP) test --target arm-linux-androideabi
|
||||
check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu:
|
||||
$(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-gnu
|
||||
$(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-musl
|
||||
|
||||
|
||||
.PHONY: dist
|
||||
|
|
|
@ -81,7 +81,7 @@ pub fn llvm(build: &Build, target: &str) {
|
|||
.profile(profile)
|
||||
.define("LLVM_ENABLE_ASSERTIONS", assertions)
|
||||
.define("LLVM_TARGETS_TO_BUILD",
|
||||
"X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430")
|
||||
"X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc")
|
||||
.define("LLVM_INCLUDE_EXAMPLES", "OFF")
|
||||
.define("LLVM_INCLUDE_TESTS", "OFF")
|
||||
.define("LLVM_INCLUDE_DOCS", "OFF")
|
||||
|
@ -109,10 +109,10 @@ pub fn llvm(build: &Build, target: &str) {
|
|||
|
||||
// MSVC handles compiler business itself
|
||||
if !target.contains("msvc") {
|
||||
if build.config.ccache {
|
||||
cfg.define("CMAKE_C_COMPILER", "ccache")
|
||||
if let Some(ref ccache) = build.config.ccache {
|
||||
cfg.define("CMAKE_C_COMPILER", ccache)
|
||||
.define("CMAKE_C_COMPILER_ARG1", build.cc(target))
|
||||
.define("CMAKE_CXX_COMPILER", "ccache")
|
||||
.define("CMAKE_CXX_COMPILER", ccache)
|
||||
.define("CMAKE_CXX_COMPILER_ARG1", build.cxx(target));
|
||||
} else {
|
||||
cfg.define("CMAKE_C_COMPILER", build.cc(target))
|
||||
|
|
|
@ -143,7 +143,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() && build.config.codegen_tests {
|
||||
panic!("filecheck executable {:?} does not exist", filecheck);
|
||||
panic!("FileCheck executable {:?} does not exist", filecheck);
|
||||
}
|
||||
|
||||
for target in build.config.target.iter() {
|
||||
|
@ -223,4 +223,8 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
|
|||
if build.lldb_version.is_some() {
|
||||
build.lldb_python_dir = run(Command::new("lldb").arg("-P")).ok();
|
||||
}
|
||||
|
||||
if let Some(ref s) = build.config.ccache {
|
||||
need_cmd(s.as_ref());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
//
|
||||
// To handle this we do a bit of dynamic dispatch to see what the dependency
|
||||
// is. If we're building a LLVM for the build triple, then we don't actually
|
||||
// have any dependencies! To do that we return a dependency on the "dummy"
|
||||
// have any dependencies! To do that we return a dependency on the `Step::noop()`
|
||||
// target which does nothing.
|
||||
//
|
||||
// If we're build a cross-compiled LLVM, however, we need to assemble the
|
||||
|
@ -104,7 +104,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
.host(true)
|
||||
.dep(move |s| {
|
||||
if s.target == build.config.build {
|
||||
dummy(s, build)
|
||||
Step::noop()
|
||||
} else {
|
||||
s.target(&build.config.build)
|
||||
}
|
||||
|
@ -115,14 +115,11 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
// going on here. You can check out the API docs below and also see a bunch
|
||||
// more examples of rules directly below as well.
|
||||
|
||||
// dummy rule to do nothing, useful when a dep maps to no deps
|
||||
rules.build("dummy", "path/to/nowhere");
|
||||
|
||||
// the compiler with no target libraries ready to go
|
||||
rules.build("rustc", "src/rustc")
|
||||
.dep(move |s| {
|
||||
if s.stage == 0 {
|
||||
dummy(s, build)
|
||||
Step::noop()
|
||||
} else {
|
||||
s.name("librustc")
|
||||
.host(&build.config.build)
|
||||
|
@ -165,7 +162,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
.dep(move |s| s.name("rustc").host(&build.config.build).target(s.host))
|
||||
.dep(move |s| {
|
||||
if s.host == build.config.build {
|
||||
dummy(s, build)
|
||||
Step::noop()
|
||||
} else {
|
||||
s.host(&build.config.build)
|
||||
}
|
||||
|
@ -183,7 +180,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
.dep(|s| s.name("libstd"))
|
||||
.dep(move |s| {
|
||||
if s.host == build.config.build {
|
||||
dummy(s, build)
|
||||
Step::noop()
|
||||
} else {
|
||||
s.host(&build.config.build)
|
||||
}
|
||||
|
@ -203,7 +200,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
.dep(move |s| s.name("llvm").host(&build.config.build).stage(0))
|
||||
.dep(move |s| {
|
||||
if s.host == build.config.build {
|
||||
dummy(s, build)
|
||||
Step::noop()
|
||||
} else {
|
||||
s.host(&build.config.build)
|
||||
}
|
||||
|
@ -233,7 +230,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
if s.target.contains("android") {
|
||||
s.name("android-copy-libs")
|
||||
} else {
|
||||
dummy(s, build)
|
||||
Step::noop()
|
||||
}
|
||||
})
|
||||
.default(true)
|
||||
|
@ -270,16 +267,18 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
// nothing to do for debuginfo tests
|
||||
} else if build.config.build.contains("apple") {
|
||||
rules.test("check-debuginfo", "src/test/debuginfo")
|
||||
.default(true)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("tool-compiletest").host(s.host))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host))
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(|s| s.name("debugger-scripts"))
|
||||
.run(move |s| check::compiletest(build, &s.compiler(), s.target,
|
||||
"debuginfo-lldb", "debuginfo"));
|
||||
} else {
|
||||
rules.test("check-debuginfo", "src/test/debuginfo")
|
||||
.default(true)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("tool-compiletest").host(s.host))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host))
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(|s| s.name("debugger-scripts"))
|
||||
.run(move |s| check::compiletest(build, &s.compiler(), s.target,
|
||||
|
@ -458,7 +457,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
for (krate, path, default) in krates("test_shim") {
|
||||
rules.doc(&krate.doc_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.default(default && build.config.docs)
|
||||
.default(default && build.config.compiler_docs)
|
||||
.run(move |s| doc::test(build, s.stage, s.target));
|
||||
}
|
||||
for (krate, path, default) in krates("rustc-main") {
|
||||
|
@ -490,16 +489,21 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
.default(true)
|
||||
.run(move |s| dist::std(build, &s.compiler(), s.target));
|
||||
rules.dist("dist-mingw", "path/to/nowhere")
|
||||
.run(move |s| dist::mingw(build, s.target));
|
||||
.default(true)
|
||||
.run(move |s| {
|
||||
if s.target.contains("pc-windows-gnu") {
|
||||
dist::mingw(build, s.target)
|
||||
}
|
||||
});
|
||||
rules.dist("dist-src", "src")
|
||||
.default(true)
|
||||
.host(true)
|
||||
.run(move |_| dist::rust_src(build));
|
||||
.run(move |s| dist::rust_src(build, s.target));
|
||||
rules.dist("dist-docs", "src/doc")
|
||||
.default(true)
|
||||
.dep(|s| s.name("default:doc"))
|
||||
.run(move |s| dist::docs(build, s.stage, s.target));
|
||||
rules.dist("dist-analysis", "src/libstd")
|
||||
rules.dist("dist-analysis", "analysis")
|
||||
.dep(|s| s.name("dist-std"))
|
||||
.default(true)
|
||||
.run(move |s| dist::analysis(build, &s.compiler(), s.target));
|
||||
|
@ -509,12 +513,6 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
|
||||
rules.verify();
|
||||
return rules;
|
||||
|
||||
fn dummy<'a>(s: &Step<'a>, build: &'a Build) -> Step<'a> {
|
||||
s.name("dummy").stage(0)
|
||||
.target(&build.config.build)
|
||||
.host(&build.config.build)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||
|
@ -538,6 +536,10 @@ struct Step<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Step<'a> {
|
||||
fn noop() -> Step<'a> {
|
||||
Step { name: "", stage: 0, host: "", target: "" }
|
||||
}
|
||||
|
||||
/// Creates a new step which is the same as this, except has a new name.
|
||||
fn name(&self, name: &'a str) -> Step<'a> {
|
||||
Step { name: name, ..*self }
|
||||
|
@ -733,6 +735,9 @@ impl<'a> Rules<'a> {
|
|||
if self.rules.contains_key(&dep.name) || dep.name.starts_with("default:") {
|
||||
continue
|
||||
}
|
||||
if dep == Step::noop() {
|
||||
continue
|
||||
}
|
||||
panic!("\
|
||||
|
||||
invalid rule dependency graph detected, was a rule added and maybe typo'd?
|
||||
|
@ -817,7 +822,16 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
|
|||
let hosts = if self.build.flags.host.len() > 0 {
|
||||
&self.build.flags.host
|
||||
} else {
|
||||
&self.build.config.host
|
||||
if kind == Kind::Dist {
|
||||
// For 'dist' steps we only distribute artifacts built from
|
||||
// the build platform, so only consider that in the hosts
|
||||
// array.
|
||||
// NOTE: This relies on the fact that the build triple is
|
||||
// always placed first, as done in `config.rs`.
|
||||
&self.build.config.host[..1]
|
||||
} else {
|
||||
&self.build.config.host
|
||||
}
|
||||
};
|
||||
let targets = if self.build.flags.target.len() > 0 {
|
||||
&self.build.flags.target
|
||||
|
@ -859,6 +873,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
|
|||
// of what we need to do.
|
||||
let mut order = Vec::new();
|
||||
let mut added = HashSet::new();
|
||||
added.insert(Step::noop());
|
||||
for step in steps.iter().cloned() {
|
||||
self.fill(step, &mut order, &mut added);
|
||||
}
|
||||
|
@ -871,6 +886,10 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
|
|||
|
||||
// And finally, iterate over everything and execute it.
|
||||
for step in order.iter() {
|
||||
if self.build.flags.keep_stage.map_or(false, |s| step.stage <= s) {
|
||||
self.build.verbose(&format!("keeping step {:?}", step));
|
||||
continue;
|
||||
}
|
||||
self.build.verbose(&format!("executing step {:?}", step));
|
||||
(self.rules[step.name].run)(step);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,12 @@ pub fn mtime(path: &Path) -> FileTime {
|
|||
/// Copies a file from `src` to `dst`, attempting to use hard links and then
|
||||
/// falling back to an actually filesystem copy if necessary.
|
||||
pub fn copy(src: &Path, dst: &Path) {
|
||||
// A call to `hard_link` will fail if `dst` exists, so remove it if it
|
||||
// already exists so we can try to help `hard_link` succeed.
|
||||
let _ = fs::remove_file(&dst);
|
||||
|
||||
// Attempt to "easy copy" by creating a hard link (symlinks don't work on
|
||||
// windows), but if that fails just fall back to a slow `copy` operation.
|
||||
let res = fs::hard_link(src, dst);
|
||||
let res = res.or_else(|_| fs::copy(src, dst).map(|_| ()));
|
||||
if let Err(e) = res {
|
||||
|
|
|
@ -47,6 +47,8 @@ pub fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
|
|||
None
|
||||
} else if target.contains("musl") {
|
||||
Some(PathBuf::from("ar"))
|
||||
} else if target.contains("openbsd") {
|
||||
Some(PathBuf::from("ar"))
|
||||
} else {
|
||||
let parent = cc.parent().unwrap();
|
||||
let file = cc.file_name().unwrap().to_str().unwrap();
|
||||
|
@ -61,6 +63,16 @@ pub fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn make(host: &str) -> PathBuf {
|
||||
if host.contains("bitrig") || host.contains("dragonfly") ||
|
||||
host.contains("freebsd") || host.contains("netbsd") ||
|
||||
host.contains("openbsd") {
|
||||
PathBuf::from("gmake")
|
||||
} else {
|
||||
PathBuf::from("make")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output(cmd: &mut Command) -> String {
|
||||
let output = match cmd.stderr(Stdio::inherit()).output() {
|
||||
Ok(status) => status,
|
||||
|
|
|
@ -16,7 +16,8 @@ RUN dpkg --add-architecture i386 && \
|
|||
expect \
|
||||
openjdk-9-jre \
|
||||
sudo \
|
||||
libstdc++6:i386
|
||||
libstdc++6:i386 \
|
||||
xz-utils
|
||||
|
||||
WORKDIR /android/
|
||||
ENV PATH=$PATH:/android/ndk-arm-9/bin:/android/sdk/tools:/android/sdk/platform-tools
|
||||
|
@ -25,8 +26,17 @@ COPY install-ndk.sh install-sdk.sh accept-licenses.sh /android/
|
|||
RUN sh /android/install-ndk.sh
|
||||
RUN sh /android/install-sdk.sh
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
|
||||
COPY start-emulator.sh /android/
|
||||
ENTRYPOINT ["/android/start-emulator.sh"]
|
||||
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/android/start-emulator.sh"]
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
ENV TARGETS=arm-linux-androideabi
|
||||
ENV TARGETS=$TARGETS,i686-linux-android
|
||||
|
|
|
@ -21,7 +21,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \
|
||||
gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross \
|
||||
gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross \
|
||||
gcc-s390x-linux-gnu libc6-dev-s390x-cross
|
||||
gcc-s390x-linux-gnu libc6-dev-s390x-cross \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV TARGETS=aarch64-unknown-linux-gnu
|
||||
ENV TARGETS=$TARGETS,arm-unknown-linux-gnueabi
|
||||
|
|
|
@ -11,7 +11,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb
|
||||
gdb \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
|
||||
ENV RUST_CHECK_TARGET check
|
||||
|
|
|
@ -11,7 +11,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb
|
||||
gdb \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
|
||||
ENV RUST_CHECK_TARGET check
|
||||
|
|
|
@ -25,18 +25,26 @@ docker \
|
|||
-t rust-ci \
|
||||
"`dirname "$script"`/$image"
|
||||
|
||||
mkdir -p $HOME/.ccache
|
||||
mkdir -p $HOME/.cargo
|
||||
mkdir -p $root_dir/obj
|
||||
|
||||
args=
|
||||
if [ "$SCCACHE_BUCKET" != "" ]; then
|
||||
args="$args --env SCCACHE_BUCKET=$SCCACHE_BUCKET"
|
||||
args="$args --env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID"
|
||||
args="$args --env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY"
|
||||
else
|
||||
mkdir -p $HOME/.cache/sccache
|
||||
args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache"
|
||||
fi
|
||||
|
||||
exec docker \
|
||||
run \
|
||||
--volume "$root_dir:/checkout:ro" \
|
||||
--volume "$root_dir/obj:/checkout/obj" \
|
||||
--workdir /checkout/obj \
|
||||
--env SRC=/checkout \
|
||||
--env CCACHE_DIR=/ccache \
|
||||
--volume "$HOME/.ccache:/ccache" \
|
||||
$args \
|
||||
--env CARGO_HOME=/cargo \
|
||||
--env LOCAL_USER_ID=`id -u` \
|
||||
--volume "$HOME/.cargo:/cargo" \
|
||||
|
|
|
@ -18,6 +18,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
COPY build-toolchain.sh /tmp/
|
||||
RUN sh /tmp/build-toolchain.sh
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
ENV \
|
||||
AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-ar \
|
||||
CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-gcc
|
||||
|
|
|
@ -11,7 +11,18 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
cmake \
|
||||
ccache \
|
||||
libssl-dev \
|
||||
sudo
|
||||
sudo \
|
||||
xz-utils \
|
||||
pkg-config
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
|
||||
ENV RUST_CHECK_TARGET check-cargotest
|
||||
|
|
|
@ -11,7 +11,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb
|
||||
gdb \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--build=x86_64-unknown-linux-gnu \
|
||||
|
|
|
@ -14,7 +14,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
gdb \
|
||||
llvm-3.7-tools \
|
||||
libedit-dev \
|
||||
zlib1g-dev
|
||||
zlib1g-dev \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--build=x86_64-unknown-linux-gnu \
|
||||
|
|
|
@ -11,7 +11,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb
|
||||
gdb \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-rustbuild
|
||||
ENV RUST_CHECK_TARGET check
|
||||
|
|
|
@ -11,7 +11,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb
|
||||
gdb \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests
|
||||
ENV RUST_CHECK_TARGET check
|
||||
|
|
|
@ -11,7 +11,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb
|
||||
gdb \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
|
||||
ENV RUST_CHECK_TARGET check
|
||||
|
|
|
@ -18,6 +18,15 @@ WORKDIR /build/
|
|||
COPY build-musl.sh /build/
|
||||
RUN sh /build/build-musl.sh && rm -rf /build
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=x86_64-unknown-linux-musl \
|
||||
--musl-root-x86_64=/musl-x86_64
|
||||
|
|
|
@ -26,17 +26,13 @@ if [ "$NO_VENDOR" = "" ]; then
|
|||
ENABLE_VENDOR=--enable-vendor
|
||||
fi
|
||||
|
||||
if [ "$NO_CCACHE" = "" ]; then
|
||||
ENABLE_CCACHE=--enable-ccache
|
||||
fi
|
||||
|
||||
set -ex
|
||||
|
||||
$SRC/configure \
|
||||
--disable-manage-submodules \
|
||||
--enable-debug-assertions \
|
||||
--enable-quiet-tests \
|
||||
$ENABLE_CCACHE \
|
||||
--enable-sccache \
|
||||
$ENABLE_VENDOR \
|
||||
$ENABLE_LLVM_ASSERTIONS \
|
||||
$RUST_CONFIGURE_ARGS
|
||||
|
|
|
@ -16,18 +16,18 @@ function result.
|
|||
|
||||
The most common case of coercion is removing mutability from a reference:
|
||||
|
||||
* `&mut T` to `&T`
|
||||
* `&mut T` to `&T`
|
||||
|
||||
An analogous conversion is to remove mutability from a
|
||||
[raw pointer](raw-pointers.md):
|
||||
|
||||
* `*mut T` to `*const T`
|
||||
* `*mut T` to `*const T`
|
||||
|
||||
References can also be coerced to raw pointers:
|
||||
|
||||
* `&T` to `*const T`
|
||||
* `&T` to `*const T`
|
||||
|
||||
* `&mut T` to `*mut T`
|
||||
* `&mut T` to `*mut T`
|
||||
|
||||
Custom coercions may be defined using [`Deref`](deref-coercions.md).
|
||||
|
||||
|
@ -59,11 +59,11 @@ A cast `e as U` is valid if `e` has type `T` and `T` *coerces* to `U`.
|
|||
|
||||
A cast `e as U` is also valid in any of the following cases:
|
||||
|
||||
* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
|
||||
* `e` is a C-like enum (with no data attached to the variants),
|
||||
and `U` is an integer type; *enum-cast*
|
||||
* `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast*
|
||||
* `e` has type `u8` and `U` is `char`; *u8-char-cast*
|
||||
* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
|
||||
* `e` is a C-like enum (with no data attached to the variants),
|
||||
and `U` is an integer type; *enum-cast*
|
||||
* `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast*
|
||||
* `e` has type `u8` and `U` is `char`; *u8-char-cast*
|
||||
|
||||
For example
|
||||
|
||||
|
|
|
@ -460,8 +460,9 @@ not actually pass as a test.
|
|||
```
|
||||
|
||||
The `no_run` attribute will compile your code, but not run it. This is
|
||||
important for examples such as "Here's how to start up a network service,"
|
||||
which you would want to make sure compile, but might run in an infinite loop!
|
||||
important for examples such as "Here's how to retrieve a web page,"
|
||||
which you would want to ensure compiles, but might be run in a test
|
||||
environment that has no network access.
|
||||
|
||||
### Documenting modules
|
||||
|
||||
|
|
|
@ -24,41 +24,40 @@ see the website][platform-support].
|
|||
|
||||
[platform-support]: https://forge.rust-lang.org/platform-support.html
|
||||
|
||||
## Installing on Linux or Mac
|
||||
## Installing Rust
|
||||
|
||||
If we're on Linux or a Mac, all we need to do is open a terminal and type this:
|
||||
All you need to do on Unix systems like Linux and macOS is open a
|
||||
terminal and type this:
|
||||
|
||||
```bash
|
||||
$ curl -sSf https://static.rust-lang.org/rustup.sh | sh
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
This will download a script, and start the installation. If it all goes well,
|
||||
you’ll see this appear:
|
||||
It will download a script, and start the installation. If everything
|
||||
goes well, you’ll see this appear:
|
||||
|
||||
```text
|
||||
Rust is ready to roll.
|
||||
Rust is installed now. Great!
|
||||
```
|
||||
|
||||
From here, press `y` for ‘yes’, and then follow the rest of the prompts.
|
||||
Installing on Windows is nearly as easy: download and run
|
||||
[rustup-init.exe]. It will start the installation in a console and
|
||||
present the above message on success.
|
||||
|
||||
## Installing on Windows
|
||||
For other installation options and information, visit the [install]
|
||||
page of the Rust website.
|
||||
|
||||
If you're on Windows, please download the appropriate [installer][install-page].
|
||||
|
||||
[install-page]: https://www.rust-lang.org/install.html
|
||||
[rustup-init.exe]: https://win.rustup.rs
|
||||
[install]: https://www.rust-lang.org/install.html
|
||||
|
||||
## Uninstalling
|
||||
|
||||
Uninstalling Rust is as easy as installing it. On Linux or Mac, run
|
||||
the uninstall script:
|
||||
Uninstalling Rust is as easy as installing it:
|
||||
|
||||
```bash
|
||||
$ sudo /usr/local/lib/rustlib/uninstall.sh
|
||||
$ rustup self uninstall
|
||||
```
|
||||
|
||||
If we used the Windows installer, we can re-run the `.msi` and it will give us
|
||||
an uninstall option.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If we've got Rust installed, we can open up a shell, and type this:
|
||||
|
@ -71,12 +70,15 @@ You should see the version number, commit hash, and commit date.
|
|||
|
||||
If you do, Rust has been installed successfully! Congrats!
|
||||
|
||||
If you don't and you're on Windows, check that Rust is in your %PATH% system
|
||||
variable: `$ echo %PATH%`. If it isn't, run the installer again, select "Change"
|
||||
on the "Change, repair, or remove installation" page and ensure "Add to PATH" is
|
||||
installed on the local hard drive. If you need to configure your path manually,
|
||||
you can find the Rust executables in a directory like
|
||||
`"C:\Program Files\Rust stable GNU 1.x\bin"`.
|
||||
If you don't, that probably means that the `PATH` environment variable
|
||||
doesn't include Cargo's binary directory, `~/.cargo/bin` on Unix, or
|
||||
`%USERPROFILE%\.cargo\bin` on Windows. This is the directory where
|
||||
Rust development tools live, and most Rust developers keep it in their
|
||||
`PATH` environment variable, which makes it possible to run `rustc` on
|
||||
the command line. Due to differences in operating systems, command
|
||||
shells, and bugs in installation, you may need to restart your shell,
|
||||
log out of the system, or configure `PATH` manually as appropriate for
|
||||
your operating environment.
|
||||
|
||||
Rust does not do its own linking, and so you’ll need to have a linker
|
||||
installed. Doing so will depend on your specific system. For
|
||||
|
@ -106,9 +108,7 @@ resources include [the user’s forum][users] and [Stack Overflow][stackoverflow
|
|||
[stackoverflow]: http://stackoverflow.com/questions/tagged/rust
|
||||
|
||||
This installer also installs a copy of the documentation locally, so we can
|
||||
read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location.
|
||||
On Windows, it's in a `share/doc` directory, inside the directory to which Rust
|
||||
was installed.
|
||||
read it offline. It's only a `rustup doc` away!
|
||||
|
||||
# Hello, world!
|
||||
|
||||
|
|
|
@ -589,11 +589,10 @@ please see the [Documentation chapter](documentation.html).
|
|||
|
||||
# Testing and concurrency
|
||||
|
||||
One thing that is important to note when writing tests is that they may be run
|
||||
concurrently using threads. For this reason you should take care that your tests
|
||||
are written in such a way as to not depend on each-other, or on any shared
|
||||
state. "Shared state" can also include the environment, such as the current
|
||||
working directory, or environment variables.
|
||||
It is important to note that tests are run concurrently using threads. For this
|
||||
reason, care should be taken to ensure your tests do not depend on each-other,
|
||||
or on any shared state. "Shared state" can also include the environment, such
|
||||
as the current working directory, or environment variables.
|
||||
|
||||
If this is an issue it is possible to control this concurrency, either by
|
||||
setting the environment variable `RUST_TEST_THREADS`, or by passing the argument
|
||||
|
|
|
@ -1731,7 +1731,8 @@ of an item to see whether it should be allowed or not. This is where privacy
|
|||
warnings are generated, or otherwise "you used a private item of another module
|
||||
and weren't allowed to."
|
||||
|
||||
By default, everything in Rust is *private*, with one exception. Enum variants
|
||||
By default, everything in Rust is *private*, with two exceptions: Associated
|
||||
items in a `pub` Trait are public by default; Enum variants
|
||||
in a `pub` enum are also public by default. When an item is declared as `pub`,
|
||||
it can be thought of as being accessible to the outside world. For example:
|
||||
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
font-family: 'Source Code Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Code Pro'), url("SourceCodePro-Regular.woff") format('woff');
|
||||
/* Avoid using locally installed font because bad versions are in circulation:
|
||||
* see https://github.com/rust-lang/rust/issues/24355 */
|
||||
src: url("SourceCodePro-Regular.woff") format('woff');
|
||||
}
|
||||
|
||||
*:not(body) {
|
||||
|
|
|
@ -392,8 +392,6 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(arc_counts)]
|
||||
///
|
||||
/// use std::sync::Arc;
|
||||
///
|
||||
/// let five = Arc::new(5);
|
||||
|
@ -404,8 +402,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// assert_eq!(1, Arc::weak_count(&five));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "arc_counts", reason = "not clearly useful, and racy",
|
||||
issue = "28356")]
|
||||
#[stable(feature = "arc_counts", since = "1.15.0")]
|
||||
pub fn weak_count(this: &Self) -> usize {
|
||||
this.inner().weak.load(SeqCst) - 1
|
||||
}
|
||||
|
@ -421,8 +418,6 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(arc_counts)]
|
||||
///
|
||||
/// use std::sync::Arc;
|
||||
///
|
||||
/// let five = Arc::new(5);
|
||||
|
@ -433,8 +428,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// assert_eq!(2, Arc::strong_count(&five));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "arc_counts", reason = "not clearly useful, and racy",
|
||||
issue = "28356")]
|
||||
#[stable(feature = "arc_counts", since = "1.15.0")]
|
||||
pub fn strong_count(this: &Self) -> usize {
|
||||
this.inner().strong.load(SeqCst)
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ pub fn usable_size(size: usize, align: usize) -> usize {
|
|||
pub const EMPTY: *mut () = 0x1 as *mut ();
|
||||
|
||||
/// The allocator for unique pointers.
|
||||
// This function must not unwind. If it does, MIR trans will fail.
|
||||
#[cfg(not(test))]
|
||||
#[lang = "exchange_malloc"]
|
||||
#[inline]
|
||||
|
@ -143,6 +144,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
|
|||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[cfg(stage0)]
|
||||
#[lang = "exchange_free"]
|
||||
#[inline]
|
||||
unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) {
|
||||
|
|
|
@ -320,7 +320,7 @@ impl<T> Rc<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rc_unique", since = "1.4.0")]
|
||||
pub fn try_unwrap(this: Self) -> Result<T, Self> {
|
||||
if Rc::would_unwrap(&this) {
|
||||
if Rc::strong_count(&this) == 1 {
|
||||
unsafe {
|
||||
let val = ptr::read(&*this); // copy the contained object
|
||||
|
||||
|
@ -343,26 +343,10 @@ impl<T> Rc<T> {
|
|||
///
|
||||
/// [try_unwrap]: struct.Rc.html#method.try_unwrap
|
||||
/// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(rc_would_unwrap)]
|
||||
///
|
||||
/// use std::rc::Rc;
|
||||
///
|
||||
/// let x = Rc::new(3);
|
||||
/// assert!(Rc::would_unwrap(&x));
|
||||
/// assert_eq!(Rc::try_unwrap(x), Ok(3));
|
||||
///
|
||||
/// let x = Rc::new(4);
|
||||
/// let _y = x.clone();
|
||||
/// assert!(!Rc::would_unwrap(&x));
|
||||
/// assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4);
|
||||
/// ```
|
||||
#[unstable(feature = "rc_would_unwrap",
|
||||
reason = "just added for niche usecase",
|
||||
issue = "28356")]
|
||||
#[rustc_deprecated(since = "1.15.0", reason = "too niche; use `strong_count` instead")]
|
||||
pub fn would_unwrap(this: &Self) -> bool {
|
||||
Rc::strong_count(&this) == 1
|
||||
}
|
||||
|
@ -482,8 +466,6 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(rc_counts)]
|
||||
///
|
||||
/// use std::rc::Rc;
|
||||
///
|
||||
/// let five = Rc::new(5);
|
||||
|
@ -492,8 +474,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// assert_eq!(1, Rc::weak_count(&five));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "rc_counts", reason = "not clearly useful",
|
||||
issue = "28356")]
|
||||
#[stable(feature = "rc_counts", since = "1.15.0")]
|
||||
pub fn weak_count(this: &Self) -> usize {
|
||||
this.weak() - 1
|
||||
}
|
||||
|
@ -503,8 +484,6 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(rc_counts)]
|
||||
///
|
||||
/// use std::rc::Rc;
|
||||
///
|
||||
/// let five = Rc::new(5);
|
||||
|
@ -513,8 +492,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// assert_eq!(2, Rc::strong_count(&five));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "rc_counts", reason = "not clearly useful",
|
||||
issue = "28356")]
|
||||
#[stable(feature = "rc_counts", since = "1.15.0")]
|
||||
pub fn strong_count(this: &Self) -> usize {
|
||||
this.strong()
|
||||
}
|
||||
|
@ -523,21 +501,11 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// this inner value.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(rc_counts)]
|
||||
///
|
||||
/// use std::rc::Rc;
|
||||
///
|
||||
/// let five = Rc::new(5);
|
||||
///
|
||||
/// assert!(Rc::is_unique(&five));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "rc_counts", reason = "uniqueness has unclear meaning",
|
||||
#[unstable(feature = "is_unique", reason = "uniqueness has unclear meaning",
|
||||
issue = "28356")]
|
||||
#[rustc_deprecated(since = "1.15.0",
|
||||
reason = "too niche; use `strong_count` and `weak_count` instead")]
|
||||
pub fn is_unique(this: &Self) -> bool {
|
||||
Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ fn main() {
|
|||
// targets, which means we have to build the alloc_jemalloc crate
|
||||
// for targets like emscripten, even if we don't use it.
|
||||
if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") ||
|
||||
target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") {
|
||||
target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") ||
|
||||
target.contains("redox") {
|
||||
println!("cargo:rustc-cfg=dummy_jemalloc");
|
||||
return;
|
||||
}
|
||||
|
@ -151,7 +152,7 @@ fn main() {
|
|||
cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));
|
||||
|
||||
run(&mut cmd);
|
||||
let mut make = Command::new("make");
|
||||
let mut make = Command::new(build_helper::make(&host));
|
||||
make.current_dir(&build_dir)
|
||||
.arg("build_lib_static");
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
issue = "27783")]
|
||||
#![feature(allocator)]
|
||||
#![feature(staged_api)]
|
||||
#![cfg_attr(unix, feature(libc))]
|
||||
#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
|
||||
|
||||
// The minimum alignment guaranteed by the architecture. This value is used to
|
||||
// add fast paths for low alignment values. In practice, the alignment is a
|
||||
|
@ -71,7 +71,7 @@ pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
|
|||
imp::usable_size(size, align)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "redox"))]
|
||||
mod imp {
|
||||
extern crate libc;
|
||||
|
||||
|
@ -87,7 +87,7 @@ mod imp {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[cfg(any(target_os = "android", target_os = "redox"))]
|
||||
unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 {
|
||||
// On android we currently target API level 9 which unfortunately
|
||||
// doesn't have the `posix_memalign` API used below. Instead we use
|
||||
|
@ -109,7 +109,7 @@ mod imp {
|
|||
libc::memalign(align as libc::size_t, size as libc::size_t) as *mut u8
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "redox")))]
|
||||
unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 {
|
||||
let mut out = ptr::null_mut();
|
||||
let ret = libc::posix_memalign(&mut out, align as libc::size_t, size as libc::size_t);
|
||||
|
|
|
@ -225,7 +225,7 @@ pub struct BinaryHeap<T> {
|
|||
/// [`peek_mut()`]: struct.BinaryHeap.html#method.peek_mut
|
||||
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
|
||||
pub struct PeekMut<'a, T: 'a + Ord> {
|
||||
heap: &'a mut BinaryHeap<T>
|
||||
heap: &'a mut BinaryHeap<T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
|
||||
|
@ -385,9 +385,7 @@ impl<T: Ord> BinaryHeap<T> {
|
|||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(PeekMut {
|
||||
heap: self
|
||||
})
|
||||
Some(PeekMut { heap: self })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1126,7 +1124,9 @@ impl<T: Ord> IntoIterator for BinaryHeap<T> {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
|
||||
impl<'a, T> IntoIterator for &'a BinaryHeap<T>
|
||||
where T: Ord
|
||||
{
|
||||
type Item = &'a T;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
|
|
|
@ -63,7 +63,9 @@ pub trait ToOwned {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> ToOwned for T where T: Clone {
|
||||
impl<T> ToOwned for T
|
||||
where T: Clone
|
||||
{
|
||||
type Owned = T;
|
||||
fn to_owned(&self) -> T {
|
||||
self.clone()
|
||||
|
@ -117,17 +119,19 @@ pub enum Cow<'a, B: ?Sized + 'a>
|
|||
{
|
||||
/// Borrowed data.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B),
|
||||
Borrowed(#[stable(feature = "rust1", since = "1.0.0")]
|
||||
&'a B),
|
||||
|
||||
/// Owned data.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Owned(
|
||||
#[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned
|
||||
),
|
||||
Owned(#[stable(feature = "rust1", since = "1.0.0")]
|
||||
<B as ToOwned>::Owned),
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
|
||||
impl<'a, B: ?Sized> Clone for Cow<'a, B>
|
||||
where B: ToOwned
|
||||
{
|
||||
fn clone(&self) -> Cow<'a, B> {
|
||||
match *self {
|
||||
Borrowed(b) => Borrowed(b),
|
||||
|
@ -139,7 +143,9 @@ impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
|
||||
impl<'a, B: ?Sized> Cow<'a, B>
|
||||
where B: ToOwned
|
||||
{
|
||||
/// Acquires a mutable reference to the owned form of the data.
|
||||
///
|
||||
/// Clones the data if it is not already owned.
|
||||
|
@ -194,7 +200,9 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
|
||||
impl<'a, B: ?Sized> Deref for Cow<'a, B>
|
||||
where B: ToOwned
|
||||
{
|
||||
type Target = B;
|
||||
|
||||
fn deref(&self) -> &B {
|
||||
|
@ -209,7 +217,9 @@ impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
|
|||
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
|
||||
impl<'a, B: ?Sized> Ord for Cow<'a, B>
|
||||
where B: Ord + ToOwned
|
||||
{
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
|
||||
Ord::cmp(&**self, &**other)
|
||||
|
@ -228,7 +238,9 @@ impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned {
|
||||
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B>
|
||||
where B: PartialOrd + ToOwned
|
||||
{
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(&**self, &**other)
|
||||
|
@ -273,7 +285,9 @@ impl<'a, B: ?Sized> Default for Cow<'a, B>
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned {
|
||||
impl<'a, B: ?Sized> Hash for Cow<'a, B>
|
||||
where B: Hash + ToOwned
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
Hash::hash(&**self, state)
|
||||
|
|
|
@ -74,24 +74,44 @@ pub struct BTreeSet<T> {
|
|||
map: BTreeMap<T, ()>,
|
||||
}
|
||||
|
||||
/// An iterator over a BTreeSet's items.
|
||||
/// An iterator over a `BTreeSet`'s items.
|
||||
///
|
||||
/// This structure is created by the [`iter`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`iter`]: struct.BTreeSet.html#method.iter
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
iter: Keys<'a, T, ()>,
|
||||
}
|
||||
|
||||
/// An owning iterator over a BTreeSet's items.
|
||||
/// An owning iterator over a `BTreeSet`'s items.
|
||||
///
|
||||
/// This structure is created by the `into_iter` method on [`BTreeSet`]
|
||||
/// [`BTreeSet`] (provided by the `IntoIterator` trait).
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IntoIter<T> {
|
||||
iter: ::btree_map::IntoIter<T, ()>,
|
||||
}
|
||||
|
||||
/// An iterator over a sub-range of BTreeSet's items.
|
||||
/// An iterator over a sub-range of `BTreeSet`'s items.
|
||||
///
|
||||
/// This structure is created by the [`range`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`range`]: struct.BTreeSet.html#method.range
|
||||
pub struct Range<'a, T: 'a> {
|
||||
iter: ::btree_map::Range<'a, T, ()>,
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set difference (in-order).
|
||||
///
|
||||
/// This structure is created by the [`difference`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`difference`]: struct.BTreeSet.html#method.difference
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Difference<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
|
@ -99,6 +119,12 @@ pub struct Difference<'a, T: 'a> {
|
|||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set symmetric difference (in-order).
|
||||
///
|
||||
/// This structure is created by the [`symmetric_difference`] method on
|
||||
/// [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct SymmetricDifference<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
|
@ -106,6 +132,11 @@ pub struct SymmetricDifference<'a, T: 'a> {
|
|||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set intersection (in-order).
|
||||
///
|
||||
/// This structure is created by the [`intersection`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`intersection`]: struct.BTreeSet.html#method.intersection
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Intersection<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
|
@ -113,6 +144,11 @@ pub struct Intersection<'a, T: 'a> {
|
|||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set union (in-order).
|
||||
///
|
||||
/// This structure is created by the [`union`] method on [`BTreeSet`].
|
||||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`union`]: struct.BTreeSet.html#method.union
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Union<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
|
@ -120,7 +156,7 @@ pub struct Union<'a, T: 'a> {
|
|||
}
|
||||
|
||||
impl<T: Ord> BTreeSet<T> {
|
||||
/// Makes a new BTreeSet with a reasonable choice of B.
|
||||
/// Makes a new `BTreeSet` with a reasonable choice of B.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -137,21 +173,32 @@ impl<T: Ord> BTreeSet<T> {
|
|||
}
|
||||
|
||||
impl<T> BTreeSet<T> {
|
||||
/// Gets an iterator over the BTreeSet's contents.
|
||||
/// Gets an iterator that visits the values in the `BTreeSet` in ascending order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::BTreeSet;
|
||||
///
|
||||
/// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
|
||||
/// let set: BTreeSet<usize> = [1, 2, 3].iter().cloned().collect();
|
||||
/// let mut set_iter = set.iter();
|
||||
/// assert_eq!(set_iter.next(), Some(&1));
|
||||
/// assert_eq!(set_iter.next(), Some(&2));
|
||||
/// assert_eq!(set_iter.next(), Some(&3));
|
||||
/// assert_eq!(set_iter.next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// for x in set.iter() {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// Values returned by the iterator are returned in ascending order:
|
||||
///
|
||||
/// let v: Vec<_> = set.iter().cloned().collect();
|
||||
/// assert_eq!(v, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
/// use std::collections::BTreeSet;
|
||||
///
|
||||
/// let set: BTreeSet<usize> = [3, 1, 2].iter().cloned().collect();
|
||||
/// let mut set_iter = set.iter();
|
||||
/// assert_eq!(set_iter.next(), Some(&1));
|
||||
/// assert_eq!(set_iter.next(), Some(&2));
|
||||
/// assert_eq!(set_iter.next(), Some(&3));
|
||||
/// assert_eq!(set_iter.next(), None);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
|
|
|
@ -276,7 +276,8 @@ impl<E: CLike> FromIterator<E> for EnumSet<E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike
|
||||
impl<'a, E> IntoIterator for &'a EnumSet<E>
|
||||
where E: CLike
|
||||
{
|
||||
type Item = E;
|
||||
type IntoIter = Iter<E>;
|
||||
|
|
|
@ -10,8 +10,15 @@
|
|||
|
||||
//! A doubly-linked list with owned nodes.
|
||||
//!
|
||||
//! The `LinkedList` allows pushing and popping elements at either end and is thus
|
||||
//! efficiently usable as a double-ended queue.
|
||||
//! The `LinkedList` allows pushing and popping elements at either end
|
||||
//! in constant time.
|
||||
//!
|
||||
//! Almost always it is better to use `Vec` or [`VecDeque`] instead of
|
||||
//! [`LinkedList`]. In general, array-based containers are faster,
|
||||
//! more memory efficient and make better use of CPU cache.
|
||||
//!
|
||||
//! [`LinkedList`]: ../linked_list/struct.LinkedList.html
|
||||
//! [`VecDeque`]: ../vec_deque/struct.VecDeque.html
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
|
@ -27,7 +34,14 @@ use core::ptr::{self, Shared};
|
|||
|
||||
use super::SpecExtend;
|
||||
|
||||
/// A doubly-linked list.
|
||||
/// A doubly-linked list with owned nodes.
|
||||
///
|
||||
/// The `LinkedList` allows pushing and popping elements at either end
|
||||
/// in constant time.
|
||||
///
|
||||
/// Almost always it is better to use `Vec` or `VecDeque` instead of
|
||||
/// `LinkedList`. In general, array-based containers are faster,
|
||||
/// more memory efficient and make better use of CPU cache.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct LinkedList<T> {
|
||||
head: Option<Shared<Node<T>>>,
|
||||
|
@ -225,15 +239,17 @@ impl<T> LinkedList<T> {
|
|||
pub fn append(&mut self, other: &mut Self) {
|
||||
match self.tail {
|
||||
None => mem::swap(self, other),
|
||||
Some(tail) => if let Some(other_head) = other.head.take() {
|
||||
unsafe {
|
||||
(**tail).next = Some(other_head);
|
||||
(**other_head).prev = Some(tail);
|
||||
}
|
||||
Some(tail) => {
|
||||
if let Some(other_head) = other.head.take() {
|
||||
unsafe {
|
||||
(**tail).next = Some(other_head);
|
||||
(**other_head).prev = Some(tail);
|
||||
}
|
||||
|
||||
self.tail = other.tail.take();
|
||||
self.len += mem::replace(&mut other.len, 0);
|
||||
},
|
||||
self.tail = other.tail.take();
|
||||
self.len += mem::replace(&mut other.len, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -674,7 +690,10 @@ impl<T> LinkedList<T> {
|
|||
reason = "method name and placement protocol are subject to change",
|
||||
issue = "30172")]
|
||||
pub fn front_place(&mut self) -> FrontPlace<T> {
|
||||
FrontPlace { list: self, node: IntermediateBox::make_place() }
|
||||
FrontPlace {
|
||||
list: self,
|
||||
node: IntermediateBox::make_place(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a place for insertion at the back of the list.
|
||||
|
@ -699,7 +718,10 @@ impl<T> LinkedList<T> {
|
|||
reason = "method name and placement protocol are subject to change",
|
||||
issue = "30172")]
|
||||
pub fn back_place(&mut self) -> BackPlace<T> {
|
||||
BackPlace { list: self, node: IntermediateBox::make_place() }
|
||||
BackPlace {
|
||||
list: self,
|
||||
node: IntermediateBox::make_place(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -852,7 +874,7 @@ impl<'a, T> IterMut<'a, T> {
|
|||
(**head).prev = node;
|
||||
|
||||
self.list.len += 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1135,9 +1157,15 @@ impl<'a, T> InPlace<T> for BackPlace<'a, T> {
|
|||
// Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters.
|
||||
#[allow(dead_code)]
|
||||
fn assert_covariance() {
|
||||
fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> { x }
|
||||
fn b<'i, 'a>(x: Iter<'i, &'static str>) -> Iter<'i, &'a str> { x }
|
||||
fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> { x }
|
||||
fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> {
|
||||
x
|
||||
}
|
||||
fn b<'i, 'a>(x: Iter<'i, &'static str>) -> Iter<'i, &'a str> {
|
||||
x
|
||||
}
|
||||
fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> {
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1298,10 +1326,10 @@ mod tests {
|
|||
fn test_send() {
|
||||
let n = list_from(&[1, 2, 3]);
|
||||
thread::spawn(move || {
|
||||
check_links(&n);
|
||||
let a: &[_] = &[&1, &2, &3];
|
||||
assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
|
||||
})
|
||||
check_links(&n);
|
||||
let a: &[_] = &[&1, &2, &3];
|
||||
assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
|
||||
})
|
||||
.join()
|
||||
.ok()
|
||||
.unwrap();
|
||||
|
|
|
@ -1496,10 +1496,10 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F)
|
|||
/// The algorithm identifies strictly descending and non-descending subsequences, which are called
|
||||
/// natural runs. There is a stack of pending runs yet to be merged. Each newly found run is pushed
|
||||
/// onto the stack, and then some pairs of adjacent runs are merged until these two invariants are
|
||||
/// satisfied, for every `i` in `0 .. runs.len() - 2`:
|
||||
/// satisfied:
|
||||
///
|
||||
/// 1. `runs[i].len > runs[i + 1].len`
|
||||
/// 2. `runs[i].len > runs[i + 1].len + runs[i + 2].len`
|
||||
/// 1. for every `i` in `1..runs.len()`: `runs[i - 1].len > runs[i].len`
|
||||
/// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len`
|
||||
///
|
||||
/// The invariants ensure that the total running time is `O(n log n)` worst-case.
|
||||
fn merge_sort<T, F>(v: &mut [T], mut compare: F)
|
||||
|
|
|
@ -1697,11 +1697,7 @@ impl str {
|
|||
debug_assert!('Σ'.len_utf8() == 2);
|
||||
let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) &&
|
||||
!case_ignoreable_then_cased(from[i + 2..].chars());
|
||||
to.push_str(if is_word_final {
|
||||
"ς"
|
||||
} else {
|
||||
"σ"
|
||||
});
|
||||
to.push_str(if is_word_final { "ς" } else { "σ" });
|
||||
}
|
||||
|
||||
fn case_ignoreable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
|
||||
|
|
|
@ -542,11 +542,7 @@ impl String {
|
|||
unsafe { *xs.get_unchecked(i) }
|
||||
}
|
||||
fn safe_get(xs: &[u8], i: usize, total: usize) -> u8 {
|
||||
if i >= total {
|
||||
0
|
||||
} else {
|
||||
unsafe_get(xs, i)
|
||||
}
|
||||
if i >= total { 0 } else { unsafe_get(xs, i) }
|
||||
}
|
||||
|
||||
let mut res = String::with_capacity(total);
|
||||
|
@ -976,7 +972,7 @@ impl String {
|
|||
pub fn push(&mut self, ch: char) {
|
||||
match ch.len_utf8() {
|
||||
1 => self.vec.push(ch as u8),
|
||||
_ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0;4]).as_bytes()),
|
||||
_ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1935,7 +1931,7 @@ impl<'a> FromIterator<String> for Cow<'a, str> {
|
|||
|
||||
#[stable(feature = "from_string_for_vec_u8", since = "1.14.0")]
|
||||
impl From<String> for Vec<u8> {
|
||||
fn from(string : String) -> Vec<u8> {
|
||||
fn from(string: String) -> Vec<u8> {
|
||||
string.into_bytes()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1902,14 +1902,13 @@ impl<T> IntoIter<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(vec_into_iter_as_slice)]
|
||||
/// let vec = vec!['a', 'b', 'c'];
|
||||
/// let mut into_iter = vec.into_iter();
|
||||
/// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
|
||||
/// let _ = into_iter.next().unwrap();
|
||||
/// assert_eq!(into_iter.as_slice(), &['b', 'c']);
|
||||
/// ```
|
||||
#[unstable(feature = "vec_into_iter_as_slice", issue = "35601")]
|
||||
#[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.ptr, self.len())
|
||||
|
@ -1921,7 +1920,6 @@ impl<T> IntoIter<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(vec_into_iter_as_slice)]
|
||||
/// let vec = vec!['a', 'b', 'c'];
|
||||
/// let mut into_iter = vec.into_iter();
|
||||
/// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
|
||||
|
@ -1930,7 +1928,7 @@ impl<T> IntoIter<T> {
|
|||
/// assert_eq!(into_iter.next().unwrap(), 'b');
|
||||
/// assert_eq!(into_iter.next().unwrap(), 'z');
|
||||
/// ```
|
||||
#[unstable(feature = "vec_into_iter_as_slice", issue = "35601")]
|
||||
#[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
|
||||
pub fn as_mut_slice(&self) -> &mut [T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.ptr as *mut T, self.len())
|
||||
|
|
|
@ -206,11 +206,7 @@ impl<T> VecDeque<T> {
|
|||
unsafe fn wrap_copy(&self, dst: usize, src: usize, len: usize) {
|
||||
#[allow(dead_code)]
|
||||
fn diff(a: usize, b: usize) -> usize {
|
||||
if a <= b {
|
||||
b - a
|
||||
} else {
|
||||
a - b
|
||||
}
|
||||
if a <= b { b - a } else { a - b }
|
||||
}
|
||||
debug_assert!(cmp::min(diff(dst, src), self.cap() - diff(dst, src)) + len <= self.cap(),
|
||||
"wrc dst={} src={} len={} cap={}",
|
||||
|
@ -552,8 +548,8 @@ impl<T> VecDeque<T> {
|
|||
let old_cap = self.cap();
|
||||
let used_cap = self.len() + 1;
|
||||
let new_cap = used_cap.checked_add(additional)
|
||||
.and_then(|needed_cap| needed_cap.checked_next_power_of_two())
|
||||
.expect("capacity overflow");
|
||||
.and_then(|needed_cap| needed_cap.checked_next_power_of_two())
|
||||
.expect("capacity overflow");
|
||||
|
||||
if new_cap > self.capacity() {
|
||||
self.buf.reserve_exact(used_cap, new_cap - used_cap);
|
||||
|
@ -1293,9 +1289,7 @@ impl<T> VecDeque<T> {
|
|||
|
||||
let contiguous = self.is_contiguous();
|
||||
|
||||
match (contiguous,
|
||||
distance_to_tail <= distance_to_head,
|
||||
idx >= self.tail) {
|
||||
match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
|
||||
(true, true, _) if index == 0 => {
|
||||
// push_front
|
||||
//
|
||||
|
@ -1513,9 +1507,7 @@ impl<T> VecDeque<T> {
|
|||
|
||||
let contiguous = self.is_contiguous();
|
||||
|
||||
match (contiguous,
|
||||
distance_to_tail <= distance_to_head,
|
||||
idx >= self.tail) {
|
||||
match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
|
||||
(true, true, _) => {
|
||||
unsafe {
|
||||
// contiguous, remove closer to tail:
|
||||
|
@ -1812,7 +1804,7 @@ fn wrap_index(index: usize, size: usize) -> usize {
|
|||
}
|
||||
|
||||
/// Returns the two slices that cover the VecDeque's valid range
|
||||
trait RingSlices : Sized {
|
||||
trait RingSlices: Sized {
|
||||
fn slice(self, from: usize, to: usize) -> Self;
|
||||
fn split_at(self, i: usize) -> (Self, Self);
|
||||
|
||||
|
@ -1895,7 +1887,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
|||
}
|
||||
|
||||
fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
|
||||
where F: FnMut(Acc, Self::Item) -> Acc,
|
||||
where F: FnMut(Acc, Self::Item) -> Acc
|
||||
{
|
||||
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
|
||||
accum = front.iter().fold(accum, &mut f);
|
||||
|
@ -1959,7 +1951,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {
|
|||
}
|
||||
|
||||
fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
|
||||
where F: FnMut(Acc, Self::Item) -> Acc,
|
||||
where F: FnMut(Acc, Self::Item) -> Acc
|
||||
{
|
||||
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
|
||||
accum = front.iter_mut().fold(accum, &mut f);
|
||||
|
@ -2082,17 +2074,15 @@ impl<'a, T: 'a> Drop for Drain<'a, T> {
|
|||
(_, 0) => {
|
||||
source_deque.head = drain_tail;
|
||||
}
|
||||
_ => {
|
||||
unsafe {
|
||||
if tail_len <= head_len {
|
||||
source_deque.tail = source_deque.wrap_sub(drain_head, tail_len);
|
||||
source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len);
|
||||
} else {
|
||||
source_deque.head = source_deque.wrap_add(drain_tail, head_len);
|
||||
source_deque.wrap_copy(drain_tail, drain_head, head_len);
|
||||
}
|
||||
_ => unsafe {
|
||||
if tail_len <= head_len {
|
||||
source_deque.tail = source_deque.wrap_sub(drain_head, tail_len);
|
||||
source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len);
|
||||
} else {
|
||||
source_deque.head = source_deque.wrap_add(drain_tail, head_len);
|
||||
source_deque.wrap_copy(drain_tail, drain_head, head_len);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2288,10 +2278,8 @@ impl<T> From<Vec<T>> for VecDeque<T> {
|
|||
|
||||
// We need to extend the buf if it's not a power of two, too small
|
||||
// or doesn't have at least one free space
|
||||
if !buf.cap().is_power_of_two()
|
||||
|| (buf.cap() < (MINIMUM_CAPACITY + 1))
|
||||
|| (buf.cap() == len)
|
||||
{
|
||||
if !buf.cap().is_power_of_two() || (buf.cap() < (MINIMUM_CAPACITY + 1)) ||
|
||||
(buf.cap() == len) {
|
||||
let cap = cmp::max(buf.cap() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
|
||||
buf.reserve_exact(len, cap - len);
|
||||
}
|
||||
|
@ -2299,7 +2287,7 @@ impl<T> From<Vec<T>> for VecDeque<T> {
|
|||
VecDeque {
|
||||
tail: 0,
|
||||
head: len,
|
||||
buf: buf
|
||||
buf: buf,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2324,18 +2312,17 @@ impl<T> From<VecDeque<T>> for Vec<T> {
|
|||
// do this in at most three copy moves.
|
||||
if (cap - tail) > head {
|
||||
// right hand block is the long one; move that enough for the left
|
||||
ptr::copy(
|
||||
buf.offset(tail as isize),
|
||||
buf.offset((tail - head) as isize),
|
||||
cap - tail);
|
||||
ptr::copy(buf.offset(tail as isize),
|
||||
buf.offset((tail - head) as isize),
|
||||
cap - tail);
|
||||
// copy left in the end
|
||||
ptr::copy(buf, buf.offset((cap - head) as isize), head);
|
||||
// shift the new thing to the start
|
||||
ptr::copy(buf.offset((tail-head) as isize), buf, len);
|
||||
ptr::copy(buf.offset((tail - head) as isize), buf, len);
|
||||
} else {
|
||||
// left hand block is the long one, we can do it in two!
|
||||
ptr::copy(buf, buf.offset((cap-tail) as isize), head);
|
||||
ptr::copy(buf.offset(tail as isize), buf, cap-tail);
|
||||
ptr::copy(buf, buf.offset((cap - tail) as isize), head);
|
||||
ptr::copy(buf.offset(tail as isize), buf, cap - tail);
|
||||
}
|
||||
} else {
|
||||
// Need to use N swaps to move the ring
|
||||
|
@ -2576,8 +2563,8 @@ mod tests {
|
|||
|
||||
// We should see the correct values in the VecDeque
|
||||
let expected: VecDeque<_> = (0..drain_start)
|
||||
.chain(drain_end..len)
|
||||
.collect();
|
||||
.chain(drain_end..len)
|
||||
.collect();
|
||||
assert_eq!(expected, tester);
|
||||
}
|
||||
}
|
||||
|
@ -2693,19 +2680,19 @@ mod tests {
|
|||
let cap = (2i32.pow(cap_pwr) - 1) as usize;
|
||||
|
||||
// In these cases there is enough free space to solve it with copies
|
||||
for len in 0..((cap+1)/2) {
|
||||
for len in 0..((cap + 1) / 2) {
|
||||
// Test contiguous cases
|
||||
for offset in 0..(cap-len) {
|
||||
for offset in 0..(cap - len) {
|
||||
create_vec_and_test_convert(cap, offset, len)
|
||||
}
|
||||
|
||||
// Test cases where block at end of buffer is bigger than block at start
|
||||
for offset in (cap-len)..(cap-(len/2)) {
|
||||
for offset in (cap - len)..(cap - (len / 2)) {
|
||||
create_vec_and_test_convert(cap, offset, len)
|
||||
}
|
||||
|
||||
// Test cases where block at start of buffer is bigger than block at end
|
||||
for offset in (cap-(len/2))..cap {
|
||||
for offset in (cap - (len / 2))..cap {
|
||||
create_vec_and_test_convert(cap, offset, len)
|
||||
}
|
||||
}
|
||||
|
@ -2714,19 +2701,19 @@ mod tests {
|
|||
// the ring will use swapping when:
|
||||
// (cap + 1 - offset) > (cap + 1 - len) && (len - (cap + 1 - offset)) > (cap + 1 - len))
|
||||
// right block size > free space && left block size > free space
|
||||
for len in ((cap+1)/2)..cap {
|
||||
for len in ((cap + 1) / 2)..cap {
|
||||
// Test contiguous cases
|
||||
for offset in 0..(cap-len) {
|
||||
for offset in 0..(cap - len) {
|
||||
create_vec_and_test_convert(cap, offset, len)
|
||||
}
|
||||
|
||||
// Test cases where block at end of buffer is bigger than block at start
|
||||
for offset in (cap-len)..(cap-(len/2)) {
|
||||
for offset in (cap - len)..(cap - (len / 2)) {
|
||||
create_vec_and_test_convert(cap, offset, len)
|
||||
}
|
||||
|
||||
// Test cases where block at start of buffer is bigger than block at end
|
||||
for offset in (cap-(len/2))..cap {
|
||||
for offset in (cap - (len / 2))..cap {
|
||||
create_vec_and_test_convert(cap, offset, len)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#![feature(test)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode)]
|
||||
#![feature(vec_into_iter_as_slice)]
|
||||
|
||||
extern crate collections;
|
||||
extern crate test;
|
||||
|
|
|
@ -242,7 +242,7 @@ fn main() {
|
|||
"atomic_thread_fence.c"]);
|
||||
}
|
||||
|
||||
if !target.contains("windows") {
|
||||
if !target.contains("redox") && !target.contains("windows") {
|
||||
sources.extend(&["emutls.c"]);
|
||||
}
|
||||
|
||||
|
|
|
@ -393,6 +393,8 @@ pub struct RefCell<T: ?Sized> {
|
|||
/// An enumeration of values returned from the `state` method on a `RefCell<T>`.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
#[unstable(feature = "borrow_state", issue = "27733")]
|
||||
#[rustc_deprecated(since = "1.15.0", reason = "use `try_borrow` instead")]
|
||||
#[allow(deprecated)]
|
||||
pub enum BorrowState {
|
||||
/// The cell is currently being read, there is at least one active `borrow`.
|
||||
Reading,
|
||||
|
@ -511,6 +513,8 @@ impl<T: ?Sized> RefCell<T> {
|
|||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "borrow_state", issue = "27733")]
|
||||
#[rustc_deprecated(since = "1.15.0", reason = "use `try_borrow` instead")]
|
||||
#[allow(deprecated)]
|
||||
#[inline]
|
||||
pub fn borrow_state(&self) -> BorrowState {
|
||||
match self.borrow.get() {
|
||||
|
@ -888,9 +892,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
|
|||
/// `Ref::clone(...)`. A `Clone` implementation or a method would interfere
|
||||
/// with the widespread use of `r.borrow().clone()` to clone the contents of
|
||||
/// a `RefCell`.
|
||||
#[unstable(feature = "cell_extras",
|
||||
reason = "likely to be moved to a method, pending language changes",
|
||||
issue = "27746")]
|
||||
#[stable(feature = "cell_extras", since = "1.15.0")]
|
||||
#[inline]
|
||||
pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
|
||||
Ref {
|
||||
|
|
|
@ -327,9 +327,9 @@ pub trait CharExt {
|
|||
fn len_utf8(self) -> usize;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn len_utf16(self) -> usize;
|
||||
#[unstable(feature = "unicode", issue = "27784")]
|
||||
#[stable(feature = "unicode_encode_char", since = "1.15.0")]
|
||||
fn encode_utf8(self, dst: &mut [u8]) -> &mut str;
|
||||
#[unstable(feature = "unicode", issue = "27784")]
|
||||
#[stable(feature = "unicode_encode_char", since = "1.15.0")]
|
||||
fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16];
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use cell::{UnsafeCell, Cell, RefCell, Ref, RefMut, BorrowState};
|
||||
use cell::{UnsafeCell, Cell, RefCell, Ref, RefMut};
|
||||
use marker::PhantomData;
|
||||
use mem;
|
||||
use num::flt2dec;
|
||||
|
@ -1634,13 +1634,13 @@ impl<T: Copy + Debug> Debug for Cell<T> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Debug> Debug for RefCell<T> {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self.borrow_state() {
|
||||
BorrowState::Unused | BorrowState::Reading => {
|
||||
match self.try_borrow() {
|
||||
Ok(borrow) => {
|
||||
f.debug_struct("RefCell")
|
||||
.field("value", &self.borrow())
|
||||
.field("value", &borrow)
|
||||
.finish()
|
||||
}
|
||||
BorrowState::Writing => {
|
||||
Err(_) => {
|
||||
f.debug_struct("RefCell")
|
||||
.field("value", &"<borrowed>")
|
||||
.finish()
|
||||
|
|
|
@ -255,10 +255,44 @@ pub trait BuildHasher {
|
|||
fn build_hasher(&self) -> Self::Hasher;
|
||||
}
|
||||
|
||||
/// A structure which implements `BuildHasher` for all `Hasher` types which also
|
||||
/// implement `Default`.
|
||||
/// The `BuildHasherDefault` structure is used in scenarios where one has a
|
||||
/// type that implements [`Hasher`] and [`Default`], but needs that type to
|
||||
/// implement [`BuildHasher`].
|
||||
///
|
||||
/// This struct is 0-sized and does not need construction.
|
||||
/// This structure is zero-sized and does not need construction.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Using `BuildHasherDefault` to specify a custom [`BuildHasher`] for
|
||||
/// [`HashMap`]:
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
/// use std::hash::{BuildHasherDefault, Hasher};
|
||||
///
|
||||
/// #[derive(Default)]
|
||||
/// struct MyHasher;
|
||||
///
|
||||
/// impl Hasher for MyHasher {
|
||||
/// fn write(&mut self, bytes: &[u8]) {
|
||||
/// // Your hashing algorithm goes here!
|
||||
/// unimplemented!()
|
||||
/// }
|
||||
///
|
||||
/// fn finish(&self) -> u64 {
|
||||
/// // Your hashing algorithm goes here!
|
||||
/// unimplemented!()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// type MyBuildHasher = BuildHasherDefault<MyHasher>;
|
||||
///
|
||||
/// let hash_map = HashMap::<u32, u32, MyBuildHasher>::default();
|
||||
/// ```
|
||||
///
|
||||
/// [`BuildHasher`]: trait.BuildHasher.html
|
||||
/// [`Default`]: ../default/trait.Default.html
|
||||
/// [`Hasher`]: trait.Hasher.html
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
pub struct BuildHasherDefault<H>(marker::PhantomData<H>);
|
||||
|
||||
|
|
|
@ -1696,12 +1696,11 @@ pub trait Iterator {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iter_max_by)]
|
||||
/// let a = [-3_i32, 0, 1, 5, -10];
|
||||
/// assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_max_by", issue="36105")]
|
||||
#[stable(feature = "iter_max_by", since = "1.15.0")]
|
||||
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
|
||||
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
|
||||
{
|
||||
|
@ -1746,12 +1745,11 @@ pub trait Iterator {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iter_min_by)]
|
||||
/// let a = [-3_i32, 0, 1, 5, -10];
|
||||
/// assert_eq!(*a.iter().min_by(|x, y| x.cmp(y)).unwrap(), -10);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_min_by", issue="36105")]
|
||||
#[stable(feature = "iter_min_by", since = "1.15.0")]
|
||||
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
|
||||
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
|
||||
{
|
||||
|
|
|
@ -117,6 +117,8 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
|
|||
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
|
||||
/// because it will attempt to drop the value previously at `*src`.
|
||||
///
|
||||
/// The pointer must be aligned; use `read_unaligned` if that is not the case.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -137,6 +139,44 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
|||
tmp
|
||||
}
|
||||
|
||||
/// Reads the value from `src` without moving it. This leaves the
|
||||
/// memory in `src` unchanged.
|
||||
///
|
||||
/// Unlike `read`, the pointer may be unaligned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Beyond accepting a raw pointer, this is unsafe because it semantically
|
||||
/// moves the value out of `src` without preventing further usage of `src`.
|
||||
/// If `T` is not `Copy`, then care must be taken to ensure that the value at
|
||||
/// `src` is not used before the data is overwritten again (e.g. with `write`,
|
||||
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
|
||||
/// because it will attempt to drop the value previously at `*src`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_unaligned)]
|
||||
///
|
||||
/// let x = 12;
|
||||
/// let y = &x as *const i32;
|
||||
///
|
||||
/// unsafe {
|
||||
/// assert_eq!(std::ptr::read_unaligned(y), 12);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[unstable(feature = "ptr_unaligned", issue = "37955")]
|
||||
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
|
||||
let mut tmp: T = mem::uninitialized();
|
||||
copy_nonoverlapping(src as *const u8,
|
||||
&mut tmp as *mut T as *mut u8,
|
||||
mem::size_of::<T>());
|
||||
tmp
|
||||
}
|
||||
|
||||
/// Overwrites a memory location with the given value without reading or
|
||||
/// dropping the old value.
|
||||
///
|
||||
|
@ -151,6 +191,8 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
|||
/// This is appropriate for initializing uninitialized memory, or overwriting
|
||||
/// memory that has previously been `read` from.
|
||||
///
|
||||
/// The pointer must be aligned; use `write_unaligned` if that is not the case.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -171,6 +213,47 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
|
|||
intrinsics::move_val_init(&mut *dst, src)
|
||||
}
|
||||
|
||||
/// Overwrites a memory location with the given value without reading or
|
||||
/// dropping the old value.
|
||||
///
|
||||
/// Unlike `write`, the pointer may be unaligned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This operation is marked unsafe because it accepts a raw pointer.
|
||||
///
|
||||
/// It does not drop the contents of `dst`. This is safe, but it could leak
|
||||
/// allocations or resources, so care must be taken not to overwrite an object
|
||||
/// that should be dropped.
|
||||
///
|
||||
/// This is appropriate for initializing uninitialized memory, or overwriting
|
||||
/// memory that has previously been `read` from.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_unaligned)]
|
||||
///
|
||||
/// let mut x = 0;
|
||||
/// let y = &mut x as *mut i32;
|
||||
/// let z = 12;
|
||||
///
|
||||
/// unsafe {
|
||||
/// std::ptr::write_unaligned(y, z);
|
||||
/// assert_eq!(std::ptr::read_unaligned(y), 12);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_unaligned", issue = "37955")]
|
||||
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
|
||||
copy_nonoverlapping(&src as *const T as *const u8,
|
||||
dst as *mut u8,
|
||||
mem::size_of::<T>());
|
||||
mem::forget(src);
|
||||
}
|
||||
|
||||
/// Performs a volatile read of the value from `src` without moving it. This
|
||||
/// leaves the memory in `src` unchanged.
|
||||
///
|
||||
|
|
|
@ -501,6 +501,8 @@ impl<T, E> Result<T, E> {
|
|||
|
||||
/// Returns an iterator over the possibly contained value.
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -512,6 +514,8 @@ impl<T, E> Result<T, E> {
|
|||
/// let x: Result<u32, &str> = Err("nothing!");
|
||||
/// assert_eq!(x.iter().next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
|
@ -520,6 +524,8 @@ impl<T, E> Result<T, E> {
|
|||
|
||||
/// Returns a mutable iterator over the possibly contained value.
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -535,6 +541,8 @@ impl<T, E> Result<T, E> {
|
|||
/// let mut x: Result<u32, &str> = Err("nothing!");
|
||||
/// assert_eq!(x.iter_mut().next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter_mut(&mut self) -> IterMut<T> {
|
||||
|
@ -848,6 +856,8 @@ impl<T, E> IntoIterator for Result<T, E> {
|
|||
|
||||
/// Returns a consuming iterator over the possibly contained value.
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -861,6 +871,8 @@ impl<T, E> IntoIterator for Result<T, E> {
|
|||
/// let v: Vec<u32> = x.into_iter().collect();
|
||||
/// assert_eq!(v, []);
|
||||
/// ```
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
#[inline]
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter { inner: self.ok() }
|
||||
|
@ -893,8 +905,13 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
|
|||
|
||||
/// An iterator over a reference to the [`Ok`] variant of a [`Result`].
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// Created by [`Result::iter`].
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
/// [`Result`]: enum.Result.html
|
||||
/// [`Result::iter`]: enum.Result.html#method.iter
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, T: 'a> { inner: Option<&'a T> }
|
||||
|
@ -934,8 +951,11 @@ impl<'a, T> Clone for Iter<'a, T> {
|
|||
|
||||
/// An iterator over a mutable reference to the [`Ok`] variant of a [`Result`].
|
||||
///
|
||||
/// Created by [`Result::iter_mut`].
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
/// [`Result`]: enum.Result.html
|
||||
/// [`Result::iter_mut`]: enum.Result.html#method.iter_mut
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> }
|
||||
|
@ -968,9 +988,12 @@ impl<'a, T> FusedIterator for IterMut<'a, T> {}
|
|||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {}
|
||||
|
||||
/// An iterator over the value in a [`Ok`] variant of a [`Result`]. This struct is
|
||||
/// created by the [`into_iter`] method on [`Result`][`Result`] (provided by
|
||||
/// the [`IntoIterator`] trait).
|
||||
/// An iterator over the value in a [`Ok`] variant of a [`Result`].
|
||||
///
|
||||
/// The iterator yields one value if the result is [`Ok`], otherwise none.
|
||||
///
|
||||
/// This struct is created by the [`into_iter`] method on
|
||||
/// [`Result`][`Result`] (provided by the [`IntoIterator`] trait).
|
||||
///
|
||||
/// [`Ok`]: enum.Result.html#variant.Ok
|
||||
/// [`Result`]: enum.Result.html
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
// * The `raw` and `bytes` submodules.
|
||||
// * Boilerplate trait implementations.
|
||||
|
||||
use borrow::Borrow;
|
||||
use cmp::Ordering::{self, Less, Equal, Greater};
|
||||
use cmp;
|
||||
use fmt;
|
||||
|
@ -100,15 +101,17 @@ pub trait SliceExt {
|
|||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn as_ptr(&self) -> *const Self::Item;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn binary_search(&self, x: &Self::Item) -> Result<usize, usize>
|
||||
where Self::Item: Ord;
|
||||
fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize>
|
||||
where Self::Item: Borrow<Q>,
|
||||
Q: Ord;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
|
||||
where F: FnMut(&'a Self::Item) -> Ordering;
|
||||
#[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
|
||||
fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize>
|
||||
fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, f: F) -> Result<usize, usize>
|
||||
where F: FnMut(&'a Self::Item) -> B,
|
||||
B: Ord;
|
||||
B: Borrow<Q>,
|
||||
Q: Ord;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn len(&self) -> usize;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
|
@ -493,8 +496,8 @@ impl<T> SliceExt for [T] {
|
|||
m >= n && needle == &self[m-n..]
|
||||
}
|
||||
|
||||
fn binary_search(&self, x: &T) -> Result<usize, usize> where T: Ord {
|
||||
self.binary_search_by(|p| p.cmp(x))
|
||||
fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize> where T: Borrow<Q>, Q: Ord {
|
||||
self.binary_search_by(|p| p.borrow().cmp(x))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -522,11 +525,12 @@ impl<T> SliceExt for [T] {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
|
||||
fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result<usize, usize>
|
||||
where F: FnMut(&'a Self::Item) -> B,
|
||||
B: Ord
|
||||
B: Borrow<Q>,
|
||||
Q: Ord
|
||||
{
|
||||
self.binary_search_by(|k| f(k).cmp(b))
|
||||
self.binary_search_by(|k| f(k).borrow().cmp(b))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,6 @@ impl AtomicBool {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_access)]
|
||||
/// use std::sync::atomic::{AtomicBool, Ordering};
|
||||
///
|
||||
/// let mut some_bool = AtomicBool::new(true);
|
||||
|
@ -212,7 +211,7 @@ impl AtomicBool {
|
|||
/// assert_eq!(some_bool.load(Ordering::SeqCst), false);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "atomic_access", issue = "35603")]
|
||||
#[stable(feature = "atomic_access", since = "1.15.0")]
|
||||
pub fn get_mut(&mut self) -> &mut bool {
|
||||
unsafe { &mut *(self.v.get() as *mut bool) }
|
||||
}
|
||||
|
@ -225,14 +224,13 @@ impl AtomicBool {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_access)]
|
||||
/// use std::sync::atomic::AtomicBool;
|
||||
///
|
||||
/// let some_bool = AtomicBool::new(true);
|
||||
/// assert_eq!(some_bool.into_inner(), true);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "atomic_access", issue = "35603")]
|
||||
#[stable(feature = "atomic_access", since = "1.15.0")]
|
||||
pub fn into_inner(self) -> bool {
|
||||
unsafe { self.v.into_inner() != 0 }
|
||||
}
|
||||
|
@ -588,7 +586,6 @@ impl<T> AtomicPtr<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_access)]
|
||||
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
///
|
||||
/// let mut atomic_ptr = AtomicPtr::new(&mut 10);
|
||||
|
@ -596,7 +593,7 @@ impl<T> AtomicPtr<T> {
|
|||
/// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "atomic_access", issue = "35603")]
|
||||
#[stable(feature = "atomic_access", since = "1.15.0")]
|
||||
pub fn get_mut(&mut self) -> &mut *mut T {
|
||||
unsafe { &mut *self.p.get() }
|
||||
}
|
||||
|
@ -609,14 +606,13 @@ impl<T> AtomicPtr<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_access)]
|
||||
/// use std::sync::atomic::AtomicPtr;
|
||||
///
|
||||
/// let atomic_ptr = AtomicPtr::new(&mut 5);
|
||||
/// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "atomic_access", issue = "35603")]
|
||||
#[stable(feature = "atomic_access", since = "1.15.0")]
|
||||
pub fn into_inner(self) -> *mut T {
|
||||
unsafe { self.p.into_inner() }
|
||||
}
|
||||
|
@ -883,7 +879,6 @@ macro_rules! atomic_int {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_access)]
|
||||
/// use std::sync::atomic::{AtomicIsize, Ordering};
|
||||
///
|
||||
/// let mut some_isize = AtomicIsize::new(10);
|
||||
|
@ -905,7 +900,6 @@ macro_rules! atomic_int {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_access)]
|
||||
/// use std::sync::atomic::AtomicIsize;
|
||||
///
|
||||
/// let some_isize = AtomicIsize::new(5);
|
||||
|
@ -1261,7 +1255,7 @@ atomic_int!{
|
|||
stable(feature = "rust1", since = "1.0.0"),
|
||||
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
||||
stable(feature = "atomic_debug", since = "1.3.0"),
|
||||
unstable(feature = "atomic_access", issue = "35603"),
|
||||
stable(feature = "atomic_access", since = "1.15.0"),
|
||||
isize AtomicIsize ATOMIC_ISIZE_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
|
@ -1269,7 +1263,7 @@ atomic_int!{
|
|||
stable(feature = "rust1", since = "1.0.0"),
|
||||
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
||||
stable(feature = "atomic_debug", since = "1.3.0"),
|
||||
unstable(feature = "atomic_access", issue = "35603"),
|
||||
stable(feature = "atomic_access", since = "1.15.0"),
|
||||
usize AtomicUsize ATOMIC_USIZE_INIT
|
||||
}
|
||||
|
||||
|
|
|
@ -59,22 +59,22 @@ fn double_imm_borrow() {
|
|||
fn no_mut_then_imm_borrow() {
|
||||
let x = RefCell::new(0);
|
||||
let _b1 = x.borrow_mut();
|
||||
assert_eq!(x.borrow_state(), BorrowState::Writing);
|
||||
assert!(x.try_borrow().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_imm_then_borrow_mut() {
|
||||
let x = RefCell::new(0);
|
||||
let _b1 = x.borrow();
|
||||
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||
assert!(x.try_borrow_mut().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_double_borrow_mut() {
|
||||
let x = RefCell::new(0);
|
||||
assert_eq!(x.borrow_state(), BorrowState::Unused);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
let _b1 = x.borrow_mut();
|
||||
assert_eq!(x.borrow_state(), BorrowState::Writing);
|
||||
assert!(x.try_borrow().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -102,7 +102,8 @@ fn double_borrow_single_release_no_borrow_mut() {
|
|||
{
|
||||
let _b2 = x.borrow();
|
||||
}
|
||||
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
assert!(x.try_borrow_mut().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -119,14 +120,18 @@ fn ref_clone_updates_flag() {
|
|||
let x = RefCell::new(0);
|
||||
{
|
||||
let b1 = x.borrow();
|
||||
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
assert!(x.try_borrow_mut().is_err());
|
||||
{
|
||||
let _b2 = Ref::clone(&b1);
|
||||
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
assert!(x.try_borrow_mut().is_err());
|
||||
}
|
||||
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
assert!(x.try_borrow_mut().is_err());
|
||||
}
|
||||
assert_eq!(x.borrow_state(), BorrowState::Unused);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
assert!(x.try_borrow_mut().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -134,15 +139,19 @@ fn ref_map_does_not_update_flag() {
|
|||
let x = RefCell::new(Some(5));
|
||||
{
|
||||
let b1: Ref<Option<u32>> = x.borrow();
|
||||
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
assert!(x.try_borrow_mut().is_err());
|
||||
{
|
||||
let b2: Ref<u32> = Ref::map(b1, |o| o.as_ref().unwrap());
|
||||
assert_eq!(*b2, 5);
|
||||
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
assert!(x.try_borrow_mut().is_err());
|
||||
}
|
||||
assert_eq!(x.borrow_state(), BorrowState::Unused);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
assert!(x.try_borrow_mut().is_ok());
|
||||
}
|
||||
assert_eq!(x.borrow_state(), BorrowState::Unused);
|
||||
assert!(x.try_borrow().is_ok());
|
||||
assert!(x.try_borrow_mut().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -247,5 +256,3 @@ fn refcell_ref_coercion() {
|
|||
assert_eq!(&*coerced, comp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -10,9 +10,7 @@
|
|||
|
||||
#![deny(warnings)]
|
||||
|
||||
#![feature(borrow_state)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(cell_extras)]
|
||||
#![feature(char_escape_debug)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(core_private_bignum)]
|
||||
|
@ -32,10 +30,9 @@
|
|||
#![feature(try_from)]
|
||||
#![feature(unicode)]
|
||||
#![feature(unique)]
|
||||
#![feature(iter_max_by)]
|
||||
#![feature(iter_min_by)]
|
||||
#![feature(ordering_chaining)]
|
||||
#![feature(result_unwrap_or_default)]
|
||||
#![feature(ptr_unaligned)]
|
||||
|
||||
extern crate core;
|
||||
extern crate test;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use core::ptr::*;
|
||||
use core::cell::RefCell;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
|
@ -189,3 +190,25 @@ pub fn test_variadic_fnptr() {
|
|||
let mut s = SipHasher::new();
|
||||
assert_eq!(p.hash(&mut s), q.hash(&mut s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_unaligned_drop() {
|
||||
thread_local! {
|
||||
static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
|
||||
}
|
||||
|
||||
struct Dropper(u32);
|
||||
|
||||
impl Drop for Dropper {
|
||||
fn drop(&mut self) {
|
||||
DROPS.with(|d| d.borrow_mut().push(self.0));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let c = Dropper(0);
|
||||
let mut t = Dropper(1);
|
||||
unsafe { write_unaligned(&mut t, c); }
|
||||
}
|
||||
DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 0ac39c5ccf6a04395b7c40dd62321cb91f63f160
|
||||
Subproject commit e49e9bb7c3d9c7f2fd893f0ee0db81617b8db21f
|
|
@ -28,7 +28,7 @@
|
|||
#![panic_runtime]
|
||||
#![feature(panic_runtime)]
|
||||
#![cfg_attr(unix, feature(libc))]
|
||||
#![cfg_attr(windows, feature(core_intrinsics))]
|
||||
#![cfg_attr(any(target_os = "redox", windows), feature(core_intrinsics))]
|
||||
|
||||
// Rust's "try" function, but if we're aborting on panics we just call the
|
||||
// function as there's nothing else we need to do here.
|
||||
|
@ -61,7 +61,7 @@ pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 {
|
|||
libc::abort();
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[cfg(any(target_os = "redox", windows))]
|
||||
unsafe fn abort() -> ! {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ mod imp;
|
|||
|
||||
// i686-pc-windows-gnu and all others
|
||||
#[cfg(any(all(unix, not(target_os = "emscripten")),
|
||||
target_os = "redox",
|
||||
all(windows, target_arch = "x86", target_env = "gnu")))]
|
||||
#[path = "gcc.rs"]
|
||||
mod imp;
|
||||
|
|
|
@ -418,7 +418,7 @@ to see something like:
|
|||
|
||||
Hir(foo) -> Collect(bar)
|
||||
Collect(bar) -> TypeckItemBody(bar)
|
||||
|
||||
|
||||
That first edge looks suspicious to you. So you set
|
||||
`RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and
|
||||
then observe the backtrace. Voila, bug fixed!
|
||||
|
@ -440,6 +440,4 @@ To achieve this, the HIR map will detect if the def-id originates in
|
|||
an inlined node and add a dependency to a suitable `MetaData` node
|
||||
instead. If you are reading a HIR node and are not sure if it may be
|
||||
inlined or not, you can use `tcx.map.read(node_id)` and it will detect
|
||||
whether the node is inlined or not and do the right thing. You can
|
||||
also use `tcx.map.is_inlined_def_id()` and
|
||||
`tcx.map.is_inlined_node_id()` to test.
|
||||
whether the node is inlined or not and do the right thing.
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
//! created. See `./README.md` for details.
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use std::cell::{BorrowState, RefCell};
|
||||
use std::cell::RefCell;
|
||||
use std::env;
|
||||
|
||||
use super::DepNode;
|
||||
|
@ -71,15 +71,11 @@ impl ShadowGraph {
|
|||
|
||||
pub fn enqueue(&self, message: &DepMessage) {
|
||||
if ENABLED {
|
||||
match self.stack.borrow_state() {
|
||||
BorrowState::Unused => {}
|
||||
_ => {
|
||||
// When we apply edge filters, that invokes the
|
||||
// Debug trait on DefIds, which in turn reads from
|
||||
// various bits of state and creates reads! Ignore
|
||||
// those recursive reads.
|
||||
return;
|
||||
}
|
||||
if self.stack.try_borrow().is_err() {
|
||||
// When we apply edge filters, that invokes the Debug trait on
|
||||
// DefIds, which in turn reads from various bits of state and
|
||||
// creates reads! Ignore those recursive reads.
|
||||
return;
|
||||
}
|
||||
|
||||
let mut stack = self.stack.borrow_mut();
|
||||
|
|
|
@ -40,7 +40,6 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
|||
let task_id = (self.dep_node_fn)(item_def_id);
|
||||
let _task = self.tcx.dep_graph.in_task(task_id.clone());
|
||||
debug!("Started task {:?}", task_id);
|
||||
assert!(!self.tcx.map.is_inlined_def_id(item_def_id));
|
||||
self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
|
||||
self.visitor.visit_item(i);
|
||||
debug!("Ended task {:?}", task_id);
|
||||
|
@ -51,7 +50,6 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
|||
let task_id = (self.dep_node_fn)(impl_item_def_id);
|
||||
let _task = self.tcx.dep_graph.in_task(task_id.clone());
|
||||
debug!("Started task {:?}", task_id);
|
||||
assert!(!self.tcx.map.is_inlined_def_id(impl_item_def_id));
|
||||
self.tcx.dep_graph.read(DepNode::Hir(impl_item_def_id));
|
||||
self.visitor.visit_impl_item(i);
|
||||
debug!("Ended task {:?}", task_id);
|
||||
|
|
|
@ -1236,6 +1236,23 @@ struct Foo<'a, T: 'a> {
|
|||
foo: &'a T
|
||||
}
|
||||
```
|
||||
|
||||
To see why this is important, consider the case where `T` is itself a reference
|
||||
(e.g., `T = &str`). If we don't include the restriction that `T: 'a`, the
|
||||
following code would be perfectly legal:
|
||||
|
||||
```compile_fail,E0309
|
||||
struct Foo<'a, T> {
|
||||
foo: &'a T
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = "42".to_string();
|
||||
let f = Foo{foo: &v};
|
||||
drop(v);
|
||||
println!("{}", f.foo); // but we've already dropped v!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0310: r##"
|
||||
|
|
|
@ -120,9 +120,7 @@ impl fmt::Debug for DefId {
|
|||
|
||||
ty::tls::with_opt(|opt_tcx| {
|
||||
if let Some(tcx) = opt_tcx {
|
||||
if let Some(def_path) = tcx.opt_def_path(*self) {
|
||||
write!(f, " => {}", def_path.to_string(tcx))?;
|
||||
}
|
||||
write!(f, " => {}", tcx.def_path(*self).to_string(tcx))?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
|
|
@ -365,7 +365,6 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
|
|||
pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
|
||||
visitor.visit_id(macro_def.id);
|
||||
visitor.visit_name(macro_def.span, macro_def.name);
|
||||
walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
|
||||
walk_list!(visitor, visit_attribute, ¯o_def.attrs);
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ pub struct LoweringContext<'a> {
|
|||
}
|
||||
|
||||
pub trait Resolver {
|
||||
// Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
|
||||
// Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc.
|
||||
fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool);
|
||||
|
||||
// Obtain the resolution for a node id
|
||||
|
@ -337,7 +337,6 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
let proj_start = p.segments.len() - resolution.depth;
|
||||
let path = P(hir::Path {
|
||||
global: p.global,
|
||||
def: resolution.base_def,
|
||||
segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
|
||||
let param_mode = match (qself_position, param_mode) {
|
||||
|
@ -404,12 +403,17 @@ impl<'a> LoweringContext<'a> {
|
|||
id: NodeId,
|
||||
p: &Path,
|
||||
name: Option<Name>,
|
||||
param_mode: ParamMode)
|
||||
param_mode: ParamMode,
|
||||
defaults_to_global: bool)
|
||||
-> hir::Path {
|
||||
let mut segments = p.segments.iter();
|
||||
if defaults_to_global && p.is_global() {
|
||||
segments.next();
|
||||
}
|
||||
|
||||
hir::Path {
|
||||
global: p.global,
|
||||
def: self.expect_full_def(id),
|
||||
segments: p.segments.iter().map(|segment| {
|
||||
segments: segments.map(|segment| {
|
||||
self.lower_path_segment(segment, param_mode)
|
||||
}).chain(name.map(|name| {
|
||||
hir::PathSegment {
|
||||
|
@ -424,22 +428,29 @@ impl<'a> LoweringContext<'a> {
|
|||
fn lower_path(&mut self,
|
||||
id: NodeId,
|
||||
p: &Path,
|
||||
param_mode: ParamMode)
|
||||
param_mode: ParamMode,
|
||||
defaults_to_global: bool)
|
||||
-> hir::Path {
|
||||
self.lower_path_extra(id, p, None, param_mode)
|
||||
self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
|
||||
}
|
||||
|
||||
fn lower_path_segment(&mut self,
|
||||
segment: &PathSegment,
|
||||
param_mode: ParamMode)
|
||||
-> hir::PathSegment {
|
||||
let parameters = match segment.parameters {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
|
||||
hir::AngleBracketedParameters(data)
|
||||
let parameters = if let Some(ref parameters) = segment.parameters {
|
||||
match **parameters {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
|
||||
hir::AngleBracketedParameters(data)
|
||||
}
|
||||
PathParameters::Parenthesized(ref data) => {
|
||||
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
|
||||
}
|
||||
}
|
||||
PathParameters::Parenthesized(ref data) =>
|
||||
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
|
||||
} else {
|
||||
let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
|
||||
hir::AngleBracketedParameters(data)
|
||||
};
|
||||
|
||||
hir::PathSegment {
|
||||
|
@ -596,8 +607,8 @@ impl<'a> LoweringContext<'a> {
|
|||
// Check if the where clause type is a plain type parameter.
|
||||
match bound_pred.bounded_ty.node {
|
||||
TyKind::Path(None, ref path)
|
||||
if !path.global && path.segments.len() == 1 &&
|
||||
bound_pred.bound_lifetimes.is_empty() => {
|
||||
if path.segments.len() == 1 &&
|
||||
bound_pred.bound_lifetimes.is_empty() => {
|
||||
if let Some(Def::TyParam(def_id)) =
|
||||
self.resolver.get_resolution(bound_pred.bounded_ty.id)
|
||||
.map(|d| d.base_def) {
|
||||
|
@ -671,7 +682,7 @@ impl<'a> LoweringContext<'a> {
|
|||
span}) => {
|
||||
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
|
||||
id: id,
|
||||
path: self.lower_path(id, path, ParamMode::Explicit),
|
||||
path: self.lower_path(id, path, ParamMode::Explicit, false),
|
||||
ty: self.lower_ty(ty),
|
||||
span: span,
|
||||
})
|
||||
|
@ -701,7 +712,7 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
|
||||
hir::TraitRef {
|
||||
path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit),
|
||||
path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit, false),
|
||||
ref_id: p.ref_id,
|
||||
}
|
||||
}
|
||||
|
@ -794,7 +805,7 @@ impl<'a> LoweringContext<'a> {
|
|||
};
|
||||
|
||||
let mut path = self.lower_path_extra(import.id, path, suffix,
|
||||
ParamMode::Explicit);
|
||||
ParamMode::Explicit, true);
|
||||
path.span = span;
|
||||
self.items.insert(import.id, hir::Item {
|
||||
id: import.id,
|
||||
|
@ -808,7 +819,7 @@ impl<'a> LoweringContext<'a> {
|
|||
path
|
||||
}
|
||||
};
|
||||
let path = P(self.lower_path(id, path, ParamMode::Explicit));
|
||||
let path = P(self.lower_path(id, path, ParamMode::Explicit, true));
|
||||
let kind = match view_path.node {
|
||||
ViewPathSimple(ident, _) => {
|
||||
*name = ident.name;
|
||||
|
@ -987,8 +998,6 @@ impl<'a> LoweringContext<'a> {
|
|||
attrs: self.lower_attrs(&m.attrs),
|
||||
id: m.id,
|
||||
span: m.span,
|
||||
imported_from: m.imported_from.map(|x| x.name),
|
||||
allow_internal_unstable: m.allow_internal_unstable,
|
||||
body: m.body.clone().into(),
|
||||
}
|
||||
}
|
||||
|
@ -1131,7 +1140,6 @@ impl<'a> LoweringContext<'a> {
|
|||
Some(def) => {
|
||||
hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path {
|
||||
span: pth1.span,
|
||||
global: false,
|
||||
def: def,
|
||||
segments: hir_vec![
|
||||
hir::PathSegment::from_name(pth1.node.name)
|
||||
|
@ -1874,7 +1882,7 @@ impl<'a> LoweringContext<'a> {
|
|||
Visibility::Crate(_) => hir::Visibility::Crate,
|
||||
Visibility::Restricted { ref path, id } => {
|
||||
hir::Visibility::Restricted {
|
||||
path: P(self.lower_path(id, path, ParamMode::Explicit)),
|
||||
path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
|
||||
id: id
|
||||
}
|
||||
}
|
||||
|
@ -1967,7 +1975,6 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path {
|
||||
span: span,
|
||||
global: false,
|
||||
def: def,
|
||||
segments: hir_vec![hir::PathSegment::from_name(id)],
|
||||
})));
|
||||
|
@ -2135,17 +2142,12 @@ impl<'a> LoweringContext<'a> {
|
|||
/// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
|
||||
/// The path is also resolved according to `is_value`.
|
||||
fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
|
||||
let idents = self.crate_root.iter().chain(components);
|
||||
|
||||
let segments: Vec<_> = idents.map(|name| {
|
||||
hir::PathSegment::from_name(Symbol::intern(name))
|
||||
}).collect();
|
||||
|
||||
let mut path = hir::Path {
|
||||
span: span,
|
||||
global: true,
|
||||
def: Def::Err,
|
||||
segments: segments.into(),
|
||||
segments: iter::once(keywords::CrateRoot.name()).chain({
|
||||
self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
|
||||
}).map(hir::PathSegment::from_name).collect(),
|
||||
};
|
||||
|
||||
self.resolver.resolve_hir_path(&mut path, is_value);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
use super::*;
|
||||
|
||||
use hir::intravisit::{Visitor, NestedVisitorMap};
|
||||
use hir::def_id::DefId;
|
||||
use middle::cstore::InlinedItem;
|
||||
use std::iter::repeat;
|
||||
use syntax::ast::{NodeId, CRATE_NODE_ID};
|
||||
|
@ -47,8 +46,6 @@ impl<'ast> NodeCollector<'ast> {
|
|||
pub fn extend(krate: &'ast Crate,
|
||||
parent: &'ast InlinedItem,
|
||||
parent_node: NodeId,
|
||||
parent_def_path: DefPath,
|
||||
parent_def_id: DefId,
|
||||
map: Vec<MapEntry<'ast>>)
|
||||
-> NodeCollector<'ast> {
|
||||
let mut collector = NodeCollector {
|
||||
|
@ -58,7 +55,6 @@ impl<'ast> NodeCollector<'ast> {
|
|||
ignore_nested_items: true
|
||||
};
|
||||
|
||||
assert_eq!(parent_def_path.krate, parent_def_id.krate);
|
||||
collector.insert_entry(parent_node, RootInlinedParent(parent));
|
||||
|
||||
collector
|
||||
|
|
|
@ -9,12 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use hir::map::definitions::*;
|
||||
|
||||
use hir;
|
||||
use hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
|
||||
|
||||
use middle::cstore::InlinedItem;
|
||||
use hir::def_id::{CRATE_DEF_INDEX, DefIndex};
|
||||
|
||||
use syntax::ast::*;
|
||||
use syntax::ext::hygiene::Mark;
|
||||
|
@ -23,9 +18,6 @@ use syntax::symbol::{Symbol, keywords};
|
|||
|
||||
/// Creates def ids for nodes in the HIR.
|
||||
pub struct DefCollector<'a> {
|
||||
// If we are walking HIR (c.f., AST), we need to keep a reference to the
|
||||
// crate.
|
||||
hir_crate: Option<&'a hir::Crate>,
|
||||
definitions: &'a mut Definitions,
|
||||
parent_def: Option<DefIndex>,
|
||||
pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>,
|
||||
|
@ -40,43 +32,16 @@ pub struct MacroInvocationData {
|
|||
impl<'a> DefCollector<'a> {
|
||||
pub fn new(definitions: &'a mut Definitions) -> Self {
|
||||
DefCollector {
|
||||
hir_crate: None,
|
||||
definitions: definitions,
|
||||
parent_def: None,
|
||||
visit_macro_invoc: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend(parent_node: NodeId,
|
||||
parent_def_path: DefPath,
|
||||
parent_def_id: DefId,
|
||||
definitions: &'a mut Definitions)
|
||||
-> Self {
|
||||
let mut collector = DefCollector::new(definitions);
|
||||
|
||||
assert_eq!(parent_def_path.krate, parent_def_id.krate);
|
||||
let root_path = Box::new(InlinedRootPath {
|
||||
data: parent_def_path.data,
|
||||
def_id: parent_def_id,
|
||||
});
|
||||
|
||||
let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
|
||||
collector.parent_def = Some(def);
|
||||
|
||||
collector
|
||||
}
|
||||
|
||||
pub fn collect_root(&mut self) {
|
||||
let root = self.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
|
||||
assert_eq!(root, CRATE_DEF_INDEX);
|
||||
self.parent_def = Some(root);
|
||||
|
||||
self.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
|
||||
}
|
||||
|
||||
pub fn walk_item(&mut self, ii: &'a InlinedItem, krate: &'a hir::Crate) {
|
||||
self.hir_crate = Some(krate);
|
||||
ii.visit(self);
|
||||
}
|
||||
|
||||
fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
|
||||
|
@ -114,16 +79,6 @@ impl<'a> DefCollector<'a> {
|
|||
self.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
fn visit_hir_const_integer(&mut self, expr: &hir::Expr) {
|
||||
// FIXME(eddyb) Closures should have separate
|
||||
// function definition IDs and expression IDs.
|
||||
if let hir::ExprClosure(..) = expr.node {
|
||||
return;
|
||||
}
|
||||
|
||||
self.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
fn visit_macro_invoc(&mut self, id: NodeId, const_integer: bool) {
|
||||
if let Some(ref mut visit) = self.visit_macro_invoc {
|
||||
visit(MacroInvocationData {
|
||||
|
@ -324,169 +279,3 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We walk the HIR rather than the AST when reading items from metadata.
|
||||
impl<'ast> Visitor<'ast> for DefCollector<'ast> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'ast> {
|
||||
// note however that we override `visit_body` below
|
||||
NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_body(&mut self, id: hir::ExprId) {
|
||||
if let Some(krate) = self.hir_crate {
|
||||
self.visit_expr(krate.expr(id));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, i: &'ast hir::Item) {
|
||||
debug!("visit_item: {:?}", i);
|
||||
|
||||
// Pick the def data. This need not be unique, but the more
|
||||
// information we encapsulate into
|
||||
let def_data = match i.node {
|
||||
hir::ItemDefaultImpl(..) | hir::ItemImpl(..) =>
|
||||
DefPathData::Impl,
|
||||
hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) |
|
||||
hir::ItemTrait(..) | hir::ItemExternCrate(..) | hir::ItemMod(..) |
|
||||
hir::ItemForeignMod(..) | hir::ItemTy(..) =>
|
||||
DefPathData::TypeNs(i.name.as_str()),
|
||||
hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) =>
|
||||
DefPathData::ValueNs(i.name.as_str()),
|
||||
hir::ItemUse(..) => DefPathData::Misc,
|
||||
};
|
||||
let def = self.create_def(i.id, def_data);
|
||||
|
||||
self.with_parent(def, |this| {
|
||||
match i.node {
|
||||
hir::ItemEnum(ref enum_definition, _) => {
|
||||
for v in &enum_definition.variants {
|
||||
let variant_def_index =
|
||||
this.create_def(v.node.data.id(),
|
||||
DefPathData::EnumVariant(v.node.name.as_str()));
|
||||
|
||||
this.with_parent(variant_def_index, |this| {
|
||||
for field in v.node.data.fields() {
|
||||
this.create_def(field.id,
|
||||
DefPathData::Field(field.name.as_str()));
|
||||
}
|
||||
if let Some(ref expr) = v.node.disr_expr {
|
||||
this.visit_hir_const_integer(expr);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
hir::ItemStruct(ref struct_def, _) |
|
||||
hir::ItemUnion(ref struct_def, _) => {
|
||||
// If this is a tuple-like struct, register the constructor.
|
||||
if !struct_def.is_struct() {
|
||||
this.create_def(struct_def.id(),
|
||||
DefPathData::StructCtor);
|
||||
}
|
||||
|
||||
for field in struct_def.fields() {
|
||||
this.create_def(field.id, DefPathData::Field(field.name.as_str()));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
intravisit::walk_item(this, i);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) {
|
||||
let def = self.create_def(foreign_item.id,
|
||||
DefPathData::ValueNs(foreign_item.name.as_str()));
|
||||
|
||||
self.with_parent(def, |this| {
|
||||
intravisit::walk_foreign_item(this, foreign_item);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, generics: &'ast hir::Generics) {
|
||||
for ty_param in generics.ty_params.iter() {
|
||||
self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name.as_str()));
|
||||
}
|
||||
|
||||
intravisit::walk_generics(self, generics);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
|
||||
let def_data = match ti.node {
|
||||
hir::MethodTraitItem(..) | hir::ConstTraitItem(..) =>
|
||||
DefPathData::ValueNs(ti.name.as_str()),
|
||||
hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name.as_str()),
|
||||
};
|
||||
|
||||
let def = self.create_def(ti.id, def_data);
|
||||
self.with_parent(def, |this| {
|
||||
if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
|
||||
this.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
intravisit::walk_trait_item(this, ti);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
|
||||
let def_data = match ii.node {
|
||||
hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) =>
|
||||
DefPathData::ValueNs(ii.name.as_str()),
|
||||
hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name.as_str()),
|
||||
};
|
||||
|
||||
let def = self.create_def(ii.id, def_data);
|
||||
self.with_parent(def, |this| {
|
||||
if let hir::ImplItemKind::Const(_, ref expr) = ii.node {
|
||||
this.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
intravisit::walk_impl_item(this, ii);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &'ast hir::Pat) {
|
||||
let parent_def = self.parent_def;
|
||||
|
||||
if let hir::PatKind::Binding(_, _, name, _) = pat.node {
|
||||
let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str()));
|
||||
self.parent_def = Some(def);
|
||||
}
|
||||
|
||||
intravisit::walk_pat(self, pat);
|
||||
self.parent_def = parent_def;
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'ast hir::Expr) {
|
||||
let parent_def = self.parent_def;
|
||||
|
||||
if let hir::ExprRepeat(_, ref count) = expr.node {
|
||||
self.visit_hir_const_integer(count);
|
||||
}
|
||||
|
||||
if let hir::ExprClosure(..) = expr.node {
|
||||
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
|
||||
self.parent_def = Some(def);
|
||||
}
|
||||
|
||||
intravisit::walk_expr(self, expr);
|
||||
self.parent_def = parent_def;
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'ast hir::Ty) {
|
||||
if let hir::TyArray(_, ref length) = ty.node {
|
||||
self.visit_hir_const_integer(length);
|
||||
}
|
||||
if let hir::TyImplTrait(..) = ty.node {
|
||||
self.create_def(ty.id, DefPathData::ImplTrait);
|
||||
}
|
||||
intravisit::walk_ty(self, ty);
|
||||
}
|
||||
|
||||
fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
|
||||
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
|
||||
}
|
||||
|
||||
fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
|
||||
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name.as_str()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,22 +8,119 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! For each definition, we track the following data. A definition
|
||||
//! here is defined somewhat circularly as "something with a def-id",
|
||||
//! but it generally corresponds to things like structs, enums, etc.
|
||||
//! There are also some rather random cases (like const initializer
|
||||
//! expressions) that are mostly just leftovers.
|
||||
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||
use std::fmt::Write;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use syntax::ast;
|
||||
use syntax::symbol::{Symbol, InternedString};
|
||||
use ty::TyCtxt;
|
||||
use util::nodemap::NodeMap;
|
||||
|
||||
/// The definition table containing node definitions
|
||||
/// The DefPathTable maps DefIndexes to DefKeys and vice versa.
|
||||
/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
|
||||
/// stores the DefIndex of its parent.
|
||||
/// There is one DefPathTable for each crate.
|
||||
#[derive(Clone)]
|
||||
pub struct DefPathTable {
|
||||
index_to_key: Vec<DefKey>,
|
||||
key_to_index: FxHashMap<DefKey, DefIndex>,
|
||||
}
|
||||
|
||||
impl DefPathTable {
|
||||
fn insert(&mut self, key: DefKey) -> DefIndex {
|
||||
let index = DefIndex::new(self.index_to_key.len());
|
||||
debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
|
||||
self.index_to_key.push(key.clone());
|
||||
self.key_to_index.insert(key, index);
|
||||
index
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
||||
self.index_to_key[index.as_usize()].clone()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn def_index_for_def_key(&self, key: &DefKey) -> Option<DefIndex> {
|
||||
self.key_to_index.get(key).cloned()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn contains_key(&self, key: &DefKey) -> bool {
|
||||
self.key_to_index.contains_key(key)
|
||||
}
|
||||
|
||||
pub fn retrace_path(&self,
|
||||
path_data: &[DisambiguatedDefPathData])
|
||||
-> Option<DefIndex> {
|
||||
let root_key = DefKey {
|
||||
parent: None,
|
||||
disambiguated_data: DisambiguatedDefPathData {
|
||||
data: DefPathData::CrateRoot,
|
||||
disambiguator: 0,
|
||||
},
|
||||
};
|
||||
|
||||
let root_index = self.key_to_index
|
||||
.get(&root_key)
|
||||
.expect("no root key?")
|
||||
.clone();
|
||||
|
||||
debug!("retrace_path: root_index={:?}", root_index);
|
||||
|
||||
let mut index = root_index;
|
||||
for data in path_data {
|
||||
let key = DefKey { parent: Some(index), disambiguated_data: data.clone() };
|
||||
debug!("retrace_path: key={:?}", key);
|
||||
match self.key_to_index.get(&key) {
|
||||
Some(&i) => index = i,
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
|
||||
Some(index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Encodable for DefPathTable {
|
||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
self.index_to_key.encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for DefPathTable {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
|
||||
let index_to_key: Vec<DefKey> = Decodable::decode(d)?;
|
||||
let key_to_index = index_to_key.iter()
|
||||
.enumerate()
|
||||
.map(|(index, key)| (key.clone(), DefIndex::new(index)))
|
||||
.collect();
|
||||
Ok(DefPathTable {
|
||||
index_to_key: index_to_key,
|
||||
key_to_index: key_to_index,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// The definition table containing node definitions.
|
||||
/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a
|
||||
/// mapping from NodeIds to local DefIds.
|
||||
#[derive(Clone)]
|
||||
pub struct Definitions {
|
||||
data: Vec<DefData>,
|
||||
key_map: FxHashMap<DefKey, DefIndex>,
|
||||
node_map: NodeMap<DefIndex>,
|
||||
table: DefPathTable,
|
||||
node_to_def_index: NodeMap<DefIndex>,
|
||||
def_index_to_node: Vec<ast::NodeId>,
|
||||
}
|
||||
|
||||
/// A unique identifier that we can use to lookup a definition
|
||||
|
@ -50,19 +147,6 @@ pub struct DisambiguatedDefPathData {
|
|||
pub disambiguator: u32
|
||||
}
|
||||
|
||||
/// For each definition, we track the following data. A definition
|
||||
/// here is defined somewhat circularly as "something with a def-id",
|
||||
/// but it generally corresponds to things like structs, enums, etc.
|
||||
/// There are also some rather random cases (like const initializer
|
||||
/// expressions) that are mostly just leftovers.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DefData {
|
||||
pub key: DefKey,
|
||||
|
||||
/// Local ID within the HIR.
|
||||
pub node_id: ast::NodeId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct DefPath {
|
||||
/// the path leading from the crate root to the item
|
||||
|
@ -77,12 +161,11 @@ impl DefPath {
|
|||
self.krate == LOCAL_CRATE
|
||||
}
|
||||
|
||||
pub fn make<FN>(start_krate: CrateNum,
|
||||
pub fn make<FN>(krate: CrateNum,
|
||||
start_index: DefIndex,
|
||||
mut get_key: FN) -> DefPath
|
||||
where FN: FnMut(DefIndex) -> DefKey
|
||||
{
|
||||
let mut krate = start_krate;
|
||||
let mut data = vec![];
|
||||
let mut index = Some(start_index);
|
||||
loop {
|
||||
|
@ -95,13 +178,6 @@ impl DefPath {
|
|||
assert!(key.parent.is_none());
|
||||
break;
|
||||
}
|
||||
DefPathData::InlinedRoot(ref p) => {
|
||||
assert!(key.parent.is_none());
|
||||
assert!(!p.def_id.is_local());
|
||||
data.extend(p.data.iter().cloned().rev());
|
||||
krate = p.def_id.krate;
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
data.push(key.disambiguated_data);
|
||||
index = key.parent;
|
||||
|
@ -131,7 +207,8 @@ impl DefPath {
|
|||
}
|
||||
|
||||
pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
|
||||
let mut state = DefaultHasher::new();
|
||||
debug!("deterministic_hash({:?})", self);
|
||||
let mut state = StableHasher::new();
|
||||
self.deterministic_hash_to(tcx, &mut state);
|
||||
state.finish()
|
||||
}
|
||||
|
@ -143,31 +220,6 @@ impl DefPath {
|
|||
}
|
||||
}
|
||||
|
||||
/// Root of an inlined item. We track the `DefPath` of the item within
|
||||
/// the original crate but also its def-id. This is kind of an
|
||||
/// augmented version of a `DefPath` that includes a `DefId`. This is
|
||||
/// all sort of ugly but the hope is that inlined items will be going
|
||||
/// away soon anyway.
|
||||
///
|
||||
/// Some of the constraints that led to the current approach:
|
||||
///
|
||||
/// - I don't want to have a `DefId` in the main `DefPath` because
|
||||
/// that gets serialized for incr. comp., and when reloaded the
|
||||
/// `DefId` is no longer valid. I'd rather maintain the invariant
|
||||
/// that every `DefId` is valid, and a potentially outdated `DefId` is
|
||||
/// represented as a `DefPath`.
|
||||
/// - (We don't serialize def-paths from inlined items, so it's ok to have one here.)
|
||||
/// - We need to be able to extract the def-id from inline items to
|
||||
/// make the symbol name. In theory we could retrace it from the
|
||||
/// data, but the metadata doesn't have the required indices, and I
|
||||
/// don't want to write the code to create one just for this.
|
||||
/// - It may be that we don't actually need `data` at all. We'll have
|
||||
/// to see about that.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct InlinedRootPath {
|
||||
pub data: Vec<DisambiguatedDefPathData>,
|
||||
pub def_id: DefId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub enum DefPathData {
|
||||
|
@ -175,8 +227,6 @@ pub enum DefPathData {
|
|||
// they are treated specially by the `def_path` function.
|
||||
/// The crate root (marker)
|
||||
CrateRoot,
|
||||
/// An inlined root
|
||||
InlinedRoot(Box<InlinedRootPath>),
|
||||
|
||||
// Catch-all for random DefId things like DUMMY_NODE_ID
|
||||
Misc,
|
||||
|
@ -218,23 +268,30 @@ impl Definitions {
|
|||
/// Create new empty definition map.
|
||||
pub fn new() -> Definitions {
|
||||
Definitions {
|
||||
data: vec![],
|
||||
key_map: FxHashMap(),
|
||||
node_map: NodeMap(),
|
||||
table: DefPathTable {
|
||||
index_to_key: vec![],
|
||||
key_to_index: FxHashMap(),
|
||||
},
|
||||
node_to_def_index: NodeMap(),
|
||||
def_index_to_node: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_path_table(&self) -> &DefPathTable {
|
||||
&self.table
|
||||
}
|
||||
|
||||
/// Get the number of definitions.
|
||||
pub fn len(&self) -> usize {
|
||||
self.data.len()
|
||||
self.def_index_to_node.len()
|
||||
}
|
||||
|
||||
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
||||
self.data[index.as_usize()].key.clone()
|
||||
self.table.def_key(index)
|
||||
}
|
||||
|
||||
pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
|
||||
self.key_map.get(&key).cloned()
|
||||
self.table.def_index_for_def_key(&key)
|
||||
}
|
||||
|
||||
/// Returns the path from the crate root to `index`. The root
|
||||
|
@ -247,7 +304,7 @@ impl Definitions {
|
|||
}
|
||||
|
||||
pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
|
||||
self.node_map.get(&node).cloned()
|
||||
self.node_to_def_index.get(&node).cloned()
|
||||
}
|
||||
|
||||
pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
|
||||
|
@ -260,8 +317,8 @@ impl Definitions {
|
|||
|
||||
pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
|
||||
if def_id.krate == LOCAL_CRATE {
|
||||
assert!(def_id.index.as_usize() < self.data.len());
|
||||
Some(self.data[def_id.index.as_usize()].node_id)
|
||||
assert!(def_id.index.as_usize() < self.def_index_to_node.len());
|
||||
Some(self.def_index_to_node[def_id.index.as_usize()])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -276,16 +333,13 @@ impl Definitions {
|
|||
debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
|
||||
parent, node_id, data);
|
||||
|
||||
assert!(!self.node_map.contains_key(&node_id),
|
||||
assert!(!self.node_to_def_index.contains_key(&node_id),
|
||||
"adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
|
||||
node_id,
|
||||
data,
|
||||
self.data[self.node_map[&node_id].as_usize()]);
|
||||
self.table.def_key(self.node_to_def_index[&node_id]));
|
||||
|
||||
assert!(parent.is_some() ^ match data {
|
||||
DefPathData::CrateRoot | DefPathData::InlinedRoot(_) => true,
|
||||
_ => false,
|
||||
});
|
||||
assert!(parent.is_some() ^ (data == DefPathData::CrateRoot));
|
||||
|
||||
// Find a unique DefKey. This basically means incrementing the disambiguator
|
||||
// until we get no match.
|
||||
|
@ -297,20 +351,18 @@ impl Definitions {
|
|||
}
|
||||
};
|
||||
|
||||
while self.key_map.contains_key(&key) {
|
||||
while self.table.contains_key(&key) {
|
||||
key.disambiguated_data.disambiguator += 1;
|
||||
}
|
||||
|
||||
debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
|
||||
|
||||
// Create the definition.
|
||||
let index = DefIndex::new(self.data.len());
|
||||
self.data.push(DefData { key: key.clone(), node_id: node_id });
|
||||
debug!("create_def_with_parent: node_map[{:?}] = {:?}", node_id, index);
|
||||
self.node_map.insert(node_id, index);
|
||||
debug!("create_def_with_parent: key_map[{:?}] = {:?}", key, index);
|
||||
self.key_map.insert(key, index);
|
||||
|
||||
let index = self.table.insert(key);
|
||||
debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
|
||||
self.node_to_def_index.insert(node_id, index);
|
||||
assert_eq!(index.as_usize(), self.def_index_to_node.len());
|
||||
self.def_index_to_node.push(node_id);
|
||||
|
||||
index
|
||||
}
|
||||
|
@ -332,7 +384,6 @@ impl DefPathData {
|
|||
|
||||
Impl |
|
||||
CrateRoot |
|
||||
InlinedRoot(_) |
|
||||
Misc |
|
||||
ClosureExpr |
|
||||
StructCtor |
|
||||
|
@ -359,9 +410,6 @@ impl DefPathData {
|
|||
// note that this does not show up in user printouts
|
||||
CrateRoot => "{{root}}",
|
||||
|
||||
// note that this does not show up in user printouts
|
||||
InlinedRoot(_) => "{{inlined-root}}",
|
||||
|
||||
Impl => "{{impl}}",
|
||||
Misc => "{{?}}",
|
||||
ClosureExpr => "{{closure}}",
|
||||
|
@ -377,4 +425,3 @@ impl DefPathData {
|
|||
self.as_interned_str().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use self::MapEntry::*;
|
|||
use self::collector::NodeCollector;
|
||||
pub use self::def_collector::{DefCollector, MacroInvocationData};
|
||||
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
|
||||
DisambiguatedDefPathData, InlinedRootPath};
|
||||
DisambiguatedDefPathData};
|
||||
|
||||
use dep_graph::{DepGraph, DepNode};
|
||||
|
||||
|
@ -221,22 +221,14 @@ pub struct Map<'ast> {
|
|||
/// plain old integers.
|
||||
map: RefCell<Vec<MapEntry<'ast>>>,
|
||||
|
||||
definitions: RefCell<Definitions>,
|
||||
definitions: Definitions,
|
||||
|
||||
/// All NodeIds that are numerically greater or equal to this value come
|
||||
/// from inlined items.
|
||||
local_node_id_watermark: NodeId,
|
||||
|
||||
/// All def-indices that are numerically greater or equal to this value come
|
||||
/// from inlined items.
|
||||
local_def_id_watermark: usize,
|
||||
}
|
||||
|
||||
impl<'ast> Map<'ast> {
|
||||
pub fn is_inlined_def_id(&self, id: DefId) -> bool {
|
||||
id.is_local() && id.index.as_usize() >= self.local_def_id_watermark
|
||||
}
|
||||
|
||||
pub fn is_inlined_node_id(&self, id: NodeId) -> bool {
|
||||
id >= self.local_node_id_watermark
|
||||
}
|
||||
|
@ -262,7 +254,6 @@ impl<'ast> Map<'ast> {
|
|||
EntryItem(_, item) => {
|
||||
assert_eq!(id, item.id);
|
||||
let def_id = self.local_def_id(id);
|
||||
assert!(!self.is_inlined_def_id(def_id));
|
||||
|
||||
if let Some(last_id) = last_expr {
|
||||
// The body of the item may have a separate dep node
|
||||
|
@ -278,7 +269,6 @@ impl<'ast> Map<'ast> {
|
|||
|
||||
EntryImplItem(_, item) => {
|
||||
let def_id = self.local_def_id(id);
|
||||
assert!(!self.is_inlined_def_id(def_id));
|
||||
|
||||
if let Some(last_id) = last_expr {
|
||||
// The body of the item may have a separate dep node
|
||||
|
@ -392,12 +382,16 @@ impl<'ast> Map<'ast> {
|
|||
}
|
||||
|
||||
pub fn num_local_def_ids(&self) -> usize {
|
||||
self.definitions.borrow().len()
|
||||
self.definitions.len()
|
||||
}
|
||||
|
||||
pub fn definitions(&self) -> &Definitions {
|
||||
&self.definitions
|
||||
}
|
||||
|
||||
pub fn def_key(&self, def_id: DefId) -> DefKey {
|
||||
assert!(def_id.is_local());
|
||||
self.definitions.borrow().def_key(def_id.index)
|
||||
self.definitions.def_key(def_id.index)
|
||||
}
|
||||
|
||||
pub fn def_path_from_id(&self, id: NodeId) -> Option<DefPath> {
|
||||
|
@ -408,11 +402,11 @@ impl<'ast> Map<'ast> {
|
|||
|
||||
pub fn def_path(&self, def_id: DefId) -> DefPath {
|
||||
assert!(def_id.is_local());
|
||||
self.definitions.borrow().def_path(def_id.index)
|
||||
self.definitions.def_path(def_id.index)
|
||||
}
|
||||
|
||||
pub fn def_index_for_def_key(&self, def_key: DefKey) -> Option<DefIndex> {
|
||||
self.definitions.borrow().def_index_for_def_key(def_key)
|
||||
self.definitions.def_index_for_def_key(def_key)
|
||||
}
|
||||
|
||||
pub fn local_def_id(&self, node: NodeId) -> DefId {
|
||||
|
@ -423,11 +417,11 @@ impl<'ast> Map<'ast> {
|
|||
}
|
||||
|
||||
pub fn opt_local_def_id(&self, node: NodeId) -> Option<DefId> {
|
||||
self.definitions.borrow().opt_local_def_id(node)
|
||||
self.definitions.opt_local_def_id(node)
|
||||
}
|
||||
|
||||
pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
|
||||
self.definitions.borrow().as_local_node_id(def_id)
|
||||
self.definitions.as_local_node_id(def_id)
|
||||
}
|
||||
|
||||
fn entry_count(&self) -> usize {
|
||||
|
@ -930,23 +924,19 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
|
|||
}
|
||||
|
||||
let local_node_id_watermark = NodeId::new(map.len());
|
||||
let local_def_id_watermark = definitions.len();
|
||||
|
||||
Map {
|
||||
forest: forest,
|
||||
dep_graph: forest.dep_graph.clone(),
|
||||
map: RefCell::new(map),
|
||||
definitions: RefCell::new(definitions),
|
||||
definitions: definitions,
|
||||
local_node_id_watermark: local_node_id_watermark,
|
||||
local_def_id_watermark: local_def_id_watermark,
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for items loaded from external crate that are being inlined into this
|
||||
/// crate.
|
||||
pub fn map_decoded_item<'ast>(map: &Map<'ast>,
|
||||
parent_def_path: DefPath,
|
||||
parent_def_id: DefId,
|
||||
ii: InlinedItem,
|
||||
ii_parent_id: NodeId)
|
||||
-> &'ast InlinedItem {
|
||||
|
@ -954,18 +944,9 @@ pub fn map_decoded_item<'ast>(map: &Map<'ast>,
|
|||
|
||||
let ii = map.forest.inlined_items.alloc(ii);
|
||||
|
||||
let defs = &mut *map.definitions.borrow_mut();
|
||||
let mut def_collector = DefCollector::extend(ii_parent_id,
|
||||
parent_def_path.clone(),
|
||||
parent_def_id,
|
||||
defs);
|
||||
def_collector.walk_item(ii, map.krate());
|
||||
|
||||
let mut collector = NodeCollector::extend(map.krate(),
|
||||
ii,
|
||||
ii_parent_id,
|
||||
parent_def_path,
|
||||
parent_def_id,
|
||||
mem::replace(&mut *map.map.borrow_mut(), vec![]));
|
||||
ii.visit(&mut collector);
|
||||
*map.map.borrow_mut() = collector.map;
|
||||
|
|
|
@ -105,15 +105,18 @@ pub struct LifetimeDef {
|
|||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
|
||||
pub struct Path {
|
||||
pub span: Span,
|
||||
/// A `::foo` path, is relative to the crate root rather than current
|
||||
/// module (like paths in an import).
|
||||
pub global: bool,
|
||||
/// The definition that the path resolved to.
|
||||
pub def: Def,
|
||||
/// The segments in the path: the things separated by `::`.
|
||||
pub segments: HirVec<PathSegment>,
|
||||
}
|
||||
|
||||
impl Path {
|
||||
pub fn is_global(&self) -> bool {
|
||||
!self.segments.is_empty() && self.segments[0].name == keywords::CrateRoot.name()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Path {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "path({})", print::path_to_string(self))
|
||||
|
@ -475,8 +478,6 @@ pub struct MacroDef {
|
|||
pub attrs: HirVec<Attribute>,
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub imported_from: Option<Name>,
|
||||
pub allow_internal_unstable: bool,
|
||||
pub body: HirVec<TokenTree>,
|
||||
}
|
||||
|
||||
|
@ -1533,8 +1534,6 @@ pub struct ItemId {
|
|||
pub id: NodeId,
|
||||
}
|
||||
|
||||
// FIXME (#3300): Should allow items to be anonymous. Right now
|
||||
// we just use dummy names for anon items.
|
||||
/// An item
|
||||
///
|
||||
/// The name might be a dummy name in case of anonymous items
|
||||
|
|
|
@ -1643,17 +1643,14 @@ impl<'a> State<'a> {
|
|||
-> io::Result<()> {
|
||||
self.maybe_print_comment(path.span.lo)?;
|
||||
|
||||
let mut first = !path.global;
|
||||
for segment in &path.segments {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
for (i, segment) in path.segments.iter().enumerate() {
|
||||
if i > 0 {
|
||||
word(&mut self.s, "::")?
|
||||
}
|
||||
|
||||
self.print_name(segment.name)?;
|
||||
|
||||
self.print_path_parameters(&segment.parameters, colons_before_params)?;
|
||||
if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" {
|
||||
self.print_name(segment.name)?;
|
||||
self.print_path_parameters(&segment.parameters, colons_before_params)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1673,15 +1670,14 @@ impl<'a> State<'a> {
|
|||
space(&mut self.s)?;
|
||||
self.word_space("as")?;
|
||||
|
||||
let mut first = !path.global;
|
||||
for segment in &path.segments[..path.segments.len() - 1] {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() {
|
||||
if i > 0 {
|
||||
word(&mut self.s, "::")?
|
||||
}
|
||||
self.print_name(segment.name)?;
|
||||
self.print_path_parameters(&segment.parameters, colons_before_params)?;
|
||||
if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" {
|
||||
self.print_name(segment.name)?;
|
||||
self.print_path_parameters(&segment.parameters, colons_before_params)?;
|
||||
}
|
||||
}
|
||||
|
||||
word(&mut self.s, ">")?;
|
||||
|
|
|
@ -1620,7 +1620,6 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
|
|||
new_segs.push(new_seg);
|
||||
hir::Path {
|
||||
span: path.span,
|
||||
global: path.global,
|
||||
def: path.def,
|
||||
segments: new_segs.into()
|
||||
}
|
||||
|
|
|
@ -1367,9 +1367,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
err: TypeError<'tcx>) {
|
||||
err: TypeError<'tcx>)
|
||||
-> DiagnosticBuilder<'tcx> {
|
||||
let trace = TypeTrace::types(cause, true, expected, actual);
|
||||
self.report_and_explain_type_error(trace, &err).emit();
|
||||
self.report_and_explain_type_error(trace, &err)
|
||||
}
|
||||
|
||||
pub fn report_conflicting_default_types(&self,
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#![cfg_attr(not(stage0), deny(warnings))]
|
||||
|
||||
#![feature(associated_consts)]
|
||||
#![feature(borrow_state)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
|
|
|
@ -211,6 +211,12 @@ declare_lint! {
|
|||
not named `mod.rs`"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub LEGACY_IMPORTS,
|
||||
Warn,
|
||||
"detects names that resolve to ambiguous glob imports with RFC 1560"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub DEPRECATED,
|
||||
Warn,
|
||||
|
@ -257,6 +263,7 @@ impl LintPass for HardwiredLints {
|
|||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
EXTRA_REQUIREMENT_IN_IMPL,
|
||||
LEGACY_DIRECTORY_OWNERSHIP,
|
||||
LEGACY_IMPORTS,
|
||||
DEPRECATED
|
||||
)
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
use hir::def::{self, Def};
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex};
|
||||
use hir::map as hir_map;
|
||||
use hir::map::definitions::{Definitions, DefKey};
|
||||
use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
|
||||
use hir::svh::Svh;
|
||||
use middle::lang_items;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
|
@ -298,8 +298,7 @@ pub trait CrateStore<'tcx> {
|
|||
|
||||
// trait/impl-item info
|
||||
fn trait_of_item(&self, def_id: DefId) -> Option<DefId>;
|
||||
fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::AssociatedItem>;
|
||||
fn associated_item(&self, def: DefId) -> Option<ty::AssociatedItem>;
|
||||
|
||||
// flags
|
||||
fn is_const_fn(&self, did: DefId) -> bool;
|
||||
|
@ -336,12 +335,12 @@ pub trait CrateStore<'tcx> {
|
|||
fn is_no_builtins(&self, cnum: CrateNum) -> bool;
|
||||
|
||||
// resolve
|
||||
fn def_index_for_def_key(&self,
|
||||
cnum: CrateNum,
|
||||
def: DefKey)
|
||||
-> Option<DefIndex>;
|
||||
fn def_key(&self, def: DefId) -> hir_map::DefKey;
|
||||
fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath>;
|
||||
fn retrace_path(&self,
|
||||
cnum: CrateNum,
|
||||
path_data: &[DisambiguatedDefPathData])
|
||||
-> Option<DefId>;
|
||||
fn def_key(&self, def: DefId) -> DefKey;
|
||||
fn def_path(&self, def: DefId) -> hir_map::DefPath;
|
||||
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
|
||||
fn item_children(&self, did: DefId) -> Vec<def::Export>;
|
||||
fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro;
|
||||
|
@ -442,12 +441,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
|||
|
||||
// trait info
|
||||
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
|
||||
fn def_index_for_def_key(&self,
|
||||
cnum: CrateNum,
|
||||
def: DefKey)
|
||||
-> Option<DefIndex> {
|
||||
None
|
||||
}
|
||||
|
||||
// impl info
|
||||
fn associated_item_def_ids(&self, def_id: DefId) -> Vec<DefId>
|
||||
|
@ -462,8 +455,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
|||
|
||||
// trait/impl-item info
|
||||
fn trait_of_item(&self, def_id: DefId) -> Option<DefId> { bug!("trait_of_item") }
|
||||
fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<ty::AssociatedItem> { bug!("associated_item") }
|
||||
fn associated_item(&self, def: DefId) -> Option<ty::AssociatedItem> { bug!("associated_item") }
|
||||
|
||||
// flags
|
||||
fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
|
||||
|
@ -508,8 +500,15 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
|||
fn is_no_builtins(&self, cnum: CrateNum) -> bool { bug!("is_no_builtins") }
|
||||
|
||||
// resolve
|
||||
fn def_key(&self, def: DefId) -> hir_map::DefKey { bug!("def_key") }
|
||||
fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath> {
|
||||
fn retrace_path(&self,
|
||||
cnum: CrateNum,
|
||||
path_data: &[DisambiguatedDefPathData])
|
||||
-> Option<DefId> {
|
||||
None
|
||||
}
|
||||
|
||||
fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") }
|
||||
fn def_path(&self, def: DefId) -> hir_map::DefPath {
|
||||
bug!("relative_def_path")
|
||||
}
|
||||
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { bug!("struct_field_names") }
|
||||
|
|
|
@ -86,20 +86,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_definition(&mut self, id: ast::NodeId, def: Def) {
|
||||
// If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar`
|
||||
match def {
|
||||
Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
|
||||
if self.tcx.trait_of_item(def.def_id()).is_some() => {
|
||||
if let Some(substs) = self.tcx.tables().item_substs.get(&id) {
|
||||
if let ty::TyAdt(tyid, _) = substs.substs.type_at(0).sty {
|
||||
self.check_def_id(tyid.did);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
fn handle_definition(&mut self, def: Def) {
|
||||
match def {
|
||||
Def::Const(_) | Def::AssociatedConst(..) => {
|
||||
self.check_def_id(def.def_id());
|
||||
|
@ -241,7 +228,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
|||
match expr.node {
|
||||
hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => {
|
||||
let def = self.tcx.tables().qpath_def(qpath, expr.id);
|
||||
self.handle_definition(expr.id, def);
|
||||
self.handle_definition(def);
|
||||
}
|
||||
hir::ExprMethodCall(..) => {
|
||||
self.lookup_and_handle_method(expr.id);
|
||||
|
@ -281,7 +268,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
|||
}
|
||||
PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => {
|
||||
let def = self.tcx.tables().qpath_def(qpath, pat.id);
|
||||
self.handle_definition(pat.id, def);
|
||||
self.handle_definition(def);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
@ -291,8 +278,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
|||
self.ignore_non_const_paths = false;
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, path: &'tcx hir::Path, id: ast::NodeId) {
|
||||
self.handle_definition(id, path.def);
|
||||
fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) {
|
||||
self.handle_definition(path.def);
|
||||
intravisit::walk_path(self, path);
|
||||
}
|
||||
}
|
||||
|
@ -426,6 +413,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
|
|||
hir::ItemStatic(..)
|
||||
| hir::ItemConst(..)
|
||||
| hir::ItemFn(..)
|
||||
| hir::ItemTy(..)
|
||||
| hir::ItemEnum(..)
|
||||
| hir::ItemStruct(..)
|
||||
| hir::ItemUnion(..) => true,
|
||||
|
|
|
@ -328,7 +328,6 @@ language_item_table! {
|
|||
PanicFmtLangItem, "panic_fmt", panic_fmt;
|
||||
|
||||
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
|
||||
ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
|
||||
BoxFreeFnLangItem, "box_free", box_free_fn;
|
||||
StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn;
|
||||
|
||||
|
|
|
@ -302,9 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
|
||||
if md.imported_from.is_none() {
|
||||
self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {});
|
||||
}
|
||||
self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,9 +371,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
|
||||
if md.imported_from.is_none() {
|
||||
self.check_missing_stability(md.id, md.span);
|
||||
}
|
||||
self.check_missing_stability(md.id, md.span);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,12 @@ impl CodeStats {
|
|||
max_variant_size = cmp::max(max_variant_size, size);
|
||||
|
||||
let mut min_offset = discr_size;
|
||||
for field in fields {
|
||||
|
||||
// We want to print fields by increasing offset.
|
||||
let mut fields = fields.clone();
|
||||
fields.sort_by_key(|f| f.offset);
|
||||
|
||||
for field in fields.iter() {
|
||||
let FieldInfo { ref name, offset, size, align } = *field;
|
||||
|
||||
// Include field alignment in output only if it caused padding injection
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue