path = src/jemalloc
url = https://github.com/rust-lang/jemalloc.git
[submodule "src/rust-installer"]
- path = src/rust-installer
+ path = src/tools/rust-installer
url = https://github.com/rust-lang/rust-installer.git
[submodule "src/liblibc"]
path = src/liblibc
os: osx
osx_image: xcode8.2
install: &osx_install_sccache >
- travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-apple-darwin &&
+ travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-apple-darwin &&
chmod +x /usr/local/bin/sccache &&
travis_retry curl -o /usr/local/bin/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin &&
chmod +x /usr/local/bin/stamp
python x.py build src/libcore --stage 0
```
-You can explore the build system throught the various `--help` pages for each
+You can explore the build system through the various `--help` pages for each
subcommand. For example to learn more about a command you can run:
```
- set PATH=C:\Python27;%PATH%
# Download and install sccache
- - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-pc-windows-msvc
- - mv 2017-04-29-sccache-x86_64-pc-windows-msvc sccache.exe
+ - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-pc-windows-msvc
+ - mv 2017-05-12-sccache-x86_64-pc-windows-msvc sccache.exe
- set PATH=%PATH%;%CD%
# Download and install ninja
- set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
# Help debug some handle issues on AppVeyor
- - ps: Invoke-WebRequest -Uri https://download.sysinternals.com/files/Handle.zip -OutFile handle.zip
+ - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-15-Handle.zip
- mkdir handle
- - ps: Expand-Archive handle.zip -dest handle
+ - 7z x -ohandle 2017-05-15-Handle.zip
- set PATH=%PATH%;%CD%\handle
- handle.exe -accepteula -help
valopt_nosave target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples"
valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
valopt_nosave docdir "${CFG_PREFIX}/share/doc/rust" "install documentation in PATH"
+valopt_nosave bindir "${CFG_PREFIX}/bin" "install binaries"
# On Windows this determines root of the subtree for target libraries.
# Host runtime libs always go to 'bin'.
CFG_PREFIX=${CFG_PREFIX%/}
CFG_MANDIR=${CFG_MANDIR%/}
CFG_DOCDIR=${CFG_DOCDIR%/}
+CFG_BINDIR=${CFG_BINDIR%/}
CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')"
CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')"
putvar CFG_NACL_CROSS_PATH
putvar CFG_MANDIR
putvar CFG_DOCDIR
+putvar CFG_BINDIR
putvar CFG_USING_LIBCPP
msg
dependencies = [
"build_helper 0.1.0",
"core 0.0.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.0.0",
]
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "backtrace"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "bitflags"
version = "0.5.0"
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (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.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (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.21 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
name = "cargotest2"
version = "0.1.0"
+[[package]]
+name = "cfg-if"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "clap"
version = "2.22.1"
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cmake"
-version = "0.1.22"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
dependencies = [
"build_helper 0.1.0",
"core 0.0.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "core"
version = "0.0.0"
+[[package]]
+name = "dbghelp-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "diff"
version = "0.1.10"
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "error-chain"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "error_index_generator"
version = "0.0.0"
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "flate2"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "gcc"
-version = "0.3.45"
+version = "0.3.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "installer"
+version = "0.0.0"
+dependencies = [
+ "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "itoa"
version = "0.3.1"
[[package]]
name = "lazy_static"
-version = "0.2.5"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "lzma-sys"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "mdbook"
version = "0.0.21"
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "miniz-sys"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "num-traits"
version = "0.1.37"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "owning_ref"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "panic_abort"
version = "0.0.0"
"fmt_macros 0.0.0",
"graphviz 0.0.0",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_back 0.0.0",
"rustc_bitflags 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
- "rustc_llvm 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
+[[package]]
+name = "rustc-demangle"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "rustc-main"
version = "0.0.0"
dependencies = [
"alloc_system 0.0.0",
"build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
]
"rustc_errors 0.0.0",
"rustc_incremental 0.0.0",
"rustc_lint 0.0.0",
- "rustc_llvm 0.0.0",
"rustc_metadata 0.0.0",
"rustc_mir 0.0.0",
"rustc_passes 0.0.0",
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_bitflags 0.0.0",
]
dependencies = [
"alloc_system 0.0.0",
"build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
]
dependencies = [
"flate 0.0.0",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"proc_macro 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
- "rustc_llvm 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_ext 0.0.0",
dependencies = [
"alloc_system 0.0.0",
"build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
]
dependencies = [
"flate 0.0.0",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_bitflags 0.0.0",
dependencies = [
"alloc_system 0.0.0",
"build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
]
"arena 0.0.0",
"build_helper 0.1.0",
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"syntax_pos 0.0.0",
]
+[[package]]
+name = "same-file"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "serde"
version = "0.9.11"
name = "serialize"
version = "0.0.0"
+[[package]]
+name = "stable_deref_trait"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "std"
version = "0.0.0"
"collections 0.0.0",
"compiler_builtins 0.0.0",
"core 0.0.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.0.0",
"panic_abort 0.0.0",
"panic_unwind 0.0.0",
"serialize 0.0.0",
]
+[[package]]
+name = "tar"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "term"
version = "0.0.0"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "walkdir"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "winapi"
version = "0.2.8"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "xattr"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "xz2"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lzma-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "yaml-rust"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[metadata]
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
+"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
+"checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842"
"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
+"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
"checksum clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e17a4a72ffea176f77d6e2db609c6c919ef221f23862c9915e687fb54d833485"
-"checksum cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "d18d68987ed4c516dcc3e7913659bfa4076f5182eea4a7e0038bb060953e76ac"
+"checksum cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "92278eb79412c8f75cfc89e707a1bb3a6490b68f7f2e78d15c774f30fe701122"
+"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
"checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472"
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
+"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
-"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae"
+"checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c"
+"checksum gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)" = "181e3cebba1d663bd92eb90e2da787e10597e027eb00de8d742b260a7850948f"
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
"checksum handlebars 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)" = "663e1728d8037fb0d4e13bcd1b1909fb5d913690a9929eb385922df157c2ff8f"
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97"
+"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
+"checksum lzma-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fedff6a5cbb24494ec6ee4784e9ac5c187161fede04c7767d49bf87544013afa"
"checksum mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2e9d848514dcfad4195788d0d42ae5153a477c191d75d5b84fab10f222fbd"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
+"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726"
"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
+"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
"checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973"
"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
"checksum rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc4277ce3c57f456b11fe3145b181a844a25201bab5cbaa1978457e6e2f27d47"
"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
+"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
"checksum rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "684ce48436d6465300c9ea783b6b14c4361d6b8dcbb1375b486a69cc19e2dfb0"
+"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f"
"checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e"
+"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
+"checksum tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ab0ef9ead2fe0aa9e18475a96a207bfd5143f4124779ef7429503a8665416ce8"
"checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
"checksum vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8cdc8b93bd0198ed872357fb2e667f7125646b1762f16d60b2c96350d361897"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+"checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc"
+"checksum xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e9510bdf100731599107c61f77daf46713a69a568f75458999c1f9dbf6ba25b0"
+"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"
"tools/build-manifest",
"tools/remote-test-client",
"tools/remote-test-server",
+ "tools/rust-installer",
]
# These projects have their own Cargo.lock
[dependencies]
build_helper = { path = "../build_helper" }
-cmake = "0.1.17"
+cmake = "0.1.23"
filetime = "0.1"
num_cpus = "1.0"
toml = "0.1"
getopts = "0.2"
rustc-serialize = "0.3"
-gcc = "0.3.38"
+gcc = "0.3.46"
libc = "0.2"
// 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.
+ //
+ // FIXME: remove condition after next stage0
if stage != "0" {
cmd.arg("-Z").arg("osx-rpath-install-name");
}
cmd.arg("-Z").arg("unstable-options");
cmd.arg("-C").arg("target-feature=+crt-static");
}
+
+ // Force all crates compiled by this compiler to (a) be unstable and (b)
+ // allow the `rustc_private` feature to link to other unstable crates
+ // also in the sysroot.
+ //
+ // FIXME: remove condition after next stage0
+ if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
+ if stage != "0" {
+ cmd.arg("-Z").arg("force-unstable-if-unmarked");
+ }
+ }
}
if verbose > 1 {
// Fallback musl-root for all targets
pub musl_root: Option<PathBuf>,
pub prefix: Option<PathBuf>,
+ pub sysconfdir: Option<PathBuf>,
pub docdir: Option<PathBuf>,
+ pub bindir: Option<PathBuf>,
pub libdir: Option<PathBuf>,
pub libdir_relative: Option<PathBuf>,
pub mandir: Option<PathBuf>,
#[derive(RustcDecodable, Default, Clone)]
struct Install {
prefix: Option<String>,
- mandir: Option<String>,
+ sysconfdir: Option<String>,
docdir: Option<String>,
+ bindir: Option<String>,
libdir: Option<String>,
+ mandir: Option<String>,
}
/// TOML representation of how the LLVM build is configured.
let table = match p.parse() {
Some(table) => table,
None => {
- println!("failed to parse TOML configuration:");
+ println!("failed to parse TOML configuration '{}':", file.to_str().unwrap());
for err in p.errors.iter() {
let (loline, locol) = p.to_linecol(err.lo);
let (hiline, hicol) = p.to_linecol(err.hi);
if let Some(ref install) = toml.install {
config.prefix = install.prefix.clone().map(PathBuf::from);
- config.mandir = install.mandir.clone().map(PathBuf::from);
+ config.sysconfdir = install.sysconfdir.clone().map(PathBuf::from);
config.docdir = install.docdir.clone().map(PathBuf::from);
+ config.bindir = install.bindir.clone().map(PathBuf::from);
config.libdir = install.libdir.clone().map(PathBuf::from);
+ config.mandir = install.mandir.clone().map(PathBuf::from);
}
if let Some(ref llvm) = toml.llvm {
"CFG_PREFIX" => {
self.prefix = Some(PathBuf::from(value));
}
+ "CFG_SYSCONFDIR" => {
+ self.sysconfdir = Some(PathBuf::from(value));
+ }
"CFG_DOCDIR" => {
self.docdir = Some(PathBuf::from(value));
}
+ "CFG_BINDIR" => {
+ self.bindir = Some(PathBuf::from(value));
+ }
"CFG_LIBDIR" => {
self.libdir = Some(PathBuf::from(value));
}
# Instead of installing to /usr/local, install to this path instead.
#prefix = "/usr/local"
+# Where to install system configuration files
+# If this is a relative path, it will get installed in `prefix` above
+#sysconfdir = "/etc"
+
+# Where to install documentation in `prefix` above
+#docdir = "share/doc/rust"
+
+# Where to install binaries in `prefix` above
+#bindir = "bin"
+
# Where to install libraries in `prefix` above
#libdir = "lib"
# Where to install man pages in `prefix` above
#mandir = "share/man"
-# Where to install documentation in `prefix` above
-#docdir = "share/doc/rust"
-
# =============================================================================
# Options for compiling Rust code itself
# =============================================================================
[rust]
# Whether or not to optimize the compiler and standard library
+# Note: the slowness of the non optimized compiler compiling itself usually
+# outweighs the time gains in not doing optimizations, therefore a
+# full bootstrap takes much more time with optimize set to false.
#optimize = true
# Number of codegen units to use for each compiler invocation. A value of 0
use build_helper::output;
-#[cfg(not(target_os = "solaris"))]
-const SH_CMD: &'static str = "sh";
-// On Solaris, sh is the historical bourne shell, not a POSIX shell, or bash.
-#[cfg(target_os = "solaris")]
-const SH_CMD: &'static str = "bash";
-
use {Build, Compiler, Mode};
use channel;
use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe};
build.out.join("tmp/dist")
}
+fn rust_installer(build: &Build) -> Command {
+ build.tool_cmd(&Compiler::new(0, &build.config.build), "rust-installer")
+}
+
/// Builds the `rust-docs` installer component.
///
/// Slurps up documentation from the `stage`'s `host`.
let src = build.out.join(host).join("doc");
cp_r(&src, &dst);
- let mut cmd = Command::new(SH_CMD);
- cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+ let mut cmd = rust_installer(build);
+ cmd.arg("generate")
.arg("--product-name=Rust-Documentation")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=Rust-documentation-is-installed.")
- .arg(format!("--image-dir={}", sanitize_sh(&image)))
- .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
- .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+ .arg("--image-dir").arg(&image)
+ .arg("--work-dir").arg(&tmpdir(build))
+ .arg("--output-dir").arg(&distdir(build))
.arg(format!("--package-name={}-{}", name, host))
.arg("--component-name=rust-docs")
.arg("--legacy-manifest-dirs=rustlib,cargo")
.arg(host);
build.run(&mut cmd);
- let mut cmd = Command::new(SH_CMD);
- cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+ let mut cmd = rust_installer(build);
+ cmd.arg("generate")
.arg("--product-name=Rust-MinGW")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=Rust-MinGW-is-installed.")
- .arg(format!("--image-dir={}", sanitize_sh(&image)))
- .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
- .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+ .arg("--image-dir").arg(&image)
+ .arg("--work-dir").arg(&tmpdir(build))
+ .arg("--output-dir").arg(&distdir(build))
.arg(format!("--package-name={}-{}", name, host))
.arg("--component-name=rust-mingw")
.arg("--legacy-manifest-dirs=rustlib,cargo");
}
// Finally, wrap everything up in a nice tarball!
- let mut cmd = Command::new(SH_CMD);
- cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+ let mut cmd = rust_installer(build);
+ cmd.arg("generate")
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=Rust-is-ready-to-roll.")
- .arg(format!("--image-dir={}", sanitize_sh(&image)))
- .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
- .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
- .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay)))
+ .arg("--image-dir").arg(&image)
+ .arg("--work-dir").arg(&tmpdir(build))
+ .arg("--output-dir").arg(&distdir(build))
+ .arg("--non-installed-overlay").arg(&overlay)
.arg(format!("--package-name={}-{}", name, host))
.arg("--component-name=rustc")
.arg("--legacy-manifest-dirs=rustlib,cargo");
let src = build.sysroot(compiler).join("lib/rustlib");
cp_r(&src.join(target), &dst);
- let mut cmd = Command::new(SH_CMD);
- cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+ let mut cmd = rust_installer(build);
+ cmd.arg("generate")
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=std-is-standing-at-the-ready.")
- .arg(format!("--image-dir={}", sanitize_sh(&image)))
- .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
- .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+ .arg("--image-dir").arg(&image)
+ .arg("--work-dir").arg(&tmpdir(build))
+ .arg("--output-dir").arg(&distdir(build))
.arg(format!("--package-name={}-{}", name, target))
.arg(format!("--component-name=rust-std-{}", target))
.arg("--legacy-manifest-dirs=rustlib,cargo");
println!("image_src: {:?}, dst: {:?}", image_src, dst);
cp_r(&image_src, &dst);
- let mut cmd = Command::new(SH_CMD);
- cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+ let mut cmd = rust_installer(build);
+ cmd.arg("generate")
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=save-analysis-saved.")
- .arg(format!("--image-dir={}", sanitize_sh(&image)))
- .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
- .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+ .arg("--image-dir").arg(&image)
+ .arg("--work-dir").arg(&tmpdir(build))
+ .arg("--output-dir").arg(&distdir(build))
.arg(format!("--package-name={}-{}", name, target))
.arg(format!("--component-name=rust-analysis-{}", target))
.arg("--legacy-manifest-dirs=rustlib,cargo");
write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes());
// Create plain source tarball
- let tarball = rust_src_location(build);
+ let mut tarball = rust_src_location(build);
+ tarball.set_extension(""); // strip .gz
+ tarball.set_extension(""); // strip .tar
if let Some(dir) = tarball.parent() {
t!(fs::create_dir_all(dir));
}
- let mut cmd = Command::new("tar");
- cmd.arg("-czf").arg(sanitize_sh(&tarball))
- .arg(&plain_name)
+ let mut cmd = rust_installer(build);
+ cmd.arg("tarball")
+ .arg("--input").arg(&plain_name)
+ .arg("--output").arg(&tarball)
+ .arg("--work-dir=.")
.current_dir(tmpdir(build));
build.run(&mut cmd);
}
// Create source tarball in rust-installer format
- let mut cmd = Command::new(SH_CMD);
- cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+ let mut cmd = rust_installer(build);
+ cmd.arg("generate")
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=Awesome-Source.")
- .arg(format!("--image-dir={}", sanitize_sh(&image)))
- .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
- .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+ .arg("--image-dir").arg(&image)
+ .arg("--work-dir").arg(&tmpdir(build))
+ .arg("--output-dir").arg(&distdir(build))
.arg(format!("--package-name={}", name))
.arg("--component-name=rust-src")
.arg("--legacy-manifest-dirs=rustlib,cargo");
t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
// Generate the installer tarball
- let mut cmd = Command::new("sh");
- cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+ let mut cmd = rust_installer(build);
+ cmd.arg("generate")
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=Rust-is-ready-to-roll.")
- .arg(format!("--image-dir={}", sanitize_sh(&image)))
- .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
- .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
- .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay)))
+ .arg("--image-dir").arg(&image)
+ .arg("--work-dir").arg(&tmpdir(build))
+ .arg("--output-dir").arg(&distdir(build))
+ .arg("--non-installed-overlay").arg(&overlay)
.arg(format!("--package-name={}-{}", name, target))
.arg("--component-name=cargo")
.arg("--legacy-manifest-dirs=rustlib,cargo");
t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
// Generate the installer tarball
- let mut cmd = Command::new("sh");
- cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+ let mut cmd = rust_installer(build);
+ cmd.arg("generate")
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=RLS-ready-to-serve.")
- .arg(format!("--image-dir={}", sanitize_sh(&image)))
- .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
- .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
- .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay)))
+ .arg("--image-dir").arg(&image)
+ .arg("--work-dir").arg(&tmpdir(build))
+ .arg("--output-dir").arg(&distdir(build))
+ .arg("--non-installed-overlay").arg(&overlay)
.arg(format!("--package-name={}-{}", name, target))
.arg("--component-name=rls")
.arg("--legacy-manifest-dirs=rustlib,cargo");
// upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
// the std files during uninstall. To do this ensure that rustc comes
// before rust-std in the list below.
- let mut input_tarballs = format!("{},{},{},{},{},{}",
- sanitize_sh(&rustc_installer),
- sanitize_sh(&cargo_installer),
- sanitize_sh(&rls_installer),
- sanitize_sh(&analysis_installer),
- sanitize_sh(&docs_installer),
- sanitize_sh(&std_installer));
+ let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer,
+ analysis_installer, docs_installer, std_installer];
if target.contains("pc-windows-gnu") {
- input_tarballs.push_str(",");
- input_tarballs.push_str(&sanitize_sh(&mingw_installer));
+ tarballs.push(mingw_installer);
+ }
+ let mut input_tarballs = tarballs[0].as_os_str().to_owned();
+ for tarball in &tarballs[1..] {
+ input_tarballs.push(",");
+ input_tarballs.push(tarball);
}
- let mut cmd = Command::new(SH_CMD);
- cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/combine-installers.sh")))
+ let mut cmd = rust_installer(build);
+ cmd.arg("combine")
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=Rust-is-ready-to-roll.")
- .arg(format!("--work-dir={}", sanitize_sh(&work)))
- .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+ .arg("--work-dir").arg(&work)
+ .arg("--output-dir").arg(&distdir(build))
.arg(format!("--package-name={}-{}", pkgname(build, "rust"), target))
.arg("--legacy-manifest-dirs=rustlib,cargo")
- .arg(format!("--input-tarballs={}", input_tarballs))
- .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay)));
+ .arg("--input-tarballs").arg(input_tarballs)
+ .arg("--non-installed-overlay").arg(&overlay);
build.run(&mut cmd);
let mut license = String::new();
/// Installs everything.
pub fn install(build: &Build, stage: u32, host: &str) {
let prefix_default = PathBuf::from("/usr/local");
+ let sysconfdir_default = PathBuf::from("/etc");
let docdir_default = PathBuf::from("share/doc/rust");
- let mandir_default = PathBuf::from("share/man");
+ let bindir_default = PathBuf::from("bin");
let libdir_default = PathBuf::from("lib");
+ let mandir_default = PathBuf::from("share/man");
let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
+ let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
+ let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);
+ let sysconfdir = prefix.join(sysconfdir);
let docdir = prefix.join(docdir);
+ let bindir = prefix.join(bindir);
let libdir = prefix.join(libdir);
let mandir = prefix.join(mandir);
let destdir = env::var_os("DESTDIR").map(PathBuf::from);
let prefix = add_destdir(&prefix, &destdir);
+ let sysconfdir = add_destdir(&sysconfdir, &destdir);
let docdir = add_destdir(&docdir, &destdir);
+ let bindir = add_destdir(&bindir, &destdir);
let libdir = add_destdir(&libdir, &destdir);
let mandir = add_destdir(&mandir, &destdir);
t!(fs::create_dir_all(&empty_dir));
if build.config.docs {
install_sh(&build, "docs", "rust-docs", &build.rust_package_vers(),
- stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+ stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+ &mandir, &empty_dir);
}
for target in build.config.target.iter() {
install_sh(&build, "std", "rust-std", &build.rust_package_vers(),
- stage, target, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+ stage, target, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+ &mandir, &empty_dir);
}
if build.config.extended {
install_sh(&build, "cargo", "cargo", &build.cargo_package_vers(),
- stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+ stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+ &mandir, &empty_dir);
install_sh(&build, "rls", "rls", &build.rls_package_vers(),
- stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+ stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+ &mandir, &empty_dir);
}
install_sh(&build, "rustc", "rustc", &build.rust_package_vers(),
- stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+ stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+ &mandir, &empty_dir);
t!(fs::remove_dir_all(&empty_dir));
}
fn install_sh(build: &Build, package: &str, name: &str, version: &str, stage: u32, host: &str,
- prefix: &Path, docdir: &Path, libdir: &Path, mandir: &Path, empty_dir: &Path) {
+ prefix: &Path, sysconfdir: &Path, docdir: &Path, bindir: &Path, libdir: &Path,
+ mandir: &Path, empty_dir: &Path) {
println!("Install {} stage{} ({})", package, stage, host);
let package_name = format!("{}-{}-{}", name, version, host);
cmd.current_dir(empty_dir)
.arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
.arg(format!("--prefix={}", sanitize_sh(prefix)))
+ .arg(format!("--sysconfdir={}", sanitize_sh(sysconfdir)))
.arg(format!("--docdir={}", sanitize_sh(docdir)))
+ .arg(format!("--bindir={}", sanitize_sh(bindir)))
.arg(format!("--libdir={}", sanitize_sh(libdir)))
.arg(format!("--mandir={}", sanitize_sh(mandir)))
.arg("--disable-ldconfig");
// compiled with debuginfo.
if mode != Mode::Tool {
cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
- .env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string());
+ .env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string())
+ .env("RUSTC_FORCE_UNSTABLE", "1");
}
// Enable usage of unstable features
// the comipiler, libs, and tests are stable and we don't want to make
// their deps unstable (since this would break the first invariant
// above).
- if mode != Mode::Tool {
+ //
+ // FIXME: remove this after next stage0
+ if mode != Mode::Tool && stage == 0 {
cargo.env("RUSTBUILD_UNSTABLE", "1");
}
cfg.define("LLVM_USE_CRT_DEBUG", "MT");
cfg.define("LLVM_USE_CRT_RELEASE", "MT");
cfg.define("LLVM_USE_CRT_RELWITHDEBINFO", "MT");
+ cfg.static_crt(true);
}
if target.starts_with("i686") {
configure.arg("no-ssl3");
let os = match target {
+ "aarch64-linux-android" => "linux-aarch64",
"aarch64-unknown-linux-gnu" => "linux-aarch64",
+ "arm-linux-androideabi" => "android",
"arm-unknown-linux-gnueabi" => "linux-armv4",
"arm-unknown-linux-gnueabihf" => "linux-armv4",
+ "armv7-linux-androideabi" => "android-armv7",
"armv7-unknown-linux-gnueabihf" => "linux-armv4",
"i686-apple-darwin" => "darwin-i386-cc",
+ "i686-linux-android" => "android-x86",
"i686-unknown-freebsd" => "BSD-x86-elf",
"i686-unknown-linux-gnu" => "linux-elf",
"i686-unknown-linux-musl" => "linux-elf",
"powerpc64le-unknown-linux-gnu" => "linux-ppc64le",
"s390x-unknown-linux-gnu" => "linux64-s390x",
"x86_64-apple-darwin" => "darwin64-x86_64-cc",
+ "x86_64-linux-android" => "linux-x86_64",
"x86_64-unknown-freebsd" => "BSD-x86_64",
"x86_64-unknown-linux-gnu" => "linux-x86_64",
"x86_64-unknown-linux-musl" => "linux-x86_64",
for flag in build.cflags(target) {
configure.arg(flag);
}
+ // There is no specific os target for android aarch64 or x86_64,
+ // so we need to pass some extra cflags
+ if target == "aarch64-linux-android" || target == "x86_64-linux-android" {
+ configure.arg("-mandroid");
+ configure.arg("-fomit-frame-pointer");
+ }
+ // Make PIE binaries
+ // Non-PIE linker support was removed in Lollipop
+ // https://source.android.com/security/enhancements/enhancements50
+ if target == "i686-linux-android" {
+ configure.arg("no-asm");
+ }
configure.current_dir(&obj);
println!("Configuring openssl for {}", target);
build.run_quiet(&mut configure);
.dep(|s| s.name("maybe-clean-tools"))
.dep(|s| s.name("libstd-tool"))
.run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client"));
+ rules.build("tool-rust-installer", "src/tools/rust-installer")
+ .dep(|s| s.name("maybe-clean-tools"))
+ .dep(|s| s.name("libstd-tool"))
+ .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer"));
rules.build("tool-cargo", "src/tools/cargo")
.host(true)
.default(build.config.extended)
.host(true)
.only_host_build(true)
.default(true)
+ .dep(move |s| tool_rust_installer(build, s))
.run(move |s| dist::rustc(build, s.stage, s.target));
rules.dist("dist-std", "src/libstd")
.dep(move |s| {
})
.default(true)
.only_host_build(true)
+ .dep(move |s| tool_rust_installer(build, s))
.run(move |s| dist::std(build, &s.compiler(), s.target));
rules.dist("dist-mingw", "path/to/nowhere")
.default(true)
.only_host_build(true)
+ .dep(move |s| tool_rust_installer(build, s))
.run(move |s| {
if s.target.contains("pc-windows-gnu") {
dist::mingw(build, s.target)
.host(true)
.only_build(true)
.only_host_build(true)
+ .dep(move |s| tool_rust_installer(build, s))
.run(move |_| dist::rust_src(build));
rules.dist("dist-docs", "src/doc")
.default(true)
.only_host_build(true)
.dep(|s| s.name("default:doc"))
+ .dep(move |s| tool_rust_installer(build, s))
.run(move |s| dist::docs(build, s.stage, s.target));
rules.dist("dist-analysis", "analysis")
.default(build.config.extended)
.dep(|s| s.name("dist-std"))
.only_host_build(true)
+ .dep(move |s| tool_rust_installer(build, s))
.run(move |s| dist::analysis(build, &s.compiler(), s.target));
rules.dist("dist-rls", "rls")
.host(true)
.only_host_build(true)
.dep(|s| s.name("tool-rls"))
+ .dep(move |s| tool_rust_installer(build, s))
.run(move |s| dist::rls(build, s.stage, s.target));
rules.dist("install", "path/to/nowhere")
.dep(|s| s.name("default:dist"))
.host(true)
.only_host_build(true)
.dep(|s| s.name("tool-cargo"))
+ .dep(move |s| tool_rust_installer(build, s))
.run(move |s| dist::cargo(build, s.stage, s.target));
rules.dist("dist-extended", "extended")
.default(build.config.extended)
.dep(|d| d.name("dist-cargo"))
.dep(|d| d.name("dist-rls"))
.dep(|d| d.name("dist-analysis"))
+ .dep(move |s| tool_rust_installer(build, s))
.run(move |s| dist::extended(build, s.stage, s.target));
rules.dist("dist-sign", "hash-and-sign")
rules.verify();
return rules;
+
+ /// Helper to depend on a stage0 build-only rust-installer tool.
+ fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> {
+ step.name("tool-rust-installer")
+ .host(&build.config.build)
+ .target(&build.config.build)
+ .stage(0)
+ }
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
# Install NDK
RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabi/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabihf/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/armv7-unknown-linux-gnueabihf/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/rustroot/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV HOSTS=i686-unknown-linux-gnu
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin
RUN ./build-powerpc64le-toolchain.sh
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/rustroot/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV HOSTS=x86_64-unknown-linux-gnu
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/x86_64-unknown-netbsd/bin
lib32stdc++6
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
- [unique](library-features/unique.md)
- [unsize](library-features/unsize.md)
- [utf8_error_error_len](library-features/utf8-error-error-len.md)
+ - [vec_resize_default](library-features/vec-resize-default.md)
- [vec_remove_item](library-features/vec-remove-item.md)
- [windows_c](library-features/windows-c.md)
- [windows_handle](library-features/windows-handle.md)
[#23121]: https://github.com/rust-lang/rust/issues/23121
-See also [`slice_patterns`](slice-patterns.html).
+See also [`slice_patterns`](language-features/slice-patterns.html).
------------------------
[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
If you need more power and don't mind losing some of the niceties of
-`asm!`, check out [global_asm](global_asm.html).
+`asm!`, check out [global_asm](language-features/global_asm.html).
[#29641]: https://github.com/rust-lang/rust/issues/29641
-See also [`box_syntax`](box-syntax.html)
+See also [`box_syntax`](language-features/box-syntax.html)
------------------------
[#27779]: https://github.com/rust-lang/rust/issues/27779
-See also [`box_patterns`](box-patterns.html)
+See also [`box_patterns`](language-features/box-patterns.html)
------------------------
If you don't need quite as much power and flexibility as
`global_asm!` provides, and you don't mind restricting your inline
-assembly to `fn` bodies only, you might try the [asm](asm.html)
-feature instead.
+assembly to `fn` bodies only, you might try the
+[asm](language-features/asm.html) feature instead.
[`plugin`] and `rustc_private` features as well. For more details, see
their docs.
-[`plugin`]: plugin.html
+[`plugin`]: language-features/plugin.html
------------------------
This feature is part of "compiler plugins." It will often be used with the
[`plugin_registrar`] and `rustc_private` features.
-[`plugin_registrar`]: plugin-registrar.html
+[`plugin_registrar`]: language-features/plugin-registrar.html
------------------------
[#23121]: https://github.com/rust-lang/rust/issues/23121
-See also [`advanced_slice_patterns`](advanced-slice-patterns.html).
+See also
+[`advanced_slice_patterns`](language-features/advanced-slice-patterns.html).
------------------------
[#33082]: https://github.com/rust-lang/rust/issues/33082
-See also [`alloc_system`](alloc-system.html).
+See also [`alloc_system`](library-features/alloc-system.html).
------------------------
[#33082]: https://github.com/rust-lang/rust/issues/33082
-See also [`alloc_jemalloc`](alloc-jemalloc.html).
+See also [`alloc_jemalloc`](library-features/alloc-jemalloc.html).
------------------------
--- /dev/null
+# `vec_resize_default`
+
+The tracking issue for this feature is: [#41758]
+
+[#41758]: https://github.com/rust-lang/rust/issues/41758
+
+------------------------
-Subproject commit 11bfb0dcf85f7aa92abd30524bb1e42e18d108c6
+Subproject commit 3288e0659c08fb5006f6d6dd4b5675ed0c2c432a
.env("AR", &ar)
.env("RANLIB", format!("{} s", ar.display()));
- if target.contains("windows") {
- // A bit of history here, this used to be --enable-lazy-lock added in
- // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which
- // was also reported to MinGW:
- //
- // http://sourceforge.net/p/mingw-w64/bugs/395/
- //
- // When updating jemalloc to 4.0, however, it was found that binaries
- // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating
- // that a thread was unlocking a mutex it never locked. Disabling this
- // "lazy lock" option seems to fix the issue, but it was enabled by
- // default for MinGW targets in 13473c7 for jemalloc.
- //
- // As a result of all that, force disabling lazy lock on Windows, and
- // after reading some code it at least *appears* that the initialization
- // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems
- // hopefully...
- //
- // tl;dr: make windows behave like other platforms by disabling lazy
- // locking, but requires passing an option due to a historical
- // default with jemalloc.
- cmd.arg("--disable-lazy-lock");
- } else if target.contains("ios") {
+ if target.contains("ios") {
cmd.arg("--disable-tls");
} else if target.contains("android") {
// We force android to have prefixed symbols because apparently
//! objects of a single type.
#![crate_name = "arena"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(generic_param_attrs)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![cfg_attr(test, feature(test))]
#![allow(deprecated)]
#[unstable(feature = "fused", issue = "35602")]
impl<'a> FusedIterator for EncodeUtf16<'a> {}
-// Return the initial codepoint accumulator for the first byte.
-// The first byte is special, only want bottom 5 bits for width 2, 4 bits
-// for width 3, and 3 bits for width 4
-macro_rules! utf8_first_byte {
- ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
-}
-
-// return the value of $ch updated with continuation byte $byte
-macro_rules! utf8_acc_cont_byte {
- ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63) as u32)
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl Borrow<str> for String {
#[inline]
}
impl<T: Clone> Vec<T> {
- /// Resizes the `Vec` in-place so that `len()` is equal to `new_len`.
+ /// Resizes the `Vec` in-place so that `len` is equal to `new_len`.
///
- /// If `new_len` is greater than `len()`, the `Vec` is extended by the
+ /// If `new_len` is greater than `len`, the `Vec` is extended by the
/// difference, with each additional slot filled with `value`.
- /// If `new_len` is less than `len()`, the `Vec` is simply truncated.
+ /// If `new_len` is less than `len`, the `Vec` is simply truncated.
+ ///
+ /// This method requires `Clone` to clone the passed value. If you'd
+ /// rather create a value with `Default` instead, see [`resize_default`].
///
/// # Examples
///
/// vec.resize(2, 0);
/// assert_eq!(vec, [1, 2]);
/// ```
+ ///
+ /// [`resize_default`]: #method.resize_default
#[stable(feature = "vec_resize", since = "1.5.0")]
pub fn resize(&mut self, new_len: usize, value: T) {
let len = self.len();
if new_len > len {
- self.extend_with_element(new_len - len, value);
+ self.extend_with(new_len - len, ExtendElement(value))
+ } else {
+ self.truncate(new_len);
+ }
+ }
+
+ /// Clones and appends all elements in a slice to the `Vec`.
+ ///
+ /// Iterates over the slice `other`, clones each element, and then appends
+ /// it to this `Vec`. The `other` vector is traversed in-order.
+ ///
+ /// Note that this function is same as `extend` except that it is
+ /// specialized to work with slices instead. If and when Rust gets
+ /// specialization this function will likely be deprecated (but still
+ /// available).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut vec = vec![1];
+ /// vec.extend_from_slice(&[2, 3, 4]);
+ /// assert_eq!(vec, [1, 2, 3, 4]);
+ /// ```
+ #[stable(feature = "vec_extend_from_slice", since = "1.6.0")]
+ pub fn extend_from_slice(&mut self, other: &[T]) {
+ self.spec_extend(other.iter())
+ }
+}
+
+impl<T: Default> Vec<T> {
+ /// Resizes the `Vec` in-place so that `len` is equal to `new_len`.
+ ///
+ /// If `new_len` is greater than `len`, the `Vec` is extended by the
+ /// difference, with each additional slot filled with `Default::default()`.
+ /// If `new_len` is less than `len`, the `Vec` is simply truncated.
+ ///
+ /// This method uses `Default` to create new values on every push. If
+ /// you'd rather `Clone` a given value, use [`resize`].
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(vec_resize_default)]
+ ///
+ /// let mut vec = vec![1, 2, 3];
+ /// vec.resize_default(5);
+ /// assert_eq!(vec, [1, 2, 3, 0, 0]);
+ ///
+ /// let mut vec = vec![1, 2, 3, 4];
+ /// vec.resize_default(2);
+ /// assert_eq!(vec, [1, 2]);
+ /// ```
+ ///
+ /// [`resize`]: #method.resize
+ #[unstable(feature = "vec_resize_default", issue = "41758")]
+ pub fn resize_default(&mut self, new_len: usize) {
+ let len = self.len();
+
+ if new_len > len {
+ self.extend_with(new_len - len, ExtendDefault);
} else {
self.truncate(new_len);
}
}
+}
- /// Extend the vector by `n` additional clones of `value`.
- fn extend_with_element(&mut self, n: usize, value: T) {
+// This code generalises `extend_with_{element,default}`.
+trait ExtendWith<T> {
+ fn next(&self) -> T;
+ fn last(self) -> T;
+}
+
+struct ExtendElement<T>(T);
+impl<T: Clone> ExtendWith<T> for ExtendElement<T> {
+ fn next(&self) -> T { self.0.clone() }
+ fn last(self) -> T { self.0 }
+}
+
+struct ExtendDefault;
+impl<T: Default> ExtendWith<T> for ExtendDefault {
+ fn next(&self) -> T { Default::default() }
+ fn last(self) -> T { Default::default() }
+}
+impl<T> Vec<T> {
+ /// Extend the vector by `n` values, using the given generator.
+ fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, value: E) {
self.reserve(n);
unsafe {
// Write all elements except the last one
for _ in 1..n {
- ptr::write(ptr, value.clone());
+ ptr::write(ptr, value.next());
ptr = ptr.offset(1);
- // Increment the length in every step in case clone() panics
+ // Increment the length in every step in case next() panics
local_len.increment_len(1);
}
if n > 0 {
// We can write the last element directly without cloning needlessly
- ptr::write(ptr, value);
+ ptr::write(ptr, value.last());
local_len.increment_len(1);
}
// len set by scope guard
}
}
-
- /// Clones and appends all elements in a slice to the `Vec`.
- ///
- /// Iterates over the slice `other`, clones each element, and then appends
- /// it to this `Vec`. The `other` vector is traversed in-order.
- ///
- /// Note that this function is same as `extend` except that it is
- /// specialized to work with slices instead. If and when Rust gets
- /// specialization this function will likely be deprecated (but still
- /// available).
- ///
- /// # Examples
- ///
- /// ```
- /// let mut vec = vec![1];
- /// vec.extend_from_slice(&[2, 3, 4]);
- /// assert_eq!(vec, [1, 2, 3, 4]);
- /// ```
- #[stable(feature = "vec_extend_from_slice", since = "1.6.0")]
- pub fn extend_from_slice(&mut self, other: &[T]) {
- self.spec_extend(other.iter())
- }
}
// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
impl<T: Clone> SpecFromElem for T {
default fn from_elem(elem: Self, n: usize) -> Vec<Self> {
let mut v = Vec::with_capacity(n);
- v.extend_with_element(n, elem);
+ v.extend_with(n, ExtendElement(elem));
v
}
}
}
}
let mut v = Vec::with_capacity(n);
- v.extend_with_element(n, elem);
+ v.extend_with(n, ExtendElement(elem));
v
}
}
{
unsafe {
let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64
- let mut parts: [flt2dec::Part; 5] = mem::uninitialized();
+ let mut parts: [flt2dec::Part; 4] = mem::uninitialized();
let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact,
*num, sign, precision,
false, &mut buf, &mut parts);
unsafe {
// enough for f32 and f64
let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized();
- let mut parts: [flt2dec::Part; 5] = mem::uninitialized();
+ let mut parts: [flt2dec::Part; 4] = mem::uninitialized();
let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest,
*num, sign, 0, false, &mut buf, &mut parts);
fmt.pad_formatted_parts(&formatted)
{
unsafe {
let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64
- let mut parts: [flt2dec::Part; 7] = mem::uninitialized();
+ let mut parts: [flt2dec::Part; 6] = mem::uninitialized();
let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact,
*num, sign, precision,
upper, &mut buf, &mut parts);
unsafe {
// enough for f32 and f64
let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized();
- let mut parts: [flt2dec::Part; 7] = mem::uninitialized();
+ let mut parts: [flt2dec::Part; 6] = mem::uninitialized();
let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest,
*num, sign, (0, 0), upper,
&mut buf, &mut parts);
/// // exactly wouldn't be possible without executing filter().
/// assert_eq!((0, Some(10)), iter.size_hint());
///
- /// // Let's add one five more numbers with chain()
+ /// // Let's add five more numbers with chain()
/// let iter = (0..10).filter(|x| x % 2 == 0).chain(15..20);
///
/// // now both bounds are increased by five
#[macro_use]
mod internal_macros;
-#[path = "num/float_macros.rs"]
-#[macro_use]
-mod float_macros;
-
#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![doc(hidden)]
-
-macro_rules! assert_approx_eq {
- ($a:expr, $b:expr) => ({
- use num::Float;
- let (a, b) = (&$a, &$b);
- assert!((*a - *b).abs() < 1.0e-6,
- "{} is not approximately equal to {}", *a, *b);
- })
-}
/// it will only print given digits and nothing else.
///
/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
-/// There should be at least 5 parts available, due to the worst case like
-/// `[+][0.][0000][45][0000]` with `frac_digits = 10`.
+/// There should be at least 4 parts available, due to the worst case like
+/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
sign: Sign, frac_digits: usize, _upper: bool,
buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
/// cannot be in this range, avoiding any confusion.
///
/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
-/// There should be at least 7 parts available, due to the worst case like
-/// `[+][1][.][2345][e][-][67]`.
+/// There should be at least 6 parts available, due to the worst case like
+/// `[+][1][.][2345][e][-][6]`.
pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T,
sign: Sign, dec_bounds: (i16, i16), upper: bool,
buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
/// The byte buffer should be at least `ndigits` bytes long unless `ndigits` is
/// so large that only the fixed number of digits will be ever written.
/// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.)
-/// There should be at least 7 parts available, due to the worst case like
-/// `[+][1][.][2345][e][-][67]`.
+/// There should be at least 6 parts available, due to the worst case like
+/// `[+][1][.][2345][e][-][6]`.
pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
sign: Sign, ndigits: usize, upper: bool,
buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
/// The byte buffer should be enough for the output unless `frac_digits` is
/// so large that only the fixed number of digits will be ever written.
/// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.)
-/// There should be at least 5 parts available, due to the worst case like
-/// `[+][0.][0000][45][0000]` with `frac_digits = 10`.
+/// There should be at least 4 parts available, due to the worst case like
+/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
sign: Sign, frac_digits: usize, _upper: bool,
buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
pub mod bignum;
pub mod diy_float;
-macro_rules! checked_op {
- ($U:ty, $op:path, $x:expr, $y:expr) => {{
- let (result, overflowed) = unsafe { $op($x as $U, $y as $U) };
- if overflowed { None } else { Some(result as Self) }
- }}
-}
-
// `Int` + `SignedInt` implemented for signed integers
macro_rules! int_impl {
($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr,
/// }
/// ```
///
+/// Here is an example of the same `Point` struct implementing the `Add` trait
+/// using generics.
+///
+/// ```
+/// use std::ops::Add;
+///
+/// #[derive(Debug)]
+/// struct Point<T> {
+/// x: T,
+/// y: T,
+/// }
+///
+/// // Notice that the implementation uses the `Output` associated type
+/// impl<T: Add<Output=T>> Add for Point<T> {
+/// type Output = Point<T>;
+///
+/// fn add(self, other: Point<T>) -> Point<T> {
+/// Point {
+/// x: self.x + other.x,
+/// y: self.y + other.y,
+/// }
+/// }
+/// }
+///
+/// impl<T: PartialEq> PartialEq for Point<T> {
+/// fn eq(&self, other: &Self) -> bool {
+/// self.x == other.x && self.y == other.y
+/// }
+/// }
+///
+/// fn main() {
+/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
+/// Point { x: 3, y: 3 });
+/// }
+/// ```
+///
/// Note that `RHS = Self` by default, but this is not mandatory. For example,
/// [std::time::SystemTime] implements `Add<Duration>`, which permits
/// operations of the form `SystemTime = SystemTime + Duration`.
/// invalid pointers, types, and double drops.
#[stable(feature = "drop_in_place", since = "1.8.0")]
#[lang="drop_in_place"]
-#[inline]
#[allow(unconditional_recursion)]
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
// Code here does not matter - this is replaced by the
//! [mz]: https://code.google.com/p/miniz/
#![crate_name = "flate"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(warnings)]
#![feature(libc)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![feature(unique)]
#![cfg_attr(test, feature(rand))]
//! generated instead.
#![crate_name = "fmt_macros"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
test(attr(deny(warnings))))]
#![deny(warnings)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![feature(unicode)]
pub use self::Piece::*;
//! ```
#![crate_name = "getopts"]
-#![unstable(feature = "rustc_private",
+#![cfg_attr(stage0, unstable(feature = "rustc_private",
reason = "use the crates.io `getopts` library instead",
- issue = "27812")]
+ issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(missing_docs)]
#![deny(warnings)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
use self::Name::*;
use self::HasArg::*;
//! * [DOT language](http://www.graphviz.org/doc/info/lang.html)
#![crate_name = "graphviz"]
-#![unstable(feature = "rustc_private", issue = "27812")]
-#![feature(staged_api)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
//! }
//! ```
#![crate_name = "proc_macro_plugin"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![feature(plugin_registrar)]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
+#![cfg_attr(stage0, feature(rustc_private))]
extern crate rustc_plugin;
extern crate syntax;
fmt_macros = { path = "../libfmt_macros" }
graphviz = { path = "../libgraphviz" }
log = "0.3"
+owning_ref = "0.3.3"
rustc_back = { path = "../librustc_back" }
rustc_bitflags = { path = "../librustc_bitflags" }
rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
-rustc_llvm = { path = "../librustc_llvm" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
use rustc_data_structures::graph;
use cfg::*;
+use middle::region::CodeExtent;
use ty::{self, TyCtxt};
use syntax::ast;
use syntax::ptr::P;
scope_id: ast::NodeId,
to_index: CFGIndex) {
let mut data = CFGEdgeData { exiting_scopes: vec![] };
- let mut scope = self.tcx.node_extent(from_expr.id);
- let target_scope = self.tcx.node_extent(scope_id);
+ let mut scope = CodeExtent::Misc(from_expr.id);
+ let target_scope = CodeExtent::Misc(scope_id);
let region_maps = self.tcx.region_maps(self.owner_def_id);
while scope != target_scope {
data.exiting_scopes.push(scope.node_id());
}
}
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind<'tcx> {
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
db.depth.hash_stable(hcx, hasher);
i.hash_stable(hcx, hasher);
}
- ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
+ ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
+ def_id.hash_stable(hcx, hasher);
index.hash_stable(hcx, hasher);
name.hash_stable(hcx, hasher);
}
Free(call_site_scope_data, decl)
});
-impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData {
- fn_id,
- body_id
-});
-
impl_stable_hash_for!(struct ty::DebruijnIndex {
depth
});
FnPtrAddrCast
});
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtentData
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtent
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
- use middle::region::CodeExtentData;
+ use middle::region::CodeExtent;
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
- CodeExtentData::Misc(node_id) |
- CodeExtentData::DestructionScope(node_id) => {
+ CodeExtent::Misc(node_id) |
+ CodeExtent::DestructionScope(node_id) => {
node_id.hash_stable(hcx, hasher);
}
- CodeExtentData::CallSiteScope { fn_id, body_id } |
- CodeExtentData::ParameterScope { fn_id, body_id } => {
- fn_id.hash_stable(hcx, hasher);
+ CodeExtent::CallSiteScope(body_id) |
+ CodeExtent::ParameterScope(body_id) => {
body_id.hash_stable(hcx, hasher);
}
- CodeExtentData::Remainder(block_remainder) => {
+ CodeExtent::Remainder(block_remainder) => {
block_remainder.hash_stable(hcx, hasher);
}
}
custom_kind
});
-impl_stable_hash_for!(struct ty::FreeRegion<'tcx> {
+impl_stable_hash_for!(struct ty::FreeRegion {
scope,
bound_region
});
use super::InferCtxt;
use super::{MiscVariable, TypeTrace};
+use hir::def_id::DefId;
use ty::{IntType, UintType};
use ty::{self, Ty, TyCtxt};
use ty::error::TypeError;
use ty::relate::{self, Relate, RelateResult, TypeRelation};
+use ty::subst::Substs;
use traits::{Obligation, PredicateObligations};
use syntax::ast;
Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?))
}
+ fn relate_item_substs(&mut self,
+ item_def_id: DefId,
+ a_subst: &'tcx Substs<'tcx>,
+ b_subst: &'tcx Substs<'tcx>)
+ -> RelateResult<'tcx, &'tcx Substs<'tcx>>
+ {
+ if self.ambient_variance == ty::Variance::Invariant {
+ // Avoid fetching the variance if we are in an invariant
+ // context; no need, and it can induce dependency cycles
+ // (e.g. #41849).
+ relate::relate_substs(self, None, a_subst, b_subst)
+ } else {
+ let opt_variances = self.tcx().variances_of(item_def_id);
+ relate::relate_substs(self, Some(&opt_variances), a_subst, b_subst)
+ }
+ }
+
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
return Ok(r);
}
- // Early-bound regions should really have been substituted away before
- // we get to this point.
- ty::ReEarlyBound(..) => {
- span_bug!(
- self.span,
- "Encountered early bound region when generalizing: {:?}",
- r);
- }
-
// Always make a fresh region variable for skolemized regions;
// the higher-ranked decision procedures rely on this.
ty::ReSkolemized(..) => { }
ty::ReStatic |
ty::ReScope(..) |
ty::ReVar(..) |
+ ty::ReEarlyBound(..) |
ty::ReFree(..) => {
match self.ambient_variance {
ty::Invariant => return Ok(r),
return;
}
};
- let scope_decorated_tag = match *scope {
- region::CodeExtentData::Misc(_) => tag,
- region::CodeExtentData::CallSiteScope { .. } => {
+ let scope_decorated_tag = match scope {
+ region::CodeExtent::Misc(_) => tag,
+ region::CodeExtent::CallSiteScope(_) => {
"scope of call-site for function"
}
- region::CodeExtentData::ParameterScope { .. } => {
+ region::CodeExtent::ParameterScope(_) => {
"scope of function body"
}
- region::CodeExtentData::DestructionScope(_) => {
+ region::CodeExtent::DestructionScope(_) => {
new_string = format!("destruction scope surrounding {}", tag);
&new_string[..]
}
- region::CodeExtentData::Remainder(r) => {
+ region::CodeExtent::Remainder(r) => {
new_string = format!("block suffix following statement {}",
r.first_statement_index);
&new_string[..]
explain_span(self, scope_decorated_tag, span)
}
- ty::ReFree(ref fr) => {
- let prefix = match fr.bound_region {
- ty::BrAnon(idx) => {
- format!("the anonymous lifetime #{} defined on", idx + 1)
+ ty::ReEarlyBound(_) |
+ ty::ReFree(_) => {
+ let scope = match *region {
+ ty::ReEarlyBound(ref br) => {
+ self.parent_def_id(br.def_id).unwrap()
}
- ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
- _ => {
- format!("the lifetime {} as defined on",
- fr.bound_region)
+ ty::ReFree(ref fr) => fr.scope,
+ _ => bug!()
+ };
+ let prefix = match *region {
+ ty::ReEarlyBound(ref br) => {
+ format!("the lifetime {} as defined on", br.name)
+ }
+ ty::ReFree(ref fr) => {
+ match fr.bound_region {
+ ty::BrAnon(idx) => {
+ format!("the anonymous lifetime #{} defined on", idx + 1)
+ }
+ ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
+ _ => {
+ format!("the lifetime {} as defined on",
+ fr.bound_region)
+ }
+ }
}
+ _ => bug!()
};
- let node = fr.scope.map(|s| s.node_id())
+ let node = self.hir.as_local_node_id(scope)
.unwrap_or(DUMMY_NODE_ID);
let unknown;
let tag = match self.hir.find(node) {
Some(_) => {
unknown = format!("unexpected node ({}) for scope {:?}. \
Please report a bug.",
- self.hir.node_to_string(node), fr.scope);
+ self.hir.node_to_string(node), scope);
&unknown
}
None => {
unknown = format!("unknown node for scope {:?}. \
- Please report a bug.", fr.scope);
+ Please report a bug.", scope);
&unknown
}
};
ty::ReEmpty => ("the empty lifetime".to_owned(), None),
- ty::ReEarlyBound(ref data) => (data.name.to_string(), None),
-
// FIXME(#13998) ReSkolemized should probably print like
// ReFree rather than dumping Debug output on the user.
//
}
let mut err = match *sub {
+ ty::ReEarlyBound(_) |
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
let mut err = struct_span_err!(self.tcx.sess,
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
- ty::ReEarlyBound(..) |
ty::ReLateBound(..) => {
// leave bound regions alone
r
}
ty::ReStatic |
+ ty::ReEarlyBound(..) |
ty::ReFree(_) |
ty::ReScope(_) |
ty::ReVar(_) |
-> ty::Region<'tcx> {
// Regions that pre-dated the LUB computation stay as they are.
if !is_var_in_set(new_vars, r0) {
- assert!(!r0.is_bound());
+ assert!(!r0.is_late_bound());
debug!("generalize_region(r0={:?}): not new variable", r0);
return r0;
}
debug!("generalize_region(r0={:?}): \
non-new-variables found in {:?}",
r0, tainted);
- assert!(!r0.is_bound());
+ assert!(!r0.is_late_bound());
return r0;
}
r0: ty::Region<'tcx>)
-> ty::Region<'tcx> {
if !is_var_in_set(new_vars, r0) {
- assert!(!r0.is_bound());
+ assert!(!r0.is_late_bound());
return r0;
}
return rev_lookup(infcx, span, a_map, a_r.unwrap());
} else if a_r.is_none() && b_r.is_none() {
// Not related to bound variables from either fn:
- assert!(!r0.is_bound());
+ assert!(!r0.is_late_bound());
return r0;
} else {
// Other:
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
Option<ty::ParameterEnvironment<'tcx>>) {
- let item_id = tcx.hir.body_owner(self);
- (Some(tcx.typeck_tables_of(tcx.hir.local_def_id(item_id))),
+ let def_id = tcx.hir.body_owner_def_id(self);
+ (Some(tcx.typeck_tables_of(def_id)),
None,
- Some(ty::ParameterEnvironment::for_item(tcx, item_id)))
+ Some(tcx.parameter_environment(def_id)))
}
}
}
pub fn add_given(&self,
- sub: ty::FreeRegion<'tcx>,
+ sub: ty::Region<'tcx>,
sup: ty::RegionVid)
{
self.region_vars.add_given(sub, sup);
pub fn resolve_regions_and_report_errors(&self,
region_context: DefId,
- region_map: &RegionMaps<'tcx>,
+ region_map: &RegionMaps,
free_regions: &FreeRegionMap<'tcx>) {
let region_rels = RegionRelations::new(self.tcx,
region_context,
graph_name: String,
region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
- node_ids: FxHashMap<Node<'tcx>, usize>,
+ node_ids: FxHashMap<Node, usize>,
}
#[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
-enum Node<'tcx> {
+enum Node {
RegionVid(ty::RegionVid),
- Region(ty::RegionKind<'tcx>),
+ Region(ty::RegionKind),
}
// type Edge = Constraint;
#[derive(Clone, PartialEq, Eq, Debug, Copy)]
enum Edge<'tcx> {
Constraint(Constraint<'tcx>),
- EnclScope(CodeExtent<'tcx>, CodeExtent<'tcx>),
+ EnclScope(CodeExtent, CodeExtent),
}
impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
}
impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
- type Node = Node<'tcx>;
+ type Node = Node;
type Edge = Edge<'tcx>;
fn graph_id(&self) -> dot::Id {
dot::Id::new(&*self.graph_name).unwrap()
}
}
-fn constraint_to_nodes<'tcx>(c: &Constraint<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
+fn constraint_to_nodes(c: &Constraint) -> (Node, Node) {
match *c {
Constraint::ConstrainVarSubVar(rv_1, rv_2) =>
(Node::RegionVid(rv_1), Node::RegionVid(rv_2)),
}
}
-fn edge_to_nodes<'tcx>(e: &Edge<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
+fn edge_to_nodes(e: &Edge) -> (Node, Node) {
match *e {
Edge::Constraint(ref c) => constraint_to_nodes(c),
Edge::EnclScope(sub, sup) => {
}
impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
- type Node = Node<'tcx>;
+ type Node = Node;
type Edge = Edge<'tcx>;
- fn nodes(&self) -> dot::Nodes<Node<'tcx>> {
+ fn nodes(&self) -> dot::Nodes<Node> {
let mut set = FxHashSet();
for node in self.node_ids.keys() {
set.insert(*node);
debug!("region graph has {} edges", v.len());
Cow::Owned(v)
}
- fn source(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
+ fn source(&self, edge: &Edge<'tcx>) -> Node {
let (n1, _) = edge_to_nodes(edge);
debug!("edge {:?} has source {:?}", edge, n1);
n1
}
- fn target(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
+ fn target(&self, edge: &Edge<'tcx>) -> Node {
let (_, n2) = edge_to_nodes(edge);
debug!("edge {:?} has target {:?}", edge, n2);
n2
use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
use std::cell::{Cell, RefCell};
-use std::cmp::Ordering::{self, Less, Greater, Equal};
use std::fmt;
use std::mem;
use std::u32;
AddVerify(usize),
/// We added the given `given`
- AddGiven(ty::FreeRegion<'tcx>, ty::RegionVid),
+ AddGiven(Region<'tcx>, ty::RegionVid),
/// We added a GLB/LUB "combinaton variable"
AddCombination(CombineMapType, TwoRegions<'tcx>),
// record the fact that `'a <= 'b` is implied by the fn signature,
// and then ignore the constraint when solving equations. This is
// a bit of a hack but seems to work.
- givens: RefCell<FxHashSet<(ty::FreeRegion<'tcx>, ty::RegionVid)>>,
+ givens: RefCell<FxHashSet<(Region<'tcx>, ty::RegionVid)>>,
lubs: RefCell<CombineMap<'tcx>>,
glbs: RefCell<CombineMap<'tcx>>,
self.add_edge(a, b);
}
&AddGiven(a, b) => {
- self.add_edge(tcx.mk_region(ReFree(a)),
- tcx.mk_region(ReVar(b)));
+ self.add_edge(a, tcx.mk_region(ReVar(b)));
}
&AddVerify(i) => {
verifys[i].bound.for_each_region(&mut |b| {
}
}
- pub fn add_given(&self, sub: ty::FreeRegion<'tcx>, sup: ty::RegionVid) {
+ pub fn add_given(&self, sub: Region<'tcx>, sup: ty::RegionVid) {
// cannot add givens once regions are resolved
assert!(self.values_are_none());
origin);
match (sub, sup) {
- (&ReEarlyBound(..), _) |
(&ReLateBound(..), _) |
- (_, &ReEarlyBound(..)) |
(_, &ReLateBound(..)) => {
span_bug!(origin.span(),
"cannot relate bound region: {:?} <= {:?}",
match (a, b) {
(&ReLateBound(..), _) |
(_, &ReLateBound(..)) |
- (&ReEarlyBound(..), _) |
- (_, &ReEarlyBound(..)) |
(&ReErased, _) |
(_, &ReErased) => {
bug!("cannot relate region: LUB({:?}, {:?})", a, b);
b);
}
- (&ReFree(fr), &ReScope(s_id)) |
- (&ReScope(s_id), &ReFree(fr)) => {
+ (&ReEarlyBound(_), &ReScope(s_id)) |
+ (&ReScope(s_id), &ReEarlyBound(_)) |
+ (&ReFree(_), &ReScope(s_id)) |
+ (&ReScope(s_id), &ReFree(_)) => {
// A "free" region can be interpreted as "some region
- // at least as big as the block fr.scope_id". So, we can
+ // at least as big as fr.scope". So, we can
// reasonably compare free regions and scopes:
- if let Some(fr_scope) = fr.scope {
- let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
- if r_id == fr_scope {
- // if the free region's scope `fr.scope_id` is bigger than
- // the scope region `s_id`, then the LUB is the free
- // region itself:
- return self.tcx.mk_region(ReFree(fr));
+ let fr_scope = match (a, b) {
+ (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
+ region_rels.region_maps.early_free_extent(self.tcx, br)
+ }
+ (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
+ region_rels.region_maps.free_extent(self.tcx, fr)
+ }
+ _ => bug!()
+ };
+ let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
+ if r_id == fr_scope {
+ // if the free region's scope `fr.scope` is bigger than
+ // the scope region `s_id`, then the LUB is the free
+ // region itself:
+ match (a, b) {
+ (_, &ReScope(_)) => return a,
+ (&ReScope(_), _) => return b,
+ _ => bug!()
}
}
self.tcx.mk_region(ReScope(lub))
}
+ (&ReEarlyBound(_), &ReEarlyBound(_)) |
+ (&ReFree(_), &ReEarlyBound(_)) |
+ (&ReEarlyBound(_), &ReFree(_)) |
(&ReFree(_), &ReFree(_)) => {
region_rels.lub_free_regions(a, b)
}
let mut givens = self.givens.borrow_mut();
let seeds: Vec<_> = givens.iter().cloned().collect();
- for (fr, vid) in seeds {
+ for (r, vid) in seeds {
let seed_index = NodeIndex(vid.index as usize);
for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
let succ_index = succ_index.0 as u32;
if succ_index < self.num_vars() {
let succ_vid = RegionVid { index: succ_index };
- givens.insert((fr, succ_vid));
+ givens.insert((r, succ_vid));
}
}
}
// Check if this relationship is implied by a given.
match *a_region {
- ty::ReFree(fr) => {
- if self.givens.borrow().contains(&(fr, b_vid)) {
+ ty::ReEarlyBound(_) |
+ ty::ReFree(_) => {
+ if self.givens.borrow().contains(&(a_region, b_vid)) {
debug!("given");
return false;
}
// We place free regions first because we are special casing
// SubSupConflict(ReFree, ReFree) when reporting error, and so
// the user will more likely get a specific suggestion.
- fn free_regions_first(a: &RegionAndOrigin, b: &RegionAndOrigin) -> Ordering {
- match (a.region, b.region) {
- (&ReFree(..), &ReFree(..)) => Equal,
- (&ReFree(..), _) => Less,
- (_, &ReFree(..)) => Greater,
- (..) => Equal,
+ fn region_order_key(x: &RegionAndOrigin) -> u8 {
+ match *x.region {
+ ReEarlyBound(_) => 0,
+ ReFree(_) => 1,
+ _ => 2
}
}
- lower_bounds.sort_by(|a, b| free_regions_first(a, b));
- upper_bounds.sort_by(|a, b| free_regions_first(a, b));
+ lower_bounds.sort_by_key(region_order_key);
+ upper_bounds.sort_by_key(region_order_key);
for lower_bound in &lower_bounds {
for upper_bound in &upper_bounds {
//! This API is completely unstable and subject to change.
#![crate_name = "rustc"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(nonzero)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(slice_patterns)]
#![feature(specialization)]
-#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(discriminant_value)]
#![feature(sort_unstable)]
#![feature(trace_macros)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
#![recursion_limit="128"]
extern crate arena;
extern crate getopts;
extern crate graphviz;
extern crate libc;
-extern crate rustc_llvm as llvm;
+extern crate owning_ref;
extern crate rustc_back;
extern crate rustc_data_structures;
extern crate serialize;
run_lints!(self, check_ident, early_passes, sp, id);
}
- fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, n: ast::NodeId) {
+ fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) {
run_lints!(self, check_mod, early_passes, m, s, n);
ast_visit::walk_mod(self, m);
run_lints!(self, check_mod_post, early_passes, m, s, n);
use util::nodemap::{NodeSet, DefIdMap};
use std::any::Any;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::rc::Rc;
+use owning_ref::ErasedBoxRef;
use syntax::ast;
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
}
}
+/// The backend's way to give the crate store access to the metadata in a library.
+/// Note that it returns the raw metadata bytes stored in the library file, whether
+/// it is compressed, uncompressed, some weird mix, etc.
+/// rmeta files are backend independent and not handled here.
+///
+/// At the time of this writing, there is only one backend and one way to store
+/// metadata in library -- this trait just serves to decouple rustc_metadata from
+/// the archive reader, which depends on LLVM.
+pub trait MetadataLoader {
+ fn get_rlib_metadata(&self,
+ target: &Target,
+ filename: &Path)
+ -> Result<ErasedBoxRef<[u8]>, String>;
+ fn get_dylib_metadata(&self,
+ target: &Target,
+ filename: &Path)
+ -> Result<ErasedBoxRef<[u8]>, String>;
+}
+
/// A store of Rust crates, through with their metadata
/// can be accessed.
pub trait CrateStore {
fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>;
+ // access to the metadata loader
+ fn metadata_loader(&self) -> &MetadataLoader;
+
// item info
fn visibility(&self, def: DefId) -> ty::Visibility;
fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
fn export_macros(&self, cnum: CrateNum);
fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>;
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>;
- fn is_staged_api(&self, cnum: CrateNum) -> bool;
fn is_allocator(&self, cnum: CrateNum) -> bool;
fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
fn used_link_args(&self) -> Vec<String>;
// utility functions
- fn metadata_filename(&self) -> &str;
- fn metadata_section_name(&self, target: &Target) -> &str;
fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>;
fn used_crate_source(&self, cnum: CrateNum) -> CrateSource;
fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
{ bug!("lang_items") }
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>
{ bug!("missing_lang_items") }
- fn is_staged_api(&self, cnum: CrateNum) -> bool { bug!("is_staged_api") }
fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") }
fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
fn used_link_args(&self) -> Vec<String> { vec![] }
// utility functions
- fn metadata_filename(&self) -> &str { bug!("metadata_filename") }
- fn metadata_section_name(&self, target: &Target) -> &str { bug!("metadata_section_name") }
fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
{ vec![] }
fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") }
bug!("encode_metadata")
}
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
+
+ // access to the metadata loader
+ fn metadata_loader(&self) -> &MetadataLoader { bug!("metadata_loader") }
}
pub trait CrateLoader {
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
-> Self
{
pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
options: mc::MemCategorizationOptions)
-> Self
{
pub context: DefId,
/// region maps for the given context
- pub region_maps: &'a RegionMaps<'tcx>,
+ pub region_maps: &'a RegionMaps,
/// free-region relationships
pub free_regions: &'a FreeRegionMap<'tcx>,
pub fn new(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
context: DefId,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
free_regions: &'a FreeRegionMap<'tcx>,
) -> Self {
Self {
(&ty::ReScope(sub_scope), &ty::ReScope(super_scope)) =>
self.region_maps.is_subscope_of(sub_scope, super_scope),
- (&ty::ReScope(sub_scope), &ty::ReFree(fr)) => {
- // 1. It is safe to unwrap `fr.scope` because we
- // should only ever wind up comparing against
- // `ReScope` in the context of a method or
- // body, where `fr.scope` should be `Some`.
- self.region_maps.is_subscope_of(sub_scope, fr.scope.unwrap() /*1*/) ||
- self.is_static(super_region)
+ (&ty::ReScope(sub_scope), &ty::ReEarlyBound(ref br)) => {
+ let fr_scope = self.region_maps.early_free_extent(self.tcx, br);
+ self.region_maps.is_subscope_of(sub_scope, fr_scope)
}
- (&ty::ReFree(_), &ty::ReFree(_)) =>
- self.free_regions.relation.contains(&sub_region, &super_region) ||
- self.is_static(super_region),
+ (&ty::ReScope(sub_scope), &ty::ReFree(ref fr)) => {
+ let fr_scope = self.region_maps.free_extent(self.tcx, fr);
+ self.region_maps.is_subscope_of(sub_scope, fr_scope)
+ }
- (&ty::ReStatic, &ty::ReFree(_)) =>
- self.is_static(super_region),
+ (&ty::ReEarlyBound(_), &ty::ReEarlyBound(_)) |
+ (&ty::ReFree(_), &ty::ReEarlyBound(_)) |
+ (&ty::ReEarlyBound(_), &ty::ReFree(_)) |
+ (&ty::ReFree(_), &ty::ReFree(_)) =>
+ self.free_regions.relation.contains(&sub_region, &super_region),
_ =>
false,
}
};
+ let result = result || self.is_static(super_region);
debug!("is_subregion_of(sub_region={:?}, super_region={:?}) = {:?}",
sub_region, super_region, result);
result
debug!("is_static(super_region={:?})", super_region);
match *super_region {
ty::ReStatic => true,
- ty::ReFree(_) => {
+ ty::ReEarlyBound(_) | ty::ReFree(_) => {
let re_static = self.tcx.mk_region(ty::ReStatic);
self.free_regions.relation.contains(&re_static, &super_region)
}
- _ => bug!("only free regions should be given to `is_static`")
+ _ => false
}
}
for implied_bound in implied_bounds {
debug!("implied bound: {:?}", implied_bound);
match *implied_bound {
- ImpliedBound::RegionSubRegion(a @ &ty::ReFree(_), b @ &ty::ReFree(_)) |
- ImpliedBound::RegionSubRegion(a @ &ty::ReStatic, b @ &ty::ReFree(_)) => {
+ ImpliedBound::RegionSubRegion(a, b) => {
self.relate_regions(a, b);
}
- ImpliedBound::RegionSubRegion(..) |
ImpliedBound::RegionSubParam(..) |
ImpliedBound::RegionSubProjection(..) => {
}
// No region bounds here
}
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
- match (r_a, r_b) {
- // `'static: 'x` is not notable
- (&ty::ReStatic, &ty::ReFree(_)) => {},
-
- (&ty::ReFree(_), &ty::ReStatic) |
- (&ty::ReFree(_), &ty::ReFree(_)) => {
- // Record that `'a:'b`. Or, put another way, `'b <= 'a`.
- self.relate_regions(r_b, r_a);
- }
-
- _ => {
- // All named regions are instantiated with free regions.
- bug!("record_region_bounds: non free region: {:?} / {:?}",
- r_a,
- r_b);
- }
- }
+ self.relate_regions(r_b, r_a);
}
}
}
}
+ // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
+ // (with the exception that `'static: 'x` is not notable)
fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
- assert!(match *sub { ty::ReFree(_) | ty::ReStatic => true, _ => false });
- assert!(match *sup { ty::ReFree(_) | ty::ReStatic => true, _ => false });
- self.relation.add(sub, sup)
+ if (is_free(sub) || *sub == ty::ReStatic) && is_free(sup) {
+ self.relation.add(sub, sup)
+ }
}
pub fn lub_free_regions<'a, 'gcx>(&self,
r_a: Region<'tcx>,
r_b: Region<'tcx>)
-> Region<'tcx> {
- assert!(match *r_a { ty::ReFree(_) => true, _ => false });
- assert!(match *r_b { ty::ReFree(_) => true, _ => false });
+ assert!(is_free(r_a));
+ assert!(is_free(r_b));
let result = if r_a == r_b { r_a } else {
match self.relation.postdom_upper_bound(&r_a, &r_b) {
None => tcx.mk_region(ty::ReStatic),
}
}
+fn is_free(r: Region) -> bool {
+ match *r {
+ ty::ReEarlyBound(_) | ty::ReFree(_) => true,
+ _ => false
+ }
+}
+
impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
relation
});
//!
//! - `fallthrough_ln`: a live node that represents a fallthrough
//!
-//! - `no_ret_var`: a synthetic variable that is only 'read' from, the
-//! fallthrough node. This allows us to detect functions where we fail
-//! to return explicitly.
//! - `clean_exit_var`: a synthetic variable that is only 'read' from the
//! fallthrough node. It is only live if the function could converge
//! via means other than an explicit `return` expression. That is, it is
use self::VarKind::*;
use hir::def::*;
-use ty::{self, TyCtxt, ParameterEnvironment};
-use traits::{self, Reveal};
-use ty::subst::Subst;
+use ty::{self, TyCtxt};
use lint;
use util::nodemap::NodeMap;
enum VarKind {
Arg(NodeId, ast::Name),
Local(LocalInfo),
- ImplicitRet,
CleanExit
}
Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => {
self.variable_map.insert(node_id, v);
},
- ImplicitRet | CleanExit => {}
+ CleanExit => {}
}
debug!("{:?} is {:?}", v, vk);
Local(LocalInfo { name, .. }) | Arg(_, name) => {
name.to_string()
},
- ImplicitRet => "<implicit-ret>".to_string(),
CleanExit => "<clean-exit>".to_string()
}
}
// check for various error conditions
lsets.visit_body(body);
- lsets.check_ret(id, sp, entry_ln, body);
lsets.warn_about_unused_args(body, entry_ln);
}
struct Specials {
exit_ln: LiveNode,
fallthrough_ln: LiveNode,
- no_ret_var: Variable,
clean_exit_var: Variable
}
let specials = Specials {
exit_ln: ir.add_live_node(ExitNode),
fallthrough_ln: ir.add_live_node(ExitNode),
- no_ret_var: ir.add_variable(ImplicitRet),
clean_exit_var: ir.add_variable(CleanExit)
};
}
impl<'a, 'tcx> Liveness<'a, 'tcx> {
- fn check_ret(&self,
- id: NodeId,
- sp: Span,
- entry_ln: LiveNode,
- body: &hir::Body)
- {
- let fn_ty = self.ir.tcx.type_of(self.ir.tcx.hir.local_def_id(id));
- let fn_sig = match fn_ty.sty {
- ty::TyClosure(closure_def_id, substs) => {
- self.ir.tcx.closure_type(closure_def_id)
- .subst(self.ir.tcx, substs.substs)
- }
- _ => fn_ty.fn_sig()
- };
-
- let fn_ret = fn_sig.output();
-
- // within the fn body, late-bound regions are liberated
- // and must outlive the *call-site* of the function.
- let fn_ret =
- self.ir.tcx.liberate_late_bound_regions(
- Some(self.ir.tcx.call_site_extent(id, body.value.id)),
- &fn_ret);
-
- if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
- let param_env = ParameterEnvironment::for_item(self.ir.tcx, id);
- let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs);
- let is_nil = self.ir.tcx.infer_ctxt(param_env, Reveal::All).enter(|infcx| {
- let cause = traits::ObligationCause::dummy();
- traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil()
- });
-
- // for nil return types, it is ok to not return a value expl.
- if !is_nil {
- span_bug!(sp, "not all control paths return a value");
- }
- }
- }
-
fn check_lvalue(&mut self, expr: &'tcx Expr) {
match expr.node {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
#[derive(Clone)]
pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- pub region_maps: &'a RegionMaps<'tcx>,
+ pub region_maps: &'a RegionMaps,
options: MemCategorizationOptions,
}
impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
/// Context should be the `DefId` we use to fetch region-maps.
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps<'tcx>)
+ region_maps: &'a RegionMaps)
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
MemCategorizationContext::with_options(infcx,
region_maps,
}
pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
options: MemCategorizationOptions)
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
MemCategorizationContext {
cmt_result: cmt_<'tcx>)
-> cmt_<'tcx>
{
- // Look up the node ID of the closure body so we can construct
- // a free region within it
- let fn_body_id = {
- let fn_expr = match self.tcx().hir.find(upvar_id.closure_expr_id) {
- Some(hir_map::NodeExpr(e)) => e,
- _ => bug!()
- };
-
- match fn_expr.node {
- hir::ExprClosure(.., body_id, _) => body_id,
- _ => bug!()
- }
- };
-
// Region of environment pointer
let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion {
// The environment of a closure is guaranteed to
// outlive any bindings introduced in the body of the
// closure itself.
- scope: Some(self.tcx().item_extent(fn_body_id.node_id)),
+ scope: self.tcx().hir.local_def_id(upvar_id.closure_expr_id),
bound_region: ty::BrEnv
}));
pub fn temporary_scope(&self, id: ast::NodeId) -> (ty::Region<'tcx>, ty::Region<'tcx>)
{
let (scope, old_scope) =
- self.region_maps.old_and_new_temporary_scope(self.tcx(), id);
+ self.region_maps.old_and_new_temporary_scope(id);
(self.tcx().mk_region(match scope {
Some(scope) => ty::ReScope(scope),
None => ty::ReStatic
use std::mem;
use std::rc::Rc;
-use serialize;
use syntax::codemap;
use syntax::ast;
use syntax_pos::Span;
use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
use mir::transform::MirSource;
-pub type CodeExtent<'tcx> = &'tcx CodeExtentData;
-
-impl<'tcx> serialize::UseSpecializedEncodable for CodeExtent<'tcx> {}
-impl<'tcx> serialize::UseSpecializedDecodable for CodeExtent<'tcx> {}
-
/// CodeExtent represents a statically-describable extent that can be
/// used to bound the lifetime/region for values.
///
/// actually attach a more meaningful ordering to scopes than the one
/// generated via deriving here.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
-pub enum CodeExtentData {
+pub enum CodeExtent {
Misc(ast::NodeId),
// extent of the call-site for a function or closure (outlives
// the parameters as well as the body).
- CallSiteScope { fn_id: ast::NodeId, body_id: ast::NodeId },
+ CallSiteScope(hir::BodyId),
// extent of parameters passed to a function or closure (they
// outlive its body)
- ParameterScope { fn_id: ast::NodeId, body_id: ast::NodeId },
+ ParameterScope(hir::BodyId),
// extent of destructors for temporaries of node-id
DestructionScope(ast::NodeId),
Remainder(BlockRemainder)
}
-/// extent of call-site for a function/method.
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
- RustcDecodable, Debug, Copy)]
-pub struct CallSiteScopeData {
- pub fn_id: ast::NodeId, pub body_id: ast::NodeId,
-}
-
-impl CallSiteScopeData {
- pub fn to_code_extent<'a, 'tcx, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> CodeExtent<'tcx> {
- tcx.intern_code_extent(
- match *self {
- CallSiteScopeData { fn_id, body_id } =>
- CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id },
- })
- }
-}
-
/// Represents a subscope of `block` for a binding that is introduced
/// by `block.stmts[first_statement_index]`. Such subscopes represent
/// a suffix of the block. Note that each subscope does not include
/// * the subscope with `first_statement_index == 0` is scope of both
/// `a` and `b`; it does not include EXPR_1, but does include
/// everything after that first `let`. (If you want a scope that
-/// includes EXPR_1 as well, then do not use `CodeExtentData::Remainder`,
+/// includes EXPR_1 as well, then do not use `CodeExtent::Remainder`,
/// but instead another `CodeExtent` that encompasses the whole block,
-/// e.g. `CodeExtentData::Misc`.
+/// e.g. `CodeExtent::Misc`.
///
/// * the subscope with `first_statement_index == 1` is scope of `c`,
/// and thus does not include EXPR_2, but covers the `...`.
pub first_statement_index: u32,
}
-impl CodeExtentData {
+impl CodeExtent {
/// Returns a node id associated with this scope.
///
/// NB: likely to be replaced as API is refined; e.g. pnkfelix
/// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
pub fn node_id(&self) -> ast::NodeId {
match *self {
- CodeExtentData::Misc(node_id) => node_id,
+ CodeExtent::Misc(node_id) => node_id,
// These cases all return rough approximations to the
// precise extent denoted by `self`.
- CodeExtentData::Remainder(br) => br.block,
- CodeExtentData::DestructionScope(node_id) => node_id,
- CodeExtentData::CallSiteScope { fn_id: _, body_id } |
- CodeExtentData::ParameterScope { fn_id: _, body_id } => body_id,
+ CodeExtent::Remainder(br) => br.block,
+ CodeExtent::DestructionScope(node_id) => node_id,
+ CodeExtent::CallSiteScope(body_id) |
+ CodeExtent::ParameterScope(body_id) => body_id.node_id,
}
}
match hir_map.find(self.node_id()) {
Some(hir_map::NodeBlock(ref blk)) => {
match *self {
- CodeExtentData::CallSiteScope { .. } |
- CodeExtentData::ParameterScope { .. } |
- CodeExtentData::Misc(_) |
- CodeExtentData::DestructionScope(_) => Some(blk.span),
+ CodeExtent::CallSiteScope(_) |
+ CodeExtent::ParameterScope(_) |
+ CodeExtent::Misc(_) |
+ CodeExtent::DestructionScope(_) => Some(blk.span),
- CodeExtentData::Remainder(r) => {
+ CodeExtent::Remainder(r) => {
assert_eq!(r.block, blk.id);
// Want span for extent starting after the
// indexed statement and ending at end of
}
/// The region maps encode information about region relationships.
-pub struct RegionMaps<'tcx> {
+pub struct RegionMaps {
+ /// If not empty, this body is the root of this region hierarchy.
+ root_body: Option<hir::BodyId>,
+
+ /// The parent of the root body owner, if the latter is an
+ /// an associated const or method, as impls/traits can also
+ /// have lifetime parameters free in this body.
+ root_parent: Option<ast::NodeId>,
+
/// `scope_map` maps from a scope id to the enclosing scope id;
/// this is usually corresponding to the lexical nesting, though
/// in the case of closures the parent scope is the innermost
/// conditional expression or repeating block. (Note that the
/// enclosing scope id for the block associated with a closure is
/// the closure itself.)
- scope_map: FxHashMap<CodeExtent<'tcx>, CodeExtent<'tcx>>,
+ scope_map: FxHashMap<CodeExtent, CodeExtent>,
/// `var_map` maps from a variable or binding id to the block in
/// which that variable is declared.
- var_map: NodeMap<CodeExtent<'tcx>>,
+ var_map: NodeMap<CodeExtent>,
/// maps from a node-id to the associated destruction scope (if any)
- destruction_scopes: NodeMap<CodeExtent<'tcx>>,
+ destruction_scopes: NodeMap<CodeExtent>,
/// `rvalue_scopes` includes entries for those expressions whose cleanup scope is
/// larger than the default. The map goes from the expression id
/// table, the appropriate cleanup scope is the innermost
/// enclosing statement, conditional expression, or repeating
/// block (see `terminating_scopes`).
- rvalue_scopes: NodeMap<CodeExtent<'tcx>>,
+ rvalue_scopes: NodeMap<CodeExtent>,
/// Records the value of rvalue scopes before they were shrunk by
/// #36082, for error reporting.
///
/// FIXME: this should be temporary. Remove this by 1.18.0 or
/// so.
- shrunk_rvalue_scopes: NodeMap<CodeExtent<'tcx>>,
+ shrunk_rvalue_scopes: NodeMap<CodeExtent>,
/// Encodes the hierarchy of fn bodies. Every fn body (including
/// closures) forms its own distinct region hierarchy, rooted in
}
#[derive(Debug, Copy, Clone)]
-pub struct Context<'tcx> {
+pub struct Context {
/// the root of the current region tree. This is typically the id
/// of the innermost fn body. Each fn forms its own disjoint tree
/// in the region hierarchy. These fn bodies are themselves
root_id: Option<ast::NodeId>,
/// the scope that contains any new variables declared
- var_parent: Option<CodeExtent<'tcx>>,
+ var_parent: Option<CodeExtent>,
/// region parent of expressions etc
- parent: Option<CodeExtent<'tcx>>,
+ parent: Option<CodeExtent>,
}
struct RegionResolutionVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Generated maps:
- region_maps: &'a mut RegionMaps<'tcx>,
-
- cx: Context<'tcx>,
+ region_maps: RegionMaps,
- map: &'a hir_map::Map<'tcx>,
+ cx: Context,
/// `terminating_scopes` is a set containing the ids of each
/// statement, or conditional/repeating expression. These scopes
}
-impl<'tcx> RegionMaps<'tcx> {
+impl<'tcx> RegionMaps {
pub fn new() -> Self {
RegionMaps {
+ root_body: None,
+ root_parent: None,
scope_map: FxHashMap(),
destruction_scopes: FxHashMap(),
var_map: NodeMap(),
}
pub fn record_code_extent(&mut self,
- child: CodeExtent<'tcx>,
- parent: Option<CodeExtent<'tcx>>) {
+ child: CodeExtent,
+ parent: Option<CodeExtent>) {
debug!("{:?}.parent = {:?}", child, parent);
if let Some(p) = parent {
}
// record the destruction scopes for later so we can query them
- if let &CodeExtentData::DestructionScope(n) = child {
+ if let CodeExtent::DestructionScope(n) = child {
self.destruction_scopes.insert(n, child);
}
}
- pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(CodeExtent<'tcx>, CodeExtent<'tcx>) {
+ pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(CodeExtent, CodeExtent) {
for (&child, &parent) in &self.scope_map {
e(child, parent)
}
}
- pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent<'tcx>) {
- for (child, parent) in self.var_map.iter() {
+ pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent) {
+ for (child, &parent) in self.var_map.iter() {
e(child, parent)
}
}
- pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent<'tcx>> {
+ pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent> {
self.destruction_scopes.get(&n).cloned()
}
}
}
- fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+ fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id());
self.var_map.insert(var, lifetime);
}
- fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+ fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id());
self.rvalue_scopes.insert(var, lifetime);
}
- fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+ fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id());
self.shrunk_rvalue_scopes.insert(var, lifetime);
}
- pub fn opt_encl_scope(&self, id: CodeExtent<'tcx>) -> Option<CodeExtent<'tcx>> {
+ pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
//! Returns the narrowest scope that encloses `id`, if any.
self.scope_map.get(&id).cloned()
}
#[allow(dead_code)] // used in cfg
- pub fn encl_scope(&self, id: CodeExtent<'tcx>) -> CodeExtent<'tcx> {
+ pub fn encl_scope(&self, id: CodeExtent) -> CodeExtent {
//! Returns the narrowest scope that encloses `id`, if any.
self.opt_encl_scope(id).unwrap()
}
/// Returns the lifetime of the local variable `var_id`
- pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent<'tcx> {
+ pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent {
match self.var_map.get(&var_id) {
Some(&r) => r,
None => { bug!("no enclosing scope for id {:?}", var_id); }
}
}
- pub fn temporary_scope2<'a, 'gcx: 'tcx>(&self,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- expr_id: ast::NodeId)
- -> (Option<CodeExtent<'tcx>>, bool) {
- let temporary_scope = self.temporary_scope(tcx, expr_id);
+ pub fn temporary_scope2(&self, expr_id: ast::NodeId)
+ -> (Option<CodeExtent>, bool) {
+ let temporary_scope = self.temporary_scope(expr_id);
let was_shrunk = match self.shrunk_rvalue_scopes.get(&expr_id) {
Some(&s) => {
info!("temporary_scope2({:?}, scope={:?}, shrunk={:?})",
(temporary_scope, was_shrunk)
}
- pub fn old_and_new_temporary_scope<'a, 'gcx: 'tcx>(&self,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- expr_id: ast::NodeId)
- -> (Option<CodeExtent<'tcx>>,
- Option<CodeExtent<'tcx>>)
+ pub fn old_and_new_temporary_scope(&self, expr_id: ast::NodeId)
+ -> (Option<CodeExtent>,
+ Option<CodeExtent>)
{
- let temporary_scope = self.temporary_scope(tcx, expr_id);
+ let temporary_scope = self.temporary_scope(expr_id);
(temporary_scope,
self.shrunk_rvalue_scopes
.get(&expr_id).cloned()
.or(temporary_scope))
}
- pub fn temporary_scope<'a, 'gcx: 'tcx>(&self,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- expr_id: ast::NodeId)
- -> Option<CodeExtent<'tcx>> {
+ pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<CodeExtent> {
//! Returns the scope when temp created by expr_id will be cleaned up
// check for a designated rvalue scope
// if there's one. Static items, for instance, won't
// have an enclosing scope, hence no scope will be
// returned.
- let mut id = tcx.node_extent(expr_id);
+ let mut id = CodeExtent::Misc(expr_id);
- while let Some(&p) = self.scope_map.get(id) {
- match *p {
- CodeExtentData::DestructionScope(..) => {
+ while let Some(&p) = self.scope_map.get(&id) {
+ match p {
+ CodeExtent::DestructionScope(..) => {
debug!("temporary_scope({:?}) = {:?} [enclosing]",
expr_id, id);
return Some(id);
return None;
}
- pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind<'tcx> {
+ pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind {
//! Returns the lifetime of the variable `id`.
let scope = ty::ReScope(self.var_scope(id));
/// Finds the nearest common ancestor (if any) of two scopes. That is, finds the smallest
/// scope which is greater than or equal to both `scope_a` and `scope_b`.
pub fn nearest_common_ancestor(&self,
- scope_a: CodeExtent<'tcx>,
- scope_b: CodeExtent<'tcx>)
- -> CodeExtent<'tcx> {
+ scope_a: CodeExtent,
+ scope_b: CodeExtent)
+ -> CodeExtent {
if scope_a == scope_b { return scope_a; }
/// [1] The initial values for `a_buf` and `b_buf` are not used.
/// is re-initialized with new values (or else fallback to a
/// heap-allocated vector).
let mut a_buf: [CodeExtent; 32] = [scope_a /* [1] */; 32];
- let mut a_vec: Vec<CodeExtent<'tcx>> = vec![];
+ let mut a_vec: Vec<CodeExtent> = vec![];
let mut b_buf: [CodeExtent; 32] = [scope_b /* [1] */; 32];
- let mut b_vec: Vec<CodeExtent<'tcx>> = vec![];
+ let mut b_vec: Vec<CodeExtent> = vec![];
let scope_map = &self.scope_map;
let a_ancestors = ancestors_of(scope_map, scope_a, &mut a_buf, &mut a_vec);
let b_ancestors = ancestors_of(scope_map, scope_b, &mut b_buf, &mut b_vec);
let a_root_scope = a_ancestors[a_index];
let b_root_scope = a_ancestors[a_index];
return match (a_root_scope, b_root_scope) {
- (&CodeExtentData::DestructionScope(a_root_id),
- &CodeExtentData::DestructionScope(b_root_id)) => {
+ (CodeExtent::DestructionScope(a_root_id),
+ CodeExtent::DestructionScope(b_root_id)) => {
if self.fn_is_enclosed_by(a_root_id, b_root_id) {
// `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
scope_b
}
}
- fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent<'tcx>, CodeExtent<'tcx>>,
- scope: CodeExtent<'tcx>,
- buf: &'a mut [CodeExtent<'tcx>; 32],
- vec: &'a mut Vec<CodeExtent<'tcx>>)
- -> &'a [CodeExtent<'tcx>] {
+ fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent, CodeExtent>,
+ scope: CodeExtent,
+ buf: &'a mut [CodeExtent; 32],
+ vec: &'a mut Vec<CodeExtent>)
+ -> &'a [CodeExtent] {
// debug!("ancestors_of(scope={:?})", scope);
let mut scope = scope;
while i < 32 {
buf[i] = scope;
match scope_map.get(&scope) {
- Some(superscope) => scope = superscope,
+ Some(&superscope) => scope = superscope,
_ => return &buf[..i+1]
}
i += 1;
loop {
vec.push(scope);
match scope_map.get(&scope) {
- Some(superscope) => scope = superscope,
+ Some(&superscope) => scope = superscope,
_ => return &*vec
}
}
}
}
+
+ /// Assuming that the provided region was defined within this `RegionMaps`,
+ /// returns the outermost `CodeExtent` that the region outlives.
+ pub fn early_free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ br: &ty::EarlyBoundRegion)
+ -> CodeExtent {
+ let param_owner = tcx.parent_def_id(br.def_id).unwrap();
+
+ let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
+ let body_id = tcx.hir.maybe_body_owned_by(param_owner_id).unwrap_or_else(|| {
+ // The lifetime was defined on node that doesn't own a body,
+ // which in practice can only mean a trait or an impl, that
+ // is the parent of a method, and that is enforced below.
+ assert_eq!(Some(param_owner_id), self.root_parent,
+ "free_extent: {:?} not recognized by the region maps for {:?}",
+ param_owner,
+ self.root_body.map(|body| tcx.hir.body_owner_def_id(body)));
+
+ // The trait/impl lifetime is in scope for the method's body.
+ self.root_body.unwrap()
+ });
+
+ CodeExtent::CallSiteScope(body_id)
+ }
+
+ /// Assuming that the provided region was defined within this `RegionMaps`,
+ /// returns the outermost `CodeExtent` that the region outlives.
+ pub fn free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeRegion)
+ -> CodeExtent {
+ let param_owner = match fr.bound_region {
+ ty::BoundRegion::BrNamed(def_id, _) => {
+ tcx.parent_def_id(def_id).unwrap()
+ }
+ _ => fr.scope
+ };
+
+ // Ensure that the named late-bound lifetimes were defined
+ // on the same function that they ended up being freed in.
+ assert_eq!(param_owner, fr.scope);
+
+ let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
+ CodeExtent::CallSiteScope(tcx.hir.body_owned_by(param_owner_id))
+ }
}
/// Records the lifetime of a local variable as `cx.var_parent`
debug!("resolve_block(blk.id={:?})", blk.id);
let prev_cx = visitor.cx;
- let block_extent = visitor.new_node_extent_with_dtor(blk.id);
// We treat the tail expression in the block (if any) somewhat
// differently from the statements. The issue has to do with
// `other_argument()` has run and also the call to `quux(..)`
// itself has returned.
- visitor.cx = Context {
- root_id: prev_cx.root_id,
- var_parent: Some(block_extent),
- parent: Some(block_extent),
- };
+ visitor.enter_node_extent_with_dtor(blk.id);
+ visitor.cx.var_parent = visitor.cx.parent;
{
// This block should be kept approximately in sync with
// has the previous subscope in the block as a parent,
// except for the first such subscope, which has the
// block itself as a parent.
- let stmt_extent = visitor.new_code_extent(
- CodeExtentData::Remainder(BlockRemainder {
+ visitor.enter_code_extent(
+ CodeExtent::Remainder(BlockRemainder {
block: blk.id,
first_statement_index: i as u32
})
);
- visitor.cx = Context {
- root_id: prev_cx.root_id,
- var_parent: Some(stmt_extent),
- parent: Some(stmt_extent),
- };
+ visitor.cx.var_parent = visitor.cx.parent;
}
visitor.visit_stmt(statement)
}
}
fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) {
- visitor.new_node_extent(pat.id);
+ visitor.record_code_extent(CodeExtent::Misc(pat.id));
// If this is a binding then record the lifetime of that binding.
if let PatKind::Binding(..) = pat.node {
// statement plus its destructors, and thus the extent for which
// regions referenced by the destructors need to survive.
visitor.terminating_scopes.insert(stmt_id);
- let stmt_extent = visitor.new_node_extent_with_dtor(stmt_id);
let prev_parent = visitor.cx.parent;
- visitor.cx.parent = Some(stmt_extent);
+ visitor.enter_node_extent_with_dtor(stmt_id);
+
intravisit::walk_stmt(visitor, stmt);
+
visitor.cx.parent = prev_parent;
}
fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &'tcx hir::Expr) {
debug!("resolve_expr(expr.id={:?})", expr.id);
- let expr_extent = visitor.new_node_extent_with_dtor(expr.id);
let prev_cx = visitor.cx;
- visitor.cx.parent = Some(expr_extent);
+ visitor.enter_node_extent_with_dtor(expr.id);
{
let terminating_scopes = &mut visitor.terminating_scopes;
}
hir::ExprMatch(..) => {
- visitor.cx.var_parent = Some(expr_extent);
+ visitor.cx.var_parent = visitor.cx.parent;
}
hir::ExprAssignOp(..) | hir::ExprIndex(..) |
fn record_rvalue_scope_if_borrow_expr<'a, 'tcx>(
visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
expr: &hir::Expr,
- blk_id: CodeExtent<'tcx>)
+ blk_id: CodeExtent)
{
match expr.node {
hir::ExprAddrOf(_, ref subexpr) => {
/// Note: ET is intended to match "rvalues or lvalues based on rvalues".
fn record_rvalue_scope<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
expr: &hir::Expr,
- blk_scope: CodeExtent<'tcx>,
+ blk_scope: CodeExtent,
is_shrunk: bool) {
let mut expr = expr;
loop {
}
impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> {
- pub fn intern_code_extent(&mut self,
- data: CodeExtentData,
- parent: Option<CodeExtent<'tcx>>)
- -> CodeExtent<'tcx> {
- let code_extent = self.tcx.intern_code_extent(data);
- self.region_maps.record_code_extent(code_extent, parent);
- code_extent
- }
-
- pub fn intern_node(&mut self,
- n: ast::NodeId,
- parent: Option<CodeExtent<'tcx>>) -> CodeExtent<'tcx> {
- self.intern_code_extent(CodeExtentData::Misc(n), parent)
- }
-
/// Records the current parent (if any) as the parent of `child_scope`.
- fn new_code_extent(&mut self, child_scope: CodeExtentData) -> CodeExtent<'tcx> {
+ fn record_code_extent(&mut self, child_scope: CodeExtent) {
let parent = self.cx.parent;
- self.intern_code_extent(child_scope, parent)
+ self.region_maps.record_code_extent(child_scope, parent);
}
- fn new_node_extent(&mut self, child_scope: ast::NodeId) -> CodeExtent<'tcx> {
- self.new_code_extent(CodeExtentData::Misc(child_scope))
+ /// Records the current parent (if any) as the parent of `child_scope`,
+ /// and sets `child_scope` as the new current parent.
+ fn enter_code_extent(&mut self, child_scope: CodeExtent) {
+ self.record_code_extent(child_scope);
+ self.cx.parent = Some(child_scope);
}
- fn new_node_extent_with_dtor(&mut self, id: ast::NodeId) -> CodeExtent<'tcx> {
+ fn enter_node_extent_with_dtor(&mut self, id: ast::NodeId) {
// If node was previously marked as a terminating scope during the
// recursive visit of its parent node in the AST, then we need to
// account for the destruction scope representing the extent of
// the destructors that run immediately after it completes.
if self.terminating_scopes.contains(&id) {
- let ds = self.new_code_extent(
- CodeExtentData::DestructionScope(id));
- self.intern_node(id, Some(ds))
- } else {
- self.new_node_extent(id)
+ self.enter_code_extent(CodeExtent::DestructionScope(id));
}
+ self.enter_code_extent(CodeExtent::Misc(id));
}
}
fn visit_body(&mut self, body: &'tcx hir::Body) {
let body_id = body.id();
- let owner_id = self.map.body_owner(body_id);
+ let owner_id = self.tcx.hir.body_owner(body_id);
debug!("visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})",
owner_id,
}
self.cx.root_id = Some(body_id.node_id);
- self.cx.parent = Some(self.new_code_extent(
- CodeExtentData::CallSiteScope { fn_id: owner_id, body_id: body_id.node_id }));
- self.cx.parent = Some(self.new_code_extent(
- CodeExtentData::ParameterScope { fn_id: owner_id, body_id: body_id.node_id }));
+ self.enter_code_extent(CodeExtent::CallSiteScope(body_id));
+ self.enter_code_extent(CodeExtent::ParameterScope(body_id));
// The arguments and `self` are parented to the fn.
self.cx.var_parent = self.cx.parent.take();
}
fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
- -> Rc<RegionMaps<'tcx>>
+ -> Rc<RegionMaps>
{
let closure_base_def_id = tcx.closure_base_def_id(def_id);
if closure_base_def_id != def_id {
return tcx.region_maps(closure_base_def_id);
}
- let mut maps = RegionMaps::new();
-
let id = tcx.hir.as_local_node_id(def_id).unwrap();
- if let Some(body) = tcx.hir.maybe_body_owned_by(id) {
+ let maps = if let Some(body) = tcx.hir.maybe_body_owned_by(id) {
let mut visitor = RegionResolutionVisitor {
- tcx: tcx,
- region_maps: &mut maps,
- map: &tcx.hir,
+ tcx,
+ region_maps: RegionMaps::new(),
cx: Context {
root_id: None,
parent: None,
terminating_scopes: NodeSet(),
};
+ visitor.region_maps.root_body = Some(body);
+
+ // If the item is an associated const or a method,
+ // record its impl/trait parent, as it can also have
+ // lifetime parameters free in this body.
+ match tcx.hir.get(id) {
+ hir::map::NodeImplItem(_) |
+ hir::map::NodeTraitItem(_) => {
+ visitor.region_maps.root_parent = Some(tcx.hir.get_parent(id));
+ }
+ _ => {}
+ }
+
visitor.visit_body(tcx.hir.body(body));
- }
+
+ visitor.region_maps
+ } else {
+ RegionMaps::new()
+ };
Rc::new(maps)
}
use session::Session;
use hir::def::Def;
use hir::def_id::DefId;
-use middle::region;
use ty;
use std::cell::Cell;
EarlyBound(/* index */ u32, /* lifetime decl */ ast::NodeId),
LateBound(ty::DebruijnIndex, /* lifetime decl */ ast::NodeId),
LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32),
- Free(region::CallSiteScopeData, /* lifetime decl */ ast::NodeId),
+ Free(DefId, /* lifetime decl */ ast::NodeId),
}
impl Region {
};
if let Some(mut def) = result {
- if let Some(body_id) = outermost_body {
+ if let Region::EarlyBound(..) = def {
+ // Do not free early-bound regions, only late-bound ones.
+ } else if let Some(body_id) = outermost_body {
let fn_id = self.hir_map.body_owner(body_id);
- let scope_data = region::CallSiteScopeData {
- fn_id: fn_id, body_id: body_id.node_id
- };
match self.hir_map.get(fn_id) {
hir::map::NodeItem(&hir::Item {
node: hir::ItemFn(..), ..
hir::map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(..), ..
}) => {
- def = Region::Free(scope_data, def.id().unwrap());
+ let scope = self.hir_map.local_def_id(fn_id);
+ def = Region::Free(scope, def.id().unwrap());
}
_ => {}
}
pub use self::StabilityLevel::*;
-use hir::map as hir_map;
use lint;
use hir::def::Def;
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE};
use ty::{self, TyCtxt};
use middle::privacy::AccessLevels;
+use session::Session;
use syntax::symbol::Symbol;
use syntax_pos::{Span, DUMMY_SP};
use syntax::ast;
item_sp: Span, kind: AnnotationKind, visit_children: F)
where F: FnOnce(&mut Self)
{
- if self.index.staged_api[&LOCAL_CRATE] && self.tcx.sess.features.borrow().staged_api {
+ if self.index.staged_api[&LOCAL_CRATE] {
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
self.tcx.sess.span_err(item_sp, "`#[deprecated]` cannot be used in staged api, \
parent_depr: None,
in_trait_impl: false,
};
+
+ // If the `-Z force-unstable-if-unmarked` flag is passed then we provide
+ // a parent stability annotation which indicates that this is private
+ // with the `rustc_private` feature. This is intended for use when
+ // compiling librustc crates themselves so we can leverage crates.io
+ // while maintaining the invariant that all sysroot crates are unstable
+ // by default and are unable to be used.
+ if tcx.sess.opts.debugging_opts.force_unstable_if_unmarked {
+ let reason = "this crate is being loaded from the sysroot, and \
+ unstable location; did you mean to load this crate \
+ from crates.io via `Cargo.toml` instead?";
+ let stability = tcx.intern_stability(Stability {
+ level: attr::StabilityLevel::Unstable {
+ reason: Some(Symbol::intern(reason)),
+ issue: 27812,
+ },
+ feature: Symbol::intern("rustc_private"),
+ rustc_depr: None,
+ });
+ annotator.parent_stab = Some(stability);
+ }
+
annotator.annotate(ast::CRATE_NODE_ID, &krate.attrs, krate.span, AnnotationKind::Required,
|v| intravisit::walk_crate(v, krate));
}
- pub fn new(hir_map: &hir_map::Map) -> Index<'tcx> {
- let krate = hir_map.krate();
-
- let mut is_staged_api = false;
- for attr in &krate.attrs {
- if attr.path == "stable" || attr.path == "unstable" {
- is_staged_api = true;
- break
- }
- }
+ pub fn new(sess: &Session) -> Index<'tcx> {
+ let is_staged_api =
+ sess.opts.debugging_opts.force_unstable_if_unmarked ||
+ sess.features.borrow().staged_api;
let mut staged_api = FxHashMap();
staged_api.insert(LOCAL_CRATE, is_staged_api);
}
}
- let is_staged_api = *self.stability.borrow_mut().staged_api.entry(def_id.krate)
- .or_insert_with(|| self.sess.cstore.is_staged_api(def_id.krate));
+ let is_staged_api = self.lookup_stability(DefId {
+ index: CRATE_DEF_INDEX,
+ ..def_id
+ }).is_some();
if !is_staged_api {
return;
}
match stability {
Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => {
- if !self.stability.borrow().active_features.contains(feature) {
- let msg = match *reason {
- Some(ref r) => format!("use of unstable library feature '{}': {}",
- feature.as_str(), &r),
- None => format!("use of unstable library feature '{}'", &feature)
- };
- emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
- GateIssue::Library(Some(issue)), &msg);
+ if self.stability.borrow().active_features.contains(feature) {
+ return
}
+
+ // When we're compiling the compiler itself we may pull in
+ // crates from crates.io, but those crates may depend on other
+ // crates also pulled in from crates.io. We want to ideally be
+ // able to compile everything without requiring upstream
+ // modifications, so in the case that this looks like a
+ // rustc_private crate (e.g. a compiler crate) and we also have
+ // the `-Z force-unstable-if-unmarked` flag present (we're
+ // compiling a compiler crate), then let this missing feature
+ // annotation slide.
+ if *feature == "rustc_private" && issue == 27812 {
+ if self.sess.opts.debugging_opts.force_unstable_if_unmarked {
+ return
+ }
+ }
+
+ let msg = match *reason {
+ Some(ref r) => format!("use of unstable library feature '{}': {}",
+ feature.as_str(), &r),
+ None => format!("use of unstable library feature '{}'", &feature)
+ };
+ emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
+ GateIssue::Library(Some(issue)), &msg);
}
Some(_) => {
// Stable APIs are always ok to call and deprecated APIs are
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
- if tcx.stability.borrow().staged_api[&LOCAL_CRATE] && tcx.sess.features.borrow().staged_api {
+ if tcx.stability.borrow().staged_api[&LOCAL_CRATE] {
let krate = tcx.hir.krate();
let mut missing = MissingStabilityAnnotations {
tcx: tcx,
StorageDead(Lvalue<'tcx>),
InlineAsm {
- asm: InlineAsm,
+ asm: Box<InlineAsm>,
outputs: Vec<Lvalue<'tcx>>,
inputs: Vec<Operand<'tcx>>
},
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Operand<'tcx> {
Consume(Lvalue<'tcx>),
- Constant(Constant<'tcx>),
+ Constant(Box<Constant<'tcx>>),
}
impl<'tcx> Debug for Operand<'tcx> {
substs: &'tcx Substs<'tcx>,
span: Span,
) -> Self {
- Operand::Constant(Constant {
+ Operand::Constant(box Constant {
span: span,
ty: tcx.type_of(def_id).subst(tcx, substs),
literal: Literal::Value { value: ConstVal::Function(def_id, substs) },
/// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
/// that `Foo` has a destructor. These rvalues can be optimized
/// away after type-checking and before lowering.
- Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
+ Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
tuple_fmt.finish()
}
- match *kind {
+ match **kind {
AggregateKind::Array(_) => write!(fmt, "{:?}", lvs),
AggregateKind::Tuple => {
Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
Box(ty) => Box(ty.fold_with(folder)),
Aggregate(ref kind, ref fields) => {
- let kind = match *kind {
+ let kind = box match **kind {
AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
AggregateKind::Tuple => AggregateKind::Tuple,
AggregateKind::Adt(def, v, substs, n) =>
Discriminant(ref lval) => lval.visit_with(visitor),
Box(ty) => ty.visit_with(visitor),
Aggregate(ref kind, ref fields) => {
- (match *kind {
+ (match **kind {
AggregateKind::Array(ty) => ty.visit_with(visitor),
AggregateKind::Tuple => false,
AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
tcx.mk_box(t)
}
Rvalue::Aggregate(ref ak, ref ops) => {
- match *ak {
+ match **ak {
AggregateKind::Array(ty) => {
tcx.mk_array(ty, ops.len())
}
Rvalue::Aggregate(ref $($mutability)* kind,
ref $($mutability)* operands) => {
+ let kind = &$($mutability)* **kind;
match *kind {
AggregateKind::Array(ref $($mutability)* ty) => {
self.visit_ty(ty);
}
);
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum PrintRequest {
FileNames,
Sysroot,
"add a source pattern to the file path remapping config"),
remap_path_prefix_to: Vec<String> = (vec![], parse_string_push, [TRACKED],
"add a mapping target to the file path remapping config"),
+ force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
+ "force all crates to be `rustc_private` unstable"),
}
pub fn default_lib_output() -> CrateType {
use rustc_back::{LinkerFlavor, PanicStrategy};
use rustc_back::target::Target;
use rustc_data_structures::flock;
-use llvm;
use std::path::{Path, PathBuf};
use std::cell::{self, Cell, RefCell};
use std::collections::HashMap;
use std::env;
-use std::ffi::CString;
use std::io::Write;
use std::rc::Rc;
use std::fmt;
use std::time::Duration;
use std::sync::Arc;
-use libc::c_int;
mod code_stats;
pub mod config;
out_of_fuel: Cell::new(false),
};
- init_llvm(&sess);
-
sess
}
}
}
-fn init_llvm(sess: &Session) {
- unsafe {
- // Before we touch LLVM, make sure that multithreading is enabled.
- use std::sync::Once;
- static INIT: Once = Once::new();
- static mut POISONED: bool = false;
- INIT.call_once(|| {
- if llvm::LLVMStartMultithreaded() != 1 {
- // use an extra bool to make sure that all future usage of LLVM
- // cannot proceed despite the Once not running more than once.
- POISONED = true;
- }
-
- configure_llvm(sess);
- });
-
- if POISONED {
- bug!("couldn't enable multi-threaded LLVM");
- }
- }
-}
-
-unsafe fn configure_llvm(sess: &Session) {
- let mut llvm_c_strs = Vec::new();
- let mut llvm_args = Vec::new();
-
- {
- let mut add = |arg: &str| {
- let s = CString::new(arg).unwrap();
- llvm_args.push(s.as_ptr());
- llvm_c_strs.push(s);
- };
- add("rustc"); // fake program name
- if sess.time_llvm_passes() { add("-time-passes"); }
- if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
-
- for arg in &sess.opts.cg.llvm_args {
- add(&(*arg));
- }
- }
-
- llvm::LLVMInitializePasses();
-
- llvm::initialize_available_targets();
-
- llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
- llvm_args.as_ptr());
-}
-
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
let emitter: Box<Emitter> = match output {
config::ErrorOutputType::HumanReadable(color_config) => {
};
// Search for a predicate like `Self : Sized` amongst the trait bounds.
- let free_substs = self.construct_free_substs(def_id, None);
let predicates = self.predicates_of(def_id);
- let predicates = predicates.instantiate(self, free_substs).predicates;
+ let predicates = predicates.instantiate_identity(self).predicates;
elaborate_predicates(self, predicates)
.any(|predicate| {
match predicate {
}
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
- let penv = tcx.construct_parameter_environment(DUMMY_SP,
- impl1_def_id,
- None);
- let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
- .unwrap()
- .subst(tcx, &penv.free_substs);
+ let penv = tcx.parameter_environment(impl1_def_id);
+ let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
// Create a infcx, taking the predicates of impl1 as assumptions:
let result = tcx.infer_ctxt(penv, Reveal::UserFacing).enter(|infcx| {
// I want to be conservative. --nmatsakis
let ty_max = data.skip_binder().0;
let r_min = data.skip_binder().1;
- if r_min.is_bound() {
+ if r_min.is_late_bound() {
return;
}
tcx.outlives_components(ty_max)
.into_iter()
.filter_map(|component| match component {
- Component::Region(r) => if r.is_bound() {
+ Component::Region(r) => if r.is_late_bound() {
None
} else {
Some(ty::Predicate::RegionOutlives(
use hir::map::DisambiguatedDefPathData;
use middle::free_region::FreeRegionMap;
use middle::lang_items;
-use middle::region::{CodeExtent, CodeExtentData};
use middle::resolve_lifetime;
use middle::stability;
use mir::Mir;
type_: RefCell<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
type_list: RefCell<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
- region: RefCell<FxHashSet<Interned<'tcx, RegionKind<'tcx>>>>,
+ region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
}
layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
- code_extent_interner: RefCell<FxHashSet<CodeExtent<'tcx>>>,
-
/// A vector of every trait accessible in the whole crate
/// (i.e. including those from subcrates). This is used only for
/// error reporting, and so is lazily initialised and generally
interned
}
- pub fn node_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> {
- self.intern_code_extent(CodeExtentData::Misc(n))
- }
-
- // Returns the code extent for an item - the destruction scope.
- pub fn item_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> {
- self.intern_code_extent(CodeExtentData::DestructionScope(n))
- }
-
- pub fn call_site_extent(self, fn_id: ast::NodeId, body_id: ast::NodeId) -> CodeExtent<'gcx> {
- assert!(fn_id != body_id);
- self.intern_code_extent(CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id })
- }
-
- pub fn intern_code_extent(self, data: CodeExtentData) -> CodeExtent<'gcx> {
- if let Some(st) = self.code_extent_interner.borrow().get(&data) {
- return st;
- }
-
- let interned = self.global_interners.arena.alloc(data);
- if let Some(prev) = self.code_extent_interner.borrow_mut().replace(interned) {
- bug!("Tried to overwrite interned code-extent: {:?}", prev)
- }
- interned
- }
-
pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
if let Some(layout) = self.layout_interner.borrow().get(&layout) {
return layout;
data_layout: data_layout,
layout_cache: RefCell::new(FxHashMap()),
layout_interner: RefCell::new(FxHashSet()),
- code_extent_interner: RefCell::new(FxHashSet()),
layout_depth: Cell::new(0),
derive_macros: RefCell::new(NodeMap()),
stability_interner: RefCell::new(FxHashSet()),
}
}
-impl<'a, 'tcx> Lift<'tcx> for ty::FreeRegion<'a> {
- type Lifted = ty::FreeRegion<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- let scope = self.scope.map(|code_extent| tcx.intern_code_extent(*code_extent));
- let bound_region = self.bound_region;
- Some(ty::FreeRegion { scope, bound_region })
- }
-}
-
impl<'a, 'tcx> Lift<'tcx> for Region<'a> {
type Lifted = Region<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Region<'tcx>> {
}
}
-impl<'tcx> Borrow<RegionKind<'tcx>> for Interned<'tcx, RegionKind<'tcx>> {
- fn borrow<'a>(&'a self) -> &'a RegionKind<'tcx> {
+impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
+ fn borrow<'a>(&'a self) -> &'a RegionKind {
&self.0
}
}
&ty::ReVar(_) | &ty::ReSkolemized(..) => true,
_ => false
}
- }) -> RegionKind<'tcx>
+ }) -> RegionKind
);
macro_rules! slice_interners {
//! These methods return true to indicate that the visitor has found what it is looking for
//! and does not need to visit anything else.
-use middle::region;
use ty::subst::Substs;
use ty::adjustment;
use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
(result, replacer.map)
}
-
- /// Replace any late-bound regions bound in `value` with free variants attached to scope-id
- /// `scope_id`.
- pub fn liberate_late_bound_regions<T>(self,
- all_outlive_scope: Option<region::CodeExtent<'tcx>>,
- value: &Binder<T>)
- -> T
- where T : TypeFoldable<'tcx>
- {
- self.replace_late_bound_regions(value, |br| {
- self.mk_region(ty::ReFree(ty::FreeRegion {
- scope: all_outlive_scope,
- bound_region: br
- }))
- }).0
- }
-
/// Flattens two binding levels into one. So `for<'a> for<'b> Foo`
/// becomes `for<'a,'b> Foo`.
pub fn flatten_late_bound_regions<T>(self, bound2_value: &Binder<Binder<T>>)
// regions. See comment on `shift_regions_through_binders` method in
// `subst.rs` for more details.
-pub fn shift_region<'tcx>(region: ty::RegionKind<'tcx>, amount: u32) -> ty::RegionKind<'tcx> {
+pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
match region {
ty::ReLateBound(debruijn, br) => {
ty::ReLateBound(debruijn.shifted(amount), br)
let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
StructKind::AlwaysSizedUnivariant
} else {
- let param_env = tcx.construct_parameter_environment(DUMMY_SP,
- def.did, None);
+ let param_env = tcx.parameter_environment(def.did);
let fields = &def.variants[0].fields;
let last_field = &fields[fields.len()-1];
- let always_sized = last_field.ty(tcx, param_env.free_substs)
+ let always_sized = tcx.type_of(last_field.did)
.is_sized(tcx, ¶m_env, DUMMY_SP);
if !always_sized { StructKind::MaybeUnsizedUnivariant }
else { StructKind::AlwaysSizedUnivariant }
/// Per-function `RegionMaps`. The `DefId` should be the owner-def-id for the fn body;
/// in the case of closures or "inline" expressions, this will be redirected to the enclosing
/// fn item.
- [] region_maps: RegionMaps(DefId) -> Rc<RegionMaps<'tcx>>,
+ [] region_maps: RegionMaps(DefId) -> Rc<RegionMaps>,
[] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx>,
use middle::const_val::ConstVal;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::privacy::AccessLevels;
-use middle::region::CodeExtent;
use middle::resolve_lifetime::ObjectLifetimeDefault;
+use middle::region::CodeExtent;
use mir::Mir;
use traits;
use ty;
impl RegionParameterDef {
pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
ty::EarlyBoundRegion {
+ def_id: self.def_id,
index: self.index,
name: self.name,
}
}
+ pub fn to_bound_region(&self) -> ty::BoundRegion {
+ self.to_early_bound_region_data().to_bound_region()
+ }
+}
+
+impl ty::EarlyBoundRegion {
pub fn to_bound_region(&self) -> ty::BoundRegion {
ty::BoundRegion::BrNamed(self.def_id, self.name)
}
instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs)))
}
+ pub fn instantiate_identity(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+ -> InstantiatedPredicates<'tcx> {
+ let mut instantiated = InstantiatedPredicates::empty();
+ self.instantiate_identity_into(tcx, &mut instantiated);
+ instantiated
+ }
+
+ fn instantiate_identity_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ instantiated: &mut InstantiatedPredicates<'tcx>) {
+ if let Some(def_id) = self.parent {
+ tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated);
+ }
+ instantiated.predicates.extend(&self.predicates)
+ }
+
pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
poly_trait_ref: &ty::PolyTraitRef<'tcx>)
-> InstantiatedPredicates<'tcx>
/// more distinctions clearer.
#[derive(Clone)]
pub struct ParameterEnvironment<'tcx> {
- /// See `construct_free_substs` for details.
- pub free_substs: &'tcx Substs<'tcx>,
-
- /// Each type parameter has an implicit region bound that
- /// indicates it must outlive at least the function body (the user
- /// may specify stronger requirements). This field indicates the
- /// region of the callee. If it is `None`, then the parameter
- /// environment is for an item or something where the "callee" is
- /// not clear.
- pub implicit_region_bound: Option<ty::Region<'tcx>>,
-
/// Obligations that the caller must satisfy. This is basically
/// the set of bounds on the in-scope type parameters, translated
/// into Obligations, and elaborated and normalized.
pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
- /// Scope that is attached to free regions for this scope. This is
- /// usually the id of the fn body, but for more abstract scopes
- /// like structs we use None or the item extent.
- ///
- /// FIXME(#3696). It would be nice to refactor so that free
- /// regions don't have this implicit scope and instead introduce
- /// relationships in the environment.
- pub free_id_outlive: Option<CodeExtent<'tcx>>,
-
/// A cache for `moves_by_default`.
pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
-> ParameterEnvironment<'tcx>
{
ParameterEnvironment {
- free_substs: self.free_substs,
- implicit_region_bound: self.implicit_region_bound,
caller_bounds: caller_bounds,
- free_id_outlive: self.free_id_outlive,
is_copy_cache: RefCell::new(FxHashMap()),
is_sized_cache: RefCell::new(FxHashMap()),
is_freeze_cache: RefCell::new(FxHashMap()),
}
}
-
- /// Construct a parameter environment given an item, impl item, or trait item
- pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
- -> ParameterEnvironment<'tcx> {
- match tcx.hir.find(id) {
- Some(hir_map::NodeImplItem(ref impl_item)) => {
- match impl_item.node {
- hir::ImplItemKind::Type(_) => {
- // associated types don't have their own entry (for some reason),
- // so for now just grab environment for the impl
- let impl_id = tcx.hir.get_parent(id);
- let impl_def_id = tcx.hir.local_def_id(impl_id);
- tcx.construct_parameter_environment(impl_item.span,
- impl_def_id,
- Some(tcx.item_extent(id)))
- }
- hir::ImplItemKind::Const(_, body) |
- hir::ImplItemKind::Method(_, body) => {
- tcx.construct_parameter_environment(
- impl_item.span,
- tcx.hir.local_def_id(id),
- Some(tcx.call_site_extent(id, body.node_id)))
- }
- }
- }
- Some(hir_map::NodeTraitItem(trait_item)) => {
- match trait_item.node {
- hir::TraitItemKind::Type(..) |
- hir::TraitItemKind::Const(_, None) |
- hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_))=> {
- tcx.construct_parameter_environment(trait_item.span,
- tcx.hir.local_def_id(id),
- Some(tcx.item_extent(id)))
- }
- hir::TraitItemKind::Const(_, Some(body)) |
- hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body)) => {
- tcx.construct_parameter_environment(
- trait_item.span,
- tcx.hir.local_def_id(id),
- Some(tcx.call_site_extent(id, body.node_id)))
- }
- }
- }
- Some(hir_map::NodeItem(item)) => {
- match item.node {
- hir::ItemConst(_, body) |
- hir::ItemStatic(.., body) |
- hir::ItemFn(.., body) => {
- tcx.construct_parameter_environment(
- item.span,
- tcx.hir.local_def_id(id),
- Some(tcx.call_site_extent(id, body.node_id)))
- }
- hir::ItemEnum(..) |
- hir::ItemStruct(..) |
- hir::ItemUnion(..) |
- hir::ItemTy(..) |
- hir::ItemImpl(..) |
- hir::ItemTrait(..) => {
- let def_id = tcx.hir.local_def_id(id);
- tcx.construct_parameter_environment(item.span,
- def_id,
- Some(tcx.item_extent(id)))
- }
- _ => {
- span_bug!(item.span,
- "ParameterEnvironment::for_item():
- can't create a parameter \
- environment for this kind of item")
- }
- }
- }
- Some(hir_map::NodeExpr(expr)) => {
- // This is a convenience to allow closures to work.
- if let hir::ExprClosure(.., body, _) = expr.node {
- let def_id = tcx.hir.local_def_id(id);
- let base_def_id = tcx.closure_base_def_id(def_id);
- tcx.construct_parameter_environment(
- expr.span,
- base_def_id,
- Some(tcx.call_site_extent(id, body.node_id)))
- } else {
- tcx.empty_parameter_environment()
- }
- }
- Some(hir_map::NodeForeignItem(item)) => {
- let def_id = tcx.hir.local_def_id(id);
- tcx.construct_parameter_environment(item.span,
- def_id,
- None)
- }
- Some(hir_map::NodeStructCtor(..)) |
- Some(hir_map::NodeVariant(..)) => {
- let def_id = tcx.hir.local_def_id(id);
- tcx.construct_parameter_environment(tcx.hir.span(id),
- def_id,
- None)
- }
- it => {
- bug!("ParameterEnvironment::from_item(): \
- `{}` = {:?} is unsupported",
- tcx.hir.node_to_string(id), it)
- }
- }
- }
}
#[derive(Copy, Clone, Debug)]
/// are no free type/lifetime parameters in scope.
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
ty::ParameterEnvironment {
- free_substs: self.intern_substs(&[]),
caller_bounds: Slice::empty(),
- implicit_region_bound: None,
- free_id_outlive: None,
is_copy_cache: RefCell::new(FxHashMap()),
is_sized_cache: RefCell::new(FxHashMap()),
is_freeze_cache: RefCell::new(FxHashMap()),
}
}
- /// Constructs and returns a substitution that can be applied to move from
- /// the "outer" view of a type or method to the "inner" view.
- /// In general, this means converting from bound parameters to
- /// free parameters. Since we currently represent bound/free type
- /// parameters in the same way, this only has an effect on regions.
- pub fn construct_free_substs(self,
- def_id: DefId,
- free_id_outlive: Option<CodeExtent<'gcx>>)
- -> &'gcx Substs<'gcx> {
-
- let substs = Substs::for_item(self.global_tcx(), def_id, |def, _| {
- // map bound 'a => free 'a
- self.global_tcx().mk_region(ReFree(FreeRegion {
- scope: free_id_outlive,
- bound_region: def.to_bound_region()
- }))
- }, |def, _| {
- // map T => T
- self.global_tcx().mk_param_from_def(def)
- });
-
- debug!("construct_parameter_environment: {:?}", substs);
- substs
- }
-
/// See `ParameterEnvironment` struct def'n for details.
- /// If you were using `free_id: NodeId`, you might try `self.region_maps().item_extent(free_id)`
- /// for the `free_id_outlive` parameter. (But note that this is not always quite right.)
- pub fn construct_parameter_environment(self,
- span: Span,
- def_id: DefId,
- free_id_outlive: Option<CodeExtent<'gcx>>)
- -> ParameterEnvironment<'gcx>
- {
- //
- // Construct the free substs.
- //
-
- let free_substs = self.construct_free_substs(def_id, free_id_outlive);
-
+ pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> {
//
// Compute the bounds on Self and the type parameters.
//
let tcx = self.global_tcx();
- let generic_predicates = tcx.predicates_of(def_id);
- let bounds = generic_predicates.instantiate(tcx, free_substs);
- let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds));
+ let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
let predicates = bounds.predicates;
// Finally, we have to normalize the bounds in the environment, in
//
let unnormalized_env = ty::ParameterEnvironment {
- free_substs: free_substs,
- implicit_region_bound: free_id_outlive.map(|f| tcx.mk_region(ty::ReScope(f))),
caller_bounds: tcx.intern_predicates(&predicates),
- free_id_outlive: free_id_outlive,
is_copy_cache: RefCell::new(FxHashMap()),
is_sized_cache: RefCell::new(FxHashMap()),
is_freeze_cache: RefCell::new(FxHashMap()),
};
- let body_id = free_id_outlive.map(|f| f.node_id())
- .unwrap_or(DUMMY_NODE_ID);
- let cause = traits::ObligationCause::misc(span, body_id);
+ let body_id = self.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
+ self.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
+ });
+ let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
}
pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> {
- self.mk_region(ty::ReScope(self.node_extent(id)))
+ self.mk_region(ty::ReScope(CodeExtent::Misc(id)))
}
/// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region<'tcx>>) {
for r in regions {
- if !r.is_bound() {
+ if !r.is_late_bound() {
out.push(Component::Region(r));
}
}
RustcEncodable, RustcDecodable, Copy)]
/// A "free" region `fr` can be interpreted as "some region
/// at least as big as the scope `fr.scope`".
-///
-/// If `fr.scope` is None, then this is in some context (e.g., an
-/// impl) where lifetimes are more abstract and the notion of the
-/// caller/callee stack frames are not applicable.
-pub struct FreeRegion<'tcx> {
- pub scope: Option<region::CodeExtent<'tcx>>,
+pub struct FreeRegion {
+ pub scope: DefId,
pub bound_region: BoundRegion,
}
/// Fresh bound identifiers created during GLB computations.
BrFresh(u32),
- // Anonymous region for the implicit env pointer parameter
- // to a closure
+ /// Anonymous region for the implicit env pointer parameter
+ /// to a closure
BrEnv,
}
pub region_name: ast::Name,
}
-// NB: If you change this, you'll probably want to change the corresponding
-// AST structure in libsyntax/ast.rs as well.
+/// NB: If you change this, you'll probably want to change the corresponding
+/// AST structure in libsyntax/ast.rs as well.
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum TypeVariants<'tcx> {
/// The primitive boolean type. Written as `bool`.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum ExistentialPredicate<'tcx> {
- // e.g. Iterator
+ /// e.g. Iterator
Trait(ExistentialTraitRef<'tcx>),
- // e.g. Iterator::Item = T
+ /// e.g. Iterator::Item = T
Projection(ExistentialProjection<'tcx>),
- // e.g. Send
+ /// e.g. Send
AutoTrait(DefId),
}
/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
pub struct DebruijnIndex {
- // We maintain the invariant that this is never 0. So 1 indicates
- // the innermost binder. To ensure this, create with `DebruijnIndex::new`.
+ /// We maintain the invariant that this is never 0. So 1 indicates
+ /// the innermost binder. To ensure this, create with `DebruijnIndex::new`.
pub depth: u32,
}
-pub type Region<'tcx> = &'tcx RegionKind<'tcx>;
+pub type Region<'tcx> = &'tcx RegionKind;
/// Representation of regions.
///
/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)]
-pub enum RegionKind<'tcx> {
+pub enum RegionKind {
// Region bound in a type or fn declaration which will be
// substituted 'early' -- that is, at the same time when type
// parameters are substituted.
/// When checking a function body, the types of all arguments and so forth
/// that refer to bound region parameters are modified to refer to free
/// region parameters.
- ReFree(FreeRegion<'tcx>),
+ ReFree(FreeRegion),
/// A concrete region naming some statically determined extent
/// (e.g. an expression or sequence of statements) within the
/// current function.
- ReScope(region::CodeExtent<'tcx>),
+ ReScope(region::CodeExtent),
/// Static data that has an "infinite" lifetime. Top in the region lattice.
ReStatic,
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub struct EarlyBoundRegion {
+ pub def_id: DefId,
pub index: u32,
pub name: Name,
}
}
}
-// Region utilities
-impl<'tcx> RegionKind<'tcx> {
- pub fn is_bound(&self) -> bool {
+/// Region utilities
+impl RegionKind {
+ pub fn is_late_bound(&self) -> bool {
match *self {
- ty::ReEarlyBound(..) => true,
ty::ReLateBound(..) => true,
_ => false,
}
}
/// Returns the depth of `self` from the (1-based) binding level `depth`
- pub fn from_depth(&self, depth: u32) -> RegionKind<'tcx> {
+ pub fn from_depth(&self, depth: u32) -> RegionKind {
match *self {
ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex {
depth: debruijn.depth - (depth - 1)
}
}
-// Type utilities
+/// Type utilities
impl<'a, 'gcx, 'tcx> TyS<'tcx> {
pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
match self.sty {
}
}
- // Test whether this is a `()` which was produced by defaulting a
- // diverging type variable with feature(never_type) disabled.
+ /// Test whether this is a `()` which was produced by defaulting a
+ /// diverging type variable with feature(never_type) disabled.
pub fn is_defaulted_unit(&self) -> bool {
match self.sty {
TyTuple(_, true) => true,
}
}
+ /// panics if called on any type other than `Box<T>`
pub fn boxed_ty(&self) -> Ty<'tcx> {
match self.sty {
TyAdt(def, substs) if def.is_box() => substs.type_at(0),
}
}
- /*
- A scalar type is one that denotes an atomic datum, with no sub-components.
- (A TyRawPtr is scalar because it represents a non-managed pointer, so its
- contents are abstract to rustc.)
- */
+ /// A scalar type is one that denotes an atomic datum, with no sub-components.
+ /// (A TyRawPtr is scalar because it represents a non-managed pointer, so its
+ /// contents are abstract to rustc.)
pub fn is_scalar(&self) -> bool {
match self.sty {
TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
}
}
- // Returns the type and mutability of *ty.
- //
- // The parameter `explicit` indicates if this is an *explicit* dereference.
- // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
+ /// Returns the type and mutability of *ty.
+ ///
+ /// The parameter `explicit` indicates if this is an *explicit* dereference.
+ /// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference)
-> Option<TypeAndMut<'tcx>>
{
}
}
- // Returns the type of ty[i]
+ /// Returns the type of ty[i]
pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
match self.sty {
TyArray(ty, _) | TySlice(ty) => Some(ty),
}
}
- // Type accessors for substructures of types
+ /// Type accessors for substructures of types
pub fn fn_args(&self) -> ty::Binder<&'tcx [Ty<'tcx>]> {
self.fn_sig().inputs()
}
self.hash(db.depth);
self.hash(i);
}
- ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
- self.hash(index);
- self.hash(name.as_str());
+ ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) => {
+ self.def_id(def_id);
}
ty::ReLateBound(..) |
ty::ReFree(..) |
}
}
-impl<'tcx> fmt::Debug for ty::RegionKind<'tcx> {
+impl fmt::Debug for ty::RegionKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ty::ReEarlyBound(ref data) => {
impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "ParameterEnvironment(\
- free_substs={:?}, \
- implicit_region_bound={:?}, \
- caller_bounds={:?})",
- self.free_substs,
- self.implicit_region_bound,
- self.caller_bounds)
+ write!(f, "ParameterEnvironment({:?})", self.caller_bounds)
}
}
-impl<'tcx> fmt::Display for ty::RegionKind<'tcx> {
+impl<'tcx> fmt::Display for ty::RegionKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if verbose() {
return write!(f, "{:?}", *self);
}
}
-impl<'tcx> fmt::Debug for ty::FreeRegion<'tcx> {
+impl fmt::Debug for ty::FreeRegion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ReFree({:?}, {:?})",
self.scope, self.bound_region)
//! build speedups.
#![crate_name = "rustc_back"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(const_fn)]
#![feature(libc)]
#![feature(rand)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![cfg_attr(test, feature(rand))]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate syntax;
extern crate libc;
extern crate serialize;
#![crate_name = "rustc_bitflags"]
#![feature(associated_consts)]
-#![feature(staged_api)]
#![crate_type = "rlib"]
#![no_std]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![deny(warnings)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
//! A typesafe bitmask flag generator.
})
}
- pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent<'tcx>, mut op: F) -> bool where
+ pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent, mut op: F) -> bool where
F: FnMut(&Loan<'tcx>) -> bool,
{
//! Like `each_issued_loan()`, but only considers loans that are
}
fn each_in_scope_loan_affecting_path<F>(&self,
- scope: region::CodeExtent<'tcx>,
+ scope: region::CodeExtent,
loan_path: &LoanPath<'tcx>,
mut op: F)
-> bool where
let mut ret = UseOk;
self.each_in_scope_loan_affecting_path(
- self.tcx().node_extent(expr_id), use_path, |loan| {
+ region::CodeExtent::Misc(expr_id), use_path, |loan| {
if !compatible_borrow_kinds(loan.kind, borrow_kind) {
ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
false
// Check that we don't invalidate any outstanding loans
if let Some(loan_path) = opt_loan_path(&assignee_cmt) {
- let scope = self.tcx().node_extent(assignment_id);
+ let scope = region::CodeExtent::Misc(assignment_id);
self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| {
self.report_illegal_mutation(assignment_span, &loan_path, loan);
false
type R = Result<(),()>;
pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
- item_scope: region::CodeExtent<'tcx>,
+ item_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
cmt: mc::cmt<'tcx>,
bccx: &'a BorrowckCtxt<'a, 'tcx>,
// the scope of the function body for the enclosing item
- item_scope: region::CodeExtent<'tcx>,
+ item_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
bccx: bccx,
infcx: &infcx,
all_loans: Vec::new(),
- item_ub: bccx.tcx.node_extent(body.node_id),
+ item_ub: region::CodeExtent::Misc(body.node_id),
move_data: MoveData::new(),
move_error_collector: move_error::MoveErrorCollector::new(),
};
all_loans: Vec<Loan<'tcx>>,
/// `item_ub` is used as an upper-bound on the lifetime whenever we
/// ask for the scope of an expression categorized as an upvar.
- item_ub: region::CodeExtent<'tcx>,
+ item_ub: region::CodeExtent,
}
impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
let loan_scope = match *loan_region {
ty::ReScope(scope) => scope,
- ty::ReFree(ref fr) => fr.scope.unwrap_or(self.item_ub),
+ ty::ReEarlyBound(ref br) => {
+ self.bccx.region_maps.early_free_extent(self.tcx(), br)
+ }
+
+ ty::ReFree(ref fr) => {
+ self.bccx.region_maps.free_extent(self.tcx(), fr)
+ }
ty::ReStatic => self.item_ub,
ty::ReEmpty |
ty::ReLateBound(..) |
- ty::ReEarlyBound(..) |
ty::ReVar(..) |
ty::ReSkolemized(..) |
ty::ReErased => {
};
debug!("loan_scope = {:?}", loan_scope);
- let borrow_scope = self.tcx().node_extent(borrow_id);
+ let borrow_scope = region::CodeExtent::Misc(borrow_id);
let gen_scope = self.compute_gen_scope(borrow_scope, loan_scope);
debug!("gen_scope = {:?}", gen_scope);
}
pub fn compute_gen_scope(&self,
- borrow_scope: region::CodeExtent<'tcx>,
- loan_scope: region::CodeExtent<'tcx>)
- -> region::CodeExtent<'tcx> {
+ borrow_scope: region::CodeExtent,
+ loan_scope: region::CodeExtent)
+ -> region::CodeExtent {
//! Determine when to introduce the loan. Typically the loan
//! is introduced at the point of the borrow, but in some cases,
//! notably method arguments, the loan may be introduced only
}
}
- pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent<'tcx>, lp: &LoanPath<'tcx>)
- -> region::CodeExtent<'tcx> {
+ pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent, lp: &LoanPath<'tcx>)
+ -> region::CodeExtent {
//! Determine when the loan restrictions go out of scope.
//! This is either when the lifetime expires or when the
//! local variable which roots the loan-path goes out of scope,
_ => return
}
let id = src.item_id();
- let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+ let param_env = tcx.parameter_environment(tcx.hir.local_def_id(id));
let move_data = MoveData::gather_moves(mir, tcx, ¶m_env);
let elaborate_patch = {
let mir = &*mir;
}
fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
- Rvalue::Use(Operand::Constant(Constant {
+ Rvalue::Use(Operand::Constant(Box::new(Constant {
span: span,
ty: self.tcx.types.bool,
literal: Literal::Value { value: ConstVal::Bool(val) }
- }))
+ })))
}
fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) {
// steals it, but it forces the `borrowck` query.
let mir = &tcx.mir_validated(def_id).borrow();
- let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+ let param_env = tcx.parameter_environment(def_id);
let move_data = MoveData::gather_moves(mir, tcx, ¶m_env);
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
// Some in `borrowck_fn` and cleared later
tables: &'a ty::TypeckTables<'tcx>,
- region_maps: Rc<RegionMaps<'tcx>>,
+ region_maps: Rc<RegionMaps>,
owner_def_id: DefId,
}
/// cases, notably method arguments, the loan may be introduced
/// only later, once it comes into scope. See also
/// `GatherLoanCtxt::compute_gen_scope`.
- gen_scope: region::CodeExtent<'tcx>,
+ gen_scope: region::CodeExtent,
/// kill_scope indicates when the loan goes out of scope. This is
/// either when the lifetime expires or when the local variable
/// which roots the loan-path goes out of scope, whichever happens
/// faster. See also `GatherLoanCtxt::compute_kill_scope`.
- kill_scope: region::CodeExtent<'tcx>,
+ kill_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
}
}
impl<'a, 'tcx> LoanPath<'tcx> {
- pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent<'tcx> {
+ pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent {
match self.kind {
LpVar(local_id) => bccx.region_maps.var_scope(local_id),
LpUpvar(upvar_id) => {
let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx);
- bccx.tcx.node_extent(block_id)
+ region::CodeExtent::Misc(block_id)
}
LpDowncast(ref base, _) |
LpExtend(ref base, ..) => base.kill_scope(bccx),
match (&err.code, &err.cause) {
(&err_out_of_scope(&ty::ReScope(_), &ty::ReStatic, _),
&BorrowViolation(euv::ClosureCapture(span))) |
+ (&err_out_of_scope(&ty::ReScope(_), &ty::ReEarlyBound(..), _),
+ &BorrowViolation(euv::ClosureCapture(span))) |
(&err_out_of_scope(&ty::ReScope(_), &ty::ReFree(..), _),
&BorrowViolation(euv::ClosureCapture(span))) => {
return self.report_out_of_scope_escaping_closure_capture(&err, span);
// except according to those terms.
#![crate_name = "rustc_borrowck"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(associated_consts)]
#![feature(nonzero)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
extern crate syntax_pos;
b: hir::BodyId, s: Span, id: ast::NodeId) {
intravisit::walk_fn(self, fk, fd, b, s, id);
- let region_context = self.tcx.hir.local_def_id(id);
- let region_maps = self.tcx.region_maps(region_context);
+ let def_id = self.tcx.hir.local_def_id(id);
MatchVisitor {
tcx: self.tcx,
tables: self.tcx.body_tables(b),
- region_maps: ®ion_maps,
- param_env: &ty::ParameterEnvironment::for_item(self.tcx, id)
+ region_maps: &self.tcx.region_maps(def_id),
+ param_env: &self.tcx.parameter_environment(def_id)
}.visit_body(self.tcx.hir.body(b));
}
}
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
param_env: &'a ty::ParameterEnvironment<'tcx>,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
}
impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_const_eval"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(box_patterns)]
#![feature(const_fn)]
#![feature(i128_type)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate arena;
#[macro_use] extern crate syntax;
#[macro_use] extern crate log;
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_const_math"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(const_fn)]
#![feature(i128)]
#![feature(i128_type)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate syntax;
extern crate serialize as rustc_serialize; // used by deriving
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_data_structures"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(shared)]
#![feature(collections_range)]
#![feature(nonzero)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(fn_traits)]
#![feature(untagged_unions)]
#![feature(manually_drop)]
#![feature(struct_field_attributes)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
#![cfg_attr(unix, feature(libc))]
#![cfg_attr(test, feature(test))]
rustc_errors = { path = "../librustc_errors" }
rustc_incremental = { path = "../librustc_incremental" }
rustc_lint = { path = "../librustc_lint" }
-rustc_llvm = { path = "../librustc_llvm" }
rustc_metadata = { path = "../librustc_metadata" }
rustc_mir = { path = "../librustc_mir" }
rustc_passes = { path = "../librustc_passes" }
"static item recursion checking",
|| static_recursion::check_crate(sess, &hir_map))?;
- let index = stability::Index::new(&hir_map);
+ let index = stability::Index::new(&sess);
let mut local_providers = ty::maps::Providers::default();
borrowck::provide(&mut local_providers);
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_driver"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(set_stdio)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
extern crate arena;
extern crate getopts;
extern crate rustc_trans;
extern crate rustc_typeck;
extern crate serialize;
-extern crate rustc_llvm as llvm;
#[macro_use]
extern crate log;
extern crate syntax;
use rustc_save_analysis as save;
use rustc_save_analysis::DumpHandler;
use rustc_trans::back::link;
-use rustc_trans::back::write::{create_target_machine, RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
+use rustc_trans::back::write::{RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
use rustc::dep_graph::DepGraph;
use rustc::session::{self, config, Session, build_session, CompileResult};
use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
if sopts.debugging_opts.debug_llvm {
- unsafe { llvm::LLVMRustSetDebug(1); }
+ rustc_trans::enable_llvm_debug();
}
let descriptions = diagnostics_registry();
};
let dep_graph = DepGraph::new(sopts.build_dep_graph());
- let cstore = Rc::new(CStore::new(&dep_graph));
+ let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
let loader = file_loader.unwrap_or(box RealFileLoader);
let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
let mut sess = session::build_session_with_codemap(
sopts, &dep_graph, input_file_path, descriptions, cstore.clone(), codemap, emitter_dest,
);
+ rustc_trans::init(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, cfg);
return None;
}
let dep_graph = DepGraph::new(sopts.build_dep_graph());
- let cstore = Rc::new(CStore::new(&dep_graph));
+ let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
let mut sess = build_session(sopts.clone(),
&dep_graph,
None,
descriptions.clone(),
cstore.clone());
+ rustc_trans::init(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, cfg.clone());
target_features::add_configuration(&mut cfg, &sess);
&Input::File(ref ifile) => {
let path = &(*ifile);
let mut v = Vec::new();
- locator::list_file_metadata(&sess.target.target, path, &mut v).unwrap();
+ locator::list_file_metadata(&sess.target.target,
+ path,
+ sess.cstore.metadata_loader(),
+ &mut v)
+ .unwrap();
println!("{}", String::from_utf8(v).unwrap());
}
&Input::Str { .. } => {
println!("{}", cfg);
}
}
- PrintRequest::TargetCPUs => {
- let tm = create_target_machine(sess);
- unsafe { llvm::LLVMRustPrintTargetCPUs(tm); }
- }
- PrintRequest::TargetFeatures => {
- let tm = create_target_machine(sess);
- unsafe { llvm::LLVMRustPrintTargetFeatures(tm); }
- }
PrintRequest::RelocationModels => {
println!("Available relocation models:");
for &(name, _) in RELOC_MODEL_ARGS.iter() {
}
println!("");
}
+ PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
+ rustc_trans::print(*req, sess);
+ }
}
}
return Compilation::Stop;
println!("commit-date: {}", unw(commit_date_str()));
println!("host: {}", config::host_triple());
println!("release: {}", unw(release_str()));
- unsafe {
- println!("LLVM version: {}.{}",
- llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
- }
+ rustc_trans::print_version();
}
}
}
if cg_flags.contains(&"passes=list".to_string()) {
- unsafe {
- ::llvm::LLVMRustPrintPasses();
- }
+ rustc_trans::print_passes();
return None;
}
// except according to those terms.
use syntax::ast;
-use llvm::LLVMRustHasFeature;
use rustc::session::Session;
-use rustc_trans::back::write::create_target_machine;
use syntax::symbol::Symbol;
-use libc::c_char;
-
-// WARNING: the features must be known to LLVM or the feature
-// detection code will walk past the end of the feature array,
-// leading to crashes.
-
-const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"];
-
-const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
- "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
- "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
- "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"];
-
-const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];
+use rustc_trans;
/// Add `target_feature = "..."` cfgs for a variety of platform
/// specific features (SSE, NEON etc.).
/// This is performed by checking whether a whitelisted set of
/// features is available on the target machine, by querying LLVM.
pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
- let target_machine = create_target_machine(sess);
-
- let whitelist = match &*sess.target.target.arch {
- "arm" => ARM_WHITELIST,
- "x86" | "x86_64" => X86_WHITELIST,
- "hexagon" => HEXAGON_WHITELIST,
- _ => &[],
- };
-
let tf = Symbol::intern("target_feature");
- for feat in whitelist {
- assert_eq!(feat.chars().last(), Some('\0'));
- if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
- cfg.insert((tf, Some(Symbol::intern(&feat[..feat.len() - 1]))));
- }
+
+ for feat in rustc_trans::target_features(sess) {
+ cfg.insert((tf, Some(feat)));
}
let requested_features = sess.opts.cg.target_feature.split(',');
use rustc::dep_graph::DepGraph;
use rustc_lint;
use rustc_resolve::MakeGlobMap;
+use rustc_trans;
use rustc::middle::lang_items;
use rustc::middle::free_region::FreeRegionMap;
use rustc::middle::region::{CodeExtent, RegionMaps};
-use rustc::middle::region::CodeExtentData;
use rustc::middle::resolve_lifetime;
use rustc::middle::stability;
use rustc::ty::subst::{Kind, Subst};
struct Env<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
infcx: &'a infer::InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a mut RegionMaps<'tcx>,
+ region_maps: &'a mut RegionMaps,
}
struct RH<'a> {
let dep_graph = DepGraph::new(false);
let _ignore = dep_graph.in_ignore();
- let cstore = Rc::new(CStore::new(&dep_graph));
+ let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
let sess = session::build_session_(options,
&dep_graph,
None,
diagnostic_handler,
Rc::new(CodeMap::new(FilePathMapping::empty())),
cstore.clone());
+ rustc_trans::init(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let input = config::Input::Str {
name: driver::anon_src(),
// run just enough stuff to build a tcx:
let lang_items = lang_items::collect_language_items(&sess, &hir_map);
let named_region_map = resolve_lifetime::krate(&sess, &hir_map);
- let index = stability::Index::new(&hir_map);
+ let index = stability::Index::new(&sess);
TyCtxt::create_and_enter(&sess,
ty::maps::Providers::default(),
ty::maps::Providers::default(),
self.infcx.tcx
}
- pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent<'tcx>) {
- let me = self.tcx().intern_code_extent(CodeExtentData::Misc(rh.id));
+ pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent) {
+ let me = CodeExtent::Misc(rh.id);
self.region_maps.record_code_extent(me, Some(parent));
for child_rh in rh.sub {
self.create_region_hierarchy(child_rh, me);
// children of 1, etc
let node = ast::NodeId::from_u32;
- let dscope = self.tcx().intern_code_extent(CodeExtentData::DestructionScope(node(1)));
+ let dscope = CodeExtent::DestructionScope(node(1));
self.region_maps.record_code_extent(dscope, None);
self.create_region_hierarchy(&RH {
id: node(1),
pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
let name = Symbol::intern(name);
self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
- index: index,
- name: name,
+ def_id: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
+ index,
+ name,
}))
}
}
pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> {
- let r = ty::ReScope(self.tcx().node_extent(ast::NodeId::from_u32(id)));
+ let r = ty::ReScope(CodeExtent::Misc(ast::NodeId::from_u32(id)));
self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize)
}
- pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region<'tcx> {
+ pub fn re_free(&self, id: u32) -> ty::Region<'tcx> {
self.infcx.tcx.mk_region(ty::ReFree(ty::FreeRegion {
- scope: Some(self.tcx().node_extent(nid)),
+ scope: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
bound_region: ty::BrAnon(id),
}))
}
- pub fn t_rptr_free(&self, nid: u32, id: u32) -> Ty<'tcx> {
- let r = self.re_free(ast::NodeId::from_u32(nid), id);
+ pub fn t_rptr_free(&self, id: u32) -> Ty<'tcx> {
+ let r = self.re_free(id);
self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize)
}
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
let t_rptr_bound1 = env.t_rptr_late_bound(1);
env.check_not_sub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_bound1 = env.t_rptr_late_bound(1);
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
env.check_sub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
})
env.create_simple_region_hierarchy();
let t_infer1 = env.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
let t_rptr_bound1 = env.t_rptr_late_bound(1);
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_bound1 = env.t_rptr_late_bound(1);
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
fn lub_free_free() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
- let t_rptr_free1 = env.t_rptr_free(1, 1);
- let t_rptr_free2 = env.t_rptr_free(1, 2);
+ let t_rptr_free1 = env.t_rptr_free(1);
+ let t_rptr_free2 = env.t_rptr_free(2);
let t_rptr_static = env.t_rptr_static();
env.check_lub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free2], env.tcx().types.isize),
fn glb_free_free_with_common_scope() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
- let t_rptr_free1 = env.t_rptr_free(1, 1);
- let t_rptr_free2 = env.t_rptr_free(1, 2);
+ let t_rptr_free1 = env.t_rptr_free(1);
+ let t_rptr_free2 = env.t_rptr_free(2);
let t_rptr_scope = env.t_rptr_scope(1);
env.check_glb(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free2], env.tcx().types.isize),
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_bound1 = env.t_rptr_late_bound(1);
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
assert!(!env.t_nil().has_escaping_regions());
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
assert!(!t_rptr_free1.has_escaping_regions());
let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1));
// except according to those terms.
use CodeSuggestion;
+use Substitution;
use Level;
use RenderSpan;
use std::fmt;
pub code: Option<String>,
pub span: MultiSpan,
pub children: Vec<SubDiagnostic>,
- pub suggestion: Option<CodeSuggestion>,
+ pub suggestions: Vec<CodeSuggestion>,
}
/// For example a note attached to an error.
code: code,
span: MultiSpan::new(),
children: vec![],
- suggestion: None,
+ suggestions: vec![],
}
}
///
/// See `diagnostic::CodeSuggestion` for more information.
pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
- assert!(self.suggestion.is_none());
- self.suggestion = Some(CodeSuggestion {
- msp: sp.into(),
- substitutes: vec![suggestion],
+ self.suggestions.push(CodeSuggestion {
+ substitution_parts: vec![Substitution {
+ span: sp,
+ substitutions: vec![suggestion],
+ }],
+ msg: msg.to_owned(),
+ });
+ self
+ }
+
+ pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self {
+ self.suggestions.push(CodeSuggestion {
+ substitution_parts: vec![Substitution {
+ span: sp,
+ substitutions: suggestions,
+ }],
msg: msg.to_owned(),
});
self
self.handler.emitter.borrow_mut().emit(&self);
self.cancel();
- self.handler.panic_if_treat_err_as_bug();
+
+ if self.level == Level::Error {
+ self.handler.panic_if_treat_err_as_bug();
+ }
// if self.is_fatal() {
// panic!(FatalError);
msg: &str,
suggestion: String)
-> &mut Self);
+ forward!(pub fn span_suggestions(&mut self,
+ sp: Span,
+ msg: &str,
+ suggestions: Vec<String>)
+ -> &mut Self);
forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
forward!(pub fn code(&mut self, s: String) -> &mut Self);
let mut primary_span = db.span.clone();
let mut children = db.children.clone();
- if let Some(sugg) = db.suggestion.clone() {
- assert_eq!(sugg.msp.primary_spans().len(), sugg.substitutes.len());
- // don't display multispans as labels
- if sugg.substitutes.len() == 1 &&
+ if let Some((sugg, rest)) = db.suggestions.split_first() {
+ if rest.is_empty() &&
+ // don't display multipart suggestions as labels
+ sugg.substitution_parts.len() == 1 &&
+ // don't display multi-suggestions as labels
+ sugg.substitutions() == 1 &&
// don't display long messages as labels
sugg.msg.split_whitespace().count() < 10 &&
// don't display multiline suggestions as labels
- sugg.substitutes[0].find('\n').is_none() {
- let msg = format!("help: {} `{}`", sugg.msg, sugg.substitutes[0]);
- primary_span.push_span_label(sugg.msp.primary_spans()[0], msg);
+ sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
+ let substitution = &sugg.substitution_parts[0].substitutions[0];
+ let msg = format!("help: {} `{}`", sugg.msg, substitution);
+ primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg);
} else {
- children.push(SubDiagnostic {
- level: Level::Help,
- message: Vec::new(),
- span: MultiSpan::new(),
- render_span: Some(Suggestion(sugg)),
- });
+ // if there are multiple suggestions, print them all in full
+ // to be consistent. We could try to figure out if we can
+ // make one (or the first one) inline, but that would give
+ // undue importance to a semi-random suggestion
+ for sugg in &db.suggestions {
+ children.push(SubDiagnostic {
+ level: Level::Help,
+ message: Vec::new(),
+ span: MultiSpan::new(),
+ render_span: Some(Suggestion(sugg.clone())),
+ });
+ }
}
}
/// maximum number of lines we will print for each error; arbitrary.
pub const MAX_HIGHLIGHT_LINES: usize = 6;
+/// maximum number of suggestions to be shown
+///
+/// Arbitrary, but taken from trait import suggestion limit
+pub const MAX_SUGGESTIONS: usize = 4;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ColorConfig {
multiline_depth: usize,
}
-
-/// Do not use this for messages that end in `\n` – use `println_maybe_styled` instead. See
-/// `EmitterWriter::print_maybe_styled` for details.
-macro_rules! print_maybe_styled {
- ($dst: expr, $style: expr, $($arg: tt)*) => {
- $dst.print_maybe_styled(format_args!($($arg)*), $style, false)
- }
-}
-
-macro_rules! println_maybe_styled {
- ($dst: expr, $style: expr, $($arg: tt)*) => {
- $dst.print_maybe_styled(format_args!($($arg)*), $style, true)
- }
-}
-
impl EmitterWriter {
pub fn stderr(color_config: ColorConfig, code_map: Option<Rc<CodeMapper>>) -> EmitterWriter {
if color_config.use_color() {
-> io::Result<()> {
use std::borrow::Borrow;
- let primary_span = suggestion.msp.primary_span().unwrap();
+ let primary_span = suggestion.substitution_spans().next().unwrap();
if let Some(ref cm) = self.cm {
let mut buffer = StyledBuffer::new();
- buffer.append(0, &level.to_string(), Style::Level(level.clone()));
- buffer.append(0, ": ", Style::HeaderMsg);
- self.msg_to_buffer(&mut buffer,
- &[(suggestion.msg.to_owned(), Style::NoStyle)],
- max_line_num_len,
- "suggestion",
- Some(Style::HeaderMsg));
-
let lines = cm.span_to_lines(primary_span).unwrap();
assert!(!lines.lines.is_empty());
- let complete = suggestion.splice_lines(cm.borrow());
+ buffer.append(0, &level.to_string(), Style::Level(level.clone()));
+ buffer.append(0, ": ", Style::HeaderMsg);
+ self.msg_to_buffer(&mut buffer,
+ &[(suggestion.msg.to_owned(), Style::NoStyle)],
+ max_line_num_len,
+ "suggestion",
+ Some(Style::HeaderMsg));
- // print the suggestion without any line numbers, but leave
- // space for them. This helps with lining up with previous
- // snippets from the actual error being reported.
- let mut lines = complete.lines();
+ let suggestions = suggestion.splice_lines(cm.borrow());
let mut row_num = 1;
- for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
- draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
- buffer.append(row_num, line, Style::NoStyle);
- row_num += 1;
- }
+ for complete in suggestions.iter().take(MAX_SUGGESTIONS) {
+
+ // print the suggestion without any line numbers, but leave
+ // space for them. This helps with lining up with previous
+ // snippets from the actual error being reported.
+ let mut lines = complete.lines();
+ for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
+ draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
+ buffer.append(row_num, line, Style::NoStyle);
+ row_num += 1;
+ }
- // if we elided some lines, add an ellipsis
- if let Some(_) = lines.next() {
- buffer.append(row_num, "...", Style::NoStyle);
+ // if we elided some lines, add an ellipsis
+ if let Some(_) = lines.next() {
+ buffer.append(row_num, "...", Style::NoStyle);
+ }
+ }
+ if suggestions.len() > MAX_SUGGESTIONS {
+ let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS);
+ buffer.append(row_num, &msg, Style::NoStyle);
}
emit_to_destination(&buffer.render(), level, &mut self.dst)?;
}
// except according to those terms.
#![crate_name = "rustc_errors"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(custom_attribute)]
#![allow(unused_attributes)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(range_contains)]
#![feature(libc)]
+#![feature(conservative_impl_trait)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
extern crate term;
extern crate libc;
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct CodeSuggestion {
- pub msp: MultiSpan,
- pub substitutes: Vec<String>,
+ /// Each substitute can have multiple variants due to multiple
+ /// applicable suggestions
+ ///
+ /// `foo.bar` might be replaced with `a.b` or `x.y` by replacing
+ /// `foo` and `bar` on their own:
+ ///
+ /// ```
+ /// vec![
+ /// (0..3, vec!["a", "x"]),
+ /// (4..7, vec!["b", "y"]),
+ /// ]
+ /// ```
+ ///
+ /// or by replacing the entire span:
+ ///
+ /// ```
+ /// vec![(0..7, vec!["a.b", "x.y"])]
+ /// ```
+ pub substitution_parts: Vec<Substitution>,
pub msg: String,
}
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+/// See the docs on `CodeSuggestion::substitutions`
+pub struct Substitution {
+ pub span: Span,
+ pub substitutions: Vec<String>,
+}
+
pub trait CodeMapper {
fn lookup_char_pos(&self, pos: BytePos) -> Loc;
fn span_to_lines(&self, sp: Span) -> FileLinesResult;
}
impl CodeSuggestion {
- /// Returns the assembled code suggestion.
- pub fn splice_lines(&self, cm: &CodeMapper) -> String {
+ /// Returns the number of substitutions
+ fn substitutions(&self) -> usize {
+ self.substitution_parts[0].substitutions.len()
+ }
+
+ /// Returns the number of substitutions
+ pub fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a {
+ self.substitution_parts.iter().map(|sub| sub.span)
+ }
+
+ /// Returns the assembled code suggestions.
+ pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<String> {
use syntax_pos::{CharPos, Loc, Pos};
fn push_trailing(buf: &mut String,
}
}
- let mut primary_spans = self.msp.primary_spans().to_owned();
-
- assert_eq!(primary_spans.len(), self.substitutes.len());
- if primary_spans.is_empty() {
- return format!("");
+ if self.substitution_parts.is_empty() {
+ return vec![String::new()];
}
+ let mut primary_spans: Vec<_> = self.substitution_parts
+ .iter()
+ .map(|sub| (sub.span, &sub.substitutions))
+ .collect();
+
// Assumption: all spans are in the same file, and all spans
// are disjoint. Sort in ascending order.
- primary_spans.sort_by_key(|sp| sp.lo);
+ primary_spans.sort_by_key(|sp| sp.0.lo);
// Find the bounding span.
- let lo = primary_spans.iter().map(|sp| sp.lo).min().unwrap();
- let hi = primary_spans.iter().map(|sp| sp.hi).min().unwrap();
+ let lo = primary_spans.iter().map(|sp| sp.0.lo).min().unwrap();
+ let hi = primary_spans.iter().map(|sp| sp.0.hi).min().unwrap();
let bounding_span = Span {
lo: lo,
hi: hi,
prev_hi.col = CharPos::from_usize(0);
let mut prev_line = fm.get_line(lines.lines[0].line_index);
- let mut buf = String::new();
+ let mut bufs = vec![String::new(); self.substitutions()];
- for (sp, substitute) in primary_spans.iter().zip(self.substitutes.iter()) {
+ for (sp, substitutes) in primary_spans {
let cur_lo = cm.lookup_char_pos(sp.lo);
- if prev_hi.line == cur_lo.line {
- push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo));
- } else {
- push_trailing(&mut buf, prev_line, &prev_hi, None);
- // push lines between the previous and current span (if any)
- for idx in prev_hi.line..(cur_lo.line - 1) {
- if let Some(line) = fm.get_line(idx) {
- buf.push_str(line);
- buf.push('\n');
+ for (buf, substitute) in bufs.iter_mut().zip(substitutes) {
+ if prev_hi.line == cur_lo.line {
+ push_trailing(buf, prev_line, &prev_hi, Some(&cur_lo));
+ } else {
+ push_trailing(buf, prev_line, &prev_hi, None);
+ // push lines between the previous and current span (if any)
+ for idx in prev_hi.line..(cur_lo.line - 1) {
+ if let Some(line) = fm.get_line(idx) {
+ buf.push_str(line);
+ buf.push('\n');
+ }
+ }
+ if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
+ buf.push_str(&cur_line[..cur_lo.col.to_usize()]);
}
}
- if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
- buf.push_str(&cur_line[..cur_lo.col.to_usize()]);
- }
+ buf.push_str(substitute);
}
- buf.push_str(substitute);
prev_hi = cm.lookup_char_pos(sp.hi);
prev_line = fm.get_line(prev_hi.line - 1);
}
- push_trailing(&mut buf, prev_line, &prev_hi, None);
- // remove trailing newline
- buf.pop();
- buf
+ for buf in &mut bufs {
+ // if the replacement already ends with a newline, don't print the next line
+ if !buf.ends_with('\n') {
+ push_trailing(buf, prev_line, &prev_hi, None);
+ }
+ // remove trailing newline
+ buf.pop();
+ }
+ bufs
}
}
//! Support for serializing the dep-graph and reloading it.
#![crate_name = "rustc_incremental"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(rand)]
#![feature(conservative_impl_trait)]
#![feature(sort_unstable)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate graphviz;
#[macro_use] extern crate rustc;
extern crate rustc_data_structures;
traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
trait_ref.to_poly_trait_predicate());
- // unwrap() is ok here b/c `method` is the method
- // defined in this crate whose body we are
- // checking, so it's always local
- let node_id = tcx.hir.as_local_node_id(method.def_id).unwrap();
-
- let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
+ let param_env = tcx.parameter_environment(method.def_id);
tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let mut selcx = traits::SelectionContext::new(&infcx);
match selcx.select(&obligation) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) {
if let hir::ItemUnion(ref vdata, _) = item.node {
- let param_env = &ty::ParameterEnvironment::for_item(ctx.tcx, item.id);
+ let param_env = &ctx.tcx.parameter_environment(ctx.tcx.hir.local_def_id(item.id));
for field in vdata.fields() {
let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id));
if field_ty.needs_drop(ctx.tcx, param_env) {
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_lint"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(i128_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(slice_patterns)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use]
extern crate syntax;
#![allow(dead_code)]
#![crate_name = "rustc_llvm"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(concat_idents)]
#![feature(libc)]
#![feature(link_args)]
-#![feature(staged_api)]
-#![feature(rustc_private)]
#![feature(static_nobundle)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate libc;
#[macro_use]
#[no_link]
[dependencies]
flate = { path = "../libflate" }
log = "0.3"
+owning_ref = "0.3.3"
proc_macro = { path = "../libproc_macro" }
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
-rustc_llvm = { path = "../librustc_llvm" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_ext = { path = "../libsyntax_ext" }
rejected_via_filename: vec![],
should_match_name: true,
is_proc_macro: Some(false),
+ metadata_loader: &*self.cstore.metadata_loader,
};
self.load(&mut locate_ctxt).or_else(|| {
rejected_via_filename: vec![],
should_match_name: true,
is_proc_macro: None,
+ metadata_loader: &*self.cstore.metadata_loader,
};
let library = self.load(&mut locate_ctxt).or_else(|| {
if !is_cross {
// The crate store - a central repo for information collected about external
// crates and libraries
-use locator;
use schema::{self, Tracked};
use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind};
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId};
use rustc::hir::map::definitions::DefPathTable;
use rustc::hir::svh::Svh;
-use rustc::middle::cstore::{DepKind, ExternCrate};
+use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
use rustc_back::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap, DefIdMap};
use std::cell::{RefCell, Cell};
use std::rc::Rc;
-use flate::Bytes;
+use owning_ref::ErasedBoxRef;
use syntax::{ast, attr};
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
// own crate numbers.
pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
-pub enum MetadataBlob {
- Inflated(Bytes),
- Archive(locator::ArchiveMetadata),
- Raw(Vec<u8>),
-}
+pub struct MetadataBlob(pub ErasedBoxRef<[u8]>);
/// Holds information about a syntax_pos::FileMap imported from another crate.
/// See `imported_filemaps()` for more information.
statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
pub visible_parent_map: RefCell<DefIdMap<DefId>>,
+ pub metadata_loader: Box<MetadataLoader>,
}
impl CStore {
- pub fn new(dep_graph: &DepGraph) -> CStore {
+ pub fn new(dep_graph: &DepGraph, metadata_loader: Box<MetadataLoader>) -> CStore {
CStore {
dep_graph: dep_graph.clone(),
metas: RefCell::new(FxHashMap()),
statically_included_foreign_items: RefCell::new(FxHashSet()),
dllimport_foreign_items: RefCell::new(FxHashSet()),
visible_parent_map: RefCell::new(FxHashMap()),
+ metadata_loader: metadata_loader,
}
}
self.root.disambiguator
}
- pub fn is_staged_api(&self, dep_graph: &DepGraph) -> bool {
- for attr in self.get_item_attrs(CRATE_DEF_INDEX, dep_graph).iter() {
- if attr.path == "stable" || attr.path == "unstable" {
- return true;
- }
- }
- false
- }
-
pub fn is_allocator(&self, dep_graph: &DepGraph) -> bool {
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
attr::contains_name(&attrs, "allocator")
use cstore;
use encoder;
-use locator;
use schema;
use rustc::dep_graph::DepTrackingMapConfig;
use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind,
- ExternCrate, NativeLibrary, LinkMeta,
+ ExternCrate, NativeLibrary, MetadataLoader, LinkMeta,
LinkagePreference, LoadedMacro, EncodedMetadata};
use rustc::hir::def;
use rustc::middle::lang_items;
use syntax::symbol::Symbol;
use syntax_pos::{Span, NO_EXPANSION};
use rustc::hir::svh::Svh;
-use rustc_back::target::Target;
use rustc::hir;
macro_rules! provide {
self.get_crate_data(krate)
}
+ fn metadata_loader(&self) -> &MetadataLoader {
+ &*self.metadata_loader
+ }
+
fn visibility(&self, def: DefId) -> ty::Visibility {
self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).get_visibility(def.index)
self.get_crate_data(cnum).get_missing_lang_items(&self.dep_graph)
}
- fn is_staged_api(&self, cnum: CrateNum) -> bool
- {
- self.get_crate_data(cnum).is_staged_api(&self.dep_graph)
- }
-
fn is_allocator(&self, cnum: CrateNum) -> bool
{
self.get_crate_data(cnum).is_allocator(&self.dep_graph)
{
self.get_used_link_args().borrow().clone()
}
-
- fn metadata_filename(&self) -> &str
- {
- locator::METADATA_FILENAME
- }
-
- fn metadata_section_name(&self, target: &Target) -> &str
- {
- locator::meta_section_name(target)
- }
-
fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
{
self.do_get_used_crates(prefer)
drop(visible_parent_map);
self.visible_parent_map.borrow()
}
-}
+}
\ No newline at end of file
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::middle::lang_items;
-use rustc::middle::region;
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::Substs;
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
fn raw_bytes(self) -> &'a [u8] {
- match *self {
- MetadataBlob::Inflated(ref vec) => vec,
- MetadataBlob::Archive(ref ar) => ar.as_slice(),
- MetadataBlob::Raw(ref vec) => vec,
- }
+ &self.0
}
}
}
}
-impl<'a, 'tcx> SpecializedDecoder<region::CodeExtent<'tcx>> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<region::CodeExtent<'tcx>, Self::Error> {
- Ok(self.tcx().intern_code_extent(Decodable::decode(self)?))
- }
-}
-
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<Ty<'tcx>>> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<Ty<'tcx>>, Self::Error> {
Ok(self.tcx().mk_type_list((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
// except according to those terms.
#![crate_name = "rustc_metadata"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(proc_macro_internals)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(specialization)]
-#![feature(staged_api)]
#![feature(discriminant_value)]
+#![feature(rustc_private)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use]
extern crate log;
extern crate syntax_pos;
extern crate flate;
extern crate serialize as rustc_serialize; // used by deriving
+extern crate owning_ref;
extern crate rustc_errors as errors;
extern crate syntax_ext;
extern crate proc_macro;
extern crate rustc_back;
extern crate rustc_const_math;
extern crate rustc_data_structures;
-extern crate rustc_llvm;
mod diagnostics;
use schema::{METADATA_HEADER, rustc_version};
use rustc::hir::svh::Svh;
+use rustc::middle::cstore::MetadataLoader;
use rustc::session::{config, Session};
use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
use rustc::session::search_paths::PathKind;
-use rustc::util::common;
use rustc::util::nodemap::FxHashMap;
-use rustc_llvm as llvm;
-use rustc_llvm::{False, ObjectFile, mk_section_iter};
-use rustc_llvm::archive_ro::ArchiveRO;
use errors::DiagnosticBuilder;
use syntax::symbol::Symbol;
use syntax_pos::Span;
use std::fs::{self, File};
use std::io::{self, Read};
use std::path::{Path, PathBuf};
-use std::ptr;
-use std::slice;
use std::time::Instant;
use flate;
+use owning_ref::{ErasedBoxRef, OwningRef};
pub struct CrateMismatch {
path: PathBuf,
pub rejected_via_filename: Vec<CrateMismatch>,
pub should_match_name: bool,
pub is_proc_macro: Option<bool>,
-}
-
-pub struct ArchiveMetadata {
- _archive: ArchiveRO,
- // points into self._archive
- data: *const [u8],
+ pub metadata_loader: &'a MetadataLoader,
}
pub struct CratePaths {
pub rmeta: Option<PathBuf>,
}
-pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";
-
#[derive(Copy, Clone, PartialEq)]
enum CrateFlavor {
Rlib,
let mut err: Option<DiagnosticBuilder> = None;
for (lib, kind) in m {
info!("{} reading metadata from: {}", flavor, lib.display());
- let (hash, metadata) = match get_metadata_section(self.target, flavor, &lib) {
- Ok(blob) => {
- if let Some(h) = self.crate_matches(&blob, &lib) {
- (h, blob)
- } else {
- info!("metadata mismatch");
+ let (hash, metadata) =
+ match get_metadata_section(self.target, flavor, &lib, self.metadata_loader) {
+ Ok(blob) => {
+ if let Some(h) = self.crate_matches(&blob, &lib) {
+ (h, blob)
+ } else {
+ info!("metadata mismatch");
+ continue;
+ }
+ }
+ Err(err) => {
+ info!("no metadata found: {}", err);
continue;
}
- }
- Err(err) => {
- info!("no metadata found: {}", err);
- continue;
- }
- };
+ };
// If we see multiple hashes, emit an error about duplicate candidates.
if slot.as_ref().map_or(false, |s| s.0 != hash) {
let mut e = struct_span_err!(self.sess,
err.note(&format!("crate name: {}", name));
}
-impl ArchiveMetadata {
- fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
- let data = {
- let section = ar.iter()
- .filter_map(|s| s.ok())
- .find(|sect| sect.name() == Some(METADATA_FILENAME));
- match section {
- Some(s) => s.data() as *const [u8],
- None => {
- debug!("didn't find '{}' in the archive", METADATA_FILENAME);
- return None;
- }
- }
- };
-
- Some(ArchiveMetadata {
- _archive: ar,
- data: data,
- })
- }
-
- pub fn as_slice<'a>(&'a self) -> &'a [u8] {
- unsafe { &*self.data }
- }
-}
-
-fn verify_decompressed_encoding_version(blob: &MetadataBlob,
- filename: &Path)
- -> Result<(), String> {
- if !blob.is_compatible() {
- Err((format!("incompatible metadata version found: '{}'",
- filename.display())))
- } else {
- Ok(())
- }
-}
-
// Just a small wrapper to time how long reading metadata takes.
fn get_metadata_section(target: &Target,
flavor: CrateFlavor,
- filename: &Path)
+ filename: &Path,
+ loader: &MetadataLoader)
-> Result<MetadataBlob, String> {
let start = Instant::now();
- let ret = get_metadata_section_imp(target, flavor, filename);
+ let ret = get_metadata_section_imp(target, flavor, filename, loader);
info!("reading {:?} => {:?}",
filename.file_name().unwrap(),
start.elapsed());
fn get_metadata_section_imp(target: &Target,
flavor: CrateFlavor,
- filename: &Path)
+ filename: &Path,
+ loader: &MetadataLoader)
-> Result<MetadataBlob, String> {
if !filename.exists() {
return Err(format!("no such file: '{}'", filename.display()));
}
- if flavor == CrateFlavor::Rlib {
- // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
- // internally to read the file. We also avoid even using a memcpy by
- // just keeping the archive along while the metadata is in use.
- let archive = match ArchiveRO::open(filename) {
- Some(ar) => ar,
- None => {
- debug!("llvm didn't like `{}`", filename.display());
- return Err(format!("failed to read rlib metadata: '{}'", filename.display()));
+ let raw_bytes: ErasedBoxRef<[u8]> = match flavor {
+ CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?,
+ CrateFlavor::Dylib => {
+ let buf = loader.get_dylib_metadata(target, filename)?;
+ // The header is uncompressed
+ let header_len = METADATA_HEADER.len();
+ debug!("checking {} bytes of metadata-version stamp", header_len);
+ let header = &buf[..cmp::min(header_len, buf.len())];
+ if header != METADATA_HEADER {
+ return Err(format!("incompatible metadata version found: '{}'",
+ filename.display()));
}
- };
- return match ArchiveMetadata::new(archive).map(|ar| MetadataBlob::Archive(ar)) {
- None => Err(format!("failed to read rlib metadata: '{}'", filename.display())),
- Some(blob) => {
- verify_decompressed_encoding_version(&blob, filename)?;
- Ok(blob)
- }
- };
- } else if flavor == CrateFlavor::Rmeta {
- let mut file = File::open(filename).map_err(|_|
- format!("could not open file: '{}'", filename.display()))?;
- let mut buf = vec![];
- file.read_to_end(&mut buf).map_err(|_|
- format!("failed to read rlib metadata: '{}'", filename.display()))?;
- let blob = MetadataBlob::Raw(buf);
- verify_decompressed_encoding_version(&blob, filename)?;
- return Ok(blob);
- }
- unsafe {
- let buf = common::path2cstr(filename);
- let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
- if mb as isize == 0 {
- return Err(format!("error reading library: '{}'", filename.display()));
- }
- let of = match ObjectFile::new(mb) {
- Some(of) => of,
- _ => {
- return Err((format!("provided path not an object file: '{}'", filename.display())))
- }
- };
- let si = mk_section_iter(of.llof);
- while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
- let mut name_buf = ptr::null();
- let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
- let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
- let name = String::from_utf8(name).unwrap();
- debug!("get_metadata_section: name {}", name);
- if read_meta_section_name(target) == name {
- let cbuf = llvm::LLVMGetSectionContents(si.llsi);
- let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
- let cvbuf: *const u8 = cbuf as *const u8;
- let vlen = METADATA_HEADER.len();
- debug!("checking {} bytes of metadata-version stamp", vlen);
- let minsz = cmp::min(vlen, csz);
- let buf0 = slice::from_raw_parts(cvbuf, minsz);
- let version_ok = buf0 == METADATA_HEADER;
- if !version_ok {
- return Err((format!("incompatible metadata version found: '{}'",
- filename.display())));
- }
- let cvbuf1 = cvbuf.offset(vlen as isize);
- debug!("inflating {} bytes of compressed metadata", csz - vlen);
- let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
- match flate::inflate_bytes(bytes) {
- Ok(inflated) => {
- let blob = MetadataBlob::Inflated(inflated);
- verify_decompressed_encoding_version(&blob, filename)?;
- return Ok(blob);
- }
- Err(_) => {}
+ // Header is okay -> inflate the actual metadata
+ let compressed_bytes = &buf[header_len..];
+ debug!("inflating {} bytes of compressed metadata", compressed_bytes.len());
+ match flate::inflate_bytes(compressed_bytes) {
+ Ok(inflated) => {
+ let buf = unsafe { OwningRef::new_assert_stable_address(inflated) };
+ buf.map_owner_box().erase_owner()
+ }
+ Err(_) => {
+ return Err(format!("failed to decompress metadata: {}", filename.display()));
}
}
- llvm::LLVMMoveToNextSection(si.llsi);
}
- Err(format!("metadata not found: '{}'", filename.display()))
- }
-}
-
-pub fn meta_section_name(target: &Target) -> &'static str {
- // Historical note:
- //
- // When using link.exe it was seen that the section name `.note.rustc`
- // was getting shortened to `.note.ru`, and according to the PE and COFF
- // specification:
- //
- // > Executable images do not use a string table and do not support
- // > section names longer than 8 characters
- //
- // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
- //
- // As a result, we choose a slightly shorter name! As to why
- // `.note.rustc` works on MinGW, that's another good question...
-
- if target.options.is_like_osx {
- "__DATA,.rustc"
+ CrateFlavor::Rmeta => {
+ let mut file = File::open(filename).map_err(|_|
+ format!("could not open file: '{}'", filename.display()))?;
+ let mut buf = vec![];
+ file.read_to_end(&mut buf).map_err(|_|
+ format!("failed to read rmeta metadata: '{}'", filename.display()))?;
+ OwningRef::new(buf).map_owner_box().erase_owner()
+ }
+ };
+ let blob = MetadataBlob(raw_bytes);
+ if blob.is_compatible() {
+ Ok(blob)
} else {
- ".rustc"
+ Err(format!("incompatible metadata version found: '{}'", filename.display()))
}
}
-pub fn read_meta_section_name(_target: &Target) -> &'static str {
- ".rustc"
-}
-
// A diagnostic function for dumping crate metadata to an output stream
-pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) -> io::Result<()> {
+pub fn list_file_metadata(target: &Target,
+ path: &Path,
+ loader: &MetadataLoader,
+ out: &mut io::Write)
+ -> io::Result<()> {
let filename = path.file_name().unwrap().to_str().unwrap();
let flavor = if filename.ends_with(".rlib") {
CrateFlavor::Rlib
} else {
CrateFlavor::Dylib
};
- match get_metadata_section(target, flavor, path) {
+ match get_metadata_section(target, flavor, path, loader) {
Ok(metadata) => metadata.list_crate_metadata(out),
Err(msg) => write!(out, "{}\n", msg),
}
temp: &Lvalue<'tcx>,
constant: Constant<'tcx>) {
self.push_assign(block, source_info, temp,
- Rvalue::Use(Operand::Constant(constant)));
+ Rvalue::Use(Operand::Constant(box constant)));
}
pub fn push_assign_unit(&mut self,
source_info: SourceInfo,
lvalue: &Lvalue<'tcx>) {
self.push_assign(block, source_info, lvalue, Rvalue::Aggregate(
- AggregateKind::Tuple, vec![]
+ box AggregateKind::Tuple, vec![]
));
}
/// The operand is known to be live until the end of `scope`.
pub fn as_operand<M>(&mut self,
block: BasicBlock,
- scope: Option<CodeExtent<'tcx>>,
+ scope: Option<CodeExtent>,
expr: M) -> BlockAnd<Operand<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
fn expr_as_operand(&mut self,
mut block: BasicBlock,
- scope: Option<CodeExtent<'tcx>>,
+ scope: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Operand<'tcx>> {
debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
match category {
Category::Constant => {
let constant = this.as_constant(expr);
- block.and(Operand::Constant(constant))
+ block.and(Operand::Constant(box constant))
}
Category::Lvalue |
Category::Rvalue(..) => {
}
/// Compile `expr`, yielding an rvalue.
- pub fn as_rvalue<M>(&mut self, block: BasicBlock, scope: Option<CodeExtent<'tcx>>, expr: M)
+ pub fn as_rvalue<M>(&mut self, block: BasicBlock, scope: Option<CodeExtent>, expr: M)
-> BlockAnd<Rvalue<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
fn expr_as_rvalue(&mut self,
mut block: BasicBlock,
- scope: Option<CodeExtent<'tcx>>,
+ scope: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Rvalue<'tcx>> {
debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
.map(|f| unpack!(block = this.as_operand(block, scope, f)))
.collect();
- block.and(Rvalue::Aggregate(AggregateKind::Array(el_ty), fields))
+ block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields))
}
ExprKind::Tuple { fields } => { // see (*) above
// first process the set of fields
.map(|f| unpack!(block = this.as_operand(block, scope, f)))
.collect();
- block.and(Rvalue::Aggregate(AggregateKind::Tuple, fields))
+ block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields))
}
ExprKind::Closure { closure_id, substs, upvars } => { // see (*) above
let upvars =
upvars.into_iter()
.map(|upvar| unpack!(block = this.as_operand(block, scope, upvar)))
.collect();
- block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars))
+ block.and(Rvalue::Aggregate(box AggregateKind::Closure(closure_id, substs), upvars))
}
ExprKind::Adt {
adt_def, variant_index, substs, fields, base
field_names.iter().filter_map(|n| fields_map.get(n).cloned()).collect()
};
- let adt = AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
+ let adt =
+ box AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
block.and(Rvalue::Aggregate(adt, fields))
}
ExprKind::Assign { .. } |
/// up rvalues so as to freeze the value that will be consumed.
pub fn as_temp<M>(&mut self,
block: BasicBlock,
- temp_lifetime: Option<CodeExtent<'tcx>>,
+ temp_lifetime: Option<CodeExtent>,
expr: M)
-> BlockAnd<Lvalue<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
fn expr_as_temp(&mut self,
mut block: BasicBlock,
- temp_lifetime: Option<CodeExtent<'tcx>>,
+ temp_lifetime: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Lvalue<'tcx>> {
debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
this.cfg.push(block, Statement {
source_info: source_info,
kind: StatementKind::InlineAsm {
- asm: asm.clone(),
+ asm: box asm.clone(),
outputs: outputs,
inputs: inputs
},
let eq_block = self.cfg.start_new_block();
let cleanup = self.diverge_cleanup();
self.cfg.terminate(block, source_info, TerminatorKind::Call {
- func: Operand::Constant(Constant {
+ func: Operand::Constant(box Constant {
span: test.span,
ty: mty,
literal: method
ty: Ty<'tcx>,
literal: Literal<'tcx>)
-> Operand<'tcx> {
- let constant = Constant {
+ let constant = box Constant {
span: span,
ty: ty,
literal: literal,
}
pub fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
- Rvalue::Aggregate(AggregateKind::Tuple, vec![])
+ Rvalue::Aggregate(box AggregateKind::Tuple, vec![])
}
// Returns a zero literal operand for the appropriate type, works for
use hair::Pattern;
use rustc::hir;
use rustc::hir::def_id::DefId;
-use rustc::middle::region::{CodeExtent, CodeExtentData};
+use rustc::middle::region::CodeExtent;
use rustc::mir::*;
use rustc::mir::transform::MirSource;
use rustc::mir::visit::MutVisitor;
{
let span = tcx.hir.span(ctor_id);
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
- let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
+ let pe = tcx.parameter_environment(tcx.hir.local_def_id(ctor_id));
tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
let (mut mir, src) =
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
-> Ty<'tcx> {
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
+ let closure_def_id = tcx.hir.local_def_id(closure_expr_id);
let region = ty::ReFree(ty::FreeRegion {
- scope: Some(tcx.item_extent(body_id.node_id)),
+ scope: closure_def_id,
bound_region: ty::BoundRegion::BrEnv,
});
let region = tcx.mk_region(region);
- match tcx.closure_kind(tcx.hir.local_def_id(closure_expr_id)) {
+ match tcx.closure_kind(closure_def_id) {
ty::ClosureKind::Fn =>
tcx.mk_ref(region,
ty::TypeAndMut { ty: closure_ty,
let span = tcx.hir.span(fn_id);
let mut builder = Builder::new(hir.clone(), span, arguments.len(), return_ty);
- let call_site_extent =
- tcx.intern_code_extent(
- CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body.value.id });
- let arg_extent =
- tcx.intern_code_extent(
- CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.value.id });
+ let call_site_extent = CodeExtent::CallSiteScope(body.id());
+ let arg_extent = CodeExtent::ParameterScope(body.id());
let mut block = START_BLOCK;
unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
unpack!(block = builder.in_scope(arg_extent, block, |builder| {
let span = tcx.hir.span(owner_id);
let mut builder = Builder::new(hir.clone(), span, 0, ty);
- let extent = hir.region_maps.temporary_scope(tcx, ast_expr.id)
- .unwrap_or(tcx.item_extent(owner_id));
let mut block = START_BLOCK;
- let _ = builder.in_scope(extent, block, |builder| {
- let expr = builder.hir.mirror(ast_expr);
- unpack!(block = builder.into(&Lvalue::Local(RETURN_POINTER), block, expr));
+ let expr = builder.hir.mirror(ast_expr);
+ unpack!(block = builder.into_expr(&Lvalue::Local(RETURN_POINTER), block, expr));
- let source_info = builder.source_info(span);
- let return_block = builder.return_block();
- builder.cfg.terminate(block, source_info,
- TerminatorKind::Goto { target: return_block });
- builder.cfg.terminate(return_block, source_info,
- TerminatorKind::Return);
+ let source_info = builder.source_info(span);
+ builder.cfg.terminate(block, source_info, TerminatorKind::Return);
- return_block.unit()
- });
+ // Constants can't `return` so a return block should not be created.
+ assert_eq!(builder.cached_return_block, None);
builder.finish(vec![], ty)
}
fn args_and_body(&mut self,
mut block: BasicBlock,
arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
- argument_extent: CodeExtent<'tcx>,
+ argument_extent: CodeExtent,
ast_body: &'gcx hir::Expr)
-> BlockAnd<()>
{
*/
use build::{BlockAnd, BlockAndExtension, Builder, CFG};
-use rustc::middle::region::{CodeExtent, CodeExtentData};
+use rustc::middle::region::CodeExtent;
use rustc::middle::lang_items;
use rustc::middle::const_val::ConstVal;
use rustc::ty::subst::{Kind, Subst};
visibility_scope: VisibilityScope,
/// the extent of this scope within source code.
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
/// Whether there's anything to do for the cleanup path, that is,
/// when unwinding through this scope. This includes destructors,
free: Option<FreeData<'tcx>>,
/// The cache for drop chain on “normal” exit into a particular BasicBlock.
- cached_exits: FxHashMap<(BasicBlock, CodeExtent<'tcx>), BasicBlock>,
+ cached_exits: FxHashMap<(BasicBlock, CodeExtent), BasicBlock>,
}
struct DropData<'tcx> {
#[derive(Clone, Debug)]
pub struct BreakableScope<'tcx> {
/// Extent of the loop
- pub extent: CodeExtent<'tcx>,
+ pub extent: CodeExtent,
/// Where the body of the loop begins. `None` if block
pub continue_block: Option<BasicBlock>,
/// Block to branch into when the loop or block terminates (either by being `break`-en out
/// Convenience wrapper that pushes a scope and then executes `f`
/// to build its contents, popping the scope afterwards.
pub fn in_scope<F, R>(&mut self,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
mut block: BasicBlock,
f: F)
-> BlockAnd<R>
/// scope and call `pop_scope` afterwards. Note that these two
/// calls must be paired; using `in_scope` as a convenience
/// wrapper maybe preferable.
- pub fn push_scope(&mut self, extent: CodeExtent<'tcx>) {
+ pub fn push_scope(&mut self, extent: CodeExtent) {
debug!("push_scope({:?})", extent);
let vis_scope = self.visibility_scope;
self.scopes.push(Scope {
/// drops onto the end of `block` that are needed. This must
/// match 1-to-1 with `push_scope`.
pub fn pop_scope(&mut self,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
mut block: BasicBlock)
-> BlockAnd<()> {
debug!("pop_scope({:?}, {:?})", extent, block);
/// module comment for details.
pub fn exit_scope(&mut self,
span: Span,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
mut block: BasicBlock,
target: BasicBlock) {
debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target);
/// resolving `break` and `continue`.
pub fn find_breakable_scope(&mut self,
span: Span,
- label: CodeExtent<'tcx>)
+ label: CodeExtent)
-> &mut BreakableScope<'tcx> {
// find the loop-scope with the correct id
self.breakable_scopes.iter_mut()
/// Returns the extent of the scope which should be exited by a
/// return.
- pub fn extent_of_return_scope(&self) -> CodeExtent<'tcx> {
+ pub fn extent_of_return_scope(&self) -> CodeExtent {
// The outermost scope (`scopes[0]`) will be the `CallSiteScope`.
// We want `scopes[1]`, which is the `ParameterScope`.
assert!(self.scopes.len() >= 2);
- assert!(match *self.scopes[1].extent {
- CodeExtentData::ParameterScope { .. } => true,
+ assert!(match self.scopes[1].extent {
+ CodeExtent::ParameterScope(_) => true,
_ => false,
});
self.scopes[1].extent
/// Returns the topmost active scope, which is known to be alive until
/// the next scope expression.
- pub fn topmost_scope(&self) -> CodeExtent<'tcx> {
+ pub fn topmost_scope(&self) -> CodeExtent {
self.scopes.last().expect("topmost_scope: no scopes present").extent
}
/// `extent`.
pub fn schedule_drop(&mut self,
span: Span,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
lvalue: &Lvalue<'tcx>,
lvalue_ty: Ty<'tcx>) {
let needs_drop = self.hir.needs_drop(lvalue_ty);
/// There may only be one “free” scheduled in any given scope.
pub fn schedule_box_free(&mut self,
span: Span,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
value: &Lvalue<'tcx>,
item_ty: Ty<'tcx>) {
for scope in self.scopes.iter_mut().rev() {
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
let substs = tcx.intern_substs(&[Kind::from(data.item_ty)]);
TerminatorKind::Call {
- func: Operand::Constant(Constant {
+ func: Operand::Constant(box Constant {
span: data.span,
ty: tcx.type_of(free_func).subst(tcx, substs),
literal: Literal::Value {
use hair::*;
use hair::cx::Cx;
use hair::cx::to_ref::ToRef;
-use rustc::middle::region::{BlockRemainder, CodeExtentData};
+use rustc::middle::region::{BlockRemainder, CodeExtent};
use rustc::hir;
use syntax::ast;
let stmts = mirror_stmts(cx, self.id, &*self.stmts);
Block {
targeted_by_break: self.targeted_by_break,
- extent: cx.tcx.node_extent(self.id),
+ extent: CodeExtent::Misc(self.id),
span: self.span,
stmts: stmts,
expr: self.expr.to_ref(),
result.push(StmtRef::Mirror(Box::new(Stmt {
span: stmt.span,
kind: StmtKind::Expr {
- scope: cx.tcx.node_extent(id),
+ scope: CodeExtent::Misc(id),
expr: expr.to_ref(),
},
})))
// ignore for purposes of the MIR
}
hir::DeclLocal(ref local) => {
- let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
+ let remainder_extent = CodeExtent::Remainder(BlockRemainder {
block: block_id,
first_statement_index: index as u32,
});
- let remainder_extent =
- cx.tcx.intern_code_extent(remainder_extent);
let pattern = Pattern::from_hir(cx.tcx, cx.tables(), &local.pat);
result.push(StmtRef::Mirror(Box::new(Stmt {
span: stmt.span,
kind: StmtKind::Let {
remainder_scope: remainder_extent,
- init_scope: cx.tcx.node_extent(id),
+ init_scope: CodeExtent::Misc(id),
pattern: pattern,
initializer: local.init.to_ref(),
},
block: &'tcx hir::Block)
-> ExprRef<'tcx> {
let block_ty = cx.tables().node_id_to_type(block.id);
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, block.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(block.id);
let expr = Expr {
ty: block_ty,
temp_lifetime: temp_lifetime,
use hair::cx::Cx;
use hair::cx::block;
use hair::cx::to_ref::ToRef;
-use rustc::hir::map;
use rustc::hir::def::{Def, CtorKind};
use rustc::middle::const_val::ConstVal;
use rustc::ty::{self, AdtKind, VariantDef, Ty};
type Output = Expr<'tcx>;
fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, self.id);
- let expr_extent = cx.tcx.node_extent(self.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(self.id);
+ let expr_extent = CodeExtent::Misc(self.id);
debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
expr: &'tcx hir::Expr)
-> Expr<'tcx> {
let expr_ty = cx.tables().expr_ty(expr);
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
let kind = match expr.node {
// Here comes the interesting stuff:
match dest.target_id {
hir::ScopeTarget::Block(target_id) |
hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(target_id)) => ExprKind::Break {
- label: cx.tcx.node_extent(target_id),
+ label: CodeExtent::Misc(target_id),
value: value.to_ref(),
},
hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
match dest.target_id {
hir::ScopeTarget::Block(_) => bug!("cannot continue to blocks"),
hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => ExprKind::Continue {
- label: cx.tcx.node_extent(loop_id),
+ label: CodeExtent::Misc(loop_id),
},
hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
bug!("invalid loop id for continue: {}", err)
hir::ExprBox(ref value) => {
ExprKind::Box {
value: value.to_ref(),
- value_extents: cx.tcx.node_extent(value.id),
+ value_extents: CodeExtent::Misc(value.id),
}
}
hir::ExprArray(ref fields) => ExprKind::Array { fields: fields.to_ref() },
method_call: ty::MethodCall)
-> Expr<'tcx> {
let callee = cx.tables().method_map[&method_call];
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
expr: &'tcx hir::Expr,
def: Def)
-> ExprKind<'tcx> {
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
match def {
Def::Local(def_id) => {
closure_expr_id);
let var_ty = cx.tables().node_id_to_type(id_var);
- let body_id = match cx.tcx.hir.find(closure_expr_id) {
- Some(map::NodeExpr(expr)) => {
- match expr.node {
- hir::ExprClosure(.., body, _) => body.node_id,
- _ => {
- span_bug!(expr.span, "closure expr is not a closure expr");
- }
- }
- }
- _ => {
- span_bug!(expr.span, "ast-map has garbage for closure expr");
- }
- };
-
// FIXME free regions in closures are not right
let closure_ty = cx.tables().node_id_to_type(closure_expr_id);
// FIXME we're just hard-coding the idea that the
// signature will be &self or &mut self and hence will
// have a bound region with number 0
+ let closure_def_id = cx.tcx.hir.local_def_id(closure_expr_id);
let region = ty::ReFree(ty::FreeRegion {
- scope: Some(cx.tcx.node_extent(body_id)),
+ scope: closure_def_id,
bound_region: ty::BoundRegion::BrAnon(0),
});
let region = cx.tcx.mk_region(region);
- let self_expr = match cx.tcx.closure_kind(cx.tcx.hir.local_def_id(closure_expr_id)) {
+ let self_expr = match cx.tcx.closure_kind(closure_def_id) {
ty::ClosureKind::Fn => {
let ref_closure_ty = cx.tcx.mk_ref(region,
ty::TypeAndMut {
PassArgs::ByRef => {
let region = cx.tcx.node_scope_region(expr.id);
let (temp_lifetime, was_shrunk) =
- cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ cx.region_maps.temporary_scope2(expr.id);
argrefs.extend(args.iter()
.map(|arg| {
let arg_ty = cx.tables().expr_ty_adjusted(arg);
// construct the complete expression `foo()` for the overloaded call,
// which will yield the &T type
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
let ref_kind = overloaded_operator(cx, expr, method_call, pass_args, receiver, args);
let ref_expr = Expr {
temp_lifetime: temp_lifetime,
closure_expr_id: closure_expr.id,
};
let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap();
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, closure_expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(closure_expr.id);
let var_ty = cx.tables().node_id_to_type(id_var);
let captured_var = Expr {
temp_lifetime: temp_lifetime,
pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- pub region_maps: Rc<RegionMaps<'tcx>>,
+ pub region_maps: Rc<RegionMaps>,
constness: hir::Constness,
/// True if this constant/function needs overflow checks.
#[derive(Clone, Debug)]
pub struct Block<'tcx> {
pub targeted_by_break: bool,
- pub extent: CodeExtent<'tcx>,
+ pub extent: CodeExtent,
pub span: Span,
pub stmts: Vec<StmtRef<'tcx>>,
pub expr: Option<ExprRef<'tcx>>,
pub enum StmtKind<'tcx> {
Expr {
/// scope for this statement; may be used as lifetime of temporaries
- scope: CodeExtent<'tcx>,
+ scope: CodeExtent,
/// expression being evaluated in this statement
expr: ExprRef<'tcx>,
Let {
/// scope for variables bound in this let; covers this and
/// remaining statements in block
- remainder_scope: CodeExtent<'tcx>,
+ remainder_scope: CodeExtent,
/// scope for the initialization itself; might be used as
/// lifetime of temporaries
- init_scope: CodeExtent<'tcx>,
+ init_scope: CodeExtent,
/// let <PAT> = ...
pattern: Pattern<'tcx>,
/// lifetime of this expression if it should be spilled into a
/// temporary; should be None only if in a constant context
- pub temp_lifetime: Option<CodeExtent<'tcx>>,
+ pub temp_lifetime: Option<CodeExtent>,
/// whether this temp lifetime was shrunk by #36082.
pub temp_lifetime_was_shrunk: bool,
#[derive(Clone, Debug)]
pub enum ExprKind<'tcx> {
Scope {
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
value: ExprRef<'tcx>,
},
Box {
value: ExprRef<'tcx>,
- value_extents: CodeExtent<'tcx>,
+ value_extents: CodeExtent,
},
Call {
ty: ty::Ty<'tcx>,
arg: ExprRef<'tcx>,
},
Break {
- label: CodeExtent<'tcx>,
+ label: CodeExtent,
value: Option<ExprRef<'tcx>>,
},
Continue {
- label: CodeExtent<'tcx>,
+ label: CodeExtent,
},
Return {
value: Option<ExprRef<'tcx>>,
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![deny(warnings)]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![feature(associated_consts)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(i128_type)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(placement_in_syntax)]
#![feature(collection_placement)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
#[macro_use] extern crate log;
extern crate graphviz as dot;
#[macro_use]
use rustc::mir::*;
use rustc::mir::transform::MirSource;
use rustc::ty::{self, Ty};
-use rustc::ty::subst::{Kind, Subst};
+use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::ty::maps::Providers;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
{
debug!("make_shim({:?})", instance);
let did = instance.def_id();
- let span = tcx.def_span(did);
- let param_env = tcx.construct_parameter_environment(span, did, None);
+ let param_env = tcx.parameter_environment(did);
let mut result = match instance {
ty::InstanceDef::Item(..) =>
build_call_shim(
tcx,
- ¶m_env,
def_id,
adjustment,
CallKind::Indirect,
// trans::mir knows to turn to an actual virtual call.
build_call_shim(
tcx,
- ¶m_env,
def_id,
Adjustment::Identity,
CallKind::Direct(def_id),
build_call_shim(
tcx,
- ¶m_env,
call_once,
Adjustment::RefMut,
CallKind::Direct(call_mut),
let substs = if let Some(ty) = ty {
tcx.mk_substs(iter::once(Kind::from(ty)))
} else {
- param_env.free_substs
+ Substs::identity_for_item(tcx, def_id)
};
let fn_ty = tcx.type_of(def_id).subst(tcx, substs);
let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
/// If `untuple_args` is a vec of types, the second argument of the
/// function will be untupled as these types.
fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>,
def_id: DefId,
rcvr_adjustment: Adjustment,
call_kind: CallKind,
call_kind={:?}, untuple_args={:?})",
def_id, rcvr_adjustment, call_kind, untuple_args);
- let fn_ty = tcx.type_of(def_id).subst(tcx, param_env.free_substs);
+ let fn_ty = tcx.type_of(def_id);
let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
let span = tcx.def_span(def_id);
let (callee, mut args) = match call_kind {
CallKind::Indirect => (rcvr, vec![]),
CallKind::Direct(def_id) => (
- Operand::Constant(Constant {
+ Operand::Constant(box Constant {
span: span,
- ty: tcx.type_of(def_id).subst(tcx, param_env.free_substs),
+ ty: tcx.type_of(def_id),
literal: Literal::Value {
- value: ConstVal::Function(def_id, param_env.free_substs),
+ value: ConstVal::Function(def_id,
+ Substs::identity_for_item(tcx, def_id)),
},
}),
vec![rcvr]
kind: StatementKind::Assign(
Lvalue::Local(RETURN_POINTER),
Rvalue::Aggregate(
- AggregateKind::Adt(adt_def, variant_no, substs, None),
+ box AggregateKind::Adt(adt_def, variant_no, substs, None),
(1..sig.inputs().len()+1).map(|i| {
Operand::Consume(Lvalue::Local(Local::new(i)))
}).collect()
_ => return,
}
- *operand = Operand::Constant(self.constant.clone());
+ *operand = Operand::Constant(box self.constant.clone());
self.uses_replaced += 1
}
}
&Rvalue::Aggregate(ref agg_kind, ref operands) => (agg_kind, operands),
_ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs),
};
- let (adt_def, variant, substs) = match agg_kind {
- &AggregateKind::Adt(adt_def, variant, substs, None)
+ let (adt_def, variant, substs) = match **agg_kind {
+ AggregateKind::Adt(adt_def, variant, substs, None)
=> (adt_def, variant, substs),
_ => span_bug!(src_info.span, "expected struct, not {:?}", rhs),
};
&Rvalue::Aggregate(ref kind, ref operands) => (kind, operands),
_ => continue,
};
- let (adt_def, variant) = match kind {
- &AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant),
+ let (adt_def, variant) = match **kind {
+ AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant),
_ => continue,
};
if operands.len() == 0 {
// FIXME: Give a bonus to functions with only a single caller
- let param_env = ty::ParameterEnvironment::for_item(tcx, self.source.item_id());
+ let def_id = tcx.hir.local_def_id(self.source.item_id());
+ let param_env = tcx.parameter_environment(def_id);
let mut first_block = true;
let mut cost = 0;
(if self.keep_original {
rhs.clone()
} else {
- let unit = Rvalue::Aggregate(AggregateKind::Tuple, vec![]);
+ let unit = Rvalue::Aggregate(box AggregateKind::Tuple, vec![]);
mem::replace(rhs, unit)
}, statement.source_info)
};
fn promote_candidate(mut self, candidate: Candidate) {
let span = self.promoted.span;
- let new_operand = Operand::Constant(Constant {
+ let new_operand = Operand::Constant(box Constant {
span: span,
ty: self.promoted.return_ty,
literal: Literal::Promoted {
}
Rvalue::Aggregate(ref kind, _) => {
- if let AggregateKind::Adt(def, ..) = *kind {
+ if let AggregateKind::Adt(def, ..) = **kind {
if def.has_dtor(self.tcx) {
self.add(Qualif::NEEDS_DROP);
self.deny_drop();
return Qualif::NOT_CONST.bits();
}
- let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
- let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
+ let param_env = tcx.parameter_environment(def_id);
let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const);
qualifier.qualify_const().bits()
MirSource::Const(_) |
MirSource::Promoted(..) => return
};
- let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+ let param_env = tcx.parameter_environment(def_id);
if mode == Mode::Fn || mode == Mode::ConstFn {
// This is ugly because Qualifier holds onto mir,
for block in mir.basic_blocks_mut() {
let terminator = block.terminator_mut();
terminator.kind = match terminator.kind {
- TerminatorKind::SwitchInt { discr: Operand::Constant(Constant {
+ TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant {
literal: Literal::Value { ref value }, ..
}), ref values, ref targets, .. } => {
if let Some(ref constint) = value.to_const_int() {
continue
}
},
- TerminatorKind::Assert { target, cond: Operand::Constant(Constant {
+ TerminatorKind::Assert { target, cond: Operand::Constant(box Constant {
literal: Literal::Value {
value: ConstVal::Bool(cond)
}, ..
}
}
}
-
fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
match operand {
- &Operand::Constant(Constant {
+ &Operand::Constant(box Constant {
literal: Literal::Value {
value: ConstVal::Function(def_id, _), ..
}, ..
// broken MIR, so try not to report duplicate errors.
return;
}
- let param_env = ty::ParameterEnvironment::for_item(tcx, item_id);
+ let param_env = tcx.parameter_environment(def_id);
tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let mut checker = TypeChecker::new(&infcx, item_id);
{
impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
- fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _n: NodeId) {
+ fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _a: &[ast::Attribute], _n: NodeId) {
self.record("Mod", Id::None, m);
ast_visit::walk_mod(self, m)
}
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_passes"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(warnings)]
#![feature(rustc_diagnostic_macros)]
-#![feature(staged_api)]
-#![feature(rustc_private)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use]
extern crate rustc;
Rvalue::Aggregate(ref kind, ref _operands) => {
// AggregateKind is not distinguished by visit API, so
// record it. (`super_rvalue` handles `_operands`.)
- self.record(match *kind {
+ self.record(match **kind {
AggregateKind::Array(_) => "AggregateKind::Array",
AggregateKind::Tuple => "AggregateKind::Tuple",
AggregateKind::Adt(..) => "AggregateKind::Adt",
// except according to those terms.
#![crate_name = "rustc_platform_intrinsics"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![deny(warnings)]
#![allow(bad_style)]
//! for more examples.
#![crate_name = "rustc_plugin"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(staged_api)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use] extern crate syntax;
// except according to those terms.
#![crate_name = "rustc_privacy"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(warnings)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
extern crate rustc;
#[macro_use] extern crate syntax;
view_path.span,
ResolutionError::SelfImportsOnlyAllowedWithin);
} else if source_name == "$crate" && full_path.segments.len() == 1 {
- let crate_root = self.resolve_crate_var(source.ctxt);
+ let crate_root = self.resolve_crate_var(source.ctxt, item.span);
let crate_name = match crate_root.kind {
ModuleKind::Def(_, name) => name,
ModuleKind::Block(..) => unreachable!(),
// n.b. we don't need to look at the path option here, because cstore already did
let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap();
- let module = self.get_extern_crate_root(crate_id);
+ let module = self.get_extern_crate_root(crate_id, item.span);
self.populate_module_if_necessary(module);
let used = self.process_legacy_macro_imports(item, module, expansion);
let binding =
no_implicit_prelude: parent.no_implicit_prelude || {
attr::contains_name(&item.attrs, "no_implicit_prelude")
},
- ..ModuleData::new(Some(parent), module_kind, def_id)
+ ..ModuleData::new(Some(parent), module_kind, def_id, item.span)
});
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.module_map.insert(def_id, module);
ItemKind::Enum(ref enum_definition, _) => {
let def = Def::Enum(self.definitions.local_def_id(item.id));
let module_kind = ModuleKind::Def(def, ident.name);
- let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
+ let module = self.new_module(parent,
+ module_kind,
+ parent.normal_ancestor_id,
+ item.span);
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
for variant in &(*enum_definition).variants {
// Add all the items within to a new module.
let module_kind = ModuleKind::Def(Def::Trait(def_id), ident.name);
- let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
+ let module = self.new_module(parent,
+ module_kind,
+ parent.normal_ancestor_id,
+ item.span);
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.current_module = module;
}
fn build_reduced_graph_for_block(&mut self, block: &Block) {
let parent = self.current_module;
if self.block_needs_anonymous_module(block) {
- let module =
- self.new_module(parent, ModuleKind::Block(block.id), parent.normal_ancestor_id);
+ let module = self.new_module(parent,
+ ModuleKind::Block(block.id),
+ parent.normal_ancestor_id,
+ block.span);
self.block_map.insert(block.id, module);
self.current_module = module; // Descend into the block.
}
let def = child.def;
let def_id = def.def_id();
let vis = self.session.cstore.visibility(def_id);
+ let span = child.span;
match def {
Def::Mod(..) | Def::Enum(..) => {
- let module = self.new_module(parent, ModuleKind::Def(def, ident.name), def_id);
+ let module = self.new_module(parent,
+ ModuleKind::Def(def, ident.name),
+ def_id,
+ span);
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
}
Def::Variant(..) | Def::TyAlias(..) => {
}
Def::Trait(..) => {
let module_kind = ModuleKind::Def(def, ident.name);
- let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
+ let module = self.new_module(parent,
+ module_kind,
+ parent.normal_ancestor_id,
+ span);
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
for child in self.session.cstore.item_children(def_id) {
}
}
- fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> {
+ fn get_extern_crate_root(&mut self, cnum: CrateNum, span: Span) -> Module<'a> {
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
let name = self.session.cstore.crate_name(cnum);
let macros_only = self.session.cstore.dep_kind(cnum).macros_only();
let module_kind = ModuleKind::Def(Def::Mod(def_id), name);
let arenas = self.arenas;
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
- arenas.alloc_module(ModuleData::new(None, module_kind, def_id))
+ arenas.alloc_module(ModuleData::new(None, module_kind, def_id, span))
})
}
- pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
+ pub fn macro_def_scope(&mut self, expansion: Mark, span: Span) -> Module<'a> {
let def_id = self.macro_defs[&expansion];
if let Some(id) = self.definitions.as_local_node_id(def_id) {
self.local_macro_def_scopes[&id]
self.graph_root
} else {
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
- self.get_extern_crate_root(module_def_id.krate)
+ self.get_extern_crate_root(module_def_id.krate, span)
}
}
} else {
for (name, span) in legacy_imports.imports {
let ident = Ident::with_empty_ctxt(name);
- let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
+ let result = self.resolve_ident_in_module(module, ident, MacroNS,
+ false, false, span);
if let Ok(binding) = result {
let directive = macro_use_directive(span);
self.potentially_unused_imports.push(directive);
for (name, span) in legacy_imports.reexports {
self.session.cstore.export_macros(module.def_id().unwrap().krate);
let ident = Ident::with_empty_ctxt(name);
- let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
+ let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
if let Ok(binding) = result {
self.macro_exports.push(Export { name: name, def: binding.def(), span: span });
} else {
"##,
E0435: r##"
-A non-constant value was used to initialise a constant.
+A non-constant value was used in a constant expression.
Erroneous code example:
```compile_fail,E0435
-let foo = 42u32;
-const FOO : u32 = foo; // error: attempt to use a non-constant value in a
- // constant
+let foo = 42;
+let a: [u8; foo]; // error: attempt to use a non-constant value in a constant
```
To fix this error, please replace the value with a constant. Example:
```
-const FOO : u32 = 42u32; // ok!
+let a: [u8; 42]; // ok!
```
Or:
```
-const OTHER_FOO : u32 = 42u32;
-const FOO : u32 = OTHER_FOO; // ok!
+const FOO: usize = 42;
+let a: [u8; FOO]; // ok!
```
"##,
// E0157, unused error code
// E0257,
// E0258,
- E0402, // cannot use an outer type parameter in this context
+// E0402, // cannot use an outer type parameter in this context
// E0406, merged into 420
// E0410, merged into 408
// E0413, merged into 530
// except according to those terms.
#![crate_name = "rustc_resolve"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(associated_consts)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use]
extern crate log;
enum ResolutionError<'a> {
/// error E0401: can't use type parameters from outer function
TypeParametersFromOuterFunction,
- /// error E0402: cannot use an outer type parameter in this context
- OuterTypeParameterContext,
/// error E0403: the name is already used for a type parameter in this type parameter list
NameAlreadyUsedInTypeParameterList(Name, &'a Span),
/// error E0407: method is not a member of trait
err.span_label(span, "use of type variable from outer function");
err
}
- ResolutionError::OuterTypeParameterContext => {
- struct_span_err!(resolver.session,
- span,
- E0402,
- "cannot use an outer type parameter in this context")
- }
ResolutionError::NameAlreadyUsedInTypeParameterList(name, first_use_span) => {
let mut err = struct_span_err!(resolver.session,
span,
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
} else if let TyKind::ImplicitSelf = ty.node {
let self_ty = keywords::SelfType.ident();
- let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.span))
+ let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, true, ty.span)
.map_or(Def::Err, |d| d.def());
self.record_def(ty.id, PathResolution::new(def));
} else if let TyKind::Array(ref element, ref length) = ty.node {
// access the children must be preceded with a
// `populate_module_if_necessary` call.
populated: Cell<bool>,
+
+ /// Span of the module itself. Used for error reporting.
+ span: Span,
}
pub type Module<'a> = &'a ModuleData<'a>;
impl<'a> ModuleData<'a> {
- fn new(parent: Option<Module<'a>>, kind: ModuleKind, normal_ancestor_id: DefId) -> Self {
+ fn new(parent: Option<Module<'a>>,
+ kind: ModuleKind,
+ normal_ancestor_id: DefId,
+ span: Span) -> Self {
ModuleData {
parent: parent,
kind: kind,
globs: RefCell::new((Vec::new())),
traits: RefCell::new(None),
populated: Cell::new(normal_ancestor_id.is_local()),
+ span: span,
}
}
let namespace = if is_value { ValueNS } else { TypeNS };
let hir::Path { ref segments, span, ref mut def } = *path;
let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect();
- match self.resolve_path(&path, Some(namespace), Some(span)) {
+ match self.resolve_path(&path, Some(namespace), true, span) {
PathResult::Module(module) => *def = module.def().unwrap(),
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
*def = path_res.base_def(),
- PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) {
+ PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) {
PathResult::Failed(msg, _) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
}
let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name());
let graph_root = arenas.alloc_module(ModuleData {
no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
- ..ModuleData::new(None, root_module_kind, root_def_id)
+ ..ModuleData::new(None, root_module_kind, root_def_id, krate.span)
});
let mut module_map = FxHashMap();
module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
self.crate_loader.postprocess(krate);
}
- fn new_module(&self, parent: Module<'a>, kind: ModuleKind, normal_ancestor_id: DefId)
- -> Module<'a> {
- self.arenas.alloc_module(ModuleData::new(Some(parent), kind, normal_ancestor_id))
+ fn new_module(
+ &self,
+ parent: Module<'a>,
+ kind: ModuleKind,
+ normal_ancestor_id: DefId,
+ span: Span,
+ ) -> Module<'a> {
+ self.arenas.alloc_module(ModuleData::new(Some(parent), kind, normal_ancestor_id, span))
}
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
fn resolve_ident_in_lexical_scope(&mut self,
mut ident: Ident,
ns: Namespace,
- record_used: Option<Span>)
+ record_used: bool,
+ path_span: Span)
-> Option<LexicalScopeBinding<'a>> {
if ns == TypeNS {
ident = ident.unhygienize();
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
// The ident resolves to a type parameter or local variable.
return Some(LexicalScopeBinding::Def(
- self.adjust_local_def(ns, i, def, record_used)
+ self.adjust_local_def(ns, i, def, record_used, path_span)
));
}
if let ModuleRibKind(module) = self.ribs[ns][i].kind {
- let item = self.resolve_ident_in_module(module, ident, ns, false, record_used);
+ let item = self.resolve_ident_in_module(module, ident, ns, false,
+ record_used, path_span);
if let Ok(binding) = item {
// The ident resolves to an item.
return Some(LexicalScopeBinding::Item(binding));
if let ModuleKind::Block(..) = module.kind { // We can see through blocks
} else if !module.no_implicit_prelude {
return self.prelude.and_then(|prelude| {
- self.resolve_ident_in_module(prelude, ident, ns, false, None).ok()
+ self.resolve_ident_in_module(prelude, ident, ns, false,
+ false, path_span).ok()
}).map(LexicalScopeBinding::Item)
} else {
return None;
None
}
- fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext) -> Module<'a> {
+ fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext, span: Span) -> Module<'a> {
let mut ctxt_data = crate_var_ctxt.data();
while ctxt_data.prev_ctxt != SyntaxContext::empty() {
ctxt_data = ctxt_data.prev_ctxt.data();
}
- let module = self.macro_def_scope(ctxt_data.outer_mark);
+ let module = self.macro_def_scope(ctxt_data.outer_mark, span);
if module.is_local() { self.graph_root } else { module }
}
this.check_proc_macro_attrs(&trait_item.attrs);
match trait_item.node {
- TraitItemKind::Const(_, ref default) => {
+ TraitItemKind::Const(ref ty, ref default) => {
+ this.visit_ty(ty);
+
// Only impose the restrictions of
- // ConstRibKind if there's an actual constant
+ // ConstRibKind for an actual constant
// expression in a provided default.
- if default.is_some() {
+ if let Some(ref expr) = *default{
this.with_constant_rib(|this| {
- visit::walk_trait_item(this, trait_item)
+ this.visit_expr(expr);
});
- } else {
- visit::walk_trait_item(this, trait_item)
}
}
TraitItemKind::Method(ref sig, _) => {
});
}
- ItemKind::Const(..) | ItemKind::Static(..) => {
- self.with_constant_rib(|this| {
- visit::walk_item(this, item);
+ ItemKind::Static(ref ty, _, ref expr) |
+ ItemKind::Const(ref ty, ref expr) => {
+ self.with_item_rib(|this| {
+ this.visit_ty(ty);
+ this.with_constant_rib(|this| {
+ this.visit_expr(expr);
+ });
});
}
self.label_ribs.pop();
}
+ fn with_item_rib<F>(&mut self, f: F)
+ where F: FnOnce(&mut Resolver)
+ {
+ self.ribs[ValueNS].push(Rib::new(ItemRibKind));
+ self.ribs[TypeNS].push(Rib::new(ItemRibKind));
+ f(self);
+ self.ribs[TypeNS].pop();
+ self.ribs[ValueNS].pop();
+ }
+
fn with_constant_rib<F>(&mut self, f: F)
where F: FnOnce(&mut Resolver)
{
self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
- self.ribs[TypeNS].push(Rib::new(ConstantItemRibKind));
f(self);
- self.ribs[TypeNS].pop();
self.ribs[ValueNS].pop();
}
PatKind::Ident(bmode, ref ident, ref opt_pat) => {
// First try to resolve the identifier as some existing
// entity, then fall back to a fresh binding.
- let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, None)
+ let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS,
+ false, pat.span)
.and_then(LexicalScopeBinding::item);
let resolution = binding.map(NameBinding::def).and_then(|def| {
let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
(format!(""), format!("the crate root"))
} else {
let mod_path = &path[..path.len() - 1];
- let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), None) {
+ let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), false, span) {
PathResult::Module(module) => module.def(),
_ => None,
}.map_or(format!(""), |def| format!("{} ", def.kind_name()));
let name = path.last().unwrap().name;
let candidates = this.lookup_import_candidates(name, ns, is_expected);
if !candidates.is_empty() {
+ let mut module_span = this.current_module.span;
+ module_span.hi = module_span.lo;
// Report import candidates as help and proceed searching for labels.
- show_candidates(&mut err, &candidates, def.is_some());
+ show_candidates(&mut err, module_span, &candidates, def.is_some());
} else if is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
let enum_candidates = this.lookup_import_candidates(name, ns, is_enum_variant);
let mut enum_candidates = enum_candidates.iter()
}
}
}
- if path.len() == 1 && this.self_type_is_available() {
+ if path.len() == 1 && this.self_type_is_available(span) {
if let Some(candidate) = this.lookup_assoc_candidate(name, ns, is_expected) {
- let self_is_available = this.self_value_is_available(path[0].ctxt);
+ let self_is_available = this.self_value_is_available(path[0].ctxt, span);
match candidate {
AssocSuggestion::Field => {
err.span_label(span, format!("did you mean `self.{}`?", path_str));
let mut levenshtein_worked = false;
// Try Levenshtein.
- if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) {
+ if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected, span) {
err.span_label(ident_span, format!("did you mean `{}`?", candidate));
levenshtein_worked = true;
}
resolution
}
- fn self_type_is_available(&mut self) -> bool {
- let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(), TypeNS, None);
+ fn self_type_is_available(&mut self, span: Span) -> bool {
+ let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(),
+ TypeNS, false, span);
if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
}
- fn self_value_is_available(&mut self, ctxt: SyntaxContext) -> bool {
+ fn self_value_is_available(&mut self, ctxt: SyntaxContext, span: Span) -> bool {
let ident = Ident { name: keywords::SelfValue.name(), ctxt: ctxt };
- let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None);
+ let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, span);
if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
}
));
}
- let result = match self.resolve_path(&path, Some(ns), Some(span)) {
+ let result = match self.resolve_path(&path, Some(ns), true, span) {
PathResult::NonModule(path_res) => path_res,
PathResult::Module(module) if !module.is_normal() => {
PathResolution::new(module.def().unwrap())
if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" {
let unqualified_result = {
- match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
+ match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) {
PathResult::NonModule(path_res) => path_res.base_def(),
PathResult::Module(module) => module.def().unwrap(),
_ => return Some(result),
fn resolve_path(&mut self,
path: &[Ident],
opt_ns: Option<Namespace>, // `None` indicates a module path
- record_used: Option<Span>)
+ record_used: bool,
+ path_span: Span)
-> PathResult<'a> {
let mut module = None;
let mut allow_super = true;
module = Some(self.graph_root);
continue
} else if i == 0 && ns == TypeNS && ident.name == "$crate" {
- module = Some(self.resolve_crate_var(ident.ctxt));
+ module = Some(self.resolve_crate_var(ident.ctxt, path_span));
continue
}
let binding = if let Some(module) = module {
- self.resolve_ident_in_module(module, ident, ns, false, record_used)
+ self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span)
} else if opt_ns == Some(MacroNS) {
- self.resolve_lexical_macro_path_segment(ident, ns, record_used)
+ self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span)
.map(MacroBinding::binding)
} else {
- match self.resolve_ident_in_lexical_scope(ident, ns, record_used) {
+ match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) {
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
Some(LexicalScopeBinding::Def(def))
if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
def, path.len() - 1
));
}
- _ => Err(if record_used.is_some() { Determined } else { Undetermined }),
+ _ => Err(if record_used { Determined } else { Undetermined }),
}
};
ns: Namespace,
rib_index: usize,
mut def: Def,
- record_used: Option<Span>) -> Def {
+ record_used: bool,
+ span: Span) -> Def {
let ribs = &self.ribs[ns][rib_index + 1..];
// An invalid forward use of a type parameter from a previous default.
if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind {
- if let Some(span) = record_used {
+ if record_used {
resolve_error(self, span,
ResolutionError::ForwardDeclaredTyParam);
}
match def {
Def::Upvar(..) => {
- span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def)
+ span_bug!(span, "unexpected {:?} in bindings", def)
}
Def::Local(def_id) => {
for rib in ribs {
let depth = vec.len();
def = Def::Upvar(def_id, depth, function_id);
- if let Some(span) = record_used {
+ if record_used {
vec.push(Freevar {
def: prev_def,
span: span,
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
// report an error.
- if let Some(span) = record_used {
+ if record_used {
resolve_error(self, span,
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
}
}
ConstantItemRibKind => {
// Still doesn't deal with upvars
- if let Some(span) = record_used {
+ if record_used {
resolve_error(self, span,
ResolutionError::AttemptToUseNonConstantValueInConstant);
}
for rib in ribs {
match rib.kind {
NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
- ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind => {
+ ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
+ ConstantItemRibKind => {
// Nothing to do. Continue.
}
ItemRibKind => {
// This was an attempt to use a type parameter outside
// its scope.
- if let Some(span) = record_used {
+ if record_used {
resolve_error(self, span,
ResolutionError::TypeParametersFromOuterFunction);
}
return Def::Err;
}
- ConstantItemRibKind => {
- // see #9186
- if let Some(span) = record_used {
- resolve_error(self, span,
- ResolutionError::OuterTypeParameterContext);
- }
- return Def::Err;
- }
}
}
}
fn lookup_typo_candidate<FilterFn>(&mut self,
path: &[Ident],
ns: Namespace,
- filter_fn: FilterFn)
+ filter_fn: FilterFn,
+ span: Span)
-> Option<Symbol>
where FilterFn: Fn(Def) -> bool
{
} else {
// Search in module.
let mod_path = &path[..path.len() - 1];
- if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) {
+ if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS),
+ false, span) {
add_module_candidates(module, &mut names);
}
}
continue
}
let ident = attr.path.segments[0].identifier;
- let result = self.resolve_lexical_macro_path_segment(ident, MacroNS, None);
+ let result = self.resolve_lexical_macro_path_segment(ident,
+ MacroNS,
+ false,
+ attr.path.span);
if let Ok(binding) = result {
if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) {
attr::mark_known(attr);
/// When an entity with a given name is not available in scope, we search for
/// entities with that name in all crates. This method allows outputting the
/// results of this search in a programmer-friendly way
-fn show_candidates(session: &mut DiagnosticBuilder,
+fn show_candidates(err: &mut DiagnosticBuilder,
+ span: Span,
candidates: &[ImportSuggestion],
better: bool) {
- // don't show more than MAX_CANDIDATES results, so
- // we're consistent with the trait suggestions
- const MAX_CANDIDATES: usize = 4;
// we want consistent results across executions, but candidates are produced
// by iterating through a hash map, so make sure they are ordered:
1 => " is found in another module, you can import it",
_ => "s are found in other modules, you can import them",
};
+ let msg = format!("possible {}candidate{} into scope", better, msg_diff);
+
+ for candidate in &mut path_strings {
+ *candidate = format!("use {};\n", candidate);
+ }
- let end = cmp::min(MAX_CANDIDATES, path_strings.len());
- session.help(&format!("possible {}candidate{} into scope:{}{}",
- better,
- msg_diff,
- &path_strings[0..end].iter().map(|candidate| {
- format!("\n `use {};`", candidate)
- }).collect::<String>(),
- if path_strings.len() > MAX_CANDIDATES {
- format!("\nand {} other candidates",
- path_strings.len() - MAX_CANDIDATES)
- } else {
- "".to_owned()
- }
- ));
+ err.span_suggestions(span, &msg, path_strings);
}
/// A somewhat inefficient routine to obtain the name of a module.
}
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
- struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>);
+ struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>, Span);
impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
let ident = path.segments[0].identifier;
if ident.name == "$crate" {
path.segments[0].identifier.name = keywords::CrateRoot.name();
- let module = self.0.resolve_crate_var(ident.ctxt);
+ let module = self.0.resolve_crate_var(ident.ctxt, self.1);
if !module.is_local() {
let span = path.segments[0].span;
path.segments.insert(1, match module.kind {
}
}
- EliminateCrateVar(self).fold_item(item).expect_one("")
+ EliminateCrateVar(self, item.span).fold_item(item).expect_one("")
}
fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool {
return Err(Determinacy::Determined);
}
- let def = match self.resolve_path(&path, Some(MacroNS), None) {
+ let def = match self.resolve_path(&path, Some(MacroNS), false, span) {
PathResult::NonModule(path_res) => match path_res.base_def() {
Def::Err => Err(Determinacy::Determined),
def @ _ => Ok(def),
let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution {
Ok(Def::Macro(binding.def_id, MacroKind::Bang))
} else {
- match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) {
+ match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, span) {
Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()),
Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined),
Err(_) => {
pub fn resolve_lexical_macro_path_segment(&mut self,
ident: Ident,
ns: Namespace,
- record_used: Option<Span>)
+ record_used: bool,
+ path_span: Span)
-> Result<MacroBinding<'a>, Determinacy> {
let mut module = Some(self.current_module);
let mut potential_illegal_shadower = Err(Determinacy::Determined);
let determinacy =
- if record_used.is_some() { Determinacy::Determined } else { Determinacy::Undetermined };
+ if record_used { Determinacy::Determined } else { Determinacy::Undetermined };
loop {
let result = if let Some(module) = module {
// Since expanded macros may not shadow the lexical scope and
// globs may not shadow global macros (both enforced below),
// we resolve with restricted shadowing (indicated by the penultimate argument).
- self.resolve_ident_in_module(module, ident, ns, true, record_used)
+ self.resolve_ident_in_module(module, ident, ns, true, record_used, path_span)
.map(MacroBinding::Modern)
} else {
self.global_macros.get(&ident.name).cloned().ok_or(determinacy)
match result.map(MacroBinding::binding) {
Ok(binding) => {
- let span = match record_used {
- Some(span) => span,
- None => return result,
- };
+ if !record_used {
+ return result;
+ }
if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower {
if shadower.def() != binding.def() {
let name = ident.name;
self.ambiguity_errors.push(AmbiguityError {
- span: span, name: name, b1: shadower, b2: binding, lexical: true,
+ span: path_span,
+ name: name,
+ b1: shadower,
+ b2: binding,
+ lexical: true,
legacy: false,
});
return potential_illegal_shadower;
pub fn finalize_current_module_macro_resolutions(&mut self) {
let module = self.current_module;
for &(ref path, span) in module.macro_resolutions.borrow().iter() {
- match self.resolve_path(path, Some(MacroNS), Some(span)) {
+ match self.resolve_path(path, Some(MacroNS), true, span) {
PathResult::NonModule(_) => {},
PathResult::Failed(msg, _) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
for &(mark, ident, span, kind) in module.legacy_macro_resolutions.borrow().iter() {
let legacy_scope = &self.invocations[&mark].legacy_scope;
let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true);
- let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span));
+ let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, span);
match (legacy_resolution, resolution) {
(Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
let msg1 = format!("`{}` could refer to the macro defined here", ident);
format!("cannot find derive macro `{}` in this scope", ident),
};
let mut err = self.session.struct_span_err(span, &msg);
- self.suggest_macro_name(&ident.name.as_str(), kind, &mut err);
+ self.suggest_macro_name(&ident.name.as_str(), kind, &mut err, span);
err.emit();
},
_ => {},
}
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
- err: &mut DiagnosticBuilder<'a>) {
+ err: &mut DiagnosticBuilder<'a>, span: Span) {
// First check if this is a locally-defined bang macro.
let suggestion = if let MacroKind::Bang = kind {
find_best_match_for_name(self.macro_names.iter(), name, None)
}
};
let ident = Ident::from_str(name);
- self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
+ self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro, span)
});
if let Some(suggestion) = suggestion {
ident: Ident,
ns: Namespace,
restricted_shadowing: bool,
- record_used: Option<Span>)
+ record_used: bool,
+ path_span: Span)
-> Result<&'a NameBinding<'a>, Determinacy> {
self.populate_module_if_necessary(module);
.try_borrow_mut()
.map_err(|_| Determined)?; // This happens when there is a cycle of imports
- if let Some(span) = record_used {
+ if record_used {
if let Some(binding) = resolution.binding {
if let Some(shadowed_glob) = resolution.shadows_glob {
let name = ident.name;
ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing
binding.def() != shadowed_glob.def() {
self.ambiguity_errors.push(AmbiguityError {
- span: span, name: name, lexical: false, b1: binding, b2: shadowed_glob,
+ span: path_span,
+ name: name,
+ lexical: false,
+ b1: binding,
+ b2: shadowed_glob,
legacy: false,
});
}
}
- if self.record_use(ident, ns, binding, span) {
+ if self.record_use(ident, ns, binding, path_span) {
return Ok(self.dummy_binding);
}
if !self.is_accessible(binding.vis) {
- self.privacy_errors.push(PrivacyError(span, ident.name, binding));
+ self.privacy_errors.push(PrivacyError(path_span, ident.name, binding));
}
}
SingleImport { source, .. } => source,
_ => unreachable!(),
};
- match self.resolve_ident_in_module(module, ident, ns, false, None) {
+ match self.resolve_ident_in_module(module, ident, ns, false, false, path_span) {
Err(Determined) => {}
_ => return Err(Undetermined),
}
for directive in module.globs.borrow().iter() {
if self.is_accessible(directive.vis.get()) {
if let Some(module) = directive.imported_module.get() {
- let result = self.resolve_ident_in_module(module, ident, ns, false, None);
+ let result = self.resolve_ident_in_module(module,
+ ident,
+ ns,
+ false,
+ false,
+ path_span);
if let Err(Undetermined) = result {
return Err(Undetermined);
}
// For better failure detection, pretend that the import will not define any names
// while resolving its module path.
directive.vis.set(ty::Visibility::Invisible);
- let result = self.resolve_path(&directive.module_path, None, None);
+ let result = self.resolve_path(&directive.module_path, None, false, directive.span);
directive.vis.set(vis);
match result {
let mut indeterminate = false;
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
if let Err(Undetermined) = result[ns].get() {
- result[ns].set(this.resolve_ident_in_module(module, source, ns, false, None));
+ result[ns].set(this.resolve_ident_in_module(module,
+ source,
+ ns,
+ false,
+ false,
+ directive.span));
} else {
return
};
self.current_module = directive.parent;
let ImportDirective { ref module_path, span, .. } = *directive;
- let module_result = self.resolve_path(&module_path, None, Some(span));
+ let module_result = self.resolve_path(&module_path, None, true, span);
let module = match module_result {
PathResult::Module(module) => module,
PathResult::Failed(msg, _) => {
let (mut self_path, mut self_result) = (module_path.clone(), None);
if !self_path.is_empty() && !token::Ident(self_path[0]).is_path_segment_keyword() {
self_path[0].name = keywords::SelfValue.name();
- self_result = Some(self.resolve_path(&self_path, None, None));
+ self_result = Some(self.resolve_path(&self_path, None, false, span));
}
return if let Some(PathResult::Module(..)) = self_result {
Some(format!("Did you mean `{}`?", names_to_string(&self_path)))
Some(this.dummy_binding);
}
}
- } else if let Ok(binding) = this.resolve_ident_in_module(module, ident, ns, false, None) {
+ } else if let Ok(binding) = this.resolve_ident_in_module(module,
+ ident,
+ ns,
+ false,
+ false,
+ directive.span) {
legacy_self_import = Some(directive);
let binding = this.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Import {
}
let mut all_ns_failed = true;
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
- match this.resolve_ident_in_module(module, ident, ns, false, Some(span)) {
+ match this.resolve_ident_in_module(module, ident, ns, false, true, span) {
Ok(_) => all_ns_failed = false,
_ => {}
}
pub items: Vec<NodeId>,
pub visibility: Visibility,
pub docs: String,
- pub sig: Signature,
+ pub sig: Option<Signature>,
pub attributes: Vec<Attribute>,
}
}
impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, D> {
+ fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], id: NodeId) {
+ // Since we handle explicit modules ourselves in visit_item, this should
+ // only get called for the root module of a crate.
+ assert_eq!(id, ast::CRATE_NODE_ID);
+
+ let qualname = format!("::{}", self.tcx.node_path_str(id));
+
+ let cm = self.tcx.sess.codemap();
+ let filename = cm.span_to_filename(span);
+ self.dumper.mod_data(ModData {
+ id: id,
+ name: String::new(),
+ qualname: qualname,
+ span: span,
+ scope: id,
+ filename: filename,
+ items: m.items.iter().map(|i| i.id).collect(),
+ visibility: Visibility::Public,
+ docs: docs_for_attrs(attrs),
+ sig: None,
+ attributes: attrs.to_owned(),
+ }.lower(self.tcx));
+ self.nest_scope(id, |v| visit::walk_mod(v, m));
+ }
+
fn visit_item(&mut self, item: &'l ast::Item) {
use syntax::ast::ItemKind::*;
self.process_macro_use(item.span, item.id);
pub items: Vec<DefId>,
pub visibility: Visibility,
pub docs: String,
- pub sig: Signature,
+ pub sig: Option<Signature>,
pub attributes: Vec<Attribute>,
}
items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(),
visibility: self.visibility,
docs: self.docs,
- sig: self.sig.lower(tcx),
+ sig: self.sig.map(|s| s.lower(tcx)),
attributes: self.attributes.lower(tcx),
}
}
parent: None,
decl_id: None,
docs: self.docs,
- sig: Some(self.sig.into()),
+ sig: self.sig.map(|s| s.into()),
attributes: vec![],
}),
_ => None,
children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(),
decl_id: None,
docs: data.docs,
- sig: Some(data.sig.into()),
+ sig: data.sig.map(|s| s.into()),
attributes: data.attributes.into_iter().map(|a| a.into()).collect(),
};
if def.span.file_name.to_str().unwrap() != def.value {
// except according to those terms.
#![crate_name = "rustc_save_analysis"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(custom_attribute)]
#![allow(unused_attributes)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use] extern crate rustc;
items: m.items.iter().map(|i| i.id).collect(),
visibility: From::from(&item.vis),
docs: docs_for_attrs(&item.attrs),
- sig: self.sig_base(item),
+ sig: Some(self.sig_base(item)),
attributes: item.attrs.clone(),
}))
}
[dependencies]
flate = { path = "../libflate" }
log = "0.3"
+owning_ref = "0.3.3"
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_bitflags = { path = "../librustc_bitflags" }
use libc;
use llvm::archive_ro::{ArchiveRO, Child};
use llvm::{self, ArchiveKind};
+use metadata::METADATA_FILENAME;
use rustc::session::Session;
pub struct ArchiveConfig<'a> {
// Ignoring all bytecode files, no matter of
// name
let bc_ext = ".bytecode.deflate";
- let metadata_filename =
- self.config.sess.cstore.metadata_filename().to_owned();
self.add_archive(rlib, move |fname: &str| {
- if fname.ends_with(bc_ext) || fname == metadata_filename {
+ if fname.ends_with(bc_ext) || fname == METADATA_FILENAME {
return true
}
use super::rpath::RPathConfig;
use super::rpath;
use super::msvc;
+use metadata::METADATA_FILENAME;
use session::config;
use session::config::NoDebugInfo;
use session::config::{OutputFilenames, Input, OutputType};
// contain the metadata in a separate file. We use a temp directory
// here so concurrent builds in the same directory don't try to use
// the same filename for metadata (stomping over one another)
- let metadata = tmpdir.join(sess.cstore.metadata_filename());
+ let metadata = tmpdir.join(METADATA_FILENAME);
emit_metadata(sess, trans, &metadata);
ab.add_file(&metadata);
archive.update_symbols();
for f in archive.src_files() {
- if f.ends_with("bytecode.deflate") ||
- f == sess.cstore.metadata_filename() {
+ if f.ends_with("bytecode.deflate") || f == METADATA_FILENAME {
archive.remove_file(&f);
continue
}
let mut any_objects = false;
for f in archive.src_files() {
- if f.ends_with("bytecode.deflate") ||
- f == sess.cstore.metadata_filename() {
+ if f.ends_with("bytecode.deflate") || f == METADATA_FILENAME {
archive.remove_file(&f);
continue
}
//! comments can also be found below leading through the various code paths.
// A simple macro to make this option mess easier to read
+#[cfg(windows)]
macro_rules! otry {
($expr:expr) => (match $expr {
Some(val) => val,
use back::symbol_export::{self, ExportedSymbols};
use llvm::{ContextRef, Linkage, ModuleRef, ValueRef, Vector, get_param};
use llvm;
+use metadata;
use rustc::hir::def_id::LOCAL_CRATE;
use middle::lang_items::StartFnLangItem;
use middle::cstore::EncodedMetadata;
};
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
- let section_name =
- tcx.sess.cstore.metadata_section_name(&tcx.sess.target.target);
+ let section_name = metadata::metadata_section_name(&tcx.sess.target.target);
let name = CString::new(section_name).unwrap();
llvm::LLVMSetSection(llglobal, name.as_ptr());
if is_inline_instance(tcx, instance) {
return true
}
+ if let ty::InstanceDef::DropGlue(..) = instance.def {
+ // Drop glue wants to be instantiated at every translation
+ // unit, but without an #[inline] hint. We should make this
+ // available to normal end-users.
+ return true
+ }
attr::requests_inline(&instance.def.attrs(tcx)[..])
}
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_trans"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(slice_patterns)]
-#![feature(staged_api)]
#![feature(unicode)]
#![feature(conservative_impl_trait)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::Symbol;
extern crate flate;
extern crate libc;
+extern crate owning_ref;
#[macro_use] extern crate rustc;
extern crate rustc_back;
extern crate rustc_data_structures;
pub use base::trans_crate;
pub use back::symbol_names::provide;
+pub use metadata::LlvmMetadataLoader;
+pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug};
+
pub mod back {
pub use rustc::hir::svh;
pub mod diagnostics;
-#[macro_use]
-mod macros;
-
mod abi;
mod adt;
mod asm;
mod declare;
mod glue;
mod intrinsic;
+mod llvm_util;
mod machine;
+mod metadata;
mod meth;
mod mir;
mod monomorphize;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use syntax_pos::symbol::Symbol;
+use back::write::create_target_machine;
+use llvm;
+use rustc::session::Session;
+use rustc::session::config::PrintRequest;
+use libc::{c_int, c_char};
+use std::ffi::CString;
+
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::Once;
+
+pub fn init(sess: &Session) {
+ unsafe {
+ // Before we touch LLVM, make sure that multithreading is enabled.
+ static POISONED: AtomicBool = AtomicBool::new(false);
+ static INIT: Once = Once::new();
+ INIT.call_once(|| {
+ if llvm::LLVMStartMultithreaded() != 1 {
+ // use an extra bool to make sure that all future usage of LLVM
+ // cannot proceed despite the Once not running more than once.
+ POISONED.store(true, Ordering::SeqCst);
+ }
+
+ configure_llvm(sess);
+ });
+
+ if POISONED.load(Ordering::SeqCst) {
+ bug!("couldn't enable multi-threaded LLVM");
+ }
+ }
+}
+
+unsafe fn configure_llvm(sess: &Session) {
+ let mut llvm_c_strs = Vec::new();
+ let mut llvm_args = Vec::new();
+
+ {
+ let mut add = |arg: &str| {
+ let s = CString::new(arg).unwrap();
+ llvm_args.push(s.as_ptr());
+ llvm_c_strs.push(s);
+ };
+ add("rustc"); // fake program name
+ if sess.time_llvm_passes() { add("-time-passes"); }
+ if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
+
+ for arg in &sess.opts.cg.llvm_args {
+ add(&(*arg));
+ }
+ }
+
+ llvm::LLVMInitializePasses();
+
+ llvm::initialize_available_targets();
+
+ llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
+ llvm_args.as_ptr());
+}
+
+// WARNING: the features must be known to LLVM or the feature
+// detection code will walk past the end of the feature array,
+// leading to crashes.
+
+const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"];
+
+const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
+ "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
+ "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
+ "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"];
+
+const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];
+
+pub fn target_features(sess: &Session) -> Vec<Symbol> {
+ let target_machine = create_target_machine(sess);
+
+ let whitelist = match &*sess.target.target.arch {
+ "arm" => ARM_WHITELIST,
+ "x86" | "x86_64" => X86_WHITELIST,
+ "hexagon" => HEXAGON_WHITELIST,
+ _ => &[],
+ };
+
+ let mut features = Vec::new();
+ for feat in whitelist {
+ assert_eq!(feat.chars().last(), Some('\0'));
+ if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
+ features.push(Symbol::intern(&feat[..feat.len() - 1]));
+ }
+ }
+ features
+}
+
+pub fn print_version() {
+ unsafe {
+ println!("LLVM version: {}.{}",
+ llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
+ }
+}
+
+pub fn print_passes() {
+ unsafe { llvm::LLVMRustPrintPasses(); }
+}
+
+pub fn print(req: PrintRequest, sess: &Session) {
+ let tm = create_target_machine(sess);
+ unsafe {
+ match req {
+ PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
+ PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
+ _ => bug!("rustc_trans can't handle print request: {:?}", req),
+ }
+ }
+}
+
+pub fn enable_llvm_debug() {
+ unsafe { llvm::LLVMRustSetDebug(1); }
+}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-macro_rules! unpack_datum {
- ($bcx: ident, $inp: expr) => (
- {
- let db = $inp;
- $bcx = db.bcx;
- db.datum
- }
- )
-}
-
-macro_rules! unpack_result {
- ($bcx: ident, $inp: expr) => (
- {
- let db = $inp;
- $bcx = db.bcx;
- db.val
- }
- )
-}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::util::common;
+use rustc::middle::cstore::MetadataLoader;
+use rustc_back::target::Target;
+use llvm;
+use llvm::{False, ObjectFile, mk_section_iter};
+use llvm::archive_ro::ArchiveRO;
+
+use owning_ref::{ErasedBoxRef, OwningRef};
+use std::path::Path;
+use std::ptr;
+use std::slice;
+
+pub const METADATA_FILENAME: &str = "rust.metadata.bin";
+
+pub struct LlvmMetadataLoader;
+
+impl MetadataLoader for LlvmMetadataLoader {
+ fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
+ // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
+ // internally to read the file. We also avoid even using a memcpy by
+ // just keeping the archive along while the metadata is in use.
+ let archive = ArchiveRO::open(filename)
+ .map(|ar| OwningRef::new(box ar))
+ .ok_or_else(|| {
+ debug!("llvm didn't like `{}`", filename.display());
+ format!("failed to read rlib metadata: '{}'", filename.display())
+ })?;
+ let buf: OwningRef<_, [u8]> = archive
+ .try_map(|ar| {
+ ar.iter()
+ .filter_map(|s| s.ok())
+ .find(|sect| sect.name() == Some(METADATA_FILENAME))
+ .map(|s| s.data())
+ .ok_or_else(|| {
+ debug!("didn't find '{}' in the archive", METADATA_FILENAME);
+ format!("failed to read rlib metadata: '{}'",
+ filename.display())
+ })
+ })?;
+ Ok(buf.erase_owner())
+ }
+
+ fn get_dylib_metadata(&self,
+ target: &Target,
+ filename: &Path)
+ -> Result<ErasedBoxRef<[u8]>, String> {
+ unsafe {
+ let buf = common::path2cstr(filename);
+ let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
+ if mb as isize == 0 {
+ return Err(format!("error reading library: '{}'", filename.display()));
+ }
+ let of = ObjectFile::new(mb)
+ .map(|of| OwningRef::new(box of))
+ .ok_or_else(|| format!("provided path not an object file: '{}'",
+ filename.display()))?;
+ let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
+ Ok(buf.erase_owner())
+ }
+ }
+}
+
+fn search_meta_section<'a>(of: &'a ObjectFile,
+ target: &Target,
+ filename: &Path)
+ -> Result<&'a [u8], String> {
+ unsafe {
+ let si = mk_section_iter(of.llof);
+ while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
+ let mut name_buf = ptr::null();
+ let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
+ let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
+ let name = String::from_utf8(name).unwrap();
+ debug!("get_metadata_section: name {}", name);
+ if read_metadata_section_name(target) == name {
+ let cbuf = llvm::LLVMGetSectionContents(si.llsi);
+ let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
+ // The buffer is valid while the object file is around
+ let buf: &'a [u8] = slice::from_raw_parts(cbuf as *const u8, csz);
+ return Ok(buf);
+ }
+ llvm::LLVMMoveToNextSection(si.llsi);
+ }
+ }
+ Err(format!("metadata not found: '{}'", filename.display()))
+}
+
+pub fn metadata_section_name(target: &Target) -> &'static str {
+ // Historical note:
+ //
+ // When using link.exe it was seen that the section name `.note.rustc`
+ // was getting shortened to `.note.ru`, and according to the PE and COFF
+ // specification:
+ //
+ // > Executable images do not use a string table and do not support
+ // > section names longer than 8 characters
+ //
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
+ //
+ // As a result, we choose a slightly shorter name! As to why
+ // `.note.rustc` works on MinGW, that's another good question...
+
+ if target.options.is_like_osx {
+ "__DATA,.rustc"
+ } else {
+ ".rustc"
+ }
+}
+
+fn read_metadata_section_name(_target: &Target) -> &'static str {
+ ".rustc"
+}
location: Location) {
match *kind {
mir::TerminatorKind::Call {
- func: mir::Operand::Constant(mir::Constant {
+ func: mir::Operand::Constant(box mir::Constant {
literal: Literal::Value {
value: ConstVal::Function(def_id, _), ..
}, ..
Value(base));
}
if projected_ty.is_bool() {
- unsafe {
- val = llvm::LLVMConstTrunc(val, Type::i1(self.ccx).to_ref());
+ let i1_type = Type::i1(self.ccx);
+ if val_ty(val) != i1_type {
+ unsafe {
+ val = llvm::LLVMConstTrunc(val, i1_type.to_ref());
+ }
}
}
(Base::Value(val), extra)
}
failure?;
- match *kind {
+ match **kind {
mir::AggregateKind::Array(_) => {
self.const_array(dest_ty, &fields)
}
}
mir::Rvalue::Aggregate(ref kind, ref operands) => {
- match *kind {
+ match **kind {
mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => {
let discr = adt_def.discriminant_for_variant(bcx.tcx(), variant_index)
.to_u128_unchecked() as u64;
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
-> ty::GenericPredicates<'tcx>;
- /// Return an (optional) substitution to convert bound type parameters that
- /// are in scope into free ones. This function should only return Some
- /// within a fn body.
- /// See ParameterEnvironment::free_substs for more information.
- fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
-
/// What lifetime should we use when a lifetime is omitted (and not elided)?
fn re_infer(&self, span: Span, _def: Option<&ty::RegionParameterDef>)
-> Option<ty::Region<'tcx>>;
Some(&rl::Region::EarlyBound(index, id)) => {
let name = tcx.hir.name(id);
tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+ def_id: tcx.hir.local_def_id(id),
index: index,
name: name
}))
Some(&rl::Region::Free(scope, id)) => {
let name = tcx.hir.name(id);
tcx.mk_region(ty::ReFree(ty::FreeRegion {
- scope: Some(scope.to_code_extent(tcx)),
+ scope,
bound_region: ty::BrNamed(tcx.hir.local_def_id(id), name)
}))
}
};
- let trait_ref = if let Some(free_substs) = self.get_free_substs() {
- trait_ref.subst(tcx, free_substs)
- } else {
- trait_ref
- };
-
let candidates =
traits::supertraits(tcx, ty::Binder(trait_ref))
.filter(|r| self.trait_defines_associated_type_named(r.def_id(),
assert_eq!(opt_self_ty, None);
self.prohibit_type_params(&path.segments);
- let ty = tcx.at(span).type_of(def_id);
- if let Some(free_substs) = self.get_free_substs() {
- ty.subst(tcx, free_substs)
- } else {
- ty
- }
+ tcx.at(span).type_of(def_id)
}
Def::SelfTy(Some(_), None) => {
// Self in trait.
use astconv::AstConv;
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::ty::{self, ToPolyTraitRef, Ty};
+use rustc::ty::subst::Substs;
use std::cmp;
use std::iter;
use syntax::abi::Abi;
decl,
Abi::RustCall,
expected_sig);
+ // `deduce_expectations_from_expected_type` introduces late-bound
+ // lifetimes defined elsewhere, which we need to anonymize away.
+ let sig = self.tcx.anonymize_late_bound_regions(&sig);
// Create type variables (for now) to represent the transformed
// types of upvars. These will be unified during the upvar
// inference phase (`upvar.rs`).
+ let base_substs = Substs::identity_for_item(self.tcx,
+ self.tcx.closure_base_def_id(expr_def_id));
let closure_type = self.tcx.mk_closure(expr_def_id,
- self.parameter_environment.free_substs.extend_to(self.tcx, expr_def_id,
+ base_substs.extend_to(self.tcx, expr_def_id,
|_, _| span_bug!(expr.span, "closure has region param"),
|_, _| self.infcx.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
)
debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
- let extent = self.tcx.call_site_extent(expr.id, body.value.id);
- let fn_sig = self.tcx.liberate_late_bound_regions(Some(extent), &sig);
+ let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
body.value.id, &fn_sig);
// Create a parameter environment that represents the implementation's
// method.
- let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_m_node_id);
+ let impl_param_env = tcx.parameter_environment(impl_m.def_id);
// Create mapping from impl to skolemized.
- let impl_to_skol_substs = &impl_param_env.free_substs;
+ let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
// Create mapping from trait to skolemized.
let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
impl_m.container.id(),
- trait_to_impl_substs.subst(tcx,
- impl_to_skol_substs));
+ trait_to_impl_substs);
debug!("compare_impl_method: trait_to_skol_substs={:?}",
trait_to_skol_substs);
impl_m,
&trait_m_generics,
&impl_m_generics,
- trait_to_skol_substs,
- impl_to_skol_substs)?;
+ trait_to_skol_substs)?;
// Create obligations for each predicate declared by the impl
// definition in the context of the trait's parameter
// however, because we want to replace all late-bound regions with
// region variables.
let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap());
- let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
+ let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
normalize_cause.clone());
tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
- let inh = Inherited::new(infcx);
+ let inh = Inherited::new(infcx, impl_m.def_id);
let infcx = &inh.infcx;
debug!("compare_impl_method: caller_bounds={:?}",
infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
infer::HigherRankedType,
&m_sig(impl_m));
- let impl_sig =
- impl_sig.subst(tcx, impl_to_skol_substs);
let impl_sig =
inh.normalize_associated_types_in(impl_m_span,
impl_m_node_id,
let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig));
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
- let trait_sig = tcx.liberate_late_bound_regions(
- infcx.parameter_environment.free_id_outlive,
+ let trait_sig = inh.liberate_late_bound_regions(
+ impl_m.def_id,
&m_sig(trait_m));
let trait_sig =
trait_sig.subst(tcx, trait_to_skol_substs);
impl_m: &ty::AssociatedItem,
trait_generics: &ty::Generics,
impl_generics: &ty::Generics,
- trait_to_skol_substs: &Substs<'tcx>,
- impl_to_skol_substs: &Substs<'tcx>)
+ trait_to_skol_substs: &Substs<'tcx>)
-> Result<(), ErrorReported> {
let trait_params = &trait_generics.regions[..];
let impl_params = &impl_generics.regions[..];
debug!("check_region_bounds_on_impl_method: \
trait_generics={:?} \
impl_generics={:?} \
- trait_to_skol_substs={:?} \
- impl_to_skol_substs={:?}",
+ trait_to_skol_substs={:?}",
trait_generics,
impl_generics,
- trait_to_skol_substs,
- impl_to_skol_substs);
+ trait_to_skol_substs);
// Must have same number of early-bound lifetime parameters.
// Unfortunately, if the user screws up the bounds, then this
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
- let inh = Inherited::new(infcx);
+ let inh = Inherited::new(infcx, impl_c.def_id);
let infcx = &inh.infcx;
// The below is for the most part highly similar to the procedure
// Create a parameter environment that represents the implementation's
// method.
let impl_c_node_id = tcx.hir.as_local_node_id(impl_c.def_id).unwrap();
- let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_c_node_id);
-
- // Create mapping from impl to skolemized.
- let impl_to_skol_substs = &impl_param_env.free_substs;
-
- // Create mapping from trait to skolemized.
- let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
- impl_c.container.id(),
- trait_to_impl_substs.subst(tcx,
- impl_to_skol_substs));
- debug!("compare_const_impl: trait_to_skol_substs={:?}",
- trait_to_skol_substs);
// Compute skolemized form of impl and trait const tys.
- let impl_ty = tcx.type_of(impl_c.def_id).subst(tcx, impl_to_skol_substs);
- let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_skol_substs);
+ let impl_ty = tcx.type_of(impl_c.def_id);
+ let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id);
// There is no "body" here, so just pass dummy id.
-> Result<(), ErrorReported>
{
let drop_impl_node_id = tcx.hir.as_local_node_id(drop_impl_did).unwrap();
- let self_type_node_id = tcx.hir.as_local_node_id(self_type_did).unwrap();
// check that the impl type can be made to match the trait type.
- let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id);
+ let impl_param_env = tcx.parameter_environment(self_type_did);
tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|ref infcx| {
let tcx = infcx.tcx;
let mut fulfillment_cx = traits::FulfillmentContext::new();
let named_type = tcx.type_of(self_type_did);
- let named_type = named_type.subst(tcx, &infcx.parameter_environment.free_substs);
let drop_impl_span = tcx.def_span(drop_impl_did);
let fresh_impl_substs =
fulfillment_cx.register_predicate_obligations(infcx, obligations);
}
Err(_) => {
- let item_span = tcx.hir.span(self_type_node_id);
+ let item_span = tcx.def_span(self_type_did);
struct_span_err!(tcx.sess, drop_impl_span, E0366,
"Implementations of Drop cannot be specialized")
.span_note(item_span,
rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>,
ty: ty::Ty<'tcx>,
span: Span,
- scope: region::CodeExtent<'tcx>)
+ scope: region::CodeExtent)
-> Result<(), ErrorReported>
{
debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
let bound_list = unsatisfied_predicates.iter()
.map(|p| format!("`{} : {}`", p.self_ty(), p))
.collect::<Vec<_>>()
- .join(", ");
+ .join("\n");
err.note(&format!("the method `{}` exists but the following trait bounds \
- were not satisfied: {}",
+ were not satisfied:\n{}",
item_name,
bound_list));
}
use rustc_back::slice::ref_slice;
use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
use rustc::infer::type_variable::{TypeVariableOrigin};
+use rustc::middle::region::CodeExtent;
use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
-use rustc::ty::{ParamTy, ParameterEnvironment};
-use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
+use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue};
use rustc::ty::{self, Ty, TyCtxt, Visibility};
use rustc::ty::{MethodCall, MethodCallee};
use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
// variables to get the concrete type, which can be used to
// deanonymize TyAnon, after typeck is done with all functions.
anon_types: RefCell<NodeMap<Ty<'tcx>>>,
+
+ /// Each type parameter has an implicit region bound that
+ /// indicates it must outlive at least the function body (the user
+ /// may specify stronger requirements). This field indicates the
+ /// region of the callee. If it is `None`, then the parameter
+ /// environment is for an item or something where the "callee" is
+ /// not clear.
+ implicit_region_bound: Option<ty::Region<'tcx>>,
}
impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
/// Necessary because we can't write the following bound:
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>).
pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>
+ infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>,
+ def_id: DefId,
}
impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
- pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId)
+ pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
-> InheritedBuilder<'a, 'gcx, 'tcx> {
let tables = ty::TypeckTables::empty();
- let param_env = ParameterEnvironment::for_item(tcx, id);
+ let param_env = tcx.parameter_environment(def_id);
InheritedBuilder {
- infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing)
+ infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing),
+ def_id,
}
}
}
fn enter<F, R>(&'tcx mut self, f: F) -> R
where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R
{
- self.infcx.enter(|infcx| f(Inherited::new(infcx)))
+ let def_id = self.def_id;
+ self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id)))
}
}
impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
- fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
+ fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self {
+ let tcx = infcx.tcx;
+ let item_id = tcx.hir.as_local_node_id(def_id);
+ let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id));
+ let implicit_region_bound = body_id.map(|body| {
+ tcx.mk_region(ty::ReScope(CodeExtent::CallSiteScope(body)))
+ });
+
Inherited {
infcx: infcx,
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
deferred_call_resolutions: RefCell::new(DefIdMap()),
deferred_cast_checks: RefCell::new(Vec::new()),
anon_types: RefCell::new(NodeMap()),
+ implicit_region_bound,
}
}
obligations);
InferOk { value, obligations }
}
+
+ /// Replace any late-bound regions bound in `value` with
+ /// free variants attached to `all_outlive_scope`.
+ fn liberate_late_bound_regions<T>(&self,
+ all_outlive_scope: DefId,
+ value: &ty::Binder<T>)
+ -> T
+ where T: TypeFoldable<'tcx>
+ {
+ self.tcx.replace_late_bound_regions(value, |br| {
+ self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
+ scope: all_outlive_scope,
+ bound_region: br
+ }))
+ }).0
+ }
}
struct CheckItemTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
});
let body = tcx.hir.body(body_id);
- Inherited::build(tcx, id).enter(|inh| {
+ Inherited::build(tcx, def_id).enter(|inh| {
let fcx = if let Some(decl) = fn_decl {
let fn_sig = tcx.type_of(def_id).fn_sig();
check_abi(tcx, span, fn_sig.abi());
// Compute the fty from point of view of inside fn.
- let fn_scope = inh.tcx.call_site_extent(id, body_id.node_id);
- let fn_sig =
- fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
let fn_sig =
- inh.tcx.liberate_late_bound_regions(Some(fn_scope), &fn_sig);
+ inh.liberate_late_bound_regions(def_id, &fn_sig);
let fn_sig =
inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);
impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
- fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
- Some(&self.parameter_environment.free_substs)
- }
-
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
-> ty::GenericPredicates<'tcx>
{
use middle::free_region::FreeRegionMap;
use middle::mem_categorization as mc;
use middle::mem_categorization::Categorization;
-use middle::region::{self, CodeExtent, RegionMaps};
+use middle::region::{CodeExtent, RegionMaps};
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::traits;
region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
- pub region_maps: Rc<RegionMaps<'tcx>>,
+ pub region_maps: Rc<RegionMaps>,
free_region_map: FreeRegionMap<'tcx>,
body_id: ast::NodeId,
// call_site scope of innermost fn
- call_site_scope: Option<CodeExtent<'tcx>>,
+ call_site_scope: Option<CodeExtent>,
// id of innermost fn or loop
repeating_scope: ast::NodeId,
}
}
- fn set_call_site_scope(&mut self, call_site_scope: Option<CodeExtent<'tcx>>)
- -> Option<CodeExtent<'tcx>> {
+ fn set_call_site_scope(&mut self, call_site_scope: Option<CodeExtent>)
+ -> Option<CodeExtent> {
mem::replace(&mut self.call_site_scope, call_site_scope)
}
let body_id = body.id();
- let call_site = self.tcx.intern_code_extent(
- region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
+ let call_site = CodeExtent::CallSiteScope(body_id);
let old_call_site_scope = self.set_call_site_scope(Some(call_site));
let fn_sig = {
let old_body_id = self.set_body_id(body_id.node_id);
self.relate_free_regions(&fn_sig_tys[..], body_id.node_id, span);
- self.link_fn_args(self.tcx.node_extent(body_id.node_id), &body.arguments);
+ self.link_fn_args(CodeExtent::Misc(body_id.node_id), &body.arguments);
self.visit_body(body);
self.visit_region_obligations(body_id.node_id);
for implication in implied_bounds {
debug!("implication: {:?}", implication);
match implication {
- ImpliedBound::RegionSubRegion(&ty::ReFree(free_a),
+ ImpliedBound::RegionSubRegion(r_a @ &ty::ReEarlyBound(_),
+ &ty::ReVar(vid_b)) |
+ ImpliedBound::RegionSubRegion(r_a @ &ty::ReFree(_),
&ty::ReVar(vid_b)) => {
- self.add_given(free_a, vid_b);
+ self.add_given(r_a, vid_b);
}
ImpliedBound::RegionSubParam(r_a, param_b) => {
self.region_bound_pairs.push((r_a, GenericKind::Param(param_b)));
// call occurs.
//
// FIXME(#6268) to support nested method calls, should be callee_id
- let callee_scope = self.tcx.node_extent(call_expr.id);
+ let callee_scope = CodeExtent::Misc(call_expr.id);
let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope));
debug!("callee_region={:?}", callee_region);
debug!("constrain_index(index_expr=?, indexed_ty={}",
self.ty_to_string(indexed_ty));
- let r_index_expr = ty::ReScope(self.tcx.node_extent(index_expr.id));
+ let r_index_expr = ty::ReScope(CodeExtent::Misc(index_expr.id));
if let ty::TyRef(r_ptr, mt) = indexed_ty.sty {
match mt.ty.sty {
ty::TySlice(_) | ty::TyStr => {
/// Computes the guarantors for any ref bindings in a match and
/// then ensures that the lifetime of the resulting pointer is
/// linked to the lifetime of its guarantor (if any).
- fn link_fn_args(&self, body_scope: CodeExtent<'tcx>, args: &[hir::Arg]) {
+ fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
let mc = &mc::MemCategorizationContext::new(self, &self.region_maps);
for arg in args {
/// must outlive `callee_scope`.
fn link_by_ref(&self,
expr: &hir::Expr,
- callee_scope: CodeExtent<'tcx>) {
+ callee_scope: CodeExtent) {
debug!("link_by_ref(expr={:?}, callee_scope={:?})",
expr, callee_scope);
let mc = mc::MemCategorizationContext::new(self, &self.region_maps);
}
fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
- let param_env = &self.parameter_environment;
-
debug!("param_bound(param_ty={:?})",
param_ty);
// Add in the default bound of fn body that applies to all in
// scope type parameters:
- param_bounds.extend(param_env.implicit_region_bound);
+ param_bounds.extend(self.implicit_region_bound);
VerifyBound::AnyRegion(param_bounds)
}
}
let mut regions = ty.regions();
- regions.retain(|r| !r.is_bound()); // ignore late-bound regions
+ regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
bounds.push(VerifyBound::AllRegions(regions));
// remove bounds that must hold, since they are not interesting
use constrained_type_params::{identify_constrained_type_params, Parameter};
use hir::def_id::DefId;
-use middle::region::{CodeExtent};
use rustc::traits::{self, ObligationCauseCode};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
error_192(tcx, item.span);
}
}
- hir::ItemFn(.., body_id) => {
- self.check_item_fn(item, body_id);
+ hir::ItemFn(..) => {
+ self.check_item_fn(item);
}
hir::ItemStatic(..) => {
self.check_item_type(item);
sig_if_method: Option<&hir::MethodSig>) {
let code = self.code.clone();
self.for_id(item_id, span).with_fcx(|fcx, this| {
- let free_substs = &fcx.parameter_environment.free_substs;
- let free_id_outlive = fcx.parameter_environment.free_id_outlive;
-
let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
let (mut implied_bounds, self_ty) = match item.container {
match item.kind {
ty::AssociatedKind::Const => {
let ty = fcx.tcx.type_of(item.def_id);
- let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
+ let ty = fcx.normalize_associated_types_in(span, &ty);
fcx.register_wf_obligation(ty, span, code.clone());
}
ty::AssociatedKind::Method => {
reject_shadowing_type_parameters(fcx.tcx, item.def_id);
let method_ty = fcx.tcx.type_of(item.def_id);
- let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
- let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs);
+ let method_ty = fcx.normalize_associated_types_in(span, &method_ty);
+ let predicates = fcx.tcx.predicates_of(item.def_id)
+ .instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(span, &predicates);
let sig = method_ty.fn_sig();
this.check_fn_or_method(fcx, span, sig, &predicates,
- free_id_outlive, &mut implied_bounds);
+ item.def_id, &mut implied_bounds);
let sig_if_method = sig_if_method.expect("bad signature for method");
- this.check_method_receiver(fcx, sig_if_method, &item,
- free_id_outlive, self_ty);
+ this.check_method_receiver(fcx, sig_if_method, &item, self_ty);
}
ty::AssociatedKind::Type => {
if item.defaultness.has_value() {
let ty = fcx.tcx.type_of(item.def_id);
- let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
+ let ty = fcx.normalize_associated_types_in(span, &ty);
fcx.register_wf_obligation(ty, span, code.clone());
}
}
fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
-> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
CheckWfFcxBuilder {
- inherited: Inherited::build(self.tcx, id),
+ inherited: Inherited::build(self.tcx, self.tcx.hir.local_def_id(id)),
code: self.code.clone(),
id: id,
span: span
}
}
- let free_substs = &fcx.parameter_environment.free_substs;
let def_id = fcx.tcx.hir.local_def_id(item.id);
- let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
+ let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
this.check_where_clauses(fcx, item.span, &predicates);
vec![] // no implied bounds in a struct def'n
}
self.for_item(item).with_fcx(|fcx, this| {
- let free_substs = &fcx.parameter_environment.free_substs;
- let predicates = fcx.instantiate_bounds(item.span, trait_def_id, free_substs);
+ let predicates = fcx.tcx.predicates_of(trait_def_id).instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
this.check_where_clauses(fcx, item.span, &predicates);
vec![]
});
}
- fn check_item_fn(&mut self,
- item: &hir::Item,
- body_id: hir::BodyId)
- {
+ fn check_item_fn(&mut self, item: &hir::Item) {
self.for_item(item).with_fcx(|fcx, this| {
- let free_substs = &fcx.parameter_environment.free_substs;
let def_id = fcx.tcx.hir.local_def_id(item.id);
let ty = fcx.tcx.type_of(def_id);
- let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &ty);
+ let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
let sig = item_ty.fn_sig();
- let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
+ let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
let mut implied_bounds = vec![];
- let free_id_outlive = fcx.tcx.call_site_extent(item.id, body_id.node_id);
this.check_fn_or_method(fcx, item.span, sig, &predicates,
- Some(free_id_outlive), &mut implied_bounds);
+ def_id, &mut implied_bounds);
implied_bounds
})
}
self.for_item(item).with_fcx(|fcx, this| {
let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
- let item_ty = fcx.instantiate_type_scheme(item.span,
- &fcx.parameter_environment
- .free_substs,
- &ty);
+ let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
fcx.register_wf_obligation(item_ty, item.span, this.code.clone());
debug!("check_impl: {:?}", item);
self.for_item(item).with_fcx(|fcx, this| {
- let free_substs = &fcx.parameter_environment.free_substs;
let item_def_id = fcx.tcx.hir.local_def_id(item.id);
match *ast_trait_ref {
Some(ref ast_trait_ref) => {
let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
let trait_ref =
- fcx.instantiate_type_scheme(
- ast_trait_ref.path.span, free_substs, &trait_ref);
+ fcx.normalize_associated_types_in(
+ ast_trait_ref.path.span, &trait_ref);
let obligations =
ty::wf::trait_obligations(fcx,
fcx.body_id,
}
None => {
let self_ty = fcx.tcx.type_of(item_def_id);
- let self_ty = fcx.instantiate_type_scheme(item.span, free_substs, &self_ty);
+ let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone());
}
}
- let predicates = fcx.instantiate_bounds(item.span, item_def_id, free_substs);
+ let predicates = fcx.tcx.predicates_of(item_def_id).instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
this.check_where_clauses(fcx, item.span, &predicates);
fcx.impl_implied_bounds(item_def_id, item.span)
span: Span,
sig: ty::PolyFnSig<'tcx>,
predicates: &ty::InstantiatedPredicates<'tcx>,
- free_id_outlive: Option<CodeExtent<'tcx>>,
+ def_id: DefId,
implied_bounds: &mut Vec<Ty<'tcx>>)
{
- let free_substs = &fcx.parameter_environment.free_substs;
- let sig = fcx.instantiate_type_scheme(span, free_substs, &sig);
- let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &sig);
+ let sig = fcx.normalize_associated_types_in(span, &sig);
+ let sig = fcx.liberate_late_bound_regions(def_id, &sig);
for input_ty in sig.inputs() {
fcx.register_wf_obligation(&input_ty, span, self.code.clone());
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
method_sig: &hir::MethodSig,
method: &ty::AssociatedItem,
- free_id_outlive: Option<CodeExtent<'tcx>>,
self_ty: ty::Ty<'tcx>)
{
// check that the type of the method's receiver matches the
let span = method_sig.decl.inputs[0].span;
- let free_substs = &fcx.parameter_environment.free_substs;
let method_ty = fcx.tcx.type_of(method.def_id);
- let fty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
- let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.fn_sig());
+ let fty = fcx.normalize_associated_types_in(span, &method_ty);
+ let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
debug!("check_method_receiver: sig={:?}", sig);
}
ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
};
- let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
- let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive,
- &ty::Binder(rcvr_ty));
+ let rcvr_ty = fcx.normalize_associated_types_in(span, &rcvr_ty);
+ let rcvr_ty = fcx.liberate_late_bound_regions(method.def_id,
+ &ty::Binder(rcvr_ty));
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
struct_def.fields().iter()
.map(|field| {
let field_ty = self.tcx.type_of(self.tcx.hir.local_def_id(field.id));
- let field_ty = self.instantiate_type_scheme(field.span,
- &self.parameter_environment
- .free_substs,
- &field_ty);
+ let field_ty = self.normalize_associated_types_in(field.span,
+ &field_ty);
AdtField { ty: field_ty, span: field.span }
})
.collect();
}
fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
- let free_substs = &self.parameter_environment.free_substs;
match self.tcx.impl_trait_ref(impl_def_id) {
Some(ref trait_ref) => {
// Trait impl: take implied bounds from all types that
// appear in the trait reference.
- let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref);
+ let trait_ref = self.normalize_associated_types_in(span, trait_ref);
trait_ref.substs.types().collect()
}
None => {
// Inherent impl: take implied bounds from the self type.
let self_ty = self.tcx.type_of(impl_def_id);
- let self_ty = self.instantiate_type_scheme(span, free_substs, &self_ty);
+ let self_ty = self.normalize_associated_types_in(span, &self_ty);
vec![self_ty]
}
}
use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
use rustc::ty::adjustment;
use rustc::ty::fold::{TypeFolder,TypeFoldable};
-use rustc::util::nodemap::{DefIdMap, DefIdSet};
+use rustc::util::nodemap::DefIdSet;
use syntax::ast;
use syntax_pos::Span;
use std::mem;
tables: ty::TypeckTables<'gcx>,
- // Mapping from free regions of the function to the
- // early-bound versions of them, visible from the
- // outside of the function. This is needed by, and
- // only populated if there are any `impl Trait`.
- free_to_bound_regions: DefIdMap<ty::Region<'gcx>>,
-
body: &'gcx hir::Body,
}
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, body: &'gcx hir::Body)
-> WritebackCx<'cx, 'gcx, 'tcx> {
- let mut wbcx = WritebackCx {
+ WritebackCx {
fcx: fcx,
tables: ty::TypeckTables::empty(),
- free_to_bound_regions: DefIdMap(),
body: body
- };
-
- // Only build the reverse mapping if `impl Trait` is used.
- if fcx.anon_types.borrow().is_empty() {
- return wbcx;
}
-
- let gcx = fcx.tcx.global_tcx();
- let free_substs = fcx.parameter_environment.free_substs;
- for (i, k) in free_substs.iter().enumerate() {
- let r = if let Some(r) = k.as_region() {
- r
- } else {
- continue;
- };
- match *r {
- ty::ReFree(ty::FreeRegion {
- bound_region: ty::BoundRegion::BrNamed(def_id, name), ..
- }) => {
- let bound_region = gcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
- index: i as u32,
- name: name,
- }));
- wbcx.free_to_bound_regions.insert(def_id, bound_region);
- }
- _ => {
- bug!("{:?} is not a free region for an early-bound lifetime", r);
- }
- }
- }
-
- wbcx
}
fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
let inside_ty = self.resolve(&concrete_ty, &node_id);
// Convert the type from the function into a type valid outside
- // the function, by replacing free regions with early-bound ones.
+ // the function, by replacing invalid regions with 'static,
+ // after producing an error for each of them.
let outside_ty = gcx.fold_regions(&inside_ty, &mut false, |r, _| {
match *r {
- // 'static is valid everywhere.
- ty::ReStatic => gcx.types.re_static,
- ty::ReEmpty => gcx.types.re_empty,
-
- // Free regions that come from early-bound regions are valid.
- ty::ReFree(ty::FreeRegion {
- bound_region: ty::BoundRegion::BrNamed(def_id, ..), ..
- }) if self.free_to_bound_regions.contains_key(&def_id) => {
- self.free_to_bound_regions[&def_id]
- }
+ // 'static and early-bound regions are valid.
+ ty::ReStatic |
+ ty::ReEarlyBound(_) |
+ ty::ReEmpty => r,
ty::ReFree(_) |
- ty::ReEarlyBound(_) |
ty::ReLateBound(..) |
ty::ReScope(_) |
ty::ReSkolemized(..) => {
use rustc::traits::{self, ObligationCause, Reveal};
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::ParameterEnvironment;
use rustc::ty::TypeFoldable;
use rustc::ty::adjustment::CoerceUnsizedInfo;
-use rustc::ty::subst::Subst;
use rustc::ty::util::CopyImplementationError;
use rustc::infer;
self_type);
let span = tcx.hir.span(impl_node_id);
- let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
- let self_type = self_type.subst(tcx, ¶m_env.free_substs);
+ let param_env = tcx.parameter_environment(impl_did);
assert!(!self_type.has_escaping_regions());
debug!("visit_implementation_of_copy: self_type={:?} (free)",
target);
let span = tcx.hir.span(impl_node_id);
- let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
- let source = source.subst(tcx, ¶m_env.free_substs);
- let target = target.subst(tcx, ¶m_env.free_substs);
+ let param_env = tcx.parameter_environment(impl_did);
assert!(!source.has_escaping_regions());
let err_info = CoerceUnsizedInfo { custom_kind: None };
return err_info;
}
+ // Here we are considering a case of converting
+ // `S<P0...Pn>` to S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
+ // which acts like a pointer to `U`, but carries along some extra data of type `T`:
+ //
+ // struct Foo<T, U> {
+ // extra: T,
+ // ptr: *mut U,
+ // }
+ //
+ // We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
+ // to `Foo<T, [i32]>`. That impl would look like:
+ //
+ // impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
+ //
+ // Here `U = [i32; 3]` and `V = [i32]`. At runtime,
+ // when this coercion occurs, we would be changing the
+ // field `ptr` from a thin pointer of type `*mut [i32;
+ // 3]` to a fat pointer of type `*mut [i32]` (with
+ // extra data `3`). **The purpose of this check is to
+ // make sure that we know how to do this conversion.**
+ //
+ // To check if this impl is legal, we would walk down
+ // the fields of `Foo` and consider their types with
+ // both substitutes. We are looking to find that
+ // exactly one (non-phantom) field has changed its
+ // type, which we will expect to be the pointer that
+ // is becoming fat (we could probably generalize this
+ // to mutiple thin pointers of the same type becoming
+ // fat, but we don't). In this case:
+ //
+ // - `extra` has type `T` before and type `T` after
+ // - `ptr` has type `*mut U` before and type `*mut V` after
+ //
+ // Since just one field changed, we would then check
+ // that `*mut U: CoerceUnsized<*mut V>` is implemented
+ // (in other words, that we know how to do this
+ // conversion). This will work out because `U:
+ // Unsize<V>`, and we have a builtin rule that `*mut
+ // U` can be coerced to `*mut V` if `U: Unsize<V>`.
let fields = &def_a.struct_variant().fields;
let diff_fields = fields.iter()
.enumerate()
return None;
}
- // Ignore fields that aren't significantly changed
- if let Ok(ok) = infcx.sub_types(false, &cause, b, a) {
+ // Ignore fields that aren't changed; it may
+ // be that we could get away with subtyping or
+ // something more accepting, but we use
+ // equality because we want to be able to
+ // perform this check without computing
+ // variance where possible. (This is because
+ // we may have to evaluate constraint
+ // expressions in the course of execution.)
+ // See e.g. #41936.
+ if let Ok(ok) = infcx.eq_types(false, &cause, b, a) {
if ok.obligations.is_empty() {
return None;
}
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id))
}
- fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
- None
- }
-
fn re_infer(&self, _span: Span, _def: Option<&ty::RegionParameterDef>)
-> Option<ty::Region<'tcx>> {
None
let mut index = parent_count + has_own_self as u32;
for param in early_bound_lifetimes_from_generics(tcx, ast_generics) {
let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+ def_id: tcx.hir.local_def_id(param.lifetime.id),
index: index,
name: param.lifetime.name
}));
*/
#![crate_name = "rustc_typeck"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(never_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
}
}
-impl<'tcx> Clean<Option<Lifetime>> for ty::RegionKind<'tcx> {
+impl Clean<Option<Lifetime>> for ty::RegionKind {
fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
match *self {
ty::ReStatic => Some(Lifetime::statik()),
use rustc::hir::map as hir_map;
use rustc::lint;
use rustc::util::nodemap::FxHashMap;
+use rustc_trans;
use rustc_trans::back::link;
use rustc_resolve as resolve;
use rustc_metadata::cstore::CStore;
let dep_graph = DepGraph::new(false);
let _ignore = dep_graph.in_ignore();
- let cstore = Rc::new(CStore::new(&dep_graph));
+ let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
let mut sess = session::build_session_(
sessopts, &dep_graph, cpath, diagnostic_handler, codemap, cstore.clone()
);
+ rustc_trans::init(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
use std::io;
use std::path::Path;
use std::str;
+use html::markdown::{Markdown, RenderType};
#[derive(Clone)]
pub struct ExternalHtml{
}
impl ExternalHtml {
- pub fn load(in_header: &[String], before_content: &[String], after_content: &[String])
+ pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
+ md_before_content: &[String], md_after_content: &[String], render: RenderType)
-> Option<ExternalHtml> {
load_external_files(in_header)
.and_then(|ih|
load_external_files(before_content)
.map(|bc| (ih, bc))
)
+ .and_then(|(ih, bc)|
+ load_external_files(md_before_content)
+ .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, render))))
+ )
.and_then(|(ih, bc)|
load_external_files(after_content)
.map(|ac| (ih, bc, ac))
)
+ .and_then(|(ih, bc, ac)|
+ load_external_files(md_after_content)
+ .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, render))))
+ )
.map(|(ih, bc, ac)|
ExternalHtml {
in_header: ih,
let quot = if f.alternate() { "\"" } else { """ };
match self.0 {
Abi::Rust => Ok(()),
- Abi::C => write!(f, "extern "),
abi => write!(f, "extern {0}{1}{0} ", quot, abi.name()),
}
}
if (hasClass(main, 'content')) {
removeClass(main, 'hidden');
}
- var search = document.getElementById('search');
- if (hasClass(main, 'content')) {
- addClass(main, 'hidden');
+ var search_c = document.getElementById('search');
+ if (hasClass(search_c, 'content')) {
+ addClass(search_c, 'hidden');
}
}
// Revert to the previous title manually since the History
// perform the search. This will empty the bar if there's
// nothing there, which lets you really go back to a
// previous state with nothing in the bar.
- document.getElementsByClassName('search-input')[0].value = params.search;
+ if (params.search) {
+ document.getElementsByClassName('search-input')[0].value = params.search;
+ } else {
+ document.getElementsByClassName('search-input')[0].value = '';
+ }
// Some browsers fire 'onpopstate' for every page load
// (Chrome), while others fire the event only when actually
// popping a state (Firefox), which is why search() is
font-size: 17px;
margin: 30px 0 20px 0;
text-align: center;
+ word-wrap: break-word;
}
.location:empty {
overflow: auto;
padding-left: 0;
}
+#search {
+ margin-left: 230px;
+}
.content pre.line-numbers {
float: left;
border: none;
top: 0;
}
+h3 > .collapse-toggle, h4 > .collapse-toggle {
+ font-size: 0.8em;
+ top: 5px;
+}
+
.toggle-wrapper > .collapse-toggle {
left: -24px;
margin-top: 0px;
// except according to those terms.
#![crate_name = "rustdoc"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(libc)]
-#![feature(rustc_private)]
#![feature(set_stdio)]
#![feature(slice_patterns)]
-#![feature(staged_api)]
#![feature(test)]
#![feature(unicode)]
#![feature(vec_remove_item)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate arena;
extern crate getopts;
extern crate env_logger;
"files to include inline between the content and </body> of a rendered \
Markdown file or generated documentation",
"FILES")),
+ unstable(optmulti("", "markdown-before-content",
+ "files to include inline between <body> and the content of a rendered \
+ Markdown file or generated documentation",
+ "FILES")),
+ unstable(optmulti("", "markdown-after-content",
+ "files to include inline between the content and </body> of a rendered \
+ Markdown file or generated documentation",
+ "FILES")),
stable(optopt("", "markdown-playground-url",
"URL to send code snippets to", "URL")),
stable(optflag("", "markdown-no-toc", "don't include table of contents")),
let external_html = match ExternalHtml::load(
&matches.opt_strs("html-in-header"),
&matches.opt_strs("html-before-content"),
- &matches.opt_strs("html-after-content")) {
+ &matches.opt_strs("html-after-content"),
+ &matches.opt_strs("markdown-before-content"),
+ &matches.opt_strs("markdown-after-content"),
+ render_type) {
Some(eh) => eh,
None => return 3,
};
use rustc_driver::driver::phase_2_configure_and_expand;
use rustc_metadata::cstore::CStore;
use rustc_resolve::MakeGlobMap;
+use rustc_trans;
use rustc_trans::back::link;
use syntax::ast;
use syntax::codemap::CodeMap;
let dep_graph = DepGraph::new(false);
let _ignore = dep_graph.in_ignore();
- let cstore = Rc::new(CStore::new(&dep_graph));
+ let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
let mut sess = session::build_session_(
sessopts, &dep_graph, Some(input_path.clone()), handler, codemap.clone(), cstore.clone(),
);
+ rustc_trans::init(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
sess.parse_sess.config =
config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
let dep_graph = DepGraph::new(false);
- let cstore = Rc::new(CStore::new(&dep_graph));
+ let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
let mut sess = session::build_session_(
sessopts, &dep_graph, None, diagnostic_handler, codemap, cstore.clone(),
);
+ rustc_trans::init(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
*/
#![crate_name = "serialize"]
-#![unstable(feature = "rustc_private",
+#![cfg_attr(stage0, unstable(feature = "rustc_private",
reason = "deprecated in favor of rustc-serialize on crates.io",
- issue = "27812")]
+ issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(core_intrinsics)]
#![feature(i128_type)]
#![feature(specialization)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![cfg_attr(test, feature(test))]
extern crate collections;
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
-/// A `CString` is created from either a byte slice or a byte vector. After
-/// being created, a `CString` predominately inherits all of its methods from
-/// the `Deref` implementation to `[c_char]`. Note that the underlying array
-/// is represented as an array of `c_char` as opposed to `u8`. A `u8` slice
-/// can be obtained with the `as_bytes` method. Slices produced from a `CString`
-/// do *not* contain the trailing nul terminator unless otherwise specified.
+/// A `CString` is created from either a byte slice or a byte vector. A `u8`
+/// slice can be obtained with the `as_bytes` method. Slices produced from a
+/// `CString` do *not* contain the trailing nul terminator unless otherwise
+/// specified.
///
/// # Examples
///
/// A thread local storage key which owns its contents.
///
/// This key uses the fastest possible implementation available to it for the
-/// target platform. It is instantiated with the `thread_local!` macro and the
-/// primary method is the `with` method.
+/// target platform. It is instantiated with the [`thread_local!`] macro and the
+/// primary method is the [`with`] method.
///
-/// The `with` method yields a reference to the contained value which cannot be
+/// The [`with`] method yields a reference to the contained value which cannot be
/// sent across threads or escape the given closure.
///
/// # Initialization and Destruction
///
-/// Initialization is dynamically performed on the first call to `with()`
-/// within a thread, and values that implement `Drop` get destructed when a
+/// Initialization is dynamically performed on the first call to [`with`]
+/// within a thread, and values that implement [`Drop`] get destructed when a
/// thread exits. Some caveats apply, which are explained below.
///
/// # Examples
/// 3. On macOS, initializing TLS during destruction of other TLS slots can
/// sometimes cancel *all* destructors for the current thread, whether or not
/// the slots have already had their destructors run or not.
+///
+/// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
+/// [`thread_local!`]: ../../std/macro.thread_local.html
+/// [`Drop`]: ../../std/ops/trait.Drop.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct LocalKey<T: 'static> {
// This outer `LocalKey<T>` type is what's going to be stored in statics,
}
}
-/// Declare a new thread local storage key of type `std::thread::LocalKey`.
+/// Declare a new thread local storage key of type [`std::thread::LocalKey`].
///
/// # Syntax
///
/// # fn main() {}
/// ```
///
-/// See [LocalKey documentation](thread/struct.LocalKey.html) for more
+/// See [LocalKey documentation][`std::thread::LocalKey`] for more
/// information.
+///
+/// [`std::thread::LocalKey`]: ../std/thread/struct.LocalKey.html
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable]
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum LocalKeyState {
/// All keys are in this state whenever a thread starts. Keys will
- /// transition to the `Valid` state once the first call to `with` happens
+ /// transition to the `Valid` state once the first call to [`with`] happens
/// and the initialization expression succeeds.
///
/// Keys in the `Uninitialized` state will yield a reference to the closure
- /// passed to `with` so long as the initialization routine does not panic.
+ /// passed to [`with`] so long as the initialization routine does not panic.
+ ///
+ /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
Uninitialized,
/// Once a key has been accessed successfully, it will enter the `Valid`
/// `Destroyed` state.
///
/// Keys in the `Valid` state will be guaranteed to yield a reference to the
- /// closure passed to `with`.
+ /// closure passed to [`with`].
+ ///
+ /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
Valid,
/// When a thread exits, the destructors for keys will be run (if
/// destructor has run, a key is in the `Destroyed` state.
///
/// Keys in the `Destroyed` states will trigger a panic when accessed via
- /// `with`.
+ /// [`with`].
+ ///
+ /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
Destroyed,
}
/// Query the current state of this key.
///
/// A key is initially in the `Uninitialized` state whenever a thread
- /// starts. It will remain in this state up until the first call to `with`
+ /// starts. It will remain in this state up until the first call to [`with`]
/// within a thread has run the initialization expression successfully.
///
/// Once the initialization expression succeeds, the key transitions to the
- /// `Valid` state which will guarantee that future calls to `with` will
+ /// `Valid` state which will guarantee that future calls to [`with`] will
/// succeed within the thread.
///
/// When a thread exits, each key will be destroyed in turn, and as keys are
/// destroyed they will enter the `Destroyed` state just before the
/// destructor starts to run. Keys may remain in the `Destroyed` state after
/// destruction has completed. Keys without destructors (e.g. with types
- /// that are `Copy`), may never enter the `Destroyed` state.
+ /// that are [`Copy`]), may never enter the `Destroyed` state.
///
/// Keys in the `Uninitialized` state can be accessed so long as the
/// initialization does not panic. Keys in the `Valid` state are guaranteed
/// to be able to be accessed. Keys in the `Destroyed` state will panic on
- /// any call to `with`.
+ /// any call to [`with`].
+ ///
+ /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
+ /// [`Copy`]: ../../std/marker/trait.Copy.html
#[unstable(feature = "thread_local_state",
reason = "state querying was recently added",
issue = "27716")]
// Builder
////////////////////////////////////////////////////////////////////////////////
-/// Thread configuration. Provides detailed control over the properties
-/// and behavior of new threads.
+/// Thread factory, which can be used in order to configure the properties of
+/// a new thread.
+///
+/// Methods can be chained on it in order to configure it.
+///
+/// The two configurations available are:
+///
+/// - [`name`]: allows to give a name to the thread which is currently
+/// only used in `panic` messages.
+/// - [`stack_size`]: specifies the desired stack size. Note that this can
+/// be overriden by the OS.
+///
+/// If the [`stack_size`] field is not specified, the stack size
+/// will be the `RUST_MIN_STACK` environment variable. If it is
+/// not specified either, a sensible default will be set.
+///
+/// If the [`name`] field is not specified, the thread will not be named.
+///
+/// The [`spawn`] method will take ownership of the builder and create an
+/// [`io::Result`] to the thread handle with the given configuration.
+///
+/// The [`thread::spawn`] free function uses a `Builder` with default
+/// configuration and [`unwrap`]s its return value.
+///
+/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want
+/// to recover from a failure to launch a thread, indeed the free function will
+/// panick where the `Builder` method will return a [`io::Result`].
///
/// # Examples
///
///
/// handler.join().unwrap();
/// ```
+///
+/// [`thread::spawn`]: ../../std/thread/fn.spawn.html
+/// [`stack_size`]: ../../std/thread/struct.Builder.html#method.stack_size
+/// [`name`]: ../../std/thread/struct.Builder.html#method.name
+/// [`spawn`]: ../../std/thread/struct.Builder.html#method.spawn
+/// [`io::Result`]: ../../std/io/type.Result.html
+/// [`unwrap`]: ../../std/result/enum.Result.html#method.unwrap
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Builder {
/// Generates the base configuration for spawning a thread, from which
/// configuration methods can be chained.
///
- /// If the [`stack_size`] field is not specified, the stack size
- /// will be the `RUST_MIN_STACK` environment variable, if it is
- /// not specified either, a sensible default size will be set (2MB as
- /// of the writting of this doc).
- ///
/// # Examples
///
/// ```
///
/// handler.join().unwrap();
/// ```
- ///
- /// [`stack_size`]: ../../std/thread/struct.Builder.html#method.stack_size
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> Builder {
Builder {
self
}
- /// Spawns a new thread, and returns a join handle for it.
+ /// Spawns a new thread by taking ownership of the `Builder`, and returns an
+ /// [`io::Result`] to its [`JoinHandle`].
///
- /// The child thread may outlive the parent (unless the parent thread
+ /// The spawned thread may outlive the caller (unless the caller thread
/// is the main thread; the whole process is terminated when the main
/// thread finishes). The join handle can be used to block on
/// termination of the child thread, including recovering its panics.
///
/// [`spawn`]: ../../std/thread/fn.spawn.html
/// [`io::Result`]: ../../std/io/type.Result.html
+ /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
///
/// # Examples
///
/// Cooperatively gives up a timeslice to the OS scheduler.
///
+/// This is used when the programmer knows that the thread will have nothing
+/// to do for some time, and thus avoid wasting computing time.
+///
+/// For example when polling on a resource, it is common to check that it is
+/// available, and if not to yield in order to avoid busy waiting.
+///
+/// Thus the pattern of `yield`ing after a failed poll is rather common when
+/// implementing low-level shared resources or synchronization primitives.
+///
+/// However programmers will usualy prefer to use, [`channel`]s, [`Condvar`]s,
+/// [`Mutex`]es or [`join`] for their synchronisation routines, as they avoid
+/// thinking about thread schedulling.
+///
+/// Note that [`channel`]s for example are implemented using this primitive.
+/// Indeed when you call `send` or `recv`, which are blocking, they will yield
+/// if the channel is not available.
+///
/// # Examples
///
/// ```
///
/// thread::yield_now();
/// ```
+///
+/// [`channel`]: ../../std/sync/mpsc/index.html
+/// [`spawn`]: ../../std/thread/fn.spawn.html
+/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
+/// [`Mutex`]: ../../std/sync/struct.Mutex.html
+/// [`Condvar`]: ../../std/sync/struct.Condvar.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn yield_now() {
imp::Thread::yield_now()
/// Perform a token equality check, ignoring syntax context (that is, an unhygienic comparison)
fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
- match (t1,t2) {
- (&token::Ident(id1),&token::Ident(id2))
- | (&token::Lifetime(id1),&token::Lifetime(id2)) =>
- id1.name == id2.name,
- _ => *t1 == *t2
+ if let (Some(id1), Some(id2)) = (t1.ident(), t2.ident()) {
+ id1.name == id2.name
+ } else if let (&token::Lifetime(id1), &token::Lifetime(id2)) = (t1, t2) {
+ id1.name == id2.name
+ } else {
+ *t1 == *t2
}
}
use codemap::{CodeMap, FilePathMapping};
use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
use errors::registry::Registry;
-use errors::{Level, DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
+use errors::{DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
use errors::emitter::Emitter;
-use errors::snippet::Style;
use std::rc::Rc;
use std::io::{self, Write};
fn from_diagnostic_builder(db: &DiagnosticBuilder,
je: &JsonEmitter)
-> Diagnostic {
- let sugg = db.suggestion.as_ref().map(|sugg| {
- SubDiagnostic {
- level: Level::Help,
- message: vec![(sugg.msg.clone(), Style::NoStyle)],
- span: MultiSpan::new(),
- render_span: Some(RenderSpan::Suggestion(sugg.clone())),
- }
+ let sugg = db.suggestions.iter().flat_map(|sugg| {
+ je.render(sugg).into_iter().map(move |rendered| {
+ Diagnostic {
+ message: sugg.msg.clone(),
+ code: None,
+ level: "help",
+ spans: DiagnosticSpan::from_suggestion(sugg, je),
+ children: vec![],
+ rendered: Some(rendered),
+ }
+ })
});
- let sugg = sugg.as_ref();
Diagnostic {
message: db.message(),
code: DiagnosticCode::map_opt_string(db.code.clone(), je),
level: db.level.to_str(),
spans: DiagnosticSpan::from_multispan(&db.span, je),
- children: db.children.iter().chain(sugg).map(|c| {
+ children: db.children.iter().map(|c| {
Diagnostic::from_sub_diagnostic(c, je)
- }).collect(),
+ }).chain(sugg).collect(),
rendered: None,
}
}
.map(|sp| DiagnosticSpan::from_render_span(sp, je))
.unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)),
children: vec![],
- rendered: db.render_span.as_ref()
- .and_then(|rsp| je.render(rsp)),
+ rendered: None,
}
}
}
fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter)
-> Vec<DiagnosticSpan> {
- assert_eq!(suggestion.msp.span_labels().len(), suggestion.substitutes.len());
- suggestion.msp.span_labels()
- .into_iter()
- .zip(&suggestion.substitutes)
- .map(|(span_label, suggestion)| {
- DiagnosticSpan::from_span_label(span_label,
- Some(suggestion),
- je)
+ suggestion.substitution_parts
+ .iter()
+ .flat_map(|substitution| {
+ substitution.substitutions.iter().map(move |suggestion| {
+ let span_label = SpanLabel {
+ span: substitution.span,
+ is_primary: true,
+ label: None,
+ };
+ DiagnosticSpan::from_span_label(span_label,
+ Some(suggestion),
+ je)
+ })
})
.collect()
}
match *rsp {
RenderSpan::FullSpan(ref msp) =>
DiagnosticSpan::from_multispan(msp, je),
- RenderSpan::Suggestion(ref suggestion) =>
- DiagnosticSpan::from_suggestion(suggestion, je),
+ // regular diagnostics don't produce this anymore
+ // FIXME(oli_obk): remove it entirely
+ RenderSpan::Suggestion(_) => unreachable!(),
}
}
}
}
impl JsonEmitter {
- fn render(&self, render_span: &RenderSpan) -> Option<String> {
- use std::borrow::Borrow;
-
- match *render_span {
- RenderSpan::FullSpan(_) => {
- None
- }
- RenderSpan::Suggestion(ref suggestion) => {
- Some(suggestion.splice_lines(self.cm.borrow()))
- }
- }
+ fn render(&self, suggestion: &CodeSuggestion) -> Vec<String> {
+ suggestion.splice_lines(&*self.cm)
}
}
//! This API is completely unstable and subject to change.
#![crate_name = "syntax"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
test(attr(deny(warnings))))]
#![deny(warnings)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(unicode)]
#![feature(rustc_diagnostic_macros)]
#![feature(i128_type)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate serialize;
#[macro_use] extern crate log;
#[macro_use] extern crate bitflags;
// integer literal followed by field/method access or a range pattern
// (`0..2` and `12.foo()`)
if self.ch_is('.') && !self.nextch_is('.') &&
- !self.nextch()
- .unwrap_or('\0')
- .is_xid_start() {
+ !ident_start(self.nextch()) {
// might have stuff after the ., and if it does, it needs to start
// with a number
self.bump();
self.count += 1;
walk_ident(self, span, ident);
}
- fn visit_mod(&mut self, m: &Mod, _s: Span, _n: NodeId) {
+ fn visit_mod(&mut self, m: &Mod, _s: Span, _a: &[Attribute], _n: NodeId) {
self.count += 1;
walk_mod(self, m)
}
fn visit_ident(&mut self, span: Span, ident: Ident) {
walk_ident(self, span, ident);
}
- fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
+ fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) {
+ walk_mod(self, m);
+ }
fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) }
fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) { walk_global_asm(self, ga) }
fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) }
}
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
- visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
+ visitor.visit_mod(&krate.module, krate.span, &krate.attrs, CRATE_NODE_ID);
walk_list!(visitor, visit_attribute, &krate.attrs);
}
item.id)
}
ItemKind::Mod(ref module) => {
- visitor.visit_mod(module, item.span, item.id)
+ visitor.visit_mod(module, item.span, &item.attrs, item.id)
}
ItemKind::ForeignMod(ref foreign_module) => {
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
)
}
-macro_rules! path {
- ($($x:tt)*) => (
- ::ext::deriving::generic::ty::Path::new( pathvec![ $($x)* ] )
- )
-}
-
macro_rules! path_local {
($x:ident) => (
::deriving::generic::ty::Path::new_local(stringify!($x))
//! Syntax extensions in the Rust compiler.
#![crate_name = "syntax_ext"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(warnings)]
#![feature(proc_macro_internals)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
extern crate fmt_macros;
extern crate log;
visit::walk_item(self, item);
}
- fn visit_mod(&mut self, m: &'a ast::Mod, _s: Span, id: NodeId) {
+ fn visit_mod(&mut self, m: &'a ast::Mod, _s: Span, _a: &[ast::Attribute], id: NodeId) {
let mut prev_in_root = self.in_root;
if id != ast::CRATE_NODE_ID {
prev_in_root = mem::replace(&mut self.in_root, false);
//! This API is completely unstable and subject to change.
#![crate_name = "syntax_pos"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(custom_attribute)]
#![feature(optin_builtin_traits)]
#![allow(unused_attributes)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(specialization)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
use std::cell::{Cell, RefCell};
use std::ops::{Add, Sub};
use std::rc::Rc;
//! [ti]: https://en.wikipedia.org/wiki/Terminfo
#![crate_name = "term"]
-#![unstable(feature = "rustc_private",
- reason = "use the crates.io `term` library instead",
- issue = "27812")]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(missing_docs)]
#![deny(warnings)]
-#![feature(box_syntax)]
#![feature(staged_api)]
#![cfg_attr(windows, feature(libc))]
// Handle rustfmt skips
#![feature(custom_attribute)]
#![allow(unused_attributes)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
+
use std::io::prelude::*;
pub use terminfo::TerminfoTerminal;
-Subproject commit cf85b5a8da7853c4de5cc57766da8b7988c06461
+Subproject commit 1ef3b9128e1baaed61b42d5b0de79dee100acf17
+++ /dev/null
-Subproject commit 2e6417f6af5218a29a8ee72ed17af085560b9b9c
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
-2017-05-06
+2017-05-13
fn main () {
let foo = 42u32;
- const FOO : u32 = foo; //~ ERROR E0435
+ let _: [u8; foo]; //~ ERROR E0435
//~| NOTE non-constant used with constant
}
pub fn test<A: Foo, B: Foo>() {
let _array = [4; <A as Foo>::Y];
- //~^ ERROR cannot use an outer type parameter in this context [E0402]
+ //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
}
fn main() {
pub fn test<A: Foo, B: Foo>() {
let _array: [u32; <A as Foo>::Y];
- //~^ ERROR cannot use an outer type parameter in this context [E0402]
+ //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
}
fn main() {
fn foo<T>() {
static a: Bar<T> = Bar::What;
- //~^ ERROR cannot use an outer type parameter in this context
+//~^ ERROR can't use type parameters from outer function; try using a local type parameter instead
}
fn main() {
fn main() {
let foo = 42u32;
const FOO : u32 = foo;
- //~^ ERROR attempt to use a non-constant value in a constant
+ //~^ ERROR can't capture dynamic environment
}
pub trait Resources<'a> {}
pub trait Buffer<'a, R: Resources<'a>> {
+ //~^ NOTE the lifetime 'a as defined on the trait at 13:0...
+ //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the trait
+
fn select(&self) -> BufferViewHandle<R>;
//~^ ERROR mismatched types
//~| lifetime mismatch
//~| NOTE expected type `Resources<'_>`
- //~| NOTE the lifetime 'a as defined on the method body at 14:4...
//~| NOTE ...does not necessarily outlive the anonymous lifetime #1 defined on the method body
//~| ERROR mismatched types
//~| lifetime mismatch
//~| NOTE expected type `Resources<'_>`
- //~| NOTE the anonymous lifetime #1 defined on the method body at 14:4...
- //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the method body
+ //~| NOTE the anonymous lifetime #1 defined on the method body at 17:4...
}
pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R);
let foo = 100;
static y: isize = foo + 1;
- //~^ ERROR attempt to use a non-constant value in a constant
+ //~^ ERROR can't capture dynamic environment
println!("{}", y);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-enum Fruit {
+// these two HELPs are actually in a new line between this line and the `enum Fruit` line
+enum Fruit { //~ HELP possible candidate is found in another module, you can import it into scope
+ //~^ HELP possible candidate is found in another module, you can import it into scope
Apple(i64),
//~^ HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`?
//~| HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`?
Apple(5)
//~^ ERROR cannot find function `Apple` in this scope
//~| NOTE not found in this scope
- //~| HELP possible candidate is found in another module, you can import it into scope
}
fn should_return_fruit_too() -> Fruit::Apple {
Apple(5)
//~^ ERROR cannot find function `Apple` in this scope
//~| NOTE not found in this scope
- //~| HELP possible candidate is found in another module, you can import it into scope
}
fn foo() -> Ok {
fn f(x:isize) {
static child: isize = x + 1;
- //~^ ERROR attempt to use a non-constant value in a constant
+ //~^ ERROR can't capture dynamic environment
}
fn main() {}
impl PTrait for P {
fn getChildOption(&self) -> Option<Box<P>> {
static childVal: Box<P> = self.child.get();
- //~^ ERROR attempt to use a non-constant value in a constant
+ //~^ ERROR can't capture dynamic environment
panic!();
}
}
struct RepeatMut<'a, T>(T, &'a ());
impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
+ //~^ NOTE ...does not necessarily outlive the lifetime 'a as defined on the impl
+
type Item = &'a mut T;
fn next(&'a mut self) -> Option<Self::Item>
//~^ ERROR method not compatible with trait
//~| lifetime mismatch
//~| NOTE expected type `fn(&mut RepeatMut<'a, T>) -> std::option::Option<&mut T>`
+ //~| NOTE the anonymous lifetime #1 defined on the method body
{
- //~^ NOTE the anonymous lifetime #1 defined on the body
- //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the body
Some(&mut self.0)
}
}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Dim {
+ fn dim() -> usize;
+}
+
+enum Dim3 {}
+
+impl Dim for Dim3 {
+ fn dim() -> usize {
+ 3
+ }
+}
+
+fn main() {
+ let array: [usize; Dim3::dim()]
+ //~^ ERROR calls in constants are limited to constant functions
+ = [0; Dim3::dim()];
+ //~^ ERROR calls in constants are limited to constant functions
+}
pub struct Vector<T, D: Dim> {
entries: [T; D::dim()]
- //~^ ERROR cannot use an outer type parameter in this context
+ //~^ ERROR no associated item named `dim` found for type `D` in the current scope
}
-fn main() {
- let array: [usize; Dim3::dim()]
- //~^ ERROR calls in constants are limited to constant functions
- = [0; Dim3::dim()];
- //~^ ERROR calls in constants are limited to constant functions
-}
+fn main() {}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo;
-
-fn main() {
- let a: Result<(), Foo> = Ok(());
- a.unwrap();
- //~^ ERROR no method named `unwrap` found for type `std::result::Result<(), Foo>`
- //~| NOTE the following trait bounds were not satisfied: `Foo : std::fmt::Debug`
-}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let a = 42._; //~ ERROR unexpected token: `_`
+}
extern crate rustc_lint;
extern crate rustc_metadata;
extern crate rustc_errors;
+extern crate rustc_trans;
extern crate syntax;
use rustc::dep_graph::DepGraph;
let descriptions = Registry::new(&rustc::DIAGNOSTICS);
let dep_graph = DepGraph::new(opts.build_dep_graph());
- let cstore = Rc::new(CStore::new(&dep_graph));
+ let cstore = Rc::new(CStore::new(&dep_graph, Box::new(rustc_trans::LlvmMetadataLoader)));
let sess = build_session(opts, &dep_graph, None, descriptions, cstore.clone());
+ rustc_trans::init(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
(sess, cstore)
}
extern crate rustc;
extern crate rustc_plugin;
+extern crate rustc_trans;
#[link(name = "llvm-function-pass", kind = "static")]
#[link(name = "llvm-module-pass", kind = "static")]
A::X - B::X
}
+trait Bar: Foo {
+ const Y: i32 = Self::X;
+}
+
fn main() {
assert_eq!(11, Abc::X);
assert_eq!(97, Def::X);
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// this used to cause exponential code-size blowup during LLVM passes.
+// min-llvm-version 3.9
+
+#![feature(test)]
+
+extern crate test;
+
+struct MayUnwind;
+
+impl Drop for MayUnwind {
+ fn drop(&mut self) {
+ if test::black_box(false) {
+ panic!()
+ }
+ }
+}
+
+struct DS<U> {
+ may_unwind: MayUnwind,
+ name: String,
+ next: U,
+}
+
+fn add<U>(ds: DS<U>, name: String) -> DS<DS<U>> {
+ DS {
+ may_unwind: MayUnwind,
+ name: "?".to_owned(),
+ next: ds,
+ }
+}
+
+fn main() {
+ let deserializers = DS { may_unwind: MayUnwind, name: "?".to_owned(), next: () };
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned()); // 0.7s
+ let deserializers = add(deserializers, "?".to_owned()); // 1.3s
+ let deserializers = add(deserializers, "?".to_owned()); // 2.4s
+ let deserializers = add(deserializers, "?".to_owned()); // 6.7s
+ let deserializers = add(deserializers, "?".to_owned()); // 26.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 114.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 228.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 400.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 800.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 1600.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 3200.0s
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Tc {}
+impl Tc for bool {}
+
+fn main() {
+ let _: &[&Tc] = &[&true];
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// A compile-time map from identifiers to arbitrary (heterogeneous) expressions
+macro_rules! ident_map {
+ ( $name:ident = { $($key:ident => $e:expr,)* } ) => {
+ macro_rules! $name {
+ $(
+ ( $key ) => { $e };
+ )*
+ // Empty invocation expands to nothing. Needed when the map is empty.
+ () => {};
+ }
+ };
+}
+
+ident_map!(my_map = {
+ main => 0,
+});
+
+fn main() {
+ my_map!(main);
+}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #41936. The coerce-unsized trait check in
+// coherence was using subtyping, which triggered variance
+// computation, which failed because it required type info for fields
+// that had not (yet) been computed.
+
+#![feature(unsize)]
+#![feature(coerce_unsized)]
+
+use std::{marker,ops};
+
+// Change the array to a non-array, and error disappears
+// Adding a new field to the end keeps the error
+struct LogDataBuf([u8;8]);
+
+struct Aref<T: ?Sized>
+{
+ // Inner structure triggers the error, removing the inner removes the message.
+ ptr: Box<ArefInner<T>>,
+}
+impl<T: ?Sized + marker::Unsize<U>, U: ?Sized> ops::CoerceUnsized<Aref<U>> for Aref<T> {}
+
+struct ArefInner<T: ?Sized>
+{
+ // Even with this field commented out, the error is raised.
+ data: T,
+}
+
+fn main(){}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Tr : Sized {
+ fn _method_on_numbers(self) {}
+}
+
+impl Tr for i32 {}
+
+fn main() {
+ 42._method_on_numbers();
+}
pub fn rust0() {}
// @has - '//code' 'fn rust1()'
pub extern "Rust" fn rust1() {}
- // @has - '//code' 'extern fn c0()'
+ // @has - '//code' 'extern "C" fn c0()'
pub extern fn c0() {}
- // @has - '//code' 'extern fn c1()'
+ // @has - '//code' 'extern "C" fn c1()'
pub extern "C" fn c1() {}
// @has - '//code' 'extern "system" fn system0()'
pub extern "system" fn system0() {}
// @has - '//code' 'impl Bar for fn()'
impl Bar for fn() {}
-// @has - '//code' 'impl Bar for extern fn()'
+// @has - '//code' 'impl Bar for extern "C" fn()'
impl Bar for extern fn() {}
// @has - '//code' 'impl Bar for extern "system" fn()'
impl Bar for extern "system" fn() {}
extern crate rustdoc_ffi as lib;
-// @has ffi/fn.foreigner.html //pre 'pub unsafe extern fn foreigner(cold_as_ice: u32)'
+// @has ffi/fn.foreigner.html //pre 'pub unsafe extern "C" fn foreigner(cold_as_ice: u32)'
pub use lib::foreigner;
extern "C" {
- // @has ffi/fn.another.html //pre 'pub unsafe extern fn another(cold_as_ice: u32)'
+ // @has ffi/fn.another.html //pre 'pub unsafe extern "C" fn another(cold_as_ice: u32)'
pub fn another(cold_as_ice: u32);
}
extern {
// @has issue_22038/fn.foo1.html \
- // '//*[@class="rust fn"]' 'pub unsafe extern fn foo1()'
+ // '//*[@class="rust fn"]' 'pub unsafe extern "C" fn foo1()'
pub fn foo1();
}
}
// @has issue_22038/fn.bar.html \
-// '//*[@class="rust fn"]' 'pub extern fn bar()'
+// '//*[@class="rust fn"]' 'pub extern "C" fn bar()'
pub extern fn bar() {}
// @has issue_22038/fn.baz.html \
// except according to those terms.
extern "C" {
- // @has variadic/fn.foo.html //pre 'pub unsafe extern fn foo(x: i32, ...)'
+ // @has variadic/fn.foo.html //pre 'pub unsafe extern "C" fn foo(x: i32, ...)'
pub fn foo(x: i32, ...);
}
12 | if x > y { x } else { y }
| ^
|
-note: ...the reference is valid for the lifetime 'a as defined on the body at 11:43...
- --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
+note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:0...
+ --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
-11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
- | ____________________________________________^
+11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^
-note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the body at 11:43
- --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
+note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:0
+ --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
-11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
- | ____________________________________________^
+11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^
|
= note: expected type `Ref<'a, _>`
found type `Ref<'_, _>`
-note: the anonymous lifetime #2 defined on the body at 15:51...
- --> $DIR/ex2a-push-one-existing-name.rs:15:52
+note: the anonymous lifetime #2 defined on the function body at 15:0...
+ --> $DIR/ex2a-push-one-existing-name.rs:15:1
|
-15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
- | ____________________________________________________^
+15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
-note: ...does not necessarily outlive the lifetime 'a as defined on the body at 15:51
- --> $DIR/ex2a-push-one-existing-name.rs:15:52
+note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:0
+ --> $DIR/ex2a-push-one-existing-name.rs:15:1
|
-15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
- | ____________________________________________________^
+15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
|
= note: expected type `Ref<'_, _>`
found type `Ref<'_, _>`
-note: the anonymous lifetime #3 defined on the body at 15:43...
- --> $DIR/ex2b-push-no-existing-names.rs:15:44
+note: the anonymous lifetime #3 defined on the function body at 15:0...
+ --> $DIR/ex2b-push-no-existing-names.rs:15:1
|
-15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
- | ____________________________________________^
+15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 15:43
- --> $DIR/ex2b-push-no-existing-names.rs:15:44
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:0
+ --> $DIR/ex2b-push-no-existing-names.rs:15:1
|
-15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
- | ____________________________________________^
+15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
16 | let z = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
- --> $DIR/ex2c-push-inference-variable.rs:15:67
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+ --> $DIR/ex2c-push-inference-variable.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let z = Ref { data: y.data };
17 | | x.push(z);
18 | | }
|
16 | let z = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
- --> $DIR/ex2c-push-inference-variable.rs:15:67
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+ --> $DIR/ex2c-push-inference-variable.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let z = Ref { data: y.data };
17 | | x.push(z);
18 | | }
17 | let b = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
- --> $DIR/ex2d-push-inference-variable-2.rs:15:67
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+ --> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | a.push(b);
|
17 | let b = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
- --> $DIR/ex2d-push-inference-variable-2.rs:15:67
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+ --> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | a.push(b);
17 | let b = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
- --> $DIR/ex2e-push-inference-variable-3.rs:15:67
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+ --> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | Vec::push(a, b);
|
17 | let b = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
- --> $DIR/ex2e-push-inference-variable-3.rs:15:67
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+ --> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | Vec::push(a, b);
17 | once::<&str>("str").fuse().filter(|a: &str| true).count();
| ^^^^^
|
- = note: the method `count` exists but the following trait bounds were not satisfied: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53] : std::ops::FnMut<(&_,)>`, `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
+ = note: the method `count` exists but the following trait bounds were not satisfied:
+ `[closure@$DIR/issue-36053-2.rs:17:39: 17:53] : std::ops::FnMut<(&_,)>`
+ `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnMut<(&'r str,)>`, but the trait `for<'r> std::ops::FnMut<(&'r &str,)>` is required
--> $DIR/issue-36053-2.rs:17:32
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo;
+
+fn main() {
+ let a: Result<(), Foo> = Ok(());
+ a.unwrap();
+ //~^ ERROR no method named `unwrap` found for type `std::result::Result<(), Foo>`
+ //~| NOTE the method `unwrap` exists but the following trait bounds were not satisfied
+}
--- /dev/null
+error: no method named `unwrap` found for type `std::result::Result<(), Foo>` in the current scope
+ --> $DIR/method-help-unsatisfied-bound.rs:15:7
+ |
+15 | a.unwrap();
+ | ^^^^^^
+ |
+ = note: the method `unwrap` exists but the following trait bounds were not satisfied:
+ `Foo : std::fmt::Debug`
+
+error: aborting due to previous error
+
15 | let _ = namespaced_enums::A;
| ^ not found in `namespaced_enums`
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use namespaced_enums::Foo::A;`
+help: possible candidate is found in another module, you can import it into scope
+ | use namespaced_enums::Foo::A;
error[E0425]: cannot find function `B` in module `namespaced_enums`
--> $DIR/enums-are-namespaced-xc.rs:18:31
18 | let _ = namespaced_enums::B(10);
| ^ not found in `namespaced_enums`
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use namespaced_enums::Foo::B;`
+help: possible candidate is found in another module, you can import it into scope
+ | use namespaced_enums::Foo::B;
error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums`
--> $DIR/enums-are-namespaced-xc.rs:21:31
21 | let _ = namespaced_enums::C { a: 10 };
| ^ not found in `namespaced_enums`
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use namespaced_enums::Foo::C;`
+help: possible candidate is found in another module, you can import it into scope
+ | use namespaced_enums::Foo::C;
error: aborting due to 3 previous errors
19 | Result {
| ^^^^^^ not a struct, variant or union type
|
- = help: possible better candidates are found in other modules, you can import them into scope:
- `use std::fmt::Result;`
- `use std::io::Result;`
- `use std::thread::Result;`
+help: possible better candidates are found in other modules, you can import them into scope
+ | use std::fmt::Result;
+ | use std::io::Result;
+ | use std::thread::Result;
error: aborting due to previous error
16 | E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E`
| ^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use SomeEnum::E;`
+help: possible candidate is found in another module, you can import it into scope
+ | use SomeEnum::E;
error: aborting due to previous error
53 | impl Mul for Foo {
| ^^^ not found in this scope
|
- = help: possible candidates are found in other modules, you can import them into scope:
- `use mul1::Mul;`
- `use mul2::Mul;`
- `use std::ops::Mul;`
+help: possible candidates are found in other modules, you can import them into scope
+ | use mul1::Mul;
+ | use mul2::Mul;
+ | use std::ops::Mul;
error[E0412]: cannot find type `Mul` in this scope
--> $DIR/issue-21221-1.rs:72:16
72 | fn getMul() -> Mul {
| ^^^ not found in this scope
|
- = help: possible candidates are found in other modules, you can import them into scope:
- `use mul1::Mul;`
- `use mul2::Mul;`
- `use mul3::Mul;`
- `use mul4::Mul;`
- and 2 other candidates
+help: possible candidates are found in other modules, you can import them into scope
+ | use mul1::Mul;
+ | use mul2::Mul;
+ | use mul3::Mul;
+ | use mul4::Mul;
+and 2 other candidates
error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope
--> $DIR/issue-21221-1.rs:83:6
88 | impl Div for Foo {
| ^^^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use std::ops::Div;`
+help: possible candidate is found in another module, you can import it into scope
+ | use std::ops::Div;
error: cannot continue compilation due to previous error
28 | impl T for Foo { }
| ^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use foo::bar::T;`
+help: possible candidate is found in another module, you can import it into scope
+ | use foo::bar::T;
error: main function not found
25 | impl OuterTrait for Foo {}
| ^^^^^^^^^^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use issue_21221_3::outer::OuterTrait;`
+help: possible candidate is found in another module, you can import it into scope
+ | use issue_21221_3::outer::OuterTrait;
error: cannot continue compilation due to previous error
20 | impl T for Foo {}
| ^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use issue_21221_4::T;`
+help: possible candidate is found in another module, you can import it into scope
+ | use issue_21221_4::T;
error: cannot continue compilation due to previous error
20 | impl Foo for S { //~ ERROR expected trait, found type alias `Foo`
| ^^^ type aliases cannot be used for traits
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use issue_3907::Foo;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use issue_3907::Foo;
error: cannot continue compilation due to previous error
| did you mean `S`?
| constructor is not visible here due to private fields
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use m::n::Z;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use m::n::Z;
error[E0423]: expected value, found struct `S`
--> $DIR/privacy-struct-ctor.rs:36:5
| did you mean `S { /* fields */ }`?
| constructor is not visible here due to private fields
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use m::S;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use m::S;
error[E0423]: expected value, found struct `xcrate::S`
--> $DIR/privacy-struct-ctor.rs:42:5
| did you mean `xcrate::S { /* fields */ }`?
| constructor is not visible here due to private fields
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use m::S;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use m::S;
error: tuple struct `Z` is private
--> $DIR/privacy-struct-ctor.rs:25:9
15 | impl<T: Clone, Add> Add for Foo<T> {
| ^^^ not a trait
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use std::ops::Add;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use std::ops::Add;
error: main function not found
-Subproject commit cf17c9f7118f544ec304ed6f50d92b3759487123
+Subproject commit 13d92c64d0153d95dbabeb49b828bbbef4b1bb34
}
fn main() {
- let docs = env::args().nth(1).unwrap();
+ let docs = env::args_os().nth(1).unwrap();
let docs = env::current_dir().unwrap().join(docs);
let mut errors = false;
walk(&mut HashMap::new(), &docs, &docs, &mut errors);
struct FileEntry {
source: String,
ids: HashSet<String>,
- names: HashSet<String>,
}
type Cache = HashMap<PathBuf, FileEntry>;
impl FileEntry {
fn parse_ids(&mut self, file: &Path, contents: &str, errors: &mut bool) {
if self.ids.is_empty() {
- with_attrs_in_source(contents, " id", |fragment, i| {
+ with_attrs_in_source(contents, " id", |fragment, i, _| {
let frag = fragment.trim_left_matches("#").to_owned();
if !self.ids.insert(frag) {
*errors = true;
});
}
}
-
- fn parse_names(&mut self, contents: &str) {
- if self.names.is_empty() {
- with_attrs_in_source(contents, " name", |fragment, _| {
- let frag = fragment.trim_left_matches("#").to_owned();
- self.names.insert(frag);
- });
- }
- }
}
fn walk(cache: &mut Cache, root: &Path, dir: &Path, errors: &mut bool) {
file: &Path,
errors: &mut bool)
-> Option<PathBuf> {
- // ignore js files as they are not prone to errors as the rest of the
- // documentation is and they otherwise bring up false positives.
- if file.extension().and_then(|s| s.to_str()) == Some("js") {
- return None;
- }
-
- // ignore handlebars files as they use {{}} to build links, we only
- // want to test the generated files
- if file.extension().and_then(|s| s.to_str()) == Some("hbs") {
+ // Ignore none HTML files.
+ if file.extension().and_then(|s| s.to_str()) != Some("html") {
return None;
}
return None;
}
- // mdbook uses the HTML <base> tag to handle links for subdirectories, which
- // linkchecker doesn't support
- if file.to_str().unwrap().contains("unstable-book") {
- return None;
- }
-
- let res = load_file(cache, root, PathBuf::from(file), SkipRedirect);
+ let res = load_file(cache, root, file, SkipRedirect);
let (pretty_file, contents) = match res {
Ok(res) => res,
Err(_) => return None,
cache.get_mut(&pretty_file)
.unwrap()
.parse_ids(&pretty_file, &contents, errors);
- cache.get_mut(&pretty_file)
- .unwrap()
- .parse_names(&contents);
}
// Search for anything that's the regex 'href[ ]*=[ ]*".*?"'
- with_attrs_in_source(&contents, " href", |url, i| {
+ with_attrs_in_source(&contents, " href", |url, i, base| {
// Ignore external URLs
if url.starts_with("http:") || url.starts_with("https:") ||
url.starts_with("javascript:") || url.starts_with("ftp:") ||
// Once we've plucked out the URL, parse it using our base url and
// then try to extract a file path.
let mut path = file.to_path_buf();
- if !url.is_empty() {
+ if !base.is_empty() || !url.is_empty() {
path.pop();
- for part in Path::new(url).components() {
+ for part in Path::new(base).join(url).components() {
match part {
Component::Prefix(_) |
Component::RootDir => panic!(),
}
}
- if let Some(extension) = path.extension() {
- // don't check these files
- if extension == "png" {
- return;
- }
- }
-
// Alright, if we've found a file name then this file had better
// exist! If it doesn't then we register and print an error.
if path.exists() {
pretty_path.display());
return;
}
- let res = load_file(cache, root, path.clone(), FromRedirect(false));
+ if let Some(extension) = path.extension() {
+ // Ignore none HTML files.
+ if extension != "html" {
+ return;
+ }
+ }
+ let res = load_file(cache, root, &path, FromRedirect(false));
let (pretty_path, contents) = match res {
Ok(res) => res,
Err(LoadError::IOError(err)) => {
- panic!(format!("error loading {}: {}", path.display(), err));
+ panic!("error loading {}: {}", path.display(), err);
}
Err(LoadError::BrokenRedirect(target, _)) => {
*errors = true;
let entry = &mut cache.get_mut(&pretty_path).unwrap();
entry.parse_ids(&pretty_path, &contents, errors);
- entry.parse_names(&contents);
- if !(entry.ids.contains(*fragment) || entry.names.contains(*fragment)) {
+ if !entry.ids.contains(*fragment) {
*errors = true;
- print!("{}:{}: broken link fragment ",
+ print!("{}:{}: broken link fragment ",
pretty_file.display(),
i + 1);
println!("`#{}` pointing to `{}`", fragment, pretty_path.display());
fn load_file(cache: &mut Cache,
root: &Path,
- mut file: PathBuf,
+ file: &Path,
redirect: Redirect)
-> Result<(PathBuf, String), LoadError> {
let mut contents = String::new();
None
}
Entry::Vacant(entry) => {
- let mut fp = File::open(file.clone()).map_err(|err| {
+ let mut fp = File::open(file).map_err(|err| {
if let FromRedirect(true) = redirect {
- LoadError::BrokenRedirect(file.clone(), err)
+ LoadError::BrokenRedirect(file.to_path_buf(), err)
} else {
LoadError::IOError(err)
}
entry.insert(FileEntry {
source: contents.clone(),
ids: HashSet::new(),
- names: HashSet::new(),
});
}
maybe
}
};
- file.pop();
- match maybe_redirect.map(|url| file.join(url)) {
+ match maybe_redirect.map(|url| file.parent().unwrap().join(url)) {
Some(redirect_file) => {
- let path = PathBuf::from(redirect_file);
- load_file(cache, root, path, FromRedirect(true))
+ load_file(cache, root, &redirect_file, FromRedirect(true))
}
None => Ok((pretty_file, contents)),
}
})
}
-fn with_attrs_in_source<F: FnMut(&str, usize)>(contents: &str, attr: &str, mut f: F) {
+fn with_attrs_in_source<F: FnMut(&str, usize, &str)>(contents: &str, attr: &str, mut f: F) {
+ let mut base = "";
for (i, mut line) in contents.lines().enumerate() {
while let Some(j) = line.find(attr) {
let rest = &line[j + attr.len()..];
+ // The base tag should always be the first link in the document so
+ // we can get away with using one pass.
+ let is_base = line[..j].ends_with("<base");
line = rest;
let pos_equals = match rest.find("=") {
Some(i) => i,
Some(i) => &rest[..i],
None => continue,
};
- f(url, i)
+ if is_base {
+ base = url;
+ continue;
+ }
+ f(url, i, base)
}
}
}
-Subproject commit 207c18da7d73faf0217fa433cce3a9d075f2fe25
+Subproject commit 38ca9b702b73c03959e447f5dae56eff7497c986
--- /dev/null
+Subproject commit 6a2c5d129101762d204185b888d62a244011c422
"Unlicense/MIT",
];
-/// These MPL licensed projects are acceptable, but only these.
+// These are exceptions to Rust's permissive licensing policy, and
+// should be considered bugs. Exceptions are only allowed in Rust
+// tooling. It is _crucial_ that no exception crates be dependencies
+// of the Rust runtime (std / test).
static EXCEPTIONS: &'static [&'static str] = &[
- "mdbook",
- "openssl",
- "pest",
- "thread-id",
+ "mdbook", // MPL2, mdbook
+ "openssl", // BSD+advertising clause, cargo, mdbook
+ "pest", // MPL2, mdbook via handlebars
+ "thread-id", // Apache-2.0, mdbook
];
pub fn check(path: &Path, bad: &mut bool) {
"src/libbacktrace",
"src/compiler-rt",
"src/rustllvm",
- "src/rust-installer",
"src/liblibc",
"src/vendor",
"src/rt/hoedown",
"src/tools/cargo",
"src/tools/rls",
+ "src/tools/rust-installer",
];
skip.iter().any(|p| path.ends_with(p))
}
contents.truncate(0);
t!(t!(File::open(file), file).read_to_string(&mut contents));
+
+ if contents.is_empty() {
+ tidy_error!(bad, "{}: empty file", file.display());
+ }
+
let skip_cr = contents.contains("ignore-tidy-cr");
let skip_tab = contents.contains("ignore-tidy-tab");
let skip_length = contents.contains("ignore-tidy-linelength");