[submodule "src/compiler-rt"]
path = src/compiler-rt
url = https://github.com/rust-lang/compiler-rt.git
-[submodule "src/rt/hoedown"]
- path = src/rt/hoedown
- url = https://github.com/rust-lang/hoedown.git
- branch = rust-2015-09-21-do-not-delete
[submodule "src/jemalloc"]
path = src/jemalloc
url = https://github.com/rust-lang/jemalloc.git
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-03-22-sccache-x86_64-apple-darwin &&
+ travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-ninja
SCRIPT: python x.py test
MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
- MINGW_ARCHIVE: i686-6.3.0-release-win32-dwarf-rt_v5-rev1.7z
+ MINGW_ARCHIVE: i686-6.2.0-release-win32-dwarf-rt_v5-rev1.7z
MINGW_DIR: mingw32
- MSYS_BITS: 64
SCRIPT: python x.py test
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-ninja
MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
- MINGW_ARCHIVE: x86_64-6.3.0-release-win32-seh-rt_v5-rev1.7z
+ MINGW_ARCHIVE: x86_64-6.2.0-release-win32-seh-rt_v5-rev1.7z
MINGW_DIR: mingw64
# 32/64 bit MSVC and GNU deployment
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-ninja
SCRIPT: python x.py dist
MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
- MINGW_ARCHIVE: i686-6.3.0-release-win32-dwarf-rt_v5-rev1.7z
+ MINGW_ARCHIVE: i686-6.2.0-release-win32-dwarf-rt_v5-rev1.7z
MINGW_DIR: mingw32
DEPLOY: 1
- MSYS_BITS: 64
SCRIPT: python x.py dist
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-ninja
MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
- MINGW_ARCHIVE: x86_64-6.3.0-release-win32-seh-rt_v5-rev1.7z
+ MINGW_ARCHIVE: x86_64-6.2.0-release-win32-seh-rt_v5-rev1.7z
MINGW_DIR: mingw64
DEPLOY: 1
- set PATH=C:\Python27;%PATH%
# Download and install sccache
- - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-22-sccache-x86_64-pc-windows-msvc
- - mv 2017-03-22-sccache-x86_64-pc-windows-msvc sccache.exe
+ - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-pc-windows-msvc
+ - mv 2017-03-24-sccache-x86_64-pc-windows-msvc sccache.exe
- set PATH=%PATH%;%CD%
# Download and install ninja
-Subproject commit c995e9eb5acf3976ae8674a0dc6d9e958053d9fd
+Subproject commit 4e95c6b41eca3388f54dd5f7787366ad2df637b5
[[package]]
name = "aho-corasick"
-version = "0.6.2"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
dependencies = [
"build_helper 0.1.0",
"core 0.0.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.0.0",
]
[[package]]
name = "bitflags"
-version = "0.8.0"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
"build_helper 0.1.0",
"cmake 0.1.22 (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.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (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 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "clap"
-version = "2.21.1"
+version = "2.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
dependencies = [
"build_helper 0.1.0",
"core 0.0.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "compiletest"
version = "0.0.0"
dependencies = [
- "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "env_logger"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "env_logger"
version = "0.4.2"
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "gcc"
-version = "0.3.44"
+version = "0.3.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
[[package]]
name = "handlebars"
-version = "0.25.1"
+version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.5 (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)",
[[package]]
name = "lazy_static"
-version = "0.2.4"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "linkchecker"
version = "0.1.0"
-[[package]]
-name = "log"
-version = "0.0.0"
-
[[package]]
name = "log"
version = "0.3.7"
version = "0.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "handlebars 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "pulldown-cmark"
+version = "0.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "qemu-test-client"
version = "0.1.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
name = "rustbook"
version = "0.1.0"
dependencies = [
- "clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
"arena 0.0.0",
"fmt_macros 0.0.0",
"graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (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",
name = "rustc_back"
version = "0.0.0"
dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"syntax 0.0.0",
]
version = "0.0.0"
dependencies = [
"graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
dependencies = [
"arena 0.0.0",
"graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_math 0.0.0",
name = "rustc_data_structures"
version = "0.0.0"
dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
]
version = "0.0.0"
dependencies = [
"arena 0.0.0",
+ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"proc_macro_plugin 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
version = "0.0.0"
dependencies = [
"graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"serialize 0.0.0",
name = "rustc_lint"
version = "0.0.0"
dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_eval 0.0.0",
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_bitflags 0.0.0",
]
version = "0.0.0"
dependencies = [
"flate 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"proc_macro 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
version = "0.0.0"
dependencies = [
"graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_bitflags 0.0.0",
"rustc_const_eval 0.0.0",
name = "rustc_passes"
version = "0.0.0"
dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0",
version = "0.0.0"
dependencies = [
"arena 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_errors 0.0.0",
"syntax 0.0.0",
name = "rustc_save_analysis"
version = "0.0.0"
dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-data 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-span 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
version = "0.0.0"
dependencies = [
"flate 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_bitflags 0.0.0",
dependencies = [
"arena 0.0.0",
"fmt_macros 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_eval 0.0.0",
dependencies = [
"arena 0.0.0",
"build_helper 0.1.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.0.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)",
+ "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",
"rustc_back 0.0.0",
"rustc_const_eval 0.0.0",
"collections 0.0.0",
"compiler_builtins 0.0.0",
"core 0.0.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.0.0",
"panic_abort 0.0.0",
"panic_unwind 0.0.0",
name = "syntax"
version = "0.0.0"
dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_bitflags 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
version = "0.0.0"
dependencies = [
"fmt_macros 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"proc_macro 0.0.0",
"rustc_errors 0.0.0",
"syntax 0.0.0",
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
-"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"
+"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 bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
-"checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162"
-"checksum clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "74a80f603221c9cd9aa27a28f52af452850051598537bb6b359c38a7d61e5cda"
+"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
+"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 dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
-"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
-"checksum gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a32cd40070d7611ab76343dcb3204b2bb28c8a9450989a83a3d590248142f439"
+"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae"
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
-"checksum handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b2249f6f0dc5a3bb2b3b1a8f797dfccbc4b053344d773d654ad565e51427d335"
+"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.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7291b1dd97d331f752620b02dfdbc231df7fc01bf282a00769e1cdb963c460dc"
+"checksum lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97"
"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 mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "06a68e8738e42b38a02755d3ce5fa12d559e17acb238e4326cbc3cc056e65280"
"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
"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 quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
.arg(sysroot)
.env(bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap());
+
+ // Pass the `rustbuild` feature flag to crates which rustbuild is
+ // building. See the comment in bootstrap/lib.rs where this env var is
+ // set for more details.
+ if env::var_os("RUSTBUILD_UNSTABLE").is_some() {
+ cmd.arg("--cfg").arg("rustbuild");
+ }
+
std::process::exit(match cmd.status() {
Ok(s) => s.code().unwrap_or(1),
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
.arg(ADB_TEST_DIR));
let target_dir = format!("{}/{}", ADB_TEST_DIR, target);
- build.run(Command::new("adb").args(&["shell", "mkdir", &target_dir[..]]));
+ build.run(Command::new("adb").args(&["shell", "mkdir", &target_dir]));
for f in t!(build.sysroot_libdir(compiler, target).read_dir()) {
let f = t!(f);
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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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 && \
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV TARGETS=arm-linux-androideabi
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin:/x-tools/x86_64-unknown-netbsd/bin
ENTRYPOINT ["/rustroot/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV HOSTS=i686-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
lib32stdc++6
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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 && \
}
curl https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \
- tar xzf -
+ tar xzf -
+
+# Some versions of the EMSDK archive have their contents in .emsdk-portable
+# and others in emsdk_portable. Make sure the EMSDK ends up in a fixed path.
+if [ -d emsdk-portable ]; then
+ mv emsdk-portable emsdk_portable
+fi
+
+if [ ! -d emsdk_portable ]; then
+ echo "ERROR: Invalid emsdk archive. Dumping working directory." >&2
+ ls -l
+ exit 1
+fi
+
+# Some versions of the EMSDK set the permissions of the root directory to
+# 0700. Ensure the directory is readable by all users.
+chmod 755 emsdk_portable
+
source emsdk_portable/emsdk_env.sh
hide_output emsdk update
hide_output emsdk install --build=Release sdk-tag-1.37.1-32bit
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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-03-22-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-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 && \
-Subproject commit 9bd223ca406b1170a24942d6474f9e8a56f4a420
+Subproject commit a2c56870d4dc589237102cc5e0fe7b9ebd0d14a1
-Subproject commit d08fe97d12b41c1ed8cc7701e545864132783941
+Subproject commit 616b98444ff4eb5260deee95ee3e090dfd98b947
-Subproject commit 516549972d61c8946542d1a34afeae97167ff77b
+Subproject commit acedc32cacae80cf2f4925753a4ce7f7ffd7c86a
- [abi_vectorcall](abi-vectorcall.md)
- [abi_x86_interrupt](abi-x86-interrupt.md)
- [advanced_slice_patterns](advanced-slice-patterns.md)
+- [alloc](alloc.md)
- [alloc_jemalloc](alloc-jemalloc.md)
- [alloc_system](alloc-system.md)
- [allocator](allocator.md)
- [allow_internal_unstable](allow-internal-unstable.md)
+- [as_unsafe_cell](as-unsafe-cell.md)
+- [ascii_ctype](ascii-ctype.md)
- [asm](asm.md)
- [associated_consts](associated-consts.md)
- [associated_type_defaults](associated-type-defaults.md)
- [attr_literals](attr-literals.md)
+- [binary_heap_extras](binary-heap-extras.md)
+- [binary_heap_peek_mut_pop](binary-heap-peek-mut-pop.md)
+- [borrow_state](borrow-state.md)
+- [box_heap](box-heap.md)
- [box_patterns](box-patterns.md)
- [box_syntax](box-syntax.md)
+- [c_void_variant](c-void-variant.md)
+- [catch_expr](catch-expr.md)
- [cfg_target_feature](cfg-target-feature.md)
- [cfg_target_has_atomic](cfg-target-has-atomic.md)
- [cfg_target_thread_local](cfg-target-thread-local.md)
- [cfg_target_vendor](cfg-target-vendor.md)
+- [char_escape_debug](char-escape-debug.md)
+- [closure_to_fn_coercion](closure-to-fn-coercion.md)
+- [coerce_unsized](coerce-unsized.md)
+- [collection_placement](collection-placement.md)
+- [collections](collections.md)
+- [collections_range](collections-range.md)
+- [command_envs](command-envs.md)
- [compiler_builtins](compiler-builtins.md)
+- [compiler_builtins_lib](compiler-builtins-lib.md)
- [concat_idents](concat-idents.md)
+- [concat_idents_macro](concat-idents-macro.md)
- [conservative_impl_trait](conservative-impl-trait.md)
- [const_fn](const-fn.md)
- [const_indexing](const-indexing.md)
+- [core_char_ext](core-char-ext.md)
+- [core_float](core-float.md)
+- [core_intrinsics](core-intrinsics.md)
+- [core_panic](core-panic.md)
+- [core_private_bignum](core-private-bignum.md)
+- [core_private_diy_float](core-private-diy-float.md)
+- [core_slice_ext](core-slice-ext.md)
+- [core_str_ext](core-str-ext.md)
- [custom_attribute](custom-attribute.md)
- [custom_derive](custom-derive.md)
+- [dec2flt](dec2flt.md)
+- [decode_utf8](decode-utf8.md)
- [default_type_parameter_fallback](default-type-parameter-fallback.md)
+- [derive_clone_copy](derive-clone-copy.md)
+- [derive_eq](derive-eq.md)
+- [discriminant_value](discriminant-value.md)
- [drop_types_in_const](drop-types-in-const.md)
- [dropck_eyepatch](dropck-eyepatch.md)
- [dropck_parametricity](dropck-parametricity.md)
+- [enumset](enumset.md)
+- [error_type_id](error-type-id.md)
+- [exact_size_is_empty](exact-size-is-empty.md)
- [exclusive_range_pattern](exclusive-range-pattern.md)
-- [field_init_shorthand](field-init-shorthand.md)
+- [fd](fd.md)
+- [fd_read](fd-read.md)
+- [fixed_size_array](fixed-size-array.md)
+- [float_extras](float-extras.md)
+- [flt2dec](flt2dec.md)
+- [fmt_flags_align](fmt-flags-align.md)
+- [fmt_internals](fmt-internals.md)
+- [fn_traits](fn-traits.md)
+- [fnbox](fnbox.md)
- [fundamental](fundamental.md)
+- [fused](fused.md)
+- [future_atomic_orderings](future-atomic-orderings.md)
- [generic_param_attrs](generic-param-attrs.md)
+- [get_type_id](get-type-id.md)
+- [heap_api](heap-api.md)
+- [i128](i128.md)
- [i128_type](i128-type.md)
+- [inclusive_range](inclusive-range.md)
- [inclusive_range_syntax](inclusive-range-syntax.md)
+- [int_error_internals](int-error-internals.md)
+- [integer_atomics](integer-atomics.md)
+- [into_boxed_c_str](into-boxed-c-str.md)
+- [into_boxed_os_str](into-boxed-os-str.md)
+- [into_boxed_path](into-boxed-path.md)
- [intrinsics](intrinsics.md)
+- [io](io.md)
+- [io_error_internals](io-error-internals.md)
+- [ip](ip.md)
+- [is_unique](is-unique.md)
+- [iter_rfind](iter-rfind.md)
- [lang_items](lang-items.md)
+- [libstd_io_internals](libstd-io-internals.md)
+- [libstd_sys_internals](libstd-sys-internals.md)
+- [libstd_thread_internals](libstd-thread-internals.md)
- [link_args](link-args.md)
- [link_cfg](link-cfg.md)
- [link_llvm_intrinsics](link-llvm-intrinsics.md)
- [linkage](linkage.md)
+- [linked_list_extras](linked-list-extras.md)
- [log_syntax](log-syntax.md)
+- [lookup_host](lookup-host.md)
- [loop_break_value](loop-break-value.md)
- [macro_reexport](macro-reexport.md)
- [main](main.md)
+- [map_entry_recover_keys](map-entry-recover-keys.md)
+- [mpsc_select](mpsc-select.md)
+- [n16](n16.md)
- [naked_functions](naked-functions.md)
- [needs_allocator](needs-allocator.md)
- [needs_panic_runtime](needs-panic-runtime.md)
- [never_type](never-type.md)
+- [never_type_impls](never-type-impls.md)
- [no_core](no-core.md)
- [no_debug](no-debug.md)
- [non_ascii_idents](non-ascii-idents.md)
+- [nonzero](nonzero.md)
- [omit_gdb_pretty_printer_section](omit-gdb-pretty-printer-section.md)
- [on_unimplemented](on-unimplemented.md)
+- [once_poison](once-poison.md)
+- [oom](oom.md)
- [optin_builtin_traits](optin-builtin-traits.md)
+- [option_entry](option-entry.md)
+- [osstring_shrink_to_fit](osstring-shrink-to-fit.md)
+- [panic_abort](panic-abort.md)
- [panic_runtime](panic-runtime.md)
+- [panic_unwind](panic-unwind.md)
+- [pattern](pattern.md)
+- [peek](peek.md)
+- [placement_in](placement-in.md)
- [placement_in_syntax](placement-in-syntax.md)
+- [placement_new_protocol](placement-new-protocol.md)
- [platform_intrinsics](platform-intrinsics.md)
- [plugin](plugin.md)
- [plugin_registrar](plugin-registrar.md)
- [prelude_import](prelude-import.md)
+- [print](print.md)
- [proc_macro](proc-macro.md)
+- [proc_macro_internals](proc-macro-internals.md)
+- [process_try_wait](process-try-wait.md)
+- [pub_restricted](pub-restricted.md)
+- [question_mark_carrier](question-mark-carrier.md)
- [quote](quote.md)
+- [rand](rand.md)
+- [range_contains](range-contains.md)
+- [raw](raw.md)
+- [rc_would_unwrap](rc-would-unwrap.md)
- [relaxed_adts](relaxed-adts.md)
- [repr_simd](repr-simd.md)
+- [retain_hash_collection](retain-hash-collection.md)
+- [rt](rt.md)
- [rustc_attrs](rustc-attrs.md)
- [rustc_diagnostic_macros](rustc-diagnostic-macros.md)
+- [rustc_private](rustc-private.md)
+- [rustdoc](rustdoc.md)
- [rvalue_static_promotion](rvalue-static-promotion.md)
- [sanitizer_runtime](sanitizer-runtime.md)
+- [sanitizer_runtime_lib](sanitizer-runtime-lib.md)
+- [set_stdio](set-stdio.md)
+- [shared](shared.md)
- [simd](simd.md)
- [simd_ffi](simd-ffi.md)
+- [sip_hash_13](sip-hash-13.md)
+- [slice_concat_ext](slice-concat-ext.md)
+- [slice_get_slice](slice-get-slice.md)
- [slice_patterns](slice-patterns.md)
+- [sort_internals](sort-internals.md)
- [sort_unstable](sort-unstable.md)
- [specialization](specialization.md)
- [staged_api](staged-api.md)
- [start](start.md)
- [static_nobundle](static-nobundle.md)
-- [static_recursion](static-recursion.md)
+- [step_by](step-by.md)
+- [step_trait](step-trait.md)
- [stmt_expr_attributes](stmt-expr-attributes.md)
+- [str_escape](str-escape.md)
+- [str_internals](str-internals.md)
- [struct_field_attributes](struct-field-attributes.md)
- [structural_match](structural-match.md)
- [target_feature](target-feature.md)
- [test](test.md)
+- [thread_id](thread-id.md)
- [thread_local](thread-local.md)
+- [thread_local_internals](thread-local-internals.md)
+- [thread_local_state](thread-local-state.md)
- [trace_macros](trace-macros.md)
+- [trusted_len](trusted-len.md)
+- [try_from](try-from.md)
- [type_ascription](type-ascription.md)
- [unboxed_closures](unboxed-closures.md)
+- [unicode](unicode.md)
+- [unique](unique.md)
+- [unsize](unsize.md)
- [untagged_unions](untagged-unions.md)
- [unwind_attributes](unwind-attributes.md)
+- [update_panic_count](update-panic-count.md)
- [use_extern_macros](use-extern-macros.md)
+- [utf8_error_error_len](utf8-error-error-len.md)
+- [vec_remove_item](vec-remove-item.md)
+- [windows_c](windows-c.md)
+- [windows_handle](windows-handle.md)
+- [windows_net](windows-net.md)
+- [windows_stdio](windows-stdio.md)
- [windows_subsystem](windows-subsystem.md)
+- [zero_one](zero-one.md)
--- /dev/null
+# `alloc`
+
+The tracking issue for this feature is: [#27783]
+
+[#27783]: https://github.com/rust-lang/rust/issues/27783
+
+------------------------
--- /dev/null
+# `as_unsafe_cell`
+
+The tracking issue for this feature is: [#27708]
+
+[#27708]: https://github.com/rust-lang/rust/issues/27708
+
+------------------------
--- /dev/null
+# `ascii_ctype`
+
+The tracking issue for this feature is: [#39658]
+
+[#39658]: https://github.com/rust-lang/rust/issues/39658
--- /dev/null
+# `binary_heap_extras`
+
+The tracking issue for this feature is: [#28147]
+
+[#28147]: https://github.com/rust-lang/rust/issues/28147
+
+------------------------
--- /dev/null
+# `binary_heap_peek_mut_pop`
+
+The tracking issue for this feature is: [#38863]
+
+[#38863]: https://github.com/rust-lang/rust/issues/38863
+
+------------------------
--- /dev/null
+# `borrow_state`
+
+The tracking issue for this feature is: [#27733]
+
+[#27733]: https://github.com/rust-lang/rust/issues/27733
+
+------------------------
--- /dev/null
+# `box_heap`
+
+The tracking issue for this feature is: [#27779]
+
+[#27779]: https://github.com/rust-lang/rust/issues/27779
+
+------------------------
--- /dev/null
+# `c_void_variant`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `catch_expr`
+
+The tracking issue for this feature is: [#31436]
+
+[#31436]: https://github.com/rust-lang/rust/issues/31436
+
+------------------------
--- /dev/null
+# `char_escape_debug`
+
+The tracking issue for this feature is: [#35068]
+
+[#35068]: https://github.com/rust-lang/rust/issues/35068
+
+------------------------
--- /dev/null
+# `closure_to_fn_coercion`
+
+The tracking issue for this feature is: [#39817]
+
+[#39817]: https://github.com/rust-lang/rust/issues/39817
+
+------------------------
--- /dev/null
+# `coerce_unsized`
+
+The tracking issue for this feature is: [#27732]
+
+[#27732]: https://github.com/rust-lang/rust/issues/27732
+
+------------------------
--- /dev/null
+# `collection_placement`
+
+The tracking issue for this feature is: [#30172]
+
+[#30172]: https://github.com/rust-lang/rust/issues/30172
+
+------------------------
--- /dev/null
+# `collections_range`
+
+The tracking issue for this feature is: [#30877]
+
+[#30877]: https://github.com/rust-lang/rust/issues/30877
+
+------------------------
--- /dev/null
+# `collections`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `command_envs`
+
+The tracking issue for this feature is: [#38526]
+
+[#38526]: https://github.com/rust-lang/rust/issues/38526
+
+------------------------
--- /dev/null
+# `compiler_builtins_lib`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `concat_idents_macro`
+
+The tracking issue for this feature is: [#29599]
+
+[#29599]: https://github.com/rust-lang/rust/issues/29599
+
+------------------------
--- /dev/null
+# `core_char_ext`
+
+The tracking issue for this feature is: [#32110]
+
+[#32110]: https://github.com/rust-lang/rust/issues/32110
+
+------------------------
--- /dev/null
+# `core_float`
+
+The tracking issue for this feature is: [#32110]
+
+[#32110]: https://github.com/rust-lang/rust/issues/32110
+
+------------------------
--- /dev/null
+# `core_intrinsics`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `core_panic`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `core_private_bignum`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `core_private_diy_float`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `core_slice_ext`
+
+The tracking issue for this feature is: [#32110]
+
+[#32110]: https://github.com/rust-lang/rust/issues/32110
+
+------------------------
--- /dev/null
+# `core_str_ext`
+
+The tracking issue for this feature is: [#32110]
+
+[#32110]: https://github.com/rust-lang/rust/issues/32110
+
+------------------------
--- /dev/null
+# `dec2flt`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `decode_utf8`
+
+The tracking issue for this feature is: [#27783]
+
+[#27783]: https://github.com/rust-lang/rust/issues/27783
+
+------------------------
--- /dev/null
+# `derive_clone_copy`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `derive_eq`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `discriminant_value`
+
+The tracking issue for this feature is: [#24263]
+
+[#24263]: https://github.com/rust-lang/rust/issues/24263
+
+------------------------
--- /dev/null
+# `enumset`
+
+The tracking issue for this feature is: [#37966]
+
+[#37966]: https://github.com/rust-lang/rust/issues/37966
+
+------------------------
--- /dev/null
+# `error_type_id`
+
+The tracking issue for this feature is: [#27745]
+
+[#27745]: https://github.com/rust-lang/rust/issues/27745
+
+------------------------
--- /dev/null
+# `exact_size_is_empty`
+
+The tracking issue for this feature is: [#35428]
+
+[#35428]: https://github.com/rust-lang/rust/issues/35428
+
+------------------------
--- /dev/null
+# `fd_read`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `fd`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
+++ /dev/null
-# `field_init_shorthand`
-
-The tracking issue for this feature is: [#37340]
-
-[#37340]: https://github.com/rust-lang/rust/issues/37340
-
-------------------------
-
-
-
--- /dev/null
+# `fixed_size_array`
+
+The tracking issue for this feature is: [#27778]
+
+[#27778]: https://github.com/rust-lang/rust/issues/27778
+
+------------------------
--- /dev/null
+# `float_extras`
+
+The tracking issue for this feature is: [#27752]
+
+[#27752]: https://github.com/rust-lang/rust/issues/27752
+
+------------------------
--- /dev/null
+# `flt2dec`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `fmt_flags_align`
+
+The tracking issue for this feature is: [#27726]
+
+[#27726]: https://github.com/rust-lang/rust/issues/27726
+
+------------------------
--- /dev/null
+# `fmt_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `fn_traits`
+
+The tracking issue for this feature is: [#29625]
+
+[#29625]: https://github.com/rust-lang/rust/issues/29625
+
+------------------------
--- /dev/null
+# `fnbox`
+
+The tracking issue for this feature is: [#28796]
+
+[#28796]: https://github.com/rust-lang/rust/issues/28796
+
+------------------------
--- /dev/null
+# `fused`
+
+The tracking issue for this feature is: [#35602]
+
+[#35602]: https://github.com/rust-lang/rust/issues/35602
+
+------------------------
--- /dev/null
+# `future_atomic_orderings`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `get_type_id`
+
+The tracking issue for this feature is: [#27745]
+
+[#27745]: https://github.com/rust-lang/rust/issues/27745
+
+------------------------
--- /dev/null
+# `heap_api`
+
+The tracking issue for this feature is: [#27700]
+
+[#27700]: https://github.com/rust-lang/rust/issues/27700
+
+------------------------
--- /dev/null
+# `i128`
+
+The tracking issue for this feature is: [#35118]
+
+[#35118]: https://github.com/rust-lang/rust/issues/35118
+
+------------------------
------------------------
+To get a range that goes from 0 to 10 and includes the value 10, you
+can write `0...10`:
+```rust
+#![feature(inclusive_range_syntax)]
+fn main() {
+ for i in 0...10 {
+ println!("{}", i);
+ }
+}
+```
--- /dev/null
+# `inclusive_range`
+
+The tracking issue for this feature is: [#28237]
+
+[#28237]: https://github.com/rust-lang/rust/issues/28237
+
+------------------------
--- /dev/null
+# `int_error_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `integer_atomics`
+
+The tracking issue for this feature is: [#32976]
+
+[#32976]: https://github.com/rust-lang/rust/issues/32976
+
+------------------------
--- /dev/null
+# `into_boxed_c_str`
+
+The tracking issue for this feature is: [#40380]
+
+[#40380]: https://github.com/rust-lang/rust/issues/40380
+
+------------------------
--- /dev/null
+# `into_boxed_os_str`
+
+The tracking issue for this feature is: [#into_boxed_os_str]
+
+[#into_boxed_os_str]: https://github.com/rust-lang/rust/issues/40380
+
+------------------------
--- /dev/null
+# `into_boxed_path`
+
+The tracking issue for this feature is: [#40380]
+
+[#40380]: https://github.com/rust-lang/rust/issues/40380
+
+------------------------
--- /dev/null
+# `io_error_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `io`
+
+The tracking issue for this feature is: [#27802]
+
+[#27802]: https://github.com/rust-lang/rust/issues/27802
+
+------------------------
--- /dev/null
+# `ip`
+
+The tracking issue for this feature is: [#27709]
+
+[#27709]: https://github.com/rust-lang/rust/issues/27709
+
+------------------------
--- /dev/null
+# `is_unique`
+
+The tracking issue for this feature is: [#28356]
+
+[#28356]: https://github.com/rust-lang/rust/issues/28356
+
+------------------------
--- /dev/null
+# `iter_rfind`
+
+The tracking issue for this feature is: [#39480]
+
+[#39480]: https://github.com/rust-lang/rust/issues/39480
+
+------------------------
--- /dev/null
+# `libstd_io_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `libstd_sys_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `libstd_thread_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `linked_list_extras`
+
+The tracking issue for this feature is: [#27794]
+
+[#27794]: https://github.com/rust-lang/rust/issues/27794
+
+------------------------
--- /dev/null
+# `lookup_host`
+
+The tracking issue for this feature is: [#27705]
+
+[#27705]: https://github.com/rust-lang/rust/issues/27705
+
+------------------------
--- /dev/null
+# `map_entry_recover_keys`
+
+The tracking issue for this feature is: [#34285]
+
+[#34285]: https://github.com/rust-lang/rust/issues/34285
--- /dev/null
+# `mpsc_select`
+
+The tracking issue for this feature is: [#27800]
+
+[#27800]: https://github.com/rust-lang/rust/issues/27800
--- /dev/null
+# `n16`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `never_type_impls`
+
+The tracking issue for this feature is: [#35121]
+
+[#35121]: https://github.com/rust-lang/rust/issues/35121
+
+------------------------
--- /dev/null
+# `nonzero`
+
+The tracking issue for this feature is: [#27730]
+
+[#27730]: https://github.com/rust-lang/rust/issues/27730
+
+------------------------
--- /dev/null
+# `once_poison`
+
+The tracking issue for this feature is: [#33577]
+
+[#33577]: https://github.com/rust-lang/rust/issues/33577
+
+------------------------
--- /dev/null
+# `oom`
+
+The tracking issue for this feature is: [#27700]
+
+[#27700]: https://github.com/rust-lang/rust/issues/27700
+
+------------------------
--- /dev/null
+# `option_entry`
+
+The tracking issue for this feature is: [#39288]
+
+[#39288]: https://github.com/rust-lang/rust/issues/39288
+
+------------------------
--- /dev/null
+# `osstring_shrink_to_fit`
+
+The tracking issue for this feature is: [#40421]
+
+[#40421]: https://github.com/rust-lang/rust/issues/40421
+
+------------------------
--- /dev/null
+# `panic_abort`
+
+The tracking issue for this feature is: [#32837]
+
+[#32837]: https://github.com/rust-lang/rust/issues/32837
+
+------------------------
--- /dev/null
+# `panic_unwind`
+
+The tracking issue for this feature is: [#32837]
+
+[#32837]: https://github.com/rust-lang/rust/issues/32837
+
+------------------------
--- /dev/null
+# `pattern`
+
+The tracking issue for this feature is: [#27721]
+
+[#27721]: https://github.com/rust-lang/rust/issues/27721
+
+------------------------
--- /dev/null
+# `peek`
+
+The tracking issue for this feature is: [#38980]
+
+[#38980]: https://github.com/rust-lang/rust/issues/38980
+
+------------------------
--- /dev/null
+# `placement_in`
+
+The tracking issue for this feature is: [#27779]
+
+[#27779]: https://github.com/rust-lang/rust/issues/27779
+
+------------------------
--- /dev/null
+# `placement_new_protocol`
+
+The tracking issue for this feature is: [#27779]
+
+[#27779]: https://github.com/rust-lang/rust/issues/27779
+
+------------------------
--- /dev/null
+# `print`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `proc_macro_internals`
+
+The tracking issue for this feature is: [#27812]
+
+[#27812]: https://github.com/rust-lang/rust/issues/27812
+
+------------------------
--- /dev/null
+# `process_try_wait`
+
+The tracking issue for this feature is: [#38903]
+
+[#38903]: https://github.com/rust-lang/rust/issues/38903
+
+------------------------
--- /dev/null
+# `pub_restricted`
+
+The tracking issue for this feature is: [#32409]
+
+[#38356]: https://github.com/rust-lang/rust/issues/32409
+
+------------------------
--- /dev/null
+# `question_mark_carrier`
+
+The tracking issue for this feature is: [#31436]
+
+[#31436]: https://github.com/rust-lang/rust/issues/31436
+
+------------------------
--- /dev/null
+# `rand`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `range_contains`
+
+The tracking issue for this feature is: [#32311]
+
+[#32311]: https://github.com/rust-lang/rust/issues/32311
+
+------------------------
--- /dev/null
+# `raw`
+
+The tracking issue for this feature is: [#27751]
+
+[#27751]: https://github.com/rust-lang/rust/issues/27751
+
+------------------------
--- /dev/null
+# `rc_would_unwrap`
+
+The tracking issue for this feature is: [#28356]
+
+[#28356]: https://github.com/rust-lang/rust/issues/28356
--- /dev/null
+# `retain_hash_collection`
+
+The tracking issue for this feature is: [#36648]
+
+[#36648]: https://github.com/rust-lang/rust/issues/36648
+
+------------------------
--- /dev/null
+# `rt`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `rustc_private`
+
+The tracking issue for this feature is: [#27812]
+
+[#27812]: https://github.com/rust-lang/rust/issues/27812
+
+------------------------
--- /dev/null
+# `rustdoc`
+
+The tracking issue for this feature is: [#27812]
+
+[#27812]: https://github.com/rust-lang/rust/issues/27812
+
+------------------------
--- /dev/null
+# `sanitizer_runtime_lib`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `set_stdio`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `shared`
+
+The tracking issue for this feature is: [#27730]
+
+[#27730]: https://github.com/rust-lang/rust/issues/27730
+
+------------------------
--- /dev/null
+# `sip_hash_13`
+
+The tracking issue for this feature is: [#34767]
+
+[#34767]: https://github.com/rust-lang/rust/issues/34767
+
+------------------------
--- /dev/null
+# `slice_concat_ext`
+
+The tracking issue for this feature is: [#27747]
+
+[#27747]: https://github.com/rust-lang/rust/issues/27747
+
+------------------------
--- /dev/null
+# `slice_get_slice`
+
+The tracking issue for this feature is: [#35729]
+
+[#35729]: https://github.com/rust-lang/rust/issues/35729
+
+------------------------
--- /dev/null
+# `sort_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
+++ /dev/null
-# `static_recursion`
-
-The tracking issue for this feature is: [#29719]
-
-[#29719]: https://github.com/rust-lang/rust/issues/29719
-
-------------------------
-
-
-
--- /dev/null
+# `step_by`
+
+The tracking issue for this feature is: [#27741]
+
+[#27741]: https://github.com/rust-lang/rust/issues/27741
+
+------------------------
--- /dev/null
+# `step_trait`
+
+The tracking issue for this feature is: [#27741]
+
+[#27741]: https://github.com/rust-lang/rust/issues/27741
+
+------------------------
--- /dev/null
+# `str_escape`
+
+The tracking issue for this feature is: [#27791]
+
+[#27791]: https://github.com/rust-lang/rust/issues/27791
+
+------------------------
--- /dev/null
+# `str_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `thread_id`
+
+The tracking issue for this feature is: [#21507]
+
+[#21507]: https://github.com/rust-lang/rust/issues/21507
+
+------------------------
--- /dev/null
+# `thread_local_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `thread_local_state`
+
+The tracking issue for this feature is: [#27716]
+
+[#27716]: https://github.com/rust-lang/rust/issues/27716
+
+------------------------
--- /dev/null
+# `trusted_len`
+
+The tracking issue for this feature is: [#37572]
+
+[#37572]: https://github.com/rust-lang/rust/issues/37572
+
+------------------------
--- /dev/null
+# `try_from`
+
+The tracking issue for this feature is: [#33417]
+
+[#33417]: https://github.com/rust-lang/rust/issues/33417
+
+------------------------
--- /dev/null
+# `unicode`
+
+The tracking issue for this feature is: [#27783]
+
+[#27783]: https://github.com/rust-lang/rust/issues/27783
+
+------------------------
--- /dev/null
+# `unique`
+
+The tracking issue for this feature is: [#27730]
+
+[#27730]: https://github.com/rust-lang/rust/issues/27730
+
+------------------------
--- /dev/null
+# `unsize`
+
+The tracking issue for this feature is: [#27732]
+
+[#27732]: https://github.com/rust-lang/rust/issues/27732
+
+------------------------
--- /dev/null
+# `update_panic_count`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `utf8_error_error_len`
+
+The tracking issue for this feature is: [#40494]
+
+[#40494]: https://github.com/rust-lang/rust/issues/40494
+
+------------------------
--- /dev/null
+# `vec_remove_item`
+
+The tracking issue for this feature is: [#40062]
+
+[#40062]: https://github.com/rust-lang/rust/issues/40062
+
+------------------------
--- /dev/null
+# `windows_c`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `windows_handle`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `windows_net`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `windows_stdio`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
--- /dev/null
+# `zero_one`
+
+The tracking issue for this feature is: [#27739]
+
+[#27739]: https://github.com/rust-lang/rust/issues/27739
+
+------------------------
let toknum = &s[content_end + 3 .. toknum_end];
let not_found = format!("didn't find token {:?} in the map", toknum);
- let proto_tok = tokens.get(toknum).expect(¬_found[..]);
+ let proto_tok = tokens.get(toknum).expect(¬_found);
let nm = Symbol::intern(content);
let mut token_file = File::open(&Path::new(&args.next().unwrap())).unwrap();
let mut token_list = String::new();
token_file.read_to_string(&mut token_list).unwrap();
- let token_map = parse_token_list(&token_list[..]);
+ let token_map = parse_token_list(&token_list);
let stdin = std::io::stdin();
let lock = stdin.lock();
let lines = lock.lines();
let antlr_tokens = lines.map(|l| parse_antlr_token(l.unwrap().trim(),
&token_map,
- &surrogate_pairs_pos[..],
+ &surrogate_pairs_pos,
has_bom));
for antlr_tok in antlr_tokens {
thread::spawn(move || {
check_links(&n);
let a: &[_] = &[&1, &2, &3];
- assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
+ assert_eq!(a, &*n.iter().collect::<Vec<_>>());
})
.join()
.ok()
//! Unicode string slices.
//!
+//! The `&str` type is one of the two main string types, the other being `String`.
+//! Unlike its `String` counterpart, its contents are borrowed.
+//!
+//! # Basic Usage
+//!
+//! A basic string declaration of `&str` type:
+//!
+//! ```
+//! let hello_world = "Hello, World!";
+//! ```
+//!
+//! Here we have declared a string literal, also known as a string slice.
+//! String literals have a static lifetime, which means the string `hello_world`
+//! is guaranteed to be valid for the duration of the entire program.
+//! We can explicitly specify `hello_world`'s lifetime as well:
+//!
+//! ```
+//! let hello_world: &'static str = "Hello, world!";
+//! ```
+//!
//! *[See also the `str` primitive type](../../std/primitive.str.html).*
-
#![stable(feature = "rust1", since = "1.0.0")]
// Many of the usings in this module are only used in the test configuration.
impl<T> FromIterator<T> for Vec<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> {
- <Self as SpecExtend<_, _>>::from_iter(iter.into_iter())
+ <Self as SpecExtend<T, I::IntoIter>>::from_iter(iter.into_iter())
}
}
impl<T> Extend<T> for Vec<T> {
#[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
- self.spec_extend(iter.into_iter())
+ <Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter())
}
}
vector
}
};
- vector.spec_extend(iterator);
+ <Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
vector
}
impl<T, I> SpecExtend<T, I> for Vec<T>
where I: TrustedLen<Item=T>,
{
- fn from_iter(iterator: I) -> Self {
+ default fn from_iter(iterator: I) -> Self {
let mut vector = Vec::new();
vector.spec_extend(iterator);
vector
}
}
+impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
+ fn from_iter(iterator: IntoIter<T>) -> Self {
+ // A common case is passing a vector into a function which immediately
+ // re-collects into a vector. We can short circuit this if the IntoIter
+ // has not been advanced at all.
+ if *iterator.buf == iterator.ptr as *mut T {
+ unsafe {
+ let vec = Vec::from_raw_parts(*iterator.buf as *mut T,
+ iterator.len(),
+ iterator.cap);
+ mem::forget(iterator);
+ vec
+ }
+ } else {
+ let mut vector = Vec::new();
+ vector.spec_extend(iterator);
+ vector
+ }
+ }
+}
+
impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>
where I: Iterator<Item=&'a T>,
T: Clone,
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
assert_eq!(vec.len(), 3);
}
+
+#[test]
+fn from_into_inner() {
+ let vec = vec![1, 2, 3];
+ let ptr = vec.as_ptr();
+ let vec = vec.into_iter().collect::<Vec<_>>();
+ assert_eq!(vec, [1, 2, 3]);
+ assert_eq!(vec.as_ptr(), ptr);
+
+ let ptr = &vec[1] as *const _;
+ let mut it = vec.into_iter();
+ it.next().unwrap();
+ let vec = it.collect::<Vec<_>>();
+ assert_eq!(vec, [2, 3]);
+ assert!(ptr != vec.as_ptr());
+}
}
}
+/// A helper struct for reverse ordering.
+///
+/// This struct is a helper to be used with functions like `Vec::sort_by_key` and
+/// can be used to reverse order a part of a key.
+///
+/// Example usage:
+///
+/// ```
+/// #![feature(reverse_cmp_key)]
+/// use std::cmp::Reverse;
+///
+/// let mut v = vec![1, 2, 3, 4, 5, 6];
+/// v.sort_by_key(|&num| (num > 3, Reverse(num)));
+/// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
+/// ```
+#[derive(PartialEq, Eq, Debug)]
+#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+pub struct Reverse<T>(pub T);
+
+#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+impl<T: PartialOrd> PartialOrd for Reverse<T> {
+ #[inline]
+ fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
+ other.0.partial_cmp(&self.0)
+ }
+}
+
+#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+impl<T: Ord> Ord for Reverse<T> {
+ #[inline]
+ fn cmp(&self, other: &Reverse<T>) -> Ordering {
+ other.0.cmp(&self.0)
+ }
+}
+
/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
///
/// An order is a total order if it is (for all `a`, `b` and `c`):
///
/// It rounds ``f`` to a float with 64 bit significand and multiplies it by the best approximation
/// of `10^e` (in the same floating point format). This is often enough to get the correct result.
-/// However, when the result is close to halfway between two adjecent (ordinary) floats, the
+/// However, when the result is close to halfway between two adjacent (ordinary) floats, the
/// compound rounding error from multiplying two approximation means the result may be off by a
/// few bits. When this happens, the iterative Algorithm R fixes things up.
///
//
// Therefore, when the rounded-off bits are != 0.5 ULP, they decide the rounding
// on their own. When they are equal and the remainder is non-zero, the value still
- // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainer
+ // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainder
// is zero, we have a half-to-even situation.
let bits = x.bit_length();
let lsb = bits - T::sig_bits() as usize;
fn drop(&mut self);
}
-/// The `Add` trait is used to specify the functionality of `+`.
+/// The addition operator `+`.
///
/// # Examples
///
add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
-/// The `Sub` trait is used to specify the functionality of `-`.
+/// The subtraction operator `-`.
///
/// # Examples
///
sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
-/// The `Mul` trait is used to specify the functionality of `*`.
+/// The multiplication operator `*`.
///
/// # Examples
///
mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
-/// The `Div` trait is used to specify the functionality of `/`.
+/// The division operator `/`.
///
/// # Examples
///
div_impl_float! { f32 f64 }
-/// The `Rem` trait is used to specify the functionality of `%`.
+/// The remainder operator `%`.
///
/// # Examples
///
rem_impl_float! { f32 f64 }
-/// The `Neg` trait is used to specify the functionality of unary `-`.
+/// The unary negation operator `-`.
///
/// # Examples
///
// neg_impl_unsigned! { usize u8 u16 u32 u64 }
neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
-/// The `Not` trait is used to specify the functionality of unary `!`.
+/// The unary logical negation operator `!`.
///
/// # Examples
///
not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-/// The `BitAnd` trait is used to specify the functionality of `&`.
+/// The bitwise AND operator `&`.
///
/// # Examples
///
bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-/// The `BitOr` trait is used to specify the functionality of `|`.
+/// The bitwise OR operator `|`.
///
/// # Examples
///
bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-/// The `BitXor` trait is used to specify the functionality of `^`.
+/// The bitwise XOR operator `^`.
///
/// # Examples
///
bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-/// The `Shl` trait is used to specify the functionality of `<<`.
+/// The left shift operator `<<`.
///
/// # Examples
///
shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
-/// The `Shr` trait is used to specify the functionality of `>>`.
+/// The right shift operator `>>`.
///
/// # Examples
///
shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
-/// The `AddAssign` trait is used to specify the functionality of `+=`.
+/// The addition assignment operator `+=`.
///
/// # Examples
///
add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
-/// The `SubAssign` trait is used to specify the functionality of `-=`.
+/// The subtraction assignment operator `-=`.
///
/// # Examples
///
sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
-/// The `MulAssign` trait is used to specify the functionality of `*=`.
+/// The multiplication assignment operator `*=`.
///
/// # Examples
///
mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
-/// The `DivAssign` trait is used to specify the functionality of `/=`.
+/// The division assignment operator `/=`.
///
/// # Examples
///
div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
-/// The `RemAssign` trait is used to specify the functionality of `%=`.
+/// The remainder assignment operator `%=`.
///
/// # Examples
///
rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
-/// The `BitAndAssign` trait is used to specify the functionality of `&=`.
+/// The bitwise AND assignment operator `&=`.
///
/// # Examples
///
bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-/// The `BitOrAssign` trait is used to specify the functionality of `|=`.
+/// The bitwise OR assignment operator `|=`.
///
/// # Examples
///
bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-/// The `BitXorAssign` trait is used to specify the functionality of `^=`.
+/// The bitwise XOR assignment operator `^=`.
///
/// # Examples
///
bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-/// The `ShlAssign` trait is used to specify the functionality of `<<=`.
+/// The left shift assignment operator `<<=`.
///
/// # Examples
///
shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
-/// The `ShrAssign` trait is used to specify the functionality of `>>=`.
+/// The right shift assignment operator `>>=`.
///
/// # Examples
///
///
/// assert_eq!(1909, good_year);
/// assert_eq!(0, bad_year);
+ /// ```
///
/// [`parse`]: ../../std/primitive.str.html#method.parse
/// [`FromStr`]: ../../std/str/trait.FromStr.html
- /// ```
#[inline]
#[stable(feature = "result_unwrap_or_default", since = "1.16.0")]
pub fn unwrap_or_default(self) -> T {
fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
where F: FnMut(&T, &T) -> bool
{
- for i in 2..v.len()+1 {
- shift_tail(&mut v[..i], is_less);
+ for i in 1..v.len() {
+ shift_tail(&mut v[..i+1], is_less);
}
}
#[cold]
fn break_patterns<T>(v: &mut [T]) {
let len = v.len();
-
if len >= 8 {
- // A random number will be taken modulo this one. The modulus is a power of two so that we
- // can simply take bitwise "and", thus avoiding costly CPU operations.
- let modulus = (len / 4).next_power_of_two();
- debug_assert!(modulus >= 1 && modulus <= len / 2);
-
- // Pseudorandom number generation from the "Xorshift RNGs" paper by George Marsaglia.
- let mut random = len;
- random ^= random << 13;
- random ^= random >> 17;
- random ^= random << 5;
- random &= modulus - 1;
- debug_assert!(random < len / 2);
-
- // The first index.
- let a = len / 4 * 2;
- debug_assert!(a >= 1 && a < len - 2);
-
- // The second index.
- let b = len / 4 + random;
- debug_assert!(b >= 1 && b < len - 2);
-
- // Swap neighbourhoods of `a` and `b`.
+ // Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia.
+ let mut random = len as u32;
+ let mut gen_u32 = || {
+ random ^= random << 13;
+ random ^= random >> 17;
+ random ^= random << 5;
+ random
+ };
+ let mut gen_usize = || {
+ if mem::size_of::<usize>() <= 4 {
+ gen_u32() as usize
+ } else {
+ (((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize
+ }
+ };
+
+ // Take random numbers modulo this number.
+ // The number fits into `usize` because `len` is not greater than `isize::MAX`.
+ let modulus = len.next_power_of_two();
+
+ // Some pivot candidates will be in the nearby of this index. Let's randomize them.
+ let pos = len / 4 * 2;
+
for i in 0..3 {
- v.swap(a - 1 + i, b - 1 + i);
+ // Generate a random number modulo `len`. However, in order to avoid costly operations
+ // we first take it modulo a power of two, and then decrease by `len` until it fits
+ // into the range `[0, len - 1]`.
+ let mut other = gen_usize() & (modulus - 1);
+ while other >= len {
+ other -= len;
+ }
+
+ v.swap(pos - 1 + i, other);
}
}
}
/// [`from_str`]: #tymethod.from_str
/// [`str`]: ../../std/primitive.str.html
/// [`parse`]: ../../std/primitive.str.html#method.parse
+///
+/// # Examples
+///
+/// Basic implementation of `FromStr` on an example `Point` type:
+///
+/// ```
+/// use std::str::FromStr;
+/// use std::num::ParseIntError;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct Point {
+/// x: i32,
+/// y: i32
+/// }
+///
+/// impl FromStr for Point {
+/// type Err = ParseIntError;
+///
+/// fn from_str(s: &str) -> Result<Self, Self::Err> {
+/// let coords: Vec<&str> = s.trim_matches(|p| p == '(' || p == ')' )
+/// .split(",")
+/// .collect();
+///
+/// let x_fromstr = coords[0].parse::<i32>()?;
+/// let y_fromstr = coords[1].parse::<i32>()?;
+///
+/// Ok(Point { x: x_fromstr, y: y_fromstr })
+/// }
+/// }
+///
+/// let p = Point::from_str("(1,2)");
+/// assert_eq!(p.unwrap(), Point{ x: 1, y: 2} )
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait FromStr: Sized {
/// The associated error which can be returned from parsing.
}
}
-/// An error returned when parsing a `bool` from a string fails.
+/// An error returned when parsing a `bool` using [`from_str`] fails
+///
+/// [`from_str`]: ../../std/primitive.bool.html#method.from_str
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseBoolError { _priv: () }
pub fn to_dot_string(&self) -> String {
match self {
&LabelStr(ref s) => format!("\"{}\"", s.escape_default()),
- &EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(&s[..])),
+ &EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(&s)),
&HtmlStr(ref s) => format!("<{}>", s),
}
}
let mut prefix = self.pre_escaped_content().into_owned();
let suffix = suffix.pre_escaped_content();
prefix.push_str(r"\n\n");
- prefix.push_str(&suffix[..]);
+ prefix.push_str(&suffix);
EscStr(prefix.into_cow())
}
}
type Node = Node;
type Edge = &'a Edge;
fn graph_id(&'a self) -> Id<'a> {
- Id::new(&self.name[..]).unwrap()
+ Id::new(self.name).unwrap()
}
fn node_id(&'a self, n: &Node) -> Id<'a> {
id_name(n)
-Subproject commit 64d954c6a76e896fbf7ed5c17e77c40e388abe84
+Subproject commit 05a2d197356ef253dfd985166576619ac9b6947f
+++ /dev/null
-[package]
-authors = ["The Rust Project Developers"]
-name = "log"
-version = "0.0.0"
-
-[lib]
-name = "log"
-path = "lib.rs"
-crate-type = ["dylib", "rlib"]
+++ /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.
-
-use std::ascii::AsciiExt;
-use std::cmp;
-
-#[derive(Debug, Clone)]
-pub struct LogDirective {
- pub name: Option<String>,
- pub level: u32,
-}
-
-pub const LOG_LEVEL_NAMES: [&'static str; 5] = ["ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
-
-/// Parse an individual log level that is either a number or a symbolic log level
-fn parse_log_level(level: &str) -> Option<u32> {
- level.parse::<u32>()
- .ok()
- .or_else(|| {
- let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
- pos.map(|p| p as u32 + 1)
- })
- .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
-}
-
-/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
-/// and return a vector with log directives.
-///
-/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in
-/// std::). Also supports string log levels of error, warn, info, and debug
-pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<String>) {
- let mut dirs = Vec::new();
-
- let mut parts = spec.split('/');
- let mods = parts.next();
- let filter = parts.next();
- if parts.next().is_some() {
- println!("warning: invalid logging spec '{}', ignoring it (too many '/'s)",
- spec);
- return (dirs, None);
- }
- if let Some(m) = mods {
- for s in m.split(',') {
- if s.is_empty() {
- continue;
- }
- let mut parts = s.split('=');
- let (log_level, name) =
- match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
- (Some(part0), None, None) => {
- // if the single argument is a log-level string or number,
- // treat that as a global fallback
- match parse_log_level(part0) {
- Some(num) => (num, None),
- None => (::MAX_LOG_LEVEL, Some(part0)),
- }
- }
- (Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
- (Some(part0), Some(part1), None) => {
- match parse_log_level(part1) {
- Some(num) => (num, Some(part0)),
- _ => {
- println!("warning: invalid logging spec '{}', ignoring it", part1);
- continue;
- }
- }
- }
- _ => {
- println!("warning: invalid logging spec '{}', ignoring it", s);
- continue;
- }
- };
- dirs.push(LogDirective {
- name: name.map(str::to_owned),
- level: log_level,
- });
- }
- }
-
- (dirs, filter.map(str::to_owned))
-}
-
-#[cfg(test)]
-mod tests {
- use super::parse_logging_spec;
-
- #[test]
- fn parse_logging_spec_valid() {
- let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4");
- assert_eq!(dirs.len(), 3);
- assert_eq!(dirs[0].name, Some("crate1::mod1".to_owned()));
- assert_eq!(dirs[0].level, 1);
-
- assert_eq!(dirs[1].name, Some("crate1::mod2".to_owned()));
- assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);
-
- assert_eq!(dirs[2].name, Some("crate2".to_owned()));
- assert_eq!(dirs[2].level, 4);
- assert!(filter.is_none());
- }
-
- #[test]
- fn parse_logging_spec_invalid_crate() {
- // test parse_logging_spec with multiple = in specification
- let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4");
- assert_eq!(dirs.len(), 1);
- assert_eq!(dirs[0].name, Some("crate2".to_owned()));
- assert_eq!(dirs[0].level, 4);
- assert!(filter.is_none());
- }
-
- #[test]
- fn parse_logging_spec_invalid_log_level() {
- // test parse_logging_spec with 'noNumber' as log level
- let (dirs, filter) = parse_logging_spec("crate1::mod1=noNumber,crate2=4");
- assert_eq!(dirs.len(), 1);
- assert_eq!(dirs[0].name, Some("crate2".to_owned()));
- assert_eq!(dirs[0].level, 4);
- assert!(filter.is_none());
- }
-
- #[test]
- fn parse_logging_spec_string_log_level() {
- // test parse_logging_spec with 'warn' as log level
- let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=warn");
- assert_eq!(dirs.len(), 1);
- assert_eq!(dirs[0].name, Some("crate2".to_owned()));
- assert_eq!(dirs[0].level, ::WARN);
- assert!(filter.is_none());
- }
-
- #[test]
- fn parse_logging_spec_empty_log_level() {
- // test parse_logging_spec with '' as log level
- let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=");
- assert_eq!(dirs.len(), 1);
- assert_eq!(dirs[0].name, Some("crate2".to_owned()));
- assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
- assert!(filter.is_none());
- }
-
- #[test]
- fn parse_logging_spec_global() {
- // test parse_logging_spec with no crate
- let (dirs, filter) = parse_logging_spec("warn,crate2=4");
- assert_eq!(dirs.len(), 2);
- assert_eq!(dirs[0].name, None);
- assert_eq!(dirs[0].level, 2);
- assert_eq!(dirs[1].name, Some("crate2".to_owned()));
- assert_eq!(dirs[1].level, 4);
- assert!(filter.is_none());
- }
-
- #[test]
- fn parse_logging_spec_valid_filter() {
- let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4/abc");
- assert_eq!(dirs.len(), 3);
- assert_eq!(dirs[0].name, Some("crate1::mod1".to_owned()));
- assert_eq!(dirs[0].level, 1);
-
- assert_eq!(dirs[1].name, Some("crate1::mod2".to_owned()));
- assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);
-
- assert_eq!(dirs[2].name, Some("crate2".to_owned()));
- assert_eq!(dirs[2].level, 4);
- assert!(filter.is_some() && filter.unwrap().to_owned() == "abc");
- }
-
- #[test]
- fn parse_logging_spec_invalid_crate_filter() {
- let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4/a.c");
- assert_eq!(dirs.len(), 1);
- assert_eq!(dirs[0].name, Some("crate2".to_owned()));
- assert_eq!(dirs[0].level, 4);
- assert!(filter.is_some() && filter.unwrap().to_owned() == "a.c");
- }
-
- #[test]
- fn parse_logging_spec_empty_with_filter() {
- let (dirs, filter) = parse_logging_spec("crate1/a*c");
- assert_eq!(dirs.len(), 1);
- assert_eq!(dirs[0].name, Some("crate1".to_owned()));
- assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
- assert!(filter.is_some() && filter.unwrap().to_owned() == "a*c");
- }
-}
+++ /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.
-
-//! Utilities for program-wide and customizable logging
-//!
-//! # Examples
-//!
-//! ```
-//! # #![feature(rustc_private)]
-//! #[macro_use] extern crate log;
-//!
-//! fn main() {
-//! debug!("this is a debug {:?}", "message");
-//! error!("this is printed by default");
-//!
-//! if log_enabled!(log::INFO) {
-//! let x = 3 * 4; // expensive computation
-//! info!("the answer was: {:?}", x);
-//! }
-//! }
-//! ```
-//!
-//! Assumes the binary is `main`:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=error ./main
-//! ERROR:main: this is printed by default
-//! ```
-//!
-//! ```{.bash}
-//! $ RUST_LOG=info ./main
-//! ERROR:main: this is printed by default
-//! INFO:main: the answer was: 12
-//! ```
-//!
-//! ```{.bash}
-//! $ RUST_LOG=debug ./main
-//! DEBUG:main: this is a debug message
-//! ERROR:main: this is printed by default
-//! INFO:main: the answer was: 12
-//! ```
-//!
-//! You can also set the log level on a per module basis:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=main=info ./main
-//! ERROR:main: this is printed by default
-//! INFO:main: the answer was: 12
-//! ```
-//!
-//! And enable all logging:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=main ./main
-//! DEBUG:main: this is a debug message
-//! ERROR:main: this is printed by default
-//! INFO:main: the answer was: 12
-//! ```
-//!
-//! # Logging Macros
-//!
-//! There are five macros that the logging subsystem uses:
-//!
-//! * `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
-//! related `format!` arguments
-//! * `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
-//! * `info!(...)` - a macro hard-wired to the log level of `INFO`
-//! * `warn!(...)` - a macro hard-wired to the log level of `WARN`
-//! * `error!(...)` - a macro hard-wired to the log level of `ERROR`
-//!
-//! All of these macros use the same style of syntax as the `format!` syntax
-//! extension. Details about the syntax can be found in the documentation of
-//! `std::fmt` along with the Rust tutorial/manual.
-//!
-//! If you want to check at runtime if a given logging level is enabled (e.g. if the
-//! information you would want to log is expensive to produce), you can use the
-//! following macro:
-//!
-//! * `log_enabled!(level)` - returns true if logging of the given level is enabled
-//!
-//! # Enabling logging
-//!
-//! Log levels are controlled on a per-module basis, and by default all logging is
-//! disabled except for `error!` (a log level of 1). Logging is controlled via the
-//! `RUST_LOG` environment variable. The value of this environment variable is a
-//! comma-separated list of logging directives. A logging directive is of the form:
-//!
-//! ```text
-//! path::to::module=log_level
-//! ```
-//!
-//! The path to the module is rooted in the name of the crate it was compiled for,
-//! so if your program is contained in a file `hello.rs`, for example, to turn on
-//! logging for this file you would use a value of `RUST_LOG=hello`.
-//! Furthermore, this path is a prefix-search, so all modules nested in the
-//! specified module will also have logging enabled.
-//!
-//! The actual `log_level` is optional to specify. If omitted, all logging will be
-//! enabled. If specified, the it must be either a numeric in the range of 1-255, or
-//! it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
-//! is specified, then all logging less than or equal to that numeral is enabled.
-//! For example, if logging level 3 is active, error, warn, and info logs will be
-//! printed, but debug will be omitted.
-//!
-//! As the log level for a module is optional, the module to enable logging for is
-//! also optional. If only a `log_level` is provided, then the global log level for
-//! all modules is set to this value.
-//!
-//! Some examples of valid values of `RUST_LOG` are:
-//!
-//! * `hello` turns on all logging for the 'hello' module
-//! * `info` turns on all info logging
-//! * `hello=debug` turns on debug logging for 'hello'
-//! * `hello=3` turns on info logging for 'hello'
-//! * `hello,std::option` turns on hello, and std's option logging
-//! * `error,hello=warn` turn on global error logging and also warn for hello
-//!
-//! # Filtering results
-//!
-//! A RUST_LOG directive may include a string filter. The syntax is to append
-//! `/` followed by a string. Each message is checked against the string and is
-//! only logged if it contains the string. Note that the matching is done after
-//! formatting the log string but before adding any logging meta-data. There is
-//! a single filter for all modules.
-//!
-//! Some examples:
-//!
-//! * `hello/foo` turns on all logging for the 'hello' module where the log message
-//! includes 'foo'.
-//! * `info/f.o` turns on all info logging where the log message includes 'foo',
-//! 'f1o', 'fao', etc.
-//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log
-//! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
-//! * `error,hello=warn/[0-9] scopes` turn on global error logging and also warn for
-//! hello. In both cases the log message must include a single digit number
-//! followed by 'scopes'
-//!
-//! # Performance and Side Effects
-//!
-//! Each of these macros will expand to code similar to:
-//!
-//! ```rust,ignore
-//! if log_level <= my_module_log_level() {
-//! ::log::log(log_level, format!(...));
-//! }
-//! ```
-//!
-//! What this means is that each of these macros are very cheap at runtime if
-//! they're turned off (just a load and an integer comparison). This also means that
-//! if logging is disabled, none of the components of the log will be executed.
-
-#![crate_name = "log"]
-#![unstable(feature = "rustc_private",
- reason = "use the crates.io `log` 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",
- html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
- html_root_url = "https://doc.rust-lang.org/nightly/",
- html_playground_url = "https://play.rust-lang.org/",
- test(attr(deny(warnings))))]
-#![deny(missing_docs)]
-#![deny(warnings)]
-
-#![feature(staged_api)]
-
-use std::cell::RefCell;
-use std::fmt;
-use std::io::{self, Stderr};
-use std::io::prelude::*;
-use std::mem;
-use std::env;
-use std::slice;
-use std::sync::{Mutex, ONCE_INIT, Once};
-
-use directive::LOG_LEVEL_NAMES;
-
-#[macro_use]
-pub mod macros;
-
-mod directive;
-
-/// Maximum logging level of a module that can be specified. Common logging
-/// levels are found in the DEBUG/INFO/WARN/ERROR constants.
-pub const MAX_LOG_LEVEL: u32 = 255;
-
-/// The default logging level of a crate if no other is specified.
-const DEFAULT_LOG_LEVEL: u32 = 1;
-
-static mut LOCK: *mut Mutex<(Vec<directive::LogDirective>, Option<String>)> = 0 as *mut _;
-
-/// An unsafe constant that is the maximum logging level of any module
-/// specified. This is the first line of defense to determining whether a
-/// logging statement should be run.
-static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL;
-
-/// Debug log level
-pub const DEBUG: u32 = 4;
-/// Info log level
-pub const INFO: u32 = 3;
-/// Warn log level
-pub const WARN: u32 = 2;
-/// Error log level
-pub const ERROR: u32 = 1;
-
-thread_local! {
- static LOCAL_LOGGER: RefCell<Option<Box<Logger + Send>>> = {
- RefCell::new(None)
- }
-}
-
-/// A trait used to represent an interface to a thread-local logger. Each thread
-/// can have its own custom logger which can respond to logging messages
-/// however it likes.
-pub trait Logger {
- /// Logs a single message described by the `record`.
- fn log(&mut self, record: &LogRecord);
-}
-
-struct DefaultLogger {
- handle: Stderr,
-}
-
-/// Wraps the log level with fmt implementations.
-#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
-pub struct LogLevel(pub u32);
-
-impl fmt::Display for LogLevel {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- let LogLevel(level) = *self;
- match LOG_LEVEL_NAMES.get(level as usize - 1) {
- Some(ref name) => fmt::Display::fmt(name, fmt),
- None => fmt::Display::fmt(&level, fmt),
- }
- }
-}
-
-impl Logger for DefaultLogger {
- fn log(&mut self, record: &LogRecord) {
- match writeln!(&mut self.handle,
- "{}:{}: {}",
- record.level,
- record.module_path,
- record.args) {
- Err(e) => panic!("failed to log: {:?}", e),
- Ok(()) => {}
- }
- }
-}
-
-impl Drop for DefaultLogger {
- fn drop(&mut self) {
- // FIXME(#12628): is panicking the right thing to do?
- match self.handle.flush() {
- Err(e) => panic!("failed to flush a logger: {:?}", e),
- Ok(()) => {}
- }
- }
-}
-
-/// This function is called directly by the compiler when using the logging
-/// macros. This function does not take into account whether the log level
-/// specified is active or not, it will always log something if this method is
-/// called.
-///
-/// It is not recommended to call this function directly, rather it should be
-/// invoked through the logging family of macros.
-#[doc(hidden)]
-pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
- // Test the literal string from args against the current filter, if there
- // is one.
- unsafe {
- let filter = (*LOCK).lock().unwrap();
- if let Some(ref filter) = filter.1 {
- if !args.to_string().contains(filter) {
- return;
- }
- }
- }
-
- // Completely remove the local logger from TLS in case anyone attempts to
- // frob the slot while we're doing the logging. This will destroy any logger
- // set during logging.
- let logger = LOCAL_LOGGER.with(|s| s.borrow_mut().take());
- let mut logger = logger.unwrap_or_else(|| Box::new(DefaultLogger { handle: io::stderr() }));
- logger.log(&LogRecord {
- level: LogLevel(level),
- args: args,
- file: loc.file,
- module_path: loc.module_path,
- line: loc.line,
- });
- set_logger(logger);
-}
-
-/// Getter for the global log level. This is a function so that it can be called
-/// safely
-#[doc(hidden)]
-#[inline(always)]
-pub fn log_level() -> u32 {
- unsafe { LOG_LEVEL }
-}
-
-/// Replaces the thread-local logger with the specified logger, returning the old
-/// logger.
-pub fn set_logger(logger: Box<Logger + Send>) -> Option<Box<Logger + Send>> {
- LOCAL_LOGGER.with(|slot| mem::replace(&mut *slot.borrow_mut(), Some(logger)))
-}
-
-/// A LogRecord is created by the logging macros, and passed as the only
-/// argument to Loggers.
-#[derive(Debug)]
-pub struct LogRecord<'a> {
- /// The module path of where the LogRecord originated.
- pub module_path: &'a str,
-
- /// The LogLevel of this record.
- pub level: LogLevel,
-
- /// The arguments from the log line.
- pub args: fmt::Arguments<'a>,
-
- /// The file of where the LogRecord originated.
- pub file: &'a str,
-
- /// The line number of where the LogRecord originated.
- pub line: u32,
-}
-
-#[doc(hidden)]
-#[derive(Copy, Clone)]
-pub struct LogLocation {
- pub module_path: &'static str,
- pub file: &'static str,
- pub line: u32,
-}
-
-/// Tests whether a given module's name is enabled for a particular level of
-/// logging. This is the second layer of defense about determining whether a
-/// module's log statement should be emitted or not.
-#[doc(hidden)]
-pub fn mod_enabled(level: u32, module: &str) -> bool {
- static INIT: Once = ONCE_INIT;
- INIT.call_once(init);
-
- // It's possible for many threads are in this function, only one of them
- // will perform the global initialization, but all of them will need to check
- // again to whether they should really be here or not. Hence, despite this
- // check being expanded manually in the logging macro, this function checks
- // the log level again.
- if level > unsafe { LOG_LEVEL } {
- return false;
- }
-
- // This assertion should never get tripped unless we're in an at_exit
- // handler after logging has been torn down and a logging attempt was made.
-
- unsafe {
- let directives = (*LOCK).lock().unwrap();
- enabled(level, module, directives.0.iter())
- }
-}
-
-fn enabled(level: u32, module: &str, iter: slice::Iter<directive::LogDirective>) -> bool {
- // Search for the longest match, the vector is assumed to be pre-sorted.
- for directive in iter.rev() {
- match directive.name {
- Some(ref name) if !module.starts_with(&name[..]) => {}
- Some(..) | None => return level <= directive.level,
- }
- }
- level <= DEFAULT_LOG_LEVEL
-}
-
-/// Initialize logging for the current process.
-///
-/// This is not threadsafe at all, so initialization is performed through a
-/// `Once` primitive (and this function is called from that primitive).
-fn init() {
- let (mut directives, filter) = match env::var("RUST_LOG") {
- Ok(spec) => directive::parse_logging_spec(&spec[..]),
- Err(..) => (Vec::new(), None),
- };
-
- // Sort the provided directives by length of their name, this allows a
- // little more efficient lookup at runtime.
- directives.sort_by(|a, b| {
- let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0);
- let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0);
- alen.cmp(&blen)
- });
-
- let max_level = {
- let max = directives.iter().max_by_key(|d| d.level);
- max.map(|d| d.level).unwrap_or(DEFAULT_LOG_LEVEL)
- };
-
- unsafe {
- LOG_LEVEL = max_level;
-
- assert!(LOCK.is_null());
- LOCK = Box::into_raw(Box::new(Mutex::new((directives, filter))));
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::enabled;
- use directive::LogDirective;
-
- #[test]
- fn match_full_path() {
- let dirs = [LogDirective {
- name: Some("crate2".to_string()),
- level: 3,
- },
- LogDirective {
- name: Some("crate1::mod1".to_string()),
- level: 2,
- }];
- assert!(enabled(2, "crate1::mod1", dirs.iter()));
- assert!(!enabled(3, "crate1::mod1", dirs.iter()));
- assert!(enabled(3, "crate2", dirs.iter()));
- assert!(!enabled(4, "crate2", dirs.iter()));
- }
-
- #[test]
- fn no_match() {
- let dirs = [LogDirective {
- name: Some("crate2".to_string()),
- level: 3,
- },
- LogDirective {
- name: Some("crate1::mod1".to_string()),
- level: 2,
- }];
- assert!(!enabled(2, "crate3", dirs.iter()));
- }
-
- #[test]
- fn match_beginning() {
- let dirs = [LogDirective {
- name: Some("crate2".to_string()),
- level: 3,
- },
- LogDirective {
- name: Some("crate1::mod1".to_string()),
- level: 2,
- }];
- assert!(enabled(3, "crate2::mod1", dirs.iter()));
- }
-
- #[test]
- fn match_beginning_longest_match() {
- let dirs = [LogDirective {
- name: Some("crate2".to_string()),
- level: 3,
- },
- LogDirective {
- name: Some("crate2::mod".to_string()),
- level: 4,
- },
- LogDirective {
- name: Some("crate1::mod1".to_string()),
- level: 2,
- }];
- assert!(enabled(4, "crate2::mod1", dirs.iter()));
- assert!(!enabled(4, "crate2", dirs.iter()));
- }
-
- #[test]
- fn match_default() {
- let dirs = [LogDirective {
- name: None,
- level: 3,
- },
- LogDirective {
- name: Some("crate1::mod1".to_string()),
- level: 2,
- }];
- assert!(enabled(2, "crate1::mod1", dirs.iter()));
- assert!(enabled(3, "crate2::mod2", dirs.iter()));
- }
-
- #[test]
- fn zero_level() {
- let dirs = [LogDirective {
- name: None,
- level: 3,
- },
- LogDirective {
- name: Some("crate1::mod1".to_string()),
- level: 0,
- }];
- assert!(!enabled(1, "crate1::mod1", dirs.iter()));
- assert!(enabled(3, "crate2::mod2", dirs.iter()));
- }
-}
+++ /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.
-
-//! Logging macros
-
-/// The standard logging macro
-///
-/// This macro will generically log over a provided level (of type u32) with a
-/// format!-based argument list. See documentation in `std::fmt` for details on
-/// how to use the syntax.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-/// log!(log::WARN, "this is a warning {}", "message");
-/// log!(log::DEBUG, "this is a debug message");
-/// log!(6, "this is a custom logging level: {level}", level=6);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=warn ./main
-/// WARN:main: this is a warning message
-/// ```
-///
-/// ```{.bash}
-/// $ RUST_LOG=debug ./main
-/// DEBUG:main: this is a debug message
-/// WARN:main: this is a warning message
-/// ```
-///
-/// ```{.bash}
-/// $ RUST_LOG=6 ./main
-/// DEBUG:main: this is a debug message
-/// WARN:main: this is a warning message
-/// 6:main: this is a custom logging level: 6
-/// ```
-#[macro_export]
-macro_rules! log {
- ($lvl:expr, $($arg:tt)+) => ({
- static LOC: ::log::LogLocation = ::log::LogLocation {
- line: line!(),
- file: file!(),
- module_path: module_path!(),
- };
- let lvl = $lvl;
- if log_enabled!(lvl) {
- ::log::log(lvl, &LOC, format_args!($($arg)+))
- }
- })
-}
-
-/// A convenience macro for logging at the error log level.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-/// let error = 3;
-/// error!("the build has failed with error code: {}", error);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=error ./main
-/// ERROR:main: the build has failed with error code: 3
-/// ```
-///
-#[macro_export]
-macro_rules! error {
- ($($arg:tt)*) => (log!(::log::ERROR, $($arg)*))
-}
-
-/// A convenience macro for logging at the warning log level.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-/// let code = 3;
-/// warn!("you may like to know that a process exited with: {}", code);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=warn ./main
-/// WARN:main: you may like to know that a process exited with: 3
-/// ```
-#[macro_export]
-macro_rules! warn {
- ($($arg:tt)*) => (log!(::log::WARN, $($arg)*))
-}
-
-/// A convenience macro for logging at the info log level.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-/// let ret = 3;
-/// info!("this function is about to return: {}", ret);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=info ./main
-/// INFO:main: this function is about to return: 3
-/// ```
-#[macro_export]
-macro_rules! info {
- ($($arg:tt)*) => (log!(::log::INFO, $($arg)*))
-}
-
-/// A convenience macro for logging at the debug log level. This macro will
-/// be omitted at compile time in an optimized build unless `-C debug-assertions`
-/// is passed to the compiler.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-/// debug!("x = {x}, y = {y}", x=10, y=20);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=debug ./main
-/// DEBUG:main: x = 10, y = 20
-/// ```
-#[macro_export]
-macro_rules! debug {
- ($($arg:tt)*) => (if cfg!(debug_assertions) { log!(::log::DEBUG, $($arg)*) })
-}
-
-/// A macro to test whether a log level is enabled for the current module.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// struct Point { x: i32, y: i32 }
-/// fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
-///
-/// fn main() {
-/// if log_enabled!(log::DEBUG) {
-/// let x = some_expensive_computation();
-/// debug!("x.x = {}, x.y = {}", x.x, x.y);
-/// }
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=error ./main
-/// ```
-///
-/// ```{.bash}
-/// $ RUST_LOG=debug ./main
-/// DEBUG:main: x.x = 1, x.y = 2
-/// ```
-#[macro_export]
-macro_rules! log_enabled {
- ($lvl:expr) => ({
- let lvl = $lvl;
- (lvl != ::log::DEBUG || cfg!(debug_assertions)) &&
- lvl <= ::log::log_level() &&
- ::log::mod_enabled(lvl, module_path!())
- })
-}
arena = { path = "../libarena" }
fmt_macros = { path = "../libfmt_macros" }
graphviz = { path = "../libgraphviz" }
-log = { path = "../liblog" }
+log = "0.3"
rustc_back = { path = "../librustc_back" }
rustc_bitflags = { path = "../librustc_bitflags" }
rustc_const_math = { path = "../librustc_const_math" }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use hir::def_id::CrateNum;
use std::fmt::Debug;
use std::sync::Arc;
CoherenceCheckImpl(D),
CoherenceOverlapCheck(D),
CoherenceOverlapCheckSpecial(D),
- CoherenceOverlapInherentCheck(D),
CoherenceOrphanCheck(D),
Variance,
WfCheck(D),
TypeckItemType(D),
UnusedTraitCheck,
CheckConst(D),
- Privacy,
+ PrivacyAccessLevels(CrateNum),
IntrinsicCheck(D),
MatchCheck(D),
CheckEntryFn => Some(CheckEntryFn),
Variance => Some(Variance),
UnusedTraitCheck => Some(UnusedTraitCheck),
- Privacy => Some(Privacy),
+ PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)),
Reachability => Some(Reachability),
DeadCheck => Some(DeadCheck),
LateLintCheck => Some(LateLintCheck),
CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
- CoherenceOverlapInherentCheck(ref d) => op(d).map(CoherenceOverlapInherentCheck),
CoherenceOrphanCheck(ref d) => op(d).map(CoherenceOrphanCheck),
WfCheck(ref d) => op(d).map(WfCheck),
TypeckItemType(ref d) => op(d).map(TypeckItemType),
pub fn keys(&self) -> Vec<M::Key> {
self.map.keys().cloned().collect()
}
-
- /// Append `elem` to the vector stored for `k`, creating a new vector if needed.
- /// This is considered a write to `k`.
- ///
- /// NOTE: Caution is required when using this method. You should
- /// be sure that nobody is **reading from the vector** while you
- /// are writing to it. Eventually, it'd be nice to remove this.
- pub fn push<E: Clone>(&mut self, k: M::Key, elem: E)
- where M: DepTrackingMapConfig<Value=Vec<E>>
- {
- self.write(&k);
- self.map.entry(k)
- .or_insert(Vec::new())
- .push(elem);
- }
}
impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
}
/// Indicates that the current task `C` reads `v` by adding an
- /// edge from `v` to `C`. If there is no current task, panics. If
- /// you want to suppress this edge, use `ignore`.
+ /// edge from `v` to `C`. If there is no current task, has no
+ /// effect. Note that *reading* from tracked state is harmless if
+ /// you are not in a task; what is bad is *writing* to tracked
+ /// state (and leaking data that you read into a tracked task).
pub fn read(&mut self, v: DepNode<D>) {
- let source = self.make_node(v);
- self.add_edge_from_current_node(|current| (source, current))
+ if self.current_node().is_some() {
+ let source = self.make_node(v);
+ self.add_edge_from_current_node(|current| (source, current))
+ }
}
/// Indicates that the current task `C` writes `v` by adding an
let mut stack = self.stack.borrow_mut();
match *message {
- DepMessage::Read(ref n) => self.check_edge(Some(Some(n)), top(&stack)),
+ // It is ok to READ shared state outside of a
+ // task. That can't do any harm (at least, the only
+ // way it can do harm is by leaking that data into a
+ // query or task, which would be a problem
+ // anyway). What would be bad is WRITING to that
+ // state.
+ DepMessage::Read(_) => { }
DepMessage::Write(ref n) => self.check_edge(top(&stack), Some(Some(n))),
DepMessage::PushTask(ref n) => stack.push(Some(n.clone())),
DepMessage::PushIgnore => stack.push(None),
(None, None) => unreachable!(),
// nothing on top of the stack
- (None, Some(n)) | (Some(n), None) => bug!("read/write of {:?} but no current task", n),
+ (None, Some(n)) | (Some(n), None) => bug!("write of {:?} but no current task", n),
// this corresponds to an Ignore being top of the stack
(Some(None), _) | (_, Some(None)) => (),
E0398: r##"
In Rust 1.3, the default object lifetime bounds are expected to change, as
-described in RFC #1156 [1]. You are getting a warning because the compiler
+described in [RFC 1156]. You are getting a warning because the compiler
thinks it is possible that this change will cause a compilation error in your
code. It is possible, though unlikely, that this is a false alarm.
This explicitly states that you expect the trait object `SomeTrait` to contain
references (with a maximum lifetime of `'a`).
-[1]: https://github.com/rust-lang/rfcs/pull/1156
+[RFC 1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md
"##,
E0452: r##"
**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
is a function pointer, which is not zero-sized.
This pattern should be rewritten. There are a few possible ways to do this:
+
- change the original fn declaration to match the expected signature,
and do the cast in the fn body (the prefered option)
- cast the fn item fo a fn pointer before calling transmute, as shown here:
hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
}
ExprKind::Range(ref e1, ref e2, lims) => {
- fn make_struct(this: &mut LoweringContext,
- ast_expr: &Expr,
- path: &[&str],
- fields: &[(&str, &P<Expr>)]) -> hir::Expr {
- let struct_path = &iter::once(&"ops").chain(path).map(|s| *s)
- .collect::<Vec<_>>();
- let unstable_span = this.allow_internal_unstable("...", ast_expr.span);
-
- if fields.len() == 0 {
- this.expr_std_path(unstable_span, struct_path,
- ast_expr.attrs.clone())
- } else {
- let fields = fields.into_iter().map(|&(s, e)| {
- let expr = P(this.lower_expr(&e));
- let unstable_span = this.allow_internal_unstable("...", e.span);
- this.field(Symbol::intern(s), expr, unstable_span)
- }).collect();
- let attrs = ast_expr.attrs.clone();
-
- this.expr_std_struct(unstable_span, struct_path, fields, None, attrs)
- }
- }
-
use syntax::ast::RangeLimits::*;
- return match (e1, e2, lims) {
- (&None, &None, HalfOpen) =>
- make_struct(self, e, &["RangeFull"], &[]),
-
- (&Some(ref e1), &None, HalfOpen) =>
- make_struct(self, e, &["RangeFrom"],
- &[("start", e1)]),
-
- (&None, &Some(ref e2), HalfOpen) =>
- make_struct(self, e, &["RangeTo"],
- &[("end", e2)]),
-
- (&Some(ref e1), &Some(ref e2), HalfOpen) =>
- make_struct(self, e, &["Range"],
- &[("start", e1), ("end", e2)]),
-
- (&None, &Some(ref e2), Closed) =>
- make_struct(self, e, &["RangeToInclusive"],
- &[("end", e2)]),
-
- (&Some(ref e1), &Some(ref e2), Closed) =>
- make_struct(self, e, &["RangeInclusive", "NonEmpty"],
- &[("start", e1), ("end", e2)]),
+ let (path, variant) = match (e1, e2, lims) {
+ (&None, &None, HalfOpen) => ("RangeFull", None),
+ (&Some(..), &None, HalfOpen) => ("RangeFrom", None),
+ (&None, &Some(..), HalfOpen) => ("RangeTo", None),
+ (&Some(..), &Some(..), HalfOpen) => ("Range", None),
+ (&None, &Some(..), Closed) => ("RangeToInclusive", None),
+ (&Some(..), &Some(..), Closed) => ("RangeInclusive", Some("NonEmpty")),
+ (_, &None, Closed) =>
+ panic!(self.diagnostic().span_fatal(
+ e.span, "inclusive range with no end")),
+ };
- _ => panic!(self.diagnostic()
- .span_fatal(e.span, "inclusive range with no end")),
+ let fields =
+ e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e)))
+ .map(|(s, e)| {
+ let expr = P(self.lower_expr(&e));
+ let unstable_span = self.allow_internal_unstable("...", e.span);
+ self.field(Symbol::intern(s), expr, unstable_span)
+ }).collect::<P<[hir::Field]>>();
+
+ let is_unit = fields.is_empty();
+ let unstable_span = self.allow_internal_unstable("...", e.span);
+ let struct_path =
+ iter::once("ops").chain(iter::once(path)).chain(variant)
+ .collect::<Vec<_>>();
+ let struct_path = self.std_path(unstable_span, &struct_path, is_unit);
+ let struct_path = hir::QPath::Resolved(None, P(struct_path));
+
+ return hir::Expr {
+ id: self.lower_node_id(e.id),
+ node: if is_unit {
+ hir::ExprPath(struct_path)
+ } else {
+ hir::ExprStruct(struct_path, fields, None)
+ },
+ span: unstable_span,
+ attrs: e.attrs.clone(),
};
}
ExprKind::Path(ref qself, ref path) => {
P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new()))
}
- fn expr_std_struct(&mut self,
- span: Span,
- components: &[&str],
- fields: hir::HirVec<hir::Field>,
- e: Option<P<hir::Expr>>,
- attrs: ThinVec<Attribute>) -> hir::Expr {
- let path = self.std_path(span, components, false);
- let qpath = hir::QPath::Resolved(None, P(path));
- self.expr(span, hir::ExprStruct(qpath, fields, e), attrs)
- }
-
fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> hir::Expr {
hir::Expr {
id: self.next_id(),
intravisit::walk_crate(&mut collector, &forest.krate);
let map = collector.map;
- if log_enabled!(::log::DEBUG) {
+ if log_enabled!(::log::LogLevel::Debug) {
// This only makes sense for ordered stores; note the
// enumerate to count the number of entries.
let (entries_less_1, _) = map.iter().filter(|&x| {
pub fn is_elided(&self) -> bool {
self.name == keywords::Invalid.name()
}
+
+ pub fn is_static(&self) -> bool {
+ self.name == keywords::StaticLifetime.name()
+ }
}
/// A lifetime definition, eg `'a: 'b+'c+'d`
impl Encodable for Fingerprint {
#[inline]
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- for &byte in &self.0[..] {
+ for &byte in &self.0 {
s.emit_u8(byte)?;
}
Ok(())
#[inline]
fn decode<D: Decoder>(d: &mut D) -> Result<Fingerprint, D::Error> {
let mut result = Fingerprint([0u8; FINGERPRINT_LENGTH]);
- for byte in &mut result.0[..] {
+ for byte in &mut result.0 {
*byte = d.read_u8()?;
}
Ok(result)
{
debug!("note_issue_32330: terr={:?}", terr);
match *terr {
- TypeError::RegionsInsufficientlyPolymorphic(_, &Region::ReVar(vid)) |
- TypeError::RegionsOverlyPolymorphic(_, &Region::ReVar(vid)) => {
- match self.region_vars.var_origin(vid) {
- RegionVariableOrigin::EarlyBoundRegion(_, _, Some(Issue32330 {
- fn_def_id,
- region_name
- })) => {
- diag.note(
- &format!("lifetime parameter `{0}` declared on fn `{1}` \
- appears only in the return type, \
- but here is required to be higher-ranked, \
- which means that `{0}` must appear in both \
- argument and return types",
- region_name,
- self.tcx.item_path_str(fn_def_id)));
- diag.note(
- &format!("this error is the result of a recent bug fix; \
- for more information, see issue #33685 \
- <https://github.com/rust-lang/rust/issues/33685>"));
- }
- _ => { }
- }
+ TypeError::RegionsInsufficientlyPolymorphic(_, _, Some(box Issue32330 {
+ fn_def_id, region_name
+ })) |
+ TypeError::RegionsOverlyPolymorphic(_, _, Some(box Issue32330 {
+ fn_def_id, region_name
+ })) => {
+ diag.note(
+ &format!("lifetime parameter `{0}` declared on fn `{1}` \
+ appears only in the return type, \
+ but here is required to be higher-ranked, \
+ which means that `{0}` must appear in both \
+ argument and return types",
+ region_name,
+ self.tcx.item_path_str(fn_def_id)));
+ diag.note(
+ &format!("this error is the result of a recent bug fix; \
+ for more information, see issue #33685 \
+ <https://github.com/rust-lang/rust/issues/33685>"));
}
- _ => { }
+ _ => {}
}
}
InferCtxt,
LateBoundRegion,
HigherRankedType,
+ RegionVariableOrigin,
SubregionOrigin,
SkolemizationMap};
use super::combine::CombineFields;
skol_br,
tainted_region);
+ let issue_32330 = if let &ty::ReVar(vid) = tainted_region {
+ match self.region_vars.var_origin(vid) {
+ RegionVariableOrigin::EarlyBoundRegion(_, _, issue_32330) => {
+ issue_32330.map(Box::new)
+ }
+ _ => None
+ }
+ } else {
+ None
+ };
+
if overly_polymorphic {
debug!("Overly polymorphic!");
return Err(TypeError::RegionsOverlyPolymorphic(skol_br,
- tainted_region));
+ tainted_region,
+ issue_32330));
} else {
debug!("Not as polymorphic!");
return Err(TypeError::RegionsInsufficientlyPolymorphic(skol_br,
- tainted_region));
+ tainted_region,
+ issue_32330));
}
}
}
use std::default::Default as StdDefault;
use std::mem;
use std::fmt;
-use std::ops::Deref;
use syntax::attr;
use syntax::ast;
use syntax::symbol::Symbol;
-use syntax_pos::{MultiSpan, Span};
+use syntax_pos::{DUMMY_SP, MultiSpan, Span};
use errors::{self, Diagnostic, DiagnosticBuilder};
use hir;
+use hir::def_id::LOCAL_CRATE;
use hir::intravisit as hir_visit;
use syntax::visit as ast_visit;
Allow => bug!("earlier conditional return should handle Allow case")
};
let hyphen_case_lint_name = name.replace("_", "-");
- if lint_flag_val.as_str().deref() == name {
+ if lint_flag_val.as_str() == name {
err.note(&format!("requested on the command line with `{} {}`",
flag, hyphen_case_lint_name));
} else {
},
Node(lint_attr_name, src) => {
def = Some(src);
- if lint_attr_name.as_str().deref() != name {
+ if lint_attr_name.as_str() != name {
let level_str = level.as_str();
err.note(&format!("#[{}({})] implied by #[{}({})]",
level_str, name, level_str, lint_attr_name));
/// Perform lint checking on a crate.
///
/// Consumes the `lint_store` field of the `Session`.
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- access_levels: &AccessLevels) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck);
+ let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
+
let krate = tcx.hir.krate();
// We want to own the lint store, so move it out of the session.
fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
- fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>;
// trait info
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
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>;
- fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- reexports: &def::ExportMap,
+ fn encode_metadata<'a, 'tcx>(&self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
reachable: &NodeSet) -> Vec<u8>;
fn metadata_encoding_version(&self) -> &[u8];
{ bug!("item_generics_cloned") }
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
- fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId> { vec![] }
// trait info
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
{ vec![] }
fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") }
fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
- fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- reexports: &def::ExportMap,
- link_meta: &LinkMeta,
- reachable: &NodeSet) -> Vec<u8> { vec![] }
+ fn encode_metadata<'a, 'tcx>(&self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ link_meta: &LinkMeta,
+ reachable: &NodeSet) -> Vec<u8> { vec![] }
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
}
use middle::privacy;
use ty::{self, TyCtxt};
use hir::def::Def;
-use hir::def_id::{DefId};
+use hir::def_id::{DefId, LOCAL_CRATE};
use lint;
use util::nodemap::FxHashSet;
use syntax::{ast, codemap};
use syntax::attr;
+use syntax::codemap::DUMMY_SP;
use syntax_pos;
// Any local node that may call something in its body block should be
}
}
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- access_levels: &privacy::AccessLevels) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let _task = tcx.dep_graph.in_task(DepNode::DeadCheck);
+ let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
let krate = tcx.hir.krate();
let live_symbols = find_live(tcx, access_levels, krate);
let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };
use syntax::abi::Abi;
use syntax::ast;
use syntax::attr;
+use syntax::codemap::DUMMY_SP;
use hir;
+use hir::def_id::LOCAL_CRATE;
use hir::intravisit::{Visitor, NestedVisitorMap};
use hir::itemlikevisit::ItemLikeVisitor;
use hir::intravisit;
}
}
-pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- access_levels: &privacy::AccessLevels)
- -> NodeSet {
+pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
let _task = tcx.dep_graph.in_task(DepNode::Reachability);
+ let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
+
let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
*ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib ||
*ty == config::CrateTypeProcMacro
use syntax::attr;
use syntax::ptr::P;
use syntax::symbol::keywords;
-use syntax_pos::Span;
+use syntax_pos::{mk_sp, Span};
use errors::DiagnosticBuilder;
use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap};
use rustc_back::slice;
self.resolve_elided_lifetimes(slice::ref_slice(lifetime_ref));
return;
}
- if lifetime_ref.name == keywords::StaticLifetime.name() {
+ if lifetime_ref.is_static() {
self.insert_lifetime(lifetime_ref, Region::Static);
return;
}
let lifetime_i = &lifetimes[i];
for lifetime in lifetimes {
- if lifetime.lifetime.name == keywords::StaticLifetime.name() {
+ if lifetime.lifetime.is_static() {
let lifetime = lifetime.lifetime;
let mut err = struct_span_err!(self.sess, lifetime.span, E0262,
"invalid lifetime parameter name: `{}`", lifetime.name);
self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime);
for bound in &lifetime_i.bounds {
- self.resolve_lifetime_ref(bound);
+ if !bound.is_static() {
+ self.resolve_lifetime_ref(bound);
+ } else {
+ self.insert_lifetime(bound, Region::Static);
+ let full_span = mk_sp(lifetime_i.lifetime.span.lo, bound.span.hi);
+ self.sess.struct_span_warn(full_span,
+ &format!("unnecessary lifetime parameter `{}`", lifetime_i.lifetime.name))
+ .help(&format!("you can use the `'static` lifetime directly, in place \
+ of `{}`", lifetime_i.lifetime.name))
+ .emit();
+ }
}
}
}
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),
+ feature.as_str(), &r),
None => format!("use of unstable library feature '{}'", &feature)
};
emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
/// Given the list of enabled features that were not language features (i.e. that
/// were expected to be library features), and the list of features used from
/// libraries, identify activated features that don't exist and error about them.
-pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- access_levels: &AccessLevels) {
+pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let sess = &tcx.sess;
+ let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
+
if tcx.stability.borrow().staged_api[&LOCAL_CRATE] && tcx.sess.features.borrow().staged_api {
let _task = tcx.dep_graph.in_task(DepNode::StabilityIndex);
let krate = tcx.hir.krate();
RawPtr(hir::Mutability),
}
+/// Information for `CoerceUnsized` impls, storing information we
+/// have computed about the coercion.
+///
+/// This struct can be obtained via the `coerce_impl_info` query.
+/// Demanding this struct also has the side-effect of reporting errors
+/// for inappropriate impls.
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+pub struct CoerceUnsizedInfo {
+ /// If this is a "custom coerce" impl, then what kind of custom
+ /// coercion is it? This applies to impls of `CoerceUnsized` for
+ /// structs, primarily, where we store a bit of info about which
+ /// fields need to be coerced.
+ pub custom_kind: Option<CustomCoerceUnsized>
+}
+
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
pub enum CustomCoerceUnsized {
/// Records the index of the field being coerced.
use lint;
use middle;
use hir::TraitMap;
-use hir::def::Def;
+use hir::def::{Def, ExportMap};
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use hir::map as hir_map;
use hir::map::DisambiguatedDefPathData;
/// is relevant; generated by resolve.
pub trait_map: TraitMap,
+ /// Export map produced by name resolution.
+ pub export_map: ExportMap,
+
pub named_region_map: resolve_lifetime::NamedRegionMap,
pub region_maps: RegionMaps,
region_maps: region_maps,
variance_computed: Cell::new(false),
trait_map: resolutions.trait_map,
+ export_map: resolutions.export_map,
fulfilled_predicates: RefCell::new(fulfilled_predicates),
hir: hir,
maps: maps::Maps::new(dep_graph, providers),
RegionsDoesNotOutlive(&'tcx Region, &'tcx Region),
RegionsNotSame(&'tcx Region, &'tcx Region),
RegionsNoOverlap(&'tcx Region, &'tcx Region),
- RegionsInsufficientlyPolymorphic(BoundRegion, &'tcx Region),
- RegionsOverlyPolymorphic(BoundRegion, &'tcx Region),
+ RegionsInsufficientlyPolymorphic(BoundRegion, &'tcx Region, Option<Box<ty::Issue32330>>),
+ RegionsOverlyPolymorphic(BoundRegion, &'tcx Region, Option<Box<ty::Issue32330>>),
Sorts(ExpectedFound<Ty<'tcx>>),
IntMismatch(ExpectedFound<ty::IntVarValue>),
FloatMismatch(ExpectedFound<ast::FloatTy>),
RegionsNoOverlap(..) => {
write!(f, "lifetimes do not intersect")
}
- RegionsInsufficientlyPolymorphic(br, _) => {
+ RegionsInsufficientlyPolymorphic(br, _, _) => {
write!(f, "expected bound lifetime parameter {}, \
found concrete lifetime", br)
}
- RegionsOverlyPolymorphic(br, _) => {
+ RegionsOverlyPolymorphic(br, _, _) => {
write!(f, "expected concrete lifetime, \
found bound lifetime parameter {}", br)
}
self.note_and_explain_region(db, "...does not overlap ",
region2, "");
}
- RegionsInsufficientlyPolymorphic(_, conc_region) => {
+ RegionsInsufficientlyPolymorphic(_, conc_region, _) => {
self.note_and_explain_region(db, "concrete lifetime that was found is ",
conc_region, "");
}
- RegionsOverlyPolymorphic(_, &ty::ReVar(_)) => {
+ RegionsOverlyPolymorphic(_, &ty::ReVar(_), _) => {
// don't bother to print out the message below for
// inference variables, it's not very illuminating.
}
- RegionsOverlyPolymorphic(_, conc_region) => {
+ RegionsOverlyPolymorphic(_, conc_region, _) => {
self.note_and_explain_region(db, "expected concrete lifetime is ",
conc_region, "");
}
} else {
// for local crates, check whether type info is
// available; typeck might not have completed yet
- self.maps.impl_trait_ref.borrow().contains_key(&impl_def_id)
+ self.maps.impl_trait_ref.borrow().contains_key(&impl_def_id) &&
+ self.maps.ty.borrow().contains_key(&impl_def_id)
};
if !use_types {
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use middle::const_val::ConstVal;
+use middle::privacy::AccessLevels;
use mir;
-use ty::{self, Ty, TyCtxt};
+use ty::{self, CrateInherentImpls, Ty, TyCtxt};
use rustc_data_structures::indexed_vec::IndexVec;
use std::cell::{RefCell, RefMut};
}
}
-impl<'tcx> QueryDescription for queries::coherent_inherent_impls<'tcx> {
+impl<'tcx> QueryDescription for queries::crate_inherent_impls<'tcx> {
+ fn describe(_: TyCtxt, k: CrateNum) -> String {
+ format!("all inherent impls defined in crate `{:?}`", k)
+ }
+}
+
+impl<'tcx> QueryDescription for queries::crate_inherent_impls_overlap_check<'tcx> {
fn describe(_: TyCtxt, _: CrateNum) -> String {
- format!("coherence checking all inherent impls")
+ format!("check for overlap between inherent impls defined in this crate")
}
}
}
}
+impl<'tcx> QueryDescription for queries::privacy_access_levels<'tcx> {
+ fn describe(_: TyCtxt, _: CrateNum) -> String {
+ format!("privacy access levels")
+ }
+}
+
macro_rules! define_maps {
(<$tcx:tt>
$($(#[$attr:meta])*
/// Maps a DefId of a type to a list of its inherent impls.
/// Contains implementations of methods that are inherent to a type.
/// Methods in these implementations don't need to be exported.
- pub inherent_impls: InherentImpls(DefId) -> Vec<DefId>,
+ pub inherent_impls: InherentImpls(DefId) -> Rc<Vec<DefId>>,
/// Maps from the def-id of a function/method or const/static
/// to its MIR. Mutation is done at an item granularity to
pub closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
/// Caches CoerceUnsized kinds for impls on custom types.
- pub custom_coerce_unsized_kind: ItemSignature(DefId)
- -> ty::adjustment::CustomCoerceUnsized,
+ pub coerce_unsized_info: ItemSignature(DefId)
+ -> ty::adjustment::CoerceUnsizedInfo,
pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
- pub coherent_inherent_impls: coherent_inherent_impls_dep_node(CrateNum) -> (),
+ /// Gets a complete map from all types to their inherent impls.
+ /// Not meant to be used directly outside of coherence.
+ /// (Defined only for LOCAL_CRATE)
+ pub crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum) -> CrateInherentImpls,
+
+ /// Checks all types in the krate for overlap in their inherent impls. Reports errors.
+ /// Not meant to be used directly outside of coherence.
+ /// (Defined only for LOCAL_CRATE)
+ pub crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),
/// Results of evaluating monomorphic constants embedded in
/// other items, such as enum variant explicit discriminants.
pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result<ConstVal<'tcx>, ()>,
+ /// Performs the privacy check and computes "access levels".
+ pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
+
pub mir_shims: mir_shim(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
}
DepNode::CoherenceCheckTrait(def_id)
}
-fn coherent_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
+fn crate_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
DepNode::Coherence
}
use dep_graph::{self, DepNode};
use hir::{map as hir_map, FreevarMap, TraitMap};
-use middle;
use hir::def::{Def, CtorKind, ExportMap};
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use middle::const_val::ConstVal;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
+use middle::privacy::AccessLevels;
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
use middle::resolve_lifetime::ObjectLifetimeDefault;
use mir::Mir;
use ty::util::IntTypeExt;
use ty::walk::TypeWalker;
use util::common::MemoizationMap;
-use util::nodemap::{NodeSet, FxHashMap};
+use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
use serialize::{self, Encodable, Encoder};
use std::borrow::Cow;
/// The complete set of all analyses described in this module. This is
/// produced by the driver and fed to trans and later passes.
+///
+/// NB: These contents are being migrated into queries using the
+/// *on-demand* infrastructure.
#[derive(Clone)]
pub struct CrateAnalysis {
- pub export_map: ExportMap,
- pub access_levels: middle::privacy::AccessLevels,
+ pub access_levels: Rc<AccessLevels>,
pub reachable: NodeSet,
pub name: String,
pub glob_map: Option<hir::GlobMap>,
pub freevars: FreevarMap,
pub trait_map: TraitMap,
pub maybe_unused_trait_imports: NodeSet,
+ pub export_map: ExportMap,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
})
}
- pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized {
- queries::custom_coerce_unsized_kind::get(self, DUMMY_SP, did)
+ pub fn coerce_unsized_info(self, did: DefId) -> adjustment::CoerceUnsizedInfo {
+ queries::coerce_unsized_info::get(self, DUMMY_SP, did)
}
pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
}
- /// Populates the type context with all the inherent implementations for
- /// the given type if necessary.
- pub fn populate_inherent_implementations_for_type_if_necessary(self,
- span: Span,
- type_id: DefId) {
- if type_id.is_local() {
- // Make sure coherence of inherent impls ran already.
- ty::queries::coherent_inherent_impls::force(self, span, LOCAL_CRATE);
- return
- }
-
- // The type is not local, hence we are reading this out of
- // metadata and don't need to track edges.
- let _ignore = self.dep_graph.in_ignore();
-
- if self.populated_external_types.borrow().contains(&type_id) {
- return
- }
-
- debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}",
- type_id);
-
- let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id);
-
- self.maps.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
- self.populated_external_types.borrow_mut().insert(type_id);
- }
-
/// Populates the type context with all the implementations for the given
/// trait if necessary.
pub fn populate_implementations_for_trait_if_necessary(self, trait_id: DefId) {
..*providers
};
}
+
+
+/// A map for the local crate mapping each type to a vector of its
+/// inherent impls. This is not meant to be used outside of coherence;
+/// rather, you should request the vector for a specific type via
+/// `ty::queries::inherent_impls::get(def_id)` so as to minimize your
+/// dependencies (constructing this map requires touching the entire
+/// crate).
+#[derive(Clone, Debug)]
+pub struct CrateInherentImpls {
+ pub inherent_impls: DefIdMap<Rc<Vec<DefId>>>,
+}
+
RegionsNoOverlap(a, b) => {
return tcx.lift(&(a, b)).map(|(a, b)| RegionsNoOverlap(a, b))
}
- RegionsInsufficientlyPolymorphic(a, b) => {
- return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b))
+ RegionsInsufficientlyPolymorphic(a, b, ref c) => {
+ let c = c.clone();
+ return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b, c))
}
- RegionsOverlyPolymorphic(a, b) => {
- return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b))
+ RegionsOverlyPolymorphic(a, b, ref c) => {
+ let c = c.clone();
+ return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b, c))
}
IntMismatch(x) => IntMismatch(x),
FloatMismatch(x) => FloatMismatch(x),
[dependencies]
syntax = { path = "../libsyntax" }
serialize = { path = "../libserialize" }
-log = { path = "../liblog" }
+log = "0.3"
[features]
jemalloc = []
test = false
[dependencies]
-log = { path = "../liblog" }
+log = "0.3"
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
graphviz = { path = "../libgraphviz" }
// First, filter out duplicates
moved.sort();
moved.dedup();
- debug!("fragments 1 moved: {:?}", path_lps(&moved[..]));
+ debug!("fragments 1 moved: {:?}", path_lps(&moved));
assigned.sort();
assigned.dedup();
- debug!("fragments 1 assigned: {:?}", path_lps(&assigned[..]));
+ debug!("fragments 1 assigned: {:?}", path_lps(&assigned));
// Second, build parents from the moved and assigned.
for m in &moved {
parents.sort();
parents.dedup();
- debug!("fragments 2 parents: {:?}", path_lps(&parents[..]));
+ debug!("fragments 2 parents: {:?}", path_lps(&parents));
// Third, filter the moved and assigned fragments down to just the non-parents
- moved.retain(|f| non_member(*f, &parents[..]));
- debug!("fragments 3 moved: {:?}", path_lps(&moved[..]));
+ moved.retain(|f| non_member(*f, &parents));
+ debug!("fragments 3 moved: {:?}", path_lps(&moved));
- assigned.retain(|f| non_member(*f, &parents[..]));
- debug!("fragments 3 assigned: {:?}", path_lps(&assigned[..]));
+ assigned.retain(|f| non_member(*f, &parents));
+ debug!("fragments 3 assigned: {:?}", path_lps(&assigned));
// Fourth, build the leftover from the moved, assigned, and parents.
for m in &moved {
unmoved.sort();
unmoved.dedup();
- debug!("fragments 4 unmoved: {:?}", frag_lps(&unmoved[..]));
+ debug!("fragments 4 unmoved: {:?}", frag_lps(&unmoved));
// Fifth, filter the leftover fragments down to its core.
unmoved.retain(|f| match *f {
AllButOneFrom(_) => true,
- Just(mpi) => non_member(mpi, &parents[..]) &&
- non_member(mpi, &moved[..]) &&
- non_member(mpi, &assigned[..])
+ Just(mpi) => non_member(mpi, &parents) &&
+ non_member(mpi, &moved) &&
+ non_member(mpi, &assigned)
});
- debug!("fragments 5 unmoved: {:?}", frag_lps(&unmoved[..]));
+ debug!("fragments 5 unmoved: {:?}", frag_lps(&unmoved));
// Swap contents back in.
fragments.unmoved_fragments = unmoved;
&flowed_moves.move_data,
owner_id);
- check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans[..], body);
+ check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
}
fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
set.push_str(", ");
}
let loan_str = self.borrowck_ctxt.loan_path_to_string(&lp);
- set.push_str(&loan_str[..]);
+ set.push_str(&loan_str);
saw_some = true;
true
});
[dependencies]
arena = { path = "../libarena" }
-log = { path = "../liblog" }
+log = "0.3"
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_const_math = { path = "../librustc_const_math" }
}).collect();
let wild_patterns: Vec<_> = wild_patterns_owned.iter().collect();
let matrix = Matrix(m.iter().flat_map(|r| {
- specialize(cx, &r[..], &ctor, &wild_patterns)
+ specialize(cx, &r, &ctor, &wild_patterns)
}).collect());
match specialize(cx, v, &ctor, &wild_patterns) {
- Some(v) => match is_useful(cx, &matrix, &v[..], witness) {
+ Some(v) => match is_useful(cx, &matrix, &v, witness) {
UsefulWithWitness(witnesses) => UsefulWithWitness(
witnesses.into_iter()
.map(|witness| witness.apply_constructor(cx, &ctor, lty))
for &(pat, hir_pat) in pats {
let v = vec![pat];
- match is_useful(cx, &seen, &v[..], LeaveOutWitness) {
+ match is_useful(cx, &seen, &v, LeaveOutWitness) {
NotUseful => {
match source {
hir::MatchSource::IfLetDesugar { .. } => {
crate-type = ["dylib"]
[dependencies]
-log = { path = "../liblog" }
+log = "0.3"
serialize = { path = "../libserialize" }
type Target = [A::Element];
fn deref(&self) -> &Self::Target {
match *self {
- AccumulateVec::Array(ref v) => &v[..],
- AccumulateVec::Heap(ref v) => &v[..],
+ AccumulateVec::Array(ref v) => v,
+ AccumulateVec::Heap(ref v) => v,
}
}
}
impl<A: Array> DerefMut for AccumulateVec<A> {
fn deref_mut(&mut self) -> &mut [A::Element] {
match *self {
- AccumulateVec::Array(ref mut v) => &mut v[..],
- AccumulateVec::Heap(ref mut v) => &mut v[..],
+ AccumulateVec::Array(ref mut v) => v,
+ AccumulateVec::Heap(ref mut v) => v,
}
}
}
#[test]
fn test_encode() {
fn test(n: u64, base: u64) {
- assert_eq!(Ok(n), u64::from_str_radix(&encode(n, base)[..], base as u32));
+ assert_eq!(Ok(n), u64::from_str_radix(&encode(n, base), base as u32));
}
for base in 2..37 {
impl ::std::fmt::Debug for Blake2bCtx {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
try!(write!(fmt, "hash: "));
- for v in &self.h[..] {
+ for v in &self.h {
try!(write!(fmt, "{:x}", v));
}
Ok(())
impl<T: Idx> Deref for IdxSetBuf<T> {
type Target = IdxSet<T>;
fn deref(&self) -> &IdxSet<T> {
- unsafe { IdxSet::from_slice(&self.bits[..]) }
+ unsafe { IdxSet::from_slice(&self.bits) }
}
}
impl<T: Idx> DerefMut for IdxSetBuf<T> {
fn deref_mut(&mut self) -> &mut IdxSet<T> {
- unsafe { IdxSet::from_slice_mut(&mut self.bits[..]) }
+ unsafe { IdxSet::from_slice_mut(&mut self.bits) }
}
}
}
pub fn words(&self) -> &[Word] {
- &self.bits[..]
+ &self.bits
}
pub fn words_mut(&mut self) -> &mut [Word] {
- &mut self.bits[..]
+ &mut self.bits
}
pub fn clone_from(&mut self, other: &IdxSet<T>) {
[dependencies]
arena = { path = "../libarena" }
graphviz = { path = "../libgraphviz" }
-log = { path = "../liblog" }
+log = { version = "0.3", features = ["release_max_level_info"] }
+env_logger = { version = "0.4", default-features = false }
proc_macro_plugin = { path = "../libproc_macro_plugin" }
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
use std::io::{self, Write};
use std::iter;
use std::path::{Path, PathBuf};
+use std::rc::Rc;
use syntax::{ast, diagnostics, visit};
use syntax::attr;
use syntax::ext::base::ExtCtxt;
result?;
- if log_enabled!(::log::INFO) {
+ if log_enabled!(::log::LogLevel::Info) {
println!("Pre-trans");
tcx.print_debug_stats();
}
let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map);
- if log_enabled!(::log::INFO) {
+ if log_enabled!(::log::LogLevel::Info) {
println!("Post-trans");
tcx.print_debug_stats();
}
}
fn keep_ast(sess: &Session) -> bool {
- sess.opts.debugging_opts.keep_ast ||
- sess.opts.debugging_opts.save_analysis ||
- sess.opts.debugging_opts.save_analysis_csv ||
- sess.opts.debugging_opts.save_analysis_api
+ sess.opts.debugging_opts.keep_ast || ::save_analysis(sess)
}
/// The name used for source code that doesn't originate in a file
expanded_crate: krate,
defs: resolver.definitions,
analysis: ty::CrateAnalysis {
- export_map: resolver.export_map,
- access_levels: AccessLevels::default(),
+ access_levels: Rc::new(AccessLevels::default()),
reachable: NodeSet(),
name: crate_name.to_string(),
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
},
resolutions: Resolutions {
freevars: resolver.freevars,
+ export_map: resolver.export_map,
trait_map: resolver.trait_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
},
- hir_forest: hir_forest
+ hir_forest: hir_forest,
})
}
let mut local_providers = ty::maps::Providers::default();
mir::provide(&mut local_providers);
+ rustc_privacy::provide(&mut local_providers);
typeck::provide(&mut local_providers);
ty::provide(&mut local_providers);
|| consts::check_crate(tcx));
analysis.access_levels =
- time(time_passes, "privacy checking", || {
- rustc_privacy::check_crate(tcx, &analysis.export_map)
- });
+ time(time_passes, "privacy checking", || rustc_privacy::check_crate(tcx));
time(time_passes,
"intrinsic checking",
analysis.reachable =
time(time_passes,
"reachability checking",
- || reachable::find_reachable(tcx, &analysis.access_levels));
+ || reachable::find_reachable(tcx));
- time(time_passes, "death checking", || {
- middle::dead::check_crate(tcx, &analysis.access_levels);
- });
+ time(time_passes, "death checking", || middle::dead::check_crate(tcx));
time(time_passes, "unused lib feature checking", || {
- stability::check_unused_or_stable_features(tcx, &analysis.access_levels)
+ stability::check_unused_or_stable_features(tcx)
});
- time(time_passes,
- "lint checking",
- || lint::check_crate(tcx, &analysis.access_levels));
+ time(time_passes, "lint checking", || lint::check_crate(tcx));
// The above three passes generate errors w/o aborting
if sess.err_count() > 0 {
extern crate arena;
extern crate getopts;
extern crate graphviz;
+extern crate env_logger;
extern crate libc;
extern crate rustc;
extern crate rustc_back;
use rustc_resolve as resolve;
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::dep_graph::DepGraph;
// Extract input (string or file and optional path) from matches.
fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>)> {
if free_matches.len() == 1 {
- let ifile = &free_matches[0][..];
+ let ifile = &free_matches[0];
if ifile == "-" {
let mut src = String::new();
io::stdin().read_to_string(&mut src).unwrap();
state.expanded_crate.unwrap(),
state.analysis.unwrap(),
state.crate_name.unwrap(),
- state.out_dir,
- save_analysis_format(state.session))
+ DumpHandler::new(save_analysis_format(state.session),
+ state.out_dir,
+ state.crate_name.unwrap()))
});
};
control.after_analysis.run_callback_on_error = true;
for lint in lints {
let name = lint.name_lower().replace("_", "-");
println!(" {} {:7.7} {}",
- padded(&name[..]),
+ padded(&name),
lint.default_level.as_str(),
lint.desc);
}
.map(|x| x.to_string().replace("_", "-"))
.collect::<Vec<String>>()
.join(", ");
- println!(" {} {}", padded(&name[..]), desc);
+ println!(" {} {}", padded(&name), desc);
}
println!("\n");
};
.into_iter()
.map(|x| x.opt_group)
.collect();
- let matches = match getopts::getopts(&args[..], &all_groups) {
+ let matches = match getopts::getopts(&args, &all_groups) {
Ok(m) => m,
Err(f) => early_error(ErrorOutputType::default(), &f.to_string()),
};
format!("we would appreciate a bug report: {}", BUG_REPORT_URL)];
for note in &xs {
handler.emit(&MultiSpan::new(),
- ¬e[..],
+ ¬e,
errors::Level::Note);
}
if match env::var_os("RUST_BACKTRACE") {
}
pub fn main() {
+ env_logger::init().unwrap();
let result = run(|| run_compiler(&env::args().collect::<Vec<_>>(),
&mut RustcDefaultCalls,
None,
-> NodesMatchingUII<'a, 'hir> {
match *self {
ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()),
- ItemViaPath(ref parts) => NodesMatchingSuffix(map.nodes_matching_suffix(&parts[..])),
+ ItemViaPath(ref parts) => NodesMatchingSuffix(map.nodes_matching_suffix(&parts)),
}
}
user_option,
self.reconstructed_input(),
is_wrong_because);
- sess.fatal(&message[..])
+ sess.fatal(&message)
};
let mut saw_node = ast::DUMMY_NODE_ID;
fn expand_err_details(r: io::Result<()>) -> io::Result<()> {
r.map_err(|ioerr| {
io::Error::new(io::ErrorKind::Other,
- &format!("graphviz::render failed: {}", ioerr)[..])
+ format!("graphviz::render failed: {}", ioerr))
})
}
}
pub fn t_param(&self, index: u32) -> Ty<'tcx> {
let name = format!("T{}", index);
- self.infcx.tcx.mk_param(index, Symbol::intern(&name[..]))
+ self.infcx.tcx.mk_param(index, Symbol::intern(&name))
}
pub fn re_early_bound(&self, index: u32, name: &'static str) -> &'tcx ty::Region {
rustc = { path = "../librustc" }
rustc_data_structures = { path = "../librustc_data_structures" }
serialize = { path = "../libserialize" }
-log = { path = "../liblog" }
+log = "0.3"
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
let rustc_version_str_len = rustc_version_str_len[0] as usize;
let mut buffer = Vec::with_capacity(rustc_version_str_len);
buffer.resize(rustc_version_str_len, 0);
- file.read_exact(&mut buffer[..])?;
+ file.read_exact(&mut buffer)?;
- if &buffer[..] != rustc_version().as_bytes() {
+ if buffer != rustc_version().as_bytes() {
report_format_mismatch(sess, path, "Different compiler version");
return Ok(None);
}
test = false
[dependencies]
-log = { path = "../liblog" }
+log = "0.3"
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_const_eval = { path = "../librustc_const_eval" }
} else {
format!("{} `{}` should have a camel case name such as `{}`", sort, name, c)
};
- cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]);
+ cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m);
}
}
}
attr.check_name("doc") &&
match attr.meta_item_list() {
None => false,
- Some(l) => attr::list_contains_name(&l[..], "hidden"),
+ Some(l) => attr::list_contains_name(&l, "hidden"),
}
});
self.doc_hidden_stack.push(doc_hidden);
ty::TyBool => return,
ty::TyAdt(def, _) => {
let attrs = cx.tcx.get_attrs(def.did);
- check_must_use(cx, &attrs[..], s.span)
+ check_must_use(cx, &attrs, s.span)
}
_ => false,
};
cfg.flag(flag);
}
- for component in &components[..] {
+ for component in &components {
let mut flag = String::from("-DLLVM_COMPONENT_");
flag.push_str(&component.to_uppercase());
cfg.flag(&flag);
if !is_crossed {
cmd.arg("--system-libs");
}
- cmd.args(&components[..]);
+ cmd.args(&components);
for lib in output(&mut cmd).split_whitespace() {
let name = if lib.starts_with("-l") {
[dependencies]
flate = { path = "../libflate" }
-log = { path = "../liblog" }
+log = "0.3"
proc_macro = { path = "../libproc_macro" }
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
name,
config::host_triple(),
self.sess.opts.target_triple);
- span_fatal!(self.sess, span, E0456, "{}", &message[..]);
+ span_fatal!(self.sess, span, E0456, "{}", &message);
}
let root = ekrate.metadata.get_root();
self.inject_allocator_crate();
self.inject_panic_runtime(krate);
- if log_enabled!(log::INFO) {
+ if log_enabled!(log::LogLevel::Info) {
dump_crates(&self.cstore);
}
}
associated_item => { cdata.get_associated_item(def_id.index) }
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
- custom_coerce_unsized_kind => {
- cdata.get_custom_coerce_unsized_kind(def_id.index).unwrap_or_else(|| {
- bug!("custom_coerce_unsized_kind: `{:?}` is missing its kind", def_id);
+ coerce_unsized_info => {
+ cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
+ bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
})
}
mir => {
typeck_tables => { cdata.item_body_tables(def_id.index, tcx) }
closure_kind => { cdata.closure_kind(def_id.index) }
closure_type => { cdata.closure_ty(def_id.index, tcx) }
+ inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
}
impl CrateStore for cstore::CStore {
self.get_crate_data(did.krate).get_fn_arg_names(did.index)
}
- fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>
- {
- self.dep_graph.read(DepNode::MetaData(def_id));
- self.get_crate_data(def_id.krate).get_inherent_implementations_for_type(def_id.index)
- }
-
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>
{
if let Some(def_id) = filter {
self.do_extern_mod_stmt_cnum(emod_id)
}
- fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- reexports: &def::ExportMap,
+ fn encode_metadata<'a, 'tcx>(&self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
reachable: &NodeSet) -> Vec<u8>
{
- encoder::encode_metadata(tcx, self, reexports, link_meta, reachable)
+ encoder::encode_metadata(tcx, self, link_meta, reachable)
}
fn metadata_encoding_version(&self) -> &[u8]
self.get_impl_data(id).polarity
}
- pub fn get_custom_coerce_unsized_kind(&self,
- id: DefIndex)
- -> Option<ty::adjustment::CustomCoerceUnsized> {
- self.get_impl_data(id).coerce_unsized_kind
+ pub fn get_coerce_unsized_info(&self,
+ id: DefIndex)
+ -> Option<ty::adjustment::CoerceUnsizedInfo> {
+ self.get_impl_data(id).coerce_unsized_info
}
pub fn get_impl_trait(&self,
use schema::*;
use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
-use rustc::hir::def;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
use rustc::hir::map::definitions::DefPathTable;
use rustc::middle::dependency_format::Linkage;
pub struct EncodeContext<'a, 'tcx: 'a> {
opaque: opaque::Encoder<'a>,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
- reexports: &'a def::ExportMap,
link_meta: &'a LinkMeta,
cstore: &'a cstore::CStore,
exported_symbols: &'a NodeSet,
let def_id = tcx.hir.local_def_id(id);
let data = ModData {
- reexports: match self.reexports.get(&id) {
+ reexports: match tcx.export_map.get(&id) {
Some(exports) if *vis == hir::Public => self.lazy_seq_ref(exports),
_ => LazySeq::empty(),
},
let data = ImplData {
polarity: hir::ImplPolarity::Positive,
parent_impl: None,
- coerce_unsized_kind: None,
+ coerce_unsized_info: None,
trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
};
None
};
+ // if this is an impl of `CoerceUnsized`, create its
+ // "unsized info", else just store None
+ let coerce_unsized_info =
+ trait_ref.and_then(|t| {
+ if Some(t.def_id) == tcx.lang_items.coerce_unsized_trait() {
+ Some(ty::queries::coerce_unsized_info::get(tcx, item.span, def_id))
+ } else {
+ None
+ }
+ });
+
let data = ImplData {
polarity: polarity,
parent_impl: parent,
- coerce_unsized_kind: tcx.maps.custom_coerce_unsized_kind
- .borrow()
- .get(&def_id)
- .cloned(),
+ coerce_unsized_info: coerce_unsized_info,
trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
};
self.encode_fields(def_id);
}
hir::ItemImpl(..) => {
- for &trait_item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
+ for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
self.record(trait_item_def_id,
EncodeContext::encode_info_for_impl_item,
trait_item_def_id);
}
}
hir::ItemTrait(..) => {
- for &item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
+ for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
self.record(item_def_id,
EncodeContext::encode_info_for_trait_item,
item_def_id);
pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
cstore: &cstore::CStore,
- reexports: &def::ExportMap,
link_meta: &LinkMeta,
exported_symbols: &NodeSet)
-> Vec<u8> {
let mut ecx = EncodeContext {
opaque: opaque::Encoder::new(&mut cursor),
tcx: tcx,
- reexports: reexports,
link_meta: link_meta,
cstore: cstore,
exported_symbols: exported_symbols,
Some(file) => file,
};
let (hash, found_kind) =
- if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") {
+ if file.starts_with(&rlib_prefix) && file.ends_with(".rlib") {
(&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib)
- } else if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rmeta") {
+ } else if file.starts_with(&rlib_prefix) && file.ends_with(".rmeta") {
(&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta)
} else if file.starts_with(&dylib_prefix) &&
file.ends_with(&dypair.1) {
(&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], CrateFlavor::Dylib)
} else {
- if file.starts_with(&staticlib_prefix[..]) && file.ends_with(&staticpair.1) {
+ if file.starts_with(&staticlib_prefix) && file.ends_with(&staticpair.1) {
staticlibs.push(CrateMismatch {
path: path.to_path_buf(),
got: "static".to_string(),
pub struct ImplData<'tcx> {
pub polarity: hir::ImplPolarity,
pub parent_impl: Option<DefId>,
- pub coerce_unsized_kind: Option<ty::adjustment::CustomCoerceUnsized>,
+
+ /// This is `Some` only for impls of `CoerceUnsized`.
+ pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
}
[dependencies]
graphviz = { path = "../libgraphviz" }
-log = { path = "../liblog" }
+log = "0.3"
rustc = { path = "../librustc" }
rustc_const_eval = { path = "../librustc_const_eval" }
rustc_const_math = { path = "../librustc_const_math" }
crate-type = ["dylib"]
[dependencies]
-log = { path = "../liblog" }
+log = "0.3"
rustc = { path = "../librustc" }
rustc_const_eval = { path = "../librustc_const_eval" }
rustc_const_math = { path = "../librustc_const_math" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
-rustc_errors = { path = "../librustc_errors" }
\ No newline at end of file
+rustc_errors = { path = "../librustc_errors" }
// inside this crate, so continue would spew "macro undefined"
// errors
Err(err) => {
- self.sess.span_fatal(span, &err[..])
+ self.sess.span_fatal(span, &err)
}
};
unsafe {
let registrar =
- match lib.symbol(&symbol[..]) {
+ match lib.symbol(&symbol) {
Ok(registrar) => {
mem::transmute::<*mut u8,PluginRegistrarFun>(registrar)
}
// again fatal if we can't register macros
Err(err) => {
- self.sess.span_fatal(span, &err[..])
+ self.sess.span_fatal(span, &err)
}
};
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
+#![cfg_attr(stage0, feature(field_init_shorthand))]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
#![feature(staged_api)]
#[macro_use] extern crate syntax;
extern crate syntax_pos;
-use rustc::dep_graph::DepNode;
use rustc::hir::{self, PatKind};
-use rustc::hir::def::{self, Def};
-use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::hir::def::Def;
+use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::DeepVisitor;
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
use rustc::middle::privacy::{AccessLevel, AccessLevels};
use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
use rustc::ty::fold::TypeVisitor;
+use rustc::ty::maps::Providers;
use rustc::util::nodemap::NodeSet;
use syntax::ast;
-use syntax_pos::Span;
+use syntax_pos::{DUMMY_SP, Span};
use std::cmp;
use std::mem::replace;
+use std::rc::Rc;
pub mod diagnostics;
struct EmbargoVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- export_map: &'a def::ExportMap,
// Accessibility levels for reachable nodes
access_levels: AccessLevels,
// This code is here instead of in visit_item so that the
// crate module gets processed as well.
if self.prev_level.is_some() {
- if let Some(exports) = self.export_map.get(&id) {
+ if let Some(exports) = self.tcx.export_map.get(&id) {
for export in exports {
if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
self.update(node_id, Some(AccessLevel::Exported));
fn visit_pat(&mut self, _: &'tcx hir::Pat) {}
}
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- export_map: &def::ExportMap)
- -> AccessLevels {
- let _task = tcx.dep_graph.in_task(DepNode::Privacy);
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers {
+ privacy_access_levels,
+ ..*providers
+ };
+}
+
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Rc<AccessLevels> {
+ tcx.dep_graph.with_ignore(|| { // FIXME
+ ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE)
+ })
+}
+
+fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ krate: CrateNum)
+ -> Rc<AccessLevels> {
+ assert_eq!(krate, LOCAL_CRATE);
let krate = tcx.hir.krate();
// items which are reachable from external crates based on visibility.
let mut visitor = EmbargoVisitor {
tcx: tcx,
- export_map: export_map,
access_levels: Default::default(),
prev_level: Some(AccessLevel::Public),
changed: false,
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
}
- visitor.access_levels
+ Rc::new(visitor.access_levels)
}
__build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }
test = false
[dependencies]
-log = { path = "../liblog" }
+log = "0.3"
syntax = { path = "../libsyntax" }
rustc = { path = "../librustc" }
arena = { path = "../libarena" }
binding: &'a NameBinding<'a>,
span: Span,
allow_shadowing: bool) {
- if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing {
+ if self.global_macros.insert(name, binding).is_some() && !allow_shadowing {
let msg = format!("`{}` is already in scope", name);
let note =
"macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
E0422: r##"
You are trying to use an identifier that is either undefined or not a struct.
Erroneous code example:
-``` compile_fail,E0422
+
+```compile_fail,E0422
fn main () {
let x = Foo { x: 1, y: 2 };
}
```
+
In this case, `Foo` is undefined, so it inherently isn't anything, and
definitely not a struct.
+
```compile_fail
fn main () {
let foo = 1;
let x = foo { x: 1, y: 2 };
}
```
+
In this case, `foo` is defined, but is not a struct, so Rust can't use it as
one.
"##,
use std::rc::Rc;
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
-use macros::{InvocationData, LegacyBinding, LegacyScope};
+use macros::{InvocationData, LegacyBinding, LegacyScope, MacroBinding};
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
fn is_local(&self) -> bool {
self.normal_ancestor_id.is_local()
}
+
+ fn nearest_item_scope(&'a self) -> Module<'a> {
+ if self.is_trait() { self.parent.unwrap() } else { self }
+ }
}
impl<'a> fmt::Debug for ModuleData<'a> {
crate_loader: &'a mut CrateLoader,
macro_names: FxHashSet<Name>,
- builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
+ global_macros: FxHashMap<Name, &'a NameBinding<'a>>,
lexical_macro_resolutions: Vec<(Name, &'a Cell<LegacyScope<'a>>)>,
macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
macro_defs: FxHashMap<Mark, DefId>,
crate_loader: crate_loader,
macro_names: FxHashSet(),
- builtin_macros: FxHashMap(),
+ global_macros: FxHashMap(),
lexical_macro_resolutions: Vec::new(),
macro_map: FxHashMap(),
macro_exports: Vec::new(),
};
}
}
- let is_builtin = self.builtin_macros.get(&path[0].name).cloned()
+ let is_global = self.global_macros.get(&path[0].name).cloned()
.map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
- if primary_ns != MacroNS && (is_builtin || self.macro_names.contains(&path[0].name)) {
+ if primary_ns != MacroNS && (is_global || self.macro_names.contains(&path[0].name)) {
// Return some dummy definition, it's enough for error reporting.
return Some(
PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
self.resolve_ident_in_module(module, ident, ns, false, record_used)
} else if opt_ns == Some(MacroNS) {
self.resolve_lexical_macro_path_segment(ident, ns, record_used)
+ .map(MacroBinding::binding)
} else {
match self.resolve_ident_in_lexical_scope(ident, ns, record_used) {
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
};
let msg1 = format!("`{}` could refer to the name {} here", name, participle(b1));
let msg2 = format!("`{}` could also refer to the name {} here", name, participle(b2));
- let note = if !lexical && b1.is_glob_import() {
+ let note = if b1.expansion == Mark::root() || !lexical && b1.is_glob_import() {
format!("consider adding an explicit import of `{}` to disambiguate", name)
} else if let Def::Macro(..) = b1.def() {
format!("macro-expanded {} do not shadow",
let msg = format!("`{}` is ambiguous", name);
self.session.add_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg);
} else {
- self.session.struct_span_err(span, &format!("`{}` is ambiguous", name))
- .span_note(b1.span, &msg1)
- .span_note(b2.span, &msg2)
- .note(¬e)
- .emit();
+ let mut err =
+ self.session.struct_span_err(span, &format!("`{}` is ambiguous", name));
+ err.span_note(b1.span, &msg1);
+ match b2.def() {
+ Def::Macro(..) if b2.span == DUMMY_SP =>
+ err.note(&format!("`{}` is also a builtin macro", name)),
+ _ => err.span_note(b2.span, &msg2),
+ };
+ err.note(¬e).emit();
}
}
if self.proc_macro_enabled { return; }
for attr in attrs {
- let name = unwrap_or!(attr.name(), continue);
- let maybe_binding = self.builtin_macros.get(&name).cloned().or_else(|| {
- let ident = Ident::with_empty_ctxt(name);
- self.resolve_lexical_macro_path_segment(ident, MacroNS, None).ok()
- });
-
- if let Some(binding) = maybe_binding {
- if let SyntaxExtension::AttrProcMacro(..) = *binding.get_macro(self) {
+ if attr.path.segments.len() > 1 {
+ continue
+ }
+ let ident = attr.path.segments[0].identifier;
+ let result = self.resolve_lexical_macro_path_segment(ident, MacroNS, None);
+ if let Ok(binding) = result {
+ if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) {
attr::mark_known(attr);
let msg = "attribute procedural macros are experimental";
feature_err(&self.session.parse_sess, feature,
attr.span, GateIssue::Language, msg)
- .span_note(binding.span, "procedural macro imported here")
+ .span_note(binding.span(), "procedural macro imported here")
.emit();
}
}
pub span: Span,
}
+#[derive(Copy, Clone)]
pub enum MacroBinding<'a> {
Legacy(&'a LegacyBinding<'a>),
+ Global(&'a NameBinding<'a>),
Modern(&'a NameBinding<'a>),
}
+impl<'a> MacroBinding<'a> {
+ pub fn span(self) -> Span {
+ match self {
+ MacroBinding::Legacy(binding) => binding.span,
+ MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding.span,
+ }
+ }
+
+ pub fn binding(self) -> &'a NameBinding<'a> {
+ match self {
+ MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding,
+ MacroBinding::Legacy(_) => panic!("unexpected MacroBinding::Legacy"),
+ }
+ }
+}
+
impl<'a> base::Resolver for Resolver<'a> {
fn next_node_id(&mut self) -> ast::NodeId {
self.session.next_node_id()
expansion: mark,
};
expansion.visit_with(&mut visitor);
- self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
invocation.expansion.set(visitor.legacy_scope);
}
vis: ty::Visibility::Invisible,
expansion: Mark::root(),
});
- self.builtin_macros.insert(ident.name, binding);
+ self.global_macros.insert(ident.name, binding);
}
fn resolve_imports(&mut self) {
attr::mark_known(&attrs[i]);
}
- match self.builtin_macros.get(&name).cloned() {
+ match self.global_macros.get(&name).cloned() {
Some(binding) => match *binding.get_macro(self) {
MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
return Some(attrs.remove(i))
}
let trait_name = traits[j].segments[0].identifier.name;
let legacy_name = Symbol::intern(&format!("derive_{}", trait_name));
- if !self.builtin_macros.contains_key(&legacy_name) {
+ if !self.global_macros.contains_key(&legacy_name) {
continue
}
let span = traits.remove(j).span;
Err(Determinacy::Determined)
},
};
- self.current_module.macro_resolutions.borrow_mut()
+ self.current_module.nearest_item_scope().macro_resolutions.borrow_mut()
.push((path.into_boxed_slice(), span));
return def;
}
let name = path[0].name;
- let result = match self.resolve_legacy_scope(&invocation.legacy_scope, name, false) {
- Some(MacroBinding::Legacy(binding)) => Ok(Def::Macro(binding.def_id, MacroKind::Bang)),
- Some(MacroBinding::Modern(binding)) => Ok(binding.def_ignoring_ambiguity()),
- None => match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) {
- Ok(binding) => Ok(binding.def_ignoring_ambiguity()),
- Err(Determinacy::Undetermined) if !force =>
- return Err(Determinacy::Undetermined),
+ let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, name, false);
+ 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) {
+ Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()),
+ Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined),
Err(_) => {
self.found_unresolved_macro = true;
Err(Determinacy::Determined)
}
- },
+ }
};
- self.current_module.legacy_macro_resolutions.borrow_mut()
+ self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut()
.push((scope, path[0], span, kind));
result
ident: Ident,
ns: Namespace,
record_used: Option<Span>)
- -> Result<&'a NameBinding<'a>, Determinacy> {
- let mut module = self.current_module;
- let mut potential_expanded_shadower: Option<&NameBinding> = None;
+ -> 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 };
loop {
- // Since expanded macros may not shadow the lexical scope (enforced below),
- // we can ignore unresolved invocations (indicated by the penultimate argument).
- match self.resolve_ident_in_module(module, ident, ns, true, record_used) {
+ 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)
+ .map(MacroBinding::Modern)
+ } else {
+ self.global_macros.get(&ident.name).cloned().ok_or(determinacy)
+ .map(MacroBinding::Global)
+ };
+
+ match result.map(MacroBinding::binding) {
Ok(binding) => {
let span = match record_used {
Some(span) => span,
- None => return Ok(binding),
+ None => return result,
};
- match potential_expanded_shadower {
- Some(shadower) if shadower.def() != binding.def() => {
+ 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,
legacy: false,
});
- return Ok(shadower);
+ return potential_illegal_shadower;
}
- _ if binding.expansion == Mark::root() => return Ok(binding),
- _ => potential_expanded_shadower = Some(binding),
+ }
+ if binding.expansion != Mark::root() ||
+ (binding.is_glob_import() && module.unwrap().def().is_some()) {
+ potential_illegal_shadower = result;
+ } else {
+ return result;
}
},
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
Err(Determinacy::Determined) => {}
}
- match module.kind {
- ModuleKind::Block(..) => module = module.parent.unwrap(),
- ModuleKind::Def(..) => return match potential_expanded_shadower {
- Some(binding) => Ok(binding),
- None if record_used.is_some() => Err(Determinacy::Determined),
- None => Err(Determinacy::Undetermined),
+ module = match module {
+ Some(module) => match module.kind {
+ ModuleKind::Block(..) => module.parent,
+ ModuleKind::Def(..) => None,
},
+ None => return potential_illegal_shadower,
}
}
}
let binding = if let Some(binding) = binding {
MacroBinding::Legacy(binding)
- } else if let Some(binding) = self.builtin_macros.get(&name).cloned() {
+ } else if let Some(binding) = self.global_macros.get(&name).cloned() {
if !self.use_extern_macros {
self.record_use(Ident::with_empty_ctxt(name), MacroNS, binding, DUMMY_SP);
}
- MacroBinding::Modern(binding)
+ MacroBinding::Global(binding)
} else {
return None;
};
let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true);
let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span));
match (legacy_resolution, resolution) {
- (Some(legacy_resolution), Ok(resolution)) => {
- let (legacy_span, participle) = match legacy_resolution {
- MacroBinding::Modern(binding)
- if binding.def() == resolution.def() => continue,
- MacroBinding::Modern(binding) => (binding.span, "imported"),
- MacroBinding::Legacy(binding) => (binding.span, "defined"),
- };
- let msg1 = format!("`{}` could refer to the macro {} here", ident, participle);
+ (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
+ let msg1 = format!("`{}` could refer to the macro defined here", ident);
let msg2 = format!("`{}` could also refer to the macro imported here", ident);
self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
- .span_note(legacy_span, &msg1)
- .span_note(resolution.span, &msg2)
+ .span_note(legacy_binding.span, &msg1)
+ .span_note(binding.span, &msg2)
.emit();
},
- (Some(MacroBinding::Modern(binding)), Err(_)) => {
+ (Some(MacroBinding::Global(binding)), Ok(MacroBinding::Global(_))) => {
self.record_use(ident, MacroNS, binding, span);
self.err_if_macro_use_proc_macro(ident.name, span, binding);
},
find_best_match_for_name(self.macro_names.iter(), name, None)
} else {
None
- // Then check builtin macros.
+ // Then check global macros.
}.or_else(|| {
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
- let builtin_macros = self.builtin_macros.clone();
- let names = builtin_macros.iter().filter_map(|(name, binding)| {
+ let global_macros = self.global_macros.clone();
+ let names = global_macros.iter().filter_map(|(name, binding)| {
if binding.get_macro(self).kind() == kind {
Some(name)
} else {
module: Module<'a>,
ident: Ident,
ns: Namespace,
- ignore_unresolved_invocations: bool,
+ restricted_shadowing: bool,
record_used: Option<Span>)
-> Result<&'a NameBinding<'a>, Determinacy> {
self.populate_module_if_necessary(module);
if let Some(binding) = resolution.binding {
if let Some(shadowed_glob) = resolution.shadows_glob {
let name = ident.name;
- // If we ignore unresolved invocations, we must forbid
- // expanded shadowing to avoid time travel.
- if ignore_unresolved_invocations &&
+ // Forbid expanded shadowing to avoid time travel.
+ if restricted_shadowing &&
binding.expansion != Mark::root() &&
ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing
binding.def() != shadowed_glob.def() {
}
let no_unresolved_invocations =
- ignore_unresolved_invocations || module.unresolved_invocations.borrow().is_empty();
+ restricted_shadowing || module.unresolved_invocations.borrow().is_empty();
match resolution.binding {
// In `MacroNS`, expanded bindings do not shadow (enforced in `try_define`).
Some(binding) if no_unresolved_invocations || ns == MacroNS =>
}
// Check if the globs are determined
+ if restricted_shadowing && module.def().is_some() {
+ return Err(Determined);
+ }
for directive in module.globs.borrow().iter() {
if self.is_accessible(directive.vis.get()) {
if let Some(module) = directive.imported_module.get() {
crate-type = ["dylib"]
[dependencies]
-log = { path = "../liblog" }
+log = "0.3"
rustc = { path = "../librustc" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v))));
strs.fold(String::new(), |mut s, ss| {
- s.push_str(&ss[..]);
+ s.push_str(&ss);
s
})
}
use data::{self, VariableKind};
use dump::Dump;
-pub struct JsonDumper<'b, W: Write + 'b> {
- output: &'b mut W,
+pub struct JsonDumper<O: DumpOutput> {
result: Analysis,
+ output: O,
}
-impl<'b, W: Write> JsonDumper<'b, W> {
- pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> {
- JsonDumper { output: writer, result: Analysis::new() }
- }
+pub trait DumpOutput {
+ fn dump(&mut self, result: &Analysis);
}
-impl<'b, W: Write> Drop for JsonDumper<'b, W> {
- fn drop(&mut self) {
- if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
+pub struct WriteOutput<'b, W: Write + 'b> {
+ output: &'b mut W,
+}
+
+impl<'b, W: Write> DumpOutput for WriteOutput<'b, W> {
+ fn dump(&mut self, result: &Analysis) {
+ if let Err(_) = write!(self.output, "{}", as_json(&result)) {
error!("Error writing output");
}
}
}
+pub struct CallbackOutput<'b> {
+ callback: &'b mut FnMut(&Analysis),
+}
+
+impl<'b> DumpOutput for CallbackOutput<'b> {
+ fn dump(&mut self, result: &Analysis) {
+ (self.callback)(result)
+ }
+}
+
+impl<'b, W: Write> JsonDumper<WriteOutput<'b, W>> {
+ pub fn new(writer: &'b mut W) -> JsonDumper<WriteOutput<'b, W>> {
+ JsonDumper { output: WriteOutput { output: writer }, result: Analysis::new() }
+ }
+}
+
+impl<'b> JsonDumper<CallbackOutput<'b>> {
+ pub fn with_callback(callback: &'b mut FnMut(&Analysis)) -> JsonDumper<CallbackOutput<'b>> {
+ JsonDumper { output: CallbackOutput { callback: callback }, result: Analysis::new() }
+ }
+}
+
+impl<O: DumpOutput> Drop for JsonDumper<O> {
+ fn drop(&mut self) {
+ self.output.dump(&self.result);
+ }
+}
+
macro_rules! impl_fn {
($fn_name: ident, $data_type: ident, $bucket: ident) => {
fn $fn_name(&mut self, data: $data_type) {
}
}
-impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> {
+impl<'b, O: DumpOutput + 'b> Dump for JsonDumper<O> {
fn crate_prelude(&mut self, data: CratePreludeData) {
self.result.prelude = Some(data)
}
use rustc::hir::map::Node;
use rustc::hir::def_id::DefId;
use rustc::session::config::CrateType::CrateTypeExecutable;
+use rustc::session::Session;
use rustc::ty::{self, TyCtxt};
use std::env;
}
}
-pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
- krate: &ast::Crate,
- analysis: &'l ty::CrateAnalysis,
- cratename: &str,
- odir: Option<&Path>,
- format: Format) {
- let _ignore = tcx.dep_graph.in_ignore();
+/// Defines what to do with the results of saving the analysis.
+pub trait SaveHandler {
+ fn save<'l, 'tcx>(&mut self,
+ save_ctxt: SaveContext<'l, 'tcx>,
+ krate: &ast::Crate,
+ cratename: &str);
+}
- assert!(analysis.glob_map.is_some());
+/// Dump the save-analysis results to a file.
+pub struct DumpHandler<'a> {
+ format: Format,
+ odir: Option<&'a Path>,
+ cratename: String
+}
- info!("Dumping crate {}", cratename);
+impl<'a> DumpHandler<'a> {
+ pub fn new(format: Format, odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
+ DumpHandler {
+ format: format,
+ odir: odir,
+ cratename: cratename.to_owned()
+ }
+ }
- // find a path to dump our data to
- let mut root_path = match env::var_os("RUST_SAVE_ANALYSIS_FOLDER") {
- Some(val) => PathBuf::from(val),
- None => match odir {
- Some(val) => val.join("save-analysis"),
- None => PathBuf::from("save-analysis-temp"),
- },
- };
+ fn output_file(&self, sess: &Session) -> File {
+ let mut root_path = match env::var_os("RUST_SAVE_ANALYSIS_FOLDER") {
+ Some(val) => PathBuf::from(val),
+ None => match self.odir {
+ Some(val) => val.join("save-analysis"),
+ None => PathBuf::from("save-analysis-temp"),
+ },
+ };
- if let Err(e) = std::fs::create_dir_all(&root_path) {
- tcx.sess.err(&format!("Could not create directory {}: {}",
- root_path.display(),
- e));
+ if let Err(e) = std::fs::create_dir_all(&root_path) {
+ error!("Could not create directory {}: {}", root_path.display(), e);
+ }
+
+ {
+ let disp = root_path.display();
+ info!("Writing output to {}", disp);
+ }
+
+ let executable = sess.crate_types.borrow().iter().any(|ct| *ct == CrateTypeExecutable);
+ let mut out_name = if executable {
+ "".to_owned()
+ } else {
+ "lib".to_owned()
+ };
+ out_name.push_str(&self.cratename);
+ out_name.push_str(&sess.opts.cg.extra_filename);
+ out_name.push_str(self.format.extension());
+ root_path.push(&out_name);
+ let output_file = File::create(&root_path).unwrap_or_else(|e| {
+ let disp = root_path.display();
+ sess.fatal(&format!("Could not open {}: {}", disp, e));
+ });
+ root_path.pop();
+ output_file
}
+}
+
+impl<'a> SaveHandler for DumpHandler<'a> {
+ fn save<'l, 'tcx>(&mut self,
+ save_ctxt: SaveContext<'l, 'tcx>,
+ krate: &ast::Crate,
+ cratename: &str) {
+ macro_rules! dump {
+ ($new_dumper: expr) => {{
+ let mut dumper = $new_dumper;
+ let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
+
+ visitor.dump_crate_info(cratename, krate);
+ visit::walk_crate(&mut visitor, krate);
+ }}
+ }
+
+ let output = &mut self.output_file(&save_ctxt.tcx.sess);
- {
- let disp = root_path.display();
- info!("Writing output to {}", disp);
+ match self.format {
+ Format::Csv => dump!(CsvDumper::new(output)),
+ Format::Json => dump!(JsonDumper::new(output)),
+ Format::JsonApi => dump!(JsonApiDumper::new(output)),
+ }
}
+}
- // Create output file.
- let executable = tcx.sess.crate_types.borrow().iter().any(|ct| *ct == CrateTypeExecutable);
- let mut out_name = if executable {
- "".to_owned()
- } else {
- "lib".to_owned()
- };
- out_name.push_str(&cratename);
- out_name.push_str(&tcx.sess.opts.cg.extra_filename);
- out_name.push_str(format.extension());
- root_path.push(&out_name);
- let mut output_file = File::create(&root_path).unwrap_or_else(|e| {
- let disp = root_path.display();
- tcx.sess.fatal(&format!("Could not open {}: {}", disp, e));
- });
- root_path.pop();
- let output = &mut output_file;
+/// Call a callback with the results of save-analysis.
+pub struct CallbackHandler<'b> {
+ pub callback: &'b mut FnMut(&rls_data::Analysis),
+}
+
+impl<'b> SaveHandler for CallbackHandler<'b> {
+ fn save<'l, 'tcx>(&mut self,
+ save_ctxt: SaveContext<'l, 'tcx>,
+ krate: &ast::Crate,
+ cratename: &str) {
+ macro_rules! dump {
+ ($new_dumper: expr) => {{
+ let mut dumper = $new_dumper;
+ let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
+
+ visitor.dump_crate_info(cratename, krate);
+ visit::walk_crate(&mut visitor, krate);
+ }}
+ }
+
+ // We're using the JsonDumper here because it has the format of the
+ // save-analysis results that we will pass to the callback. IOW, we are
+ // using the JsonDumper to collect the save-analysis results, but not
+ // actually to dump them to a file. This is all a bit convoluted and
+ // there is certainly a simpler design here trying to get out (FIXME).
+ dump!(JsonDumper::with_callback(self.callback))
+ }
+}
+
+pub fn process_crate<'l, 'tcx, H: SaveHandler>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
+ krate: &ast::Crate,
+ analysis: &'l ty::CrateAnalysis,
+ cratename: &str,
+ mut handler: H) {
+ let _ignore = tcx.dep_graph.in_ignore();
+
+ assert!(analysis.glob_map.is_some());
+
+ info!("Dumping crate {}", cratename);
let save_ctxt = SaveContext {
tcx: tcx,
span_utils: SpanUtils::new(&tcx.sess),
};
- macro_rules! dump {
- ($new_dumper: expr) => {{
- let mut dumper = $new_dumper;
- let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
-
- visitor.dump_crate_info(cratename, krate);
- visit::walk_crate(&mut visitor, krate);
- }}
- }
-
- match format {
- Format::Csv => dump!(CsvDumper::new(output)),
- Format::Json => dump!(JsonDumper::new(output)),
- Format::JsonApi => dump!(JsonApiDumper::new(output)),
- }
+ handler.save(save_ctxt, krate, cratename)
}
// Utility functions for the module.
[dependencies]
flate = { path = "../libflate" }
-log = { path = "../liblog" }
+log = "0.3"
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_bitflags = { path = "../librustc_bitflags" }
match sig.inputs().last().unwrap().sty {
ty::TyTuple(ref tupled_arguments, _) => {
inputs = &sig.inputs()[0..sig.inputs().len() - 1];
- &tupled_arguments[..]
+ &tupled_arguments
}
_ => {
bug!("argument to function with \"rust-call\" ABI \
variant_fill].iter().cloned().collect();
match name {
None => {
- Type::struct_(cx, &fields[..], false)
+ Type::struct_(cx, &fields, false)
}
Some(name) => {
let mut llty = Type::named_struct(cx, name);
- llty.set_struct_body(&fields[..], false);
+ llty.set_struct_body(&fields, false);
llty
}
}
alignment: Alignment,
) -> ValueRef {
let llptrptr = bcx.gepi(scrutinee,
- &discrfield.iter().map(|f| *f as usize).collect::<Vec<_>>()[..]);
+ &discrfield.iter().map(|f| *f as usize).collect::<Vec<_>>());
let llptr = bcx.load(llptrptr, alignment.to_align());
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
bcx.icmp(cmp, llptr, C_null(val_ty(llptr)))
base::call_memset(bcx, llptr, fill_byte, size, align, false);
} else {
let path = discrfield.iter().map(|&i| i as usize).collect::<Vec<_>>();
- let llptrptr = bcx.gepi(val, &path[..]);
+ let llptrptr = bcx.gepi(val, &path);
let llptrty = val_ty(llptrptr).element_type();
bcx.store(C_null(llptrty), llptrptr, None);
}
.chain(arch_clobbers.iter().map(|s| s.to_string()))
.collect::<Vec<String>>().join(",");
- debug!("Asm Constraints: {}", &all_constraints[..]);
+ debug!("Asm Constraints: {}", &all_constraints);
// Depending on how many outputs we have, the return type is different
let num_outputs = output_types.len();
let output_type = match num_outputs {
0 => Type::void(bcx.ccx),
1 => output_types[0],
- _ => Type::struct_(bcx.ccx, &output_types[..], false)
+ _ => Type::struct_(bcx.ccx, &output_types, false)
};
let dialect = match ia.dialect {
for path in search_paths {
debug!("looking for {} inside {:?}", name, path);
- let test = path.join(&oslibname[..]);
+ let test = path.join(&oslibname);
if test.exists() { return test }
if oslibname != unixlibname {
- let test = path.join(&unixlibname[..]);
+ let test = path.join(&unixlibname);
if test.exists() { return test }
}
}
attrs: &[ast::Attribute],
input: &Input) -> String {
let validate = |s: String, span: Option<Span>| {
- cstore::validate_crate_name(sess, &s[..], span);
+ cstore::validate_crate_name(sess, &s, span);
s
};
let msg = format!("--crate-name and #[crate_name] are \
required to match, but `{}` != `{}`",
s, name);
- sess.span_err(attr.span, &msg[..]);
+ sess.span_err(attr.span, &msg);
}
}
return validate(s.clone(), None);
outputs: &OutputFilenames)
-> Vec<PathBuf> {
trans.modules.iter().map(|module| {
- outputs.temp_path(OutputType::Object, Some(&module.name[..]))
+ outputs.temp_path(OutputType::Object, Some(&module.name))
}).collect()
}
e))
}
- let bc_data_deflated = flate::deflate_bytes(&bc_data[..]);
+ let bc_data_deflated = flate::deflate_bytes(&bc_data);
let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) {
Ok(file) => file,
pname,
prog.status))
.note(&format!("{:?}", &cmd))
- .note(&escape_string(&output[..]))
+ .note(&escape_string(&output))
.emit();
sess.abort_if_errors();
}
- info!("linker stderr:\n{}", escape_string(&prog.stderr[..]));
- info!("linker stdout:\n{}", escape_string(&prog.stdout[..]));
+ info!("linker stderr:\n{}", escape_string(&prog.stderr));
+ info!("linker stdout:\n{}", escape_string(&prog.stdout));
},
Err(e) => {
sess.struct_err(&format!("could not exec the linker `{}`: {}", pname, e))
}
let export_threshold =
- symbol_export::crates_export_threshold(&sess.crate_types.borrow()[..]);
+ symbol_export::crates_export_threshold(&sess.crate_types.borrow());
let symbol_filter = &|&(ref name, level): &(String, _)| {
if symbol_export::is_below_threshold(level, export_threshold) {
bc_decoded.len() as libc::size_t) {
write::llvm_err(sess.diagnostic(),
format!("failed to load bc of `{}`",
- &name[..]));
+ name));
}
});
}
let libs = config.used_crates.clone();
let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::<Vec<_>>();
- let rpaths = get_rpaths(config, &libs[..]);
- flags.extend_from_slice(&rpaths_to_flags(&rpaths[..]));
+ let rpaths = get_rpaths(config, &libs);
+ flags.extend_from_slice(&rpaths_to_flags(&rpaths));
// Use DT_RUNPATH instead of DT_RPATH if available
if config.linker_is_gnu {
}
}
- log_rpaths("relative", &rel_rpaths[..]);
- log_rpaths("fallback", &fallback_rpaths[..]);
+ log_rpaths("relative", &rel_rpaths);
+ log_rpaths("fallback", &fallback_rpaths);
let mut rpaths = rel_rpaths;
- rpaths.extend_from_slice(&fallback_rpaths[..]);
+ rpaths.extend_from_slice(&fallback_rpaths);
// Remove duplicates
- let rpaths = minimize_rpaths(&rpaths[..]);
+ let rpaths = minimize_rpaths(&rpaths);
return rpaths;
}
let mut set = HashSet::new();
let mut minimized = Vec::new();
for rpath in rpaths {
- if set.insert(&rpath[..]) {
+ if set.insert(rpath) {
minimized.push(rpath.clone());
}
}
cnum: CrateNum)
-> &[(String, SymbolExportLevel)] {
match self.exports.get(&cnum) {
- Some(exports) => &exports[..],
+ Some(exports) => exports,
None => &[]
}
}
{
for &(ref name, export_level) in self.exported_symbols(cnum) {
if is_below_threshold(export_level, export_threshold) {
- f(&name[..], export_level)
+ f(&name, export_level)
}
}
}
if !result.is_empty() &&
result.as_bytes()[0] != '_' as u8 &&
! (result.as_bytes()[0] as char).is_xid_start() {
- return format!("_{}", &result[..]);
+ return format!("_{}", result);
}
return result;
Some(ref code) => {
handler.emit_with_code(&MultiSpan::new(),
&diag.msg,
- &code[..],
+ &code,
diag.lvl);
},
None => {
let fdata_sections = ffunction_sections;
let code_model_arg = match sess.opts.cg.code_model {
- Some(ref s) => &s[..],
- None => &sess.target.target.options.code_model[..],
+ Some(ref s) => &s,
+ None => &sess.target.target.options.code_model,
};
let code_model = match CODE_GEN_MODEL_ARGS.iter().find(
let msg = llvm::build_string(|s| llvm::LLVMRustWriteSMDiagnosticToString(diag, s))
.expect("non-UTF8 SMDiagnostic");
- report_inline_asm(cgcx, &msg[..], cookie);
+ report_inline_asm(cgcx, &msg, cookie);
}
unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
if trans.modules.len() == 1 {
// 1) Only one codegen unit. In this case it's no difficulty
// to copy `foo.0.x` to `foo.x`.
- let module_name = Some(&(trans.modules[0].name)[..]);
+ let module_name = Some(&trans.modules[0].name[..]);
let path = crate_output.temp_path(output_type, module_name);
copy_gracefully(&path,
&crate_output.path(output_type));
if metadata_config.emit_bc && !user_wants_bitcode {
let path = crate_output.temp_path(OutputType::Bitcode,
- Some(&trans.metadata_module.name[..]));
+ Some(&trans.metadata_module.name));
remove(sess, &path);
}
}
n_bytes: ValueRef,
align: u32) {
let ccx = b.ccx;
- let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
+ let ptr_width = &ccx.sess().target.target.target_pointer_width;
let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
let memcpy = ccx.get_intrinsic(&key);
let src_ptr = b.pointercast(src, Type::i8p(ccx));
size: ValueRef,
align: ValueRef,
volatile: bool) -> ValueRef {
- let ptr_width = &b.ccx.sess().target.target.target_pointer_width[..];
+ let ptr_width = &b.ccx.sess().target.target.target_pointer_width;
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
let llintrinsicfn = b.ccx.get_intrinsic(&intrinsic_key);
let volatile = C_bool(b.ccx, volatile);
let cstore = &cx.tcx().sess.cstore;
let metadata = cstore.encode_metadata(cx.tcx(),
- cx.export_map(),
cx.link_meta(),
exported_symbols);
if kind == MetadataKind::Uncompressed {
let mut compressed = cstore.metadata_encoding_version().to_vec();
compressed.extend_from_slice(&flate::deflate_bytes(&metadata));
- let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]);
+ let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed);
let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
let name = cx.metadata_symbol_name();
let buf = CString::new(name).unwrap();
symbol_map: &SymbolMap<'tcx>,
exported_symbols: &ExportedSymbols) {
let export_threshold =
- symbol_export::crates_export_threshold(&sess.crate_types.borrow()[..]);
+ symbol_export::crates_export_threshold(&sess.crate_types.borrow());
let exported_symbols = exported_symbols
.exported_symbols(LOCAL_CRATE)
(generics.parent_types == 0 && generics.types.is_empty()) &&
// Functions marked with #[inline] are only ever translated
// with "internal" linkage and are never exported.
- !attr::requests_inline(&attributes[..])
+ !attr::requests_inline(&attributes)
}
_ => false
// particular items that will be processed.
let krate = tcx.hir.krate();
- let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
+ let ty::CrateAnalysis { reachable, name, .. } = analysis;
let exported_symbols = find_exported_symbols(tcx, reachable);
let check_overflow = tcx.sess.overflow_checks();
let link_meta = link::build_link_meta(incremental_hashes_map, &name);
let shared_ccx = SharedCrateContext::new(tcx,
- export_map,
link_meta.clone(),
exported_symbols,
check_overflow);
cgus.dedup();
for &(ref cgu_name, linkage) in cgus.iter() {
output.push_str(" ");
- output.push_str(&cgu_name[..]);
+ output.push_str(&cgu_name);
let linkage_abbrev = match linkage {
llvm::Linkage::ExternalLinkage => "External",
} else {
let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::<Vec<ValueRef>>();
self.count_insn("gepi");
- self.inbounds_gep(base, &v[..])
+ self.inbounds_gep(base, &v)
}
}
let s = format!("{} ({})",
text,
self.ccx.sess().codemap().span_to_string(sp));
- debug!("{}", &s[..]);
- self.add_comment(&s[..]);
+ debug!("{}", s);
+ self.add_comment(&s);
}
}
DepTrackingMapConfig, WorkProduct};
use middle::cstore::LinkMeta;
use rustc::hir;
-use rustc::hir::def::ExportMap;
use rustc::hir::def_id::DefId;
use rustc::traits;
use debuginfo;
metadata_llmod: ModuleRef,
metadata_llcx: ContextRef,
- export_map: ExportMap,
exported_symbols: NodeSet,
link_meta: LinkMeta,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
- export_map: ExportMap,
link_meta: LinkMeta,
exported_symbols: NodeSet,
check_overflow: bool)
SharedCrateContext {
metadata_llmod: metadata_llmod,
metadata_llcx: metadata_llcx,
- export_map: export_map,
exported_symbols: exported_symbols,
link_meta: link_meta,
empty_param_env: tcx.empty_parameter_environment(),
self.metadata_llcx
}
- pub fn export_map<'a>(&'a self) -> &'a ExportMap {
- &self.export_map
- }
-
pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
&self.exported_symbols
}
unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) }
}
- pub fn export_map<'a>(&'a self) -> &'a ExportMap {
- &self.shared.export_map
- }
-
pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
&self.shared.exported_symbols
}
match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
- scx.tcx().custom_coerce_unsized_kind(impl_def_id)
+ scx.tcx().coerce_unsized_info(impl_def_id).custom_kind.unwrap()
}
vtable => {
bug!("invalid CoerceUnsized vtable: {:?}", vtable);
test = false
[dependencies]
-log = { path = "../liblog" }
+log = "0.3"
syntax = { path = "../libsyntax" }
arena = { path = "../libarena" }
fmt_macros = { path = "../libfmt_macros" }
}
fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
- // Read the inherent implementation candidates for this type from the
- // metadata if necessary.
- self.tcx.populate_inherent_implementations_for_type_if_necessary(self.span, def_id);
-
- if let Some(impl_infos) = self.tcx.maps.inherent_impls.borrow().get(&def_id) {
- for &impl_def_id in impl_infos.iter() {
- self.assemble_inherent_impl_probe(impl_def_id);
- }
+ let impl_def_ids = ty::queries::inherent_impls::get(self.tcx, self.span, def_id);
+ for &impl_def_id in impl_def_ids.iter() {
+ self.assemble_inherent_impl_probe(impl_def_id);
}
}
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;
}
fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- coerce_unsized_trait: DefId,
+ _: DefId,
impl_did: DefId) {
debug!("visit_implementation_of_coerce_unsized: impl_did={:?}",
impl_did);
+ // Just compute this for the side-effects, in particular reporting
+ // errors; other parts of the code may demand it for the info of
+ // course.
+ if impl_did.is_local() {
+ let span = tcx.def_span(impl_did);
+ ty::queries::coerce_unsized_info::get(tcx, span, impl_did);
+ }
+}
+
+pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ impl_did: DefId)
+ -> CoerceUnsizedInfo {
+ debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
+ let coerce_unsized_trait = tcx.lang_items.coerce_unsized_trait().unwrap();
+
let unsize_trait = match tcx.lang_items.require(UnsizeTraitLangItem) {
Ok(id) => id,
Err(err) => {
}
};
- let impl_node_id = if let Some(n) = tcx.hir.as_local_node_id(impl_did) {
- n
- } else {
- debug!("visit_implementation_of_coerce_unsized(): impl not \
- in this crate");
- return;
- };
+ // this provider should only get invoked for local def-ids
+ let impl_node_id = tcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| {
+ bug!("coerce_unsized_info: invoked for non-local def-id {:?}", impl_did)
+ });
let source = tcx.item_type(impl_did);
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
+ assert_eq!(trait_ref.def_id, coerce_unsized_trait);
let target = trait_ref.substs.type_at(1);
debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)",
source,
let target = target.subst(tcx, ¶m_env.free_substs);
assert!(!source.has_escaping_regions());
+ let err_info = CoerceUnsizedInfo { custom_kind: None };
+
debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)",
source,
target);
definition; expected {}, found {}",
source_path,
target_path);
- return;
+ return err_info;
}
let fields = &def_a.struct_variant().fields;
"the trait `CoerceUnsized` may only be implemented \
for a coercion between structures with one field \
being coerced, none found");
- return;
+ return err_info;
} else if diff_fields.len() > 1 {
let item = tcx.hir.expect_item(impl_node_id);
let span = if let ItemImpl(.., Some(ref t), _, _) = item.node {
.join(", ")));
err.span_label(span, &format!("requires multiple coercions"));
err.emit();
- return;
+ return err_info;
}
let (i, a, b) = diff_fields[0];
E0376,
"the trait `CoerceUnsized` may only be implemented \
for a coercion between structures");
- return;
+ return err_info;
}
};
.caller_bounds);
infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id);
- if let Some(kind) = kind {
- tcx.maps.custom_coerce_unsized_kind.borrow_mut().insert(impl_did, kind);
+ CoerceUnsizedInfo {
+ custom_kind: kind
}
- });
+ })
}
+++ /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::dep_graph::DepNode;
-use rustc::hir::def_id::DefId;
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::lint;
-use rustc::traits::{self, Reveal};
-use rustc::ty::{self, TyCtxt};
-
-use syntax::ast;
-use syntax_pos::Span;
-
-struct InherentCollect<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>
-}
-
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
- fn visit_item(&mut self, item: &hir::Item) {
- let (unsafety, ty) = match item.node {
- hir::ItemImpl(unsafety, .., None, ref ty, _) => (unsafety, ty),
- _ => return
- };
-
- match unsafety {
- hir::Unsafety::Normal => {
- // OK
- }
- hir::Unsafety::Unsafe => {
- span_err!(self.tcx.sess,
- item.span,
- E0197,
- "inherent impls cannot be declared as unsafe");
- }
- }
-
- let def_id = self.tcx.hir.local_def_id(item.id);
- let self_ty = self.tcx.item_type(def_id);
- match self_ty.sty {
- ty::TyAdt(def, _) => {
- self.check_def_id(item, def.did);
- }
- ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
- self.check_def_id(item, data.principal().unwrap().def_id());
- }
- ty::TyChar => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.char_impl(),
- "char",
- "char",
- item.span);
- }
- ty::TyStr => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.str_impl(),
- "str",
- "str",
- item.span);
- }
- ty::TySlice(_) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.slice_impl(),
- "slice",
- "[T]",
- item.span);
- }
- ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.const_ptr_impl(),
- "const_ptr",
- "*const T",
- item.span);
- }
- ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.mut_ptr_impl(),
- "mut_ptr",
- "*mut T",
- item.span);
- }
- ty::TyInt(ast::IntTy::I8) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.i8_impl(),
- "i8",
- "i8",
- item.span);
- }
- ty::TyInt(ast::IntTy::I16) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.i16_impl(),
- "i16",
- "i16",
- item.span);
- }
- ty::TyInt(ast::IntTy::I32) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.i32_impl(),
- "i32",
- "i32",
- item.span);
- }
- ty::TyInt(ast::IntTy::I64) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.i64_impl(),
- "i64",
- "i64",
- item.span);
- }
- ty::TyInt(ast::IntTy::I128) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.i128_impl(),
- "i128",
- "i128",
- item.span);
- }
- ty::TyInt(ast::IntTy::Is) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.isize_impl(),
- "isize",
- "isize",
- item.span);
- }
- ty::TyUint(ast::UintTy::U8) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.u8_impl(),
- "u8",
- "u8",
- item.span);
- }
- ty::TyUint(ast::UintTy::U16) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.u16_impl(),
- "u16",
- "u16",
- item.span);
- }
- ty::TyUint(ast::UintTy::U32) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.u32_impl(),
- "u32",
- "u32",
- item.span);
- }
- ty::TyUint(ast::UintTy::U64) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.u64_impl(),
- "u64",
- "u64",
- item.span);
- }
- ty::TyUint(ast::UintTy::U128) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.u128_impl(),
- "u128",
- "u128",
- item.span);
- }
- ty::TyUint(ast::UintTy::Us) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.usize_impl(),
- "usize",
- "usize",
- item.span);
- }
- ty::TyFloat(ast::FloatTy::F32) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.f32_impl(),
- "f32",
- "f32",
- item.span);
- }
- ty::TyFloat(ast::FloatTy::F64) => {
- self.check_primitive_impl(def_id,
- self.tcx.lang_items.f64_impl(),
- "f64",
- "f64",
- item.span);
- }
- ty::TyError => {
- return;
- }
- _ => {
- struct_span_err!(self.tcx.sess,
- ty.span,
- E0118,
- "no base type found for inherent implementation")
- .span_label(ty.span, &format!("impl requires a base type"))
- .note(&format!("either implement a trait on it or create a newtype \
- to wrap it instead"))
- .emit();
- return;
- }
- }
- }
-
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
- }
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
- }
-}
-
-impl<'a, 'tcx> InherentCollect<'a, 'tcx> {
- fn check_def_id(&self, item: &hir::Item, def_id: DefId) {
- if def_id.is_local() {
- // Add the implementation to the mapping from implementation to base
- // type def ID, if there is a base type for this implementation and
- // the implementation does not have any associated traits.
- let impl_def_id = self.tcx.hir.local_def_id(item.id);
-
- // Subtle: it'd be better to collect these into a local map
- // and then write the vector only once all items are known,
- // but that leads to degenerate dep-graphs. The problem is
- // that the write of that big vector winds up having reads
- // from *all* impls in the krate, since we've lost the
- // precision basically. This would be ok in the firewall
- // model so once we've made progess towards that we can modify
- // the strategy here. In the meantime, using `push` is ok
- // because we are doing this as a pre-pass before anyone
- // actually reads from `inherent_impls` -- and we know this is
- // true beacuse we hold the refcell lock.
- self.tcx.maps.inherent_impls.borrow_mut().push(def_id, impl_def_id);
- } else {
- struct_span_err!(self.tcx.sess,
- item.span,
- E0116,
- "cannot define inherent `impl` for a type outside of the crate \
- where the type is defined")
- .span_label(item.span,
- &format!("impl for type defined outside of crate."))
- .note("define and implement a trait or new type instead")
- .emit();
- }
- }
-
- fn check_primitive_impl(&self,
- impl_def_id: DefId,
- lang_def_id: Option<DefId>,
- lang: &str,
- ty: &str,
- span: Span) {
- match lang_def_id {
- Some(lang_def_id) if lang_def_id == impl_def_id => {
- // OK
- }
- _ => {
- struct_span_err!(self.tcx.sess,
- span,
- E0390,
- "only a single inherent implementation marked with `#[lang = \
- \"{}\"]` is allowed for the `{}` primitive",
- lang,
- ty)
- .span_help(span, "consider using a trait to implement these methods")
- .emit();
- }
- }
- }
-}
-
-struct InherentOverlapChecker<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>
-}
-
-impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
- fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) {
- #[derive(Copy, Clone, PartialEq)]
- enum Namespace {
- Type,
- Value,
- }
-
- let name_and_namespace = |def_id| {
- let item = self.tcx.associated_item(def_id);
- (item.name, match item.kind {
- ty::AssociatedKind::Type => Namespace::Type,
- ty::AssociatedKind::Const |
- ty::AssociatedKind::Method => Namespace::Value,
- })
- };
-
- let impl_items1 = self.tcx.associated_item_def_ids(impl1);
- let impl_items2 = self.tcx.associated_item_def_ids(impl2);
-
- for &item1 in &impl_items1[..] {
- let (name, namespace) = name_and_namespace(item1);
-
- for &item2 in &impl_items2[..] {
- if (name, namespace) == name_and_namespace(item2) {
- let msg = format!("duplicate definitions with name `{}`", name);
- let node_id = self.tcx.hir.as_local_node_id(item1).unwrap();
- self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
- node_id,
- self.tcx.span_of_impl(item1).unwrap(),
- msg);
- }
- }
- }
- }
-
- fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
- let _task = self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapInherentCheck(ty_def_id));
-
- let inherent_impls = self.tcx.maps.inherent_impls.borrow();
- let impls = match inherent_impls.get(&ty_def_id) {
- Some(impls) => impls,
- None => return,
- };
-
- for (i, &impl1_def_id) in impls.iter().enumerate() {
- for &impl2_def_id in &impls[(i + 1)..] {
- self.tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
- if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
- self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
- }
- });
- }
- }
- }
-}
-
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> {
- fn visit_item(&mut self, item: &'v hir::Item) {
- match item.node {
- hir::ItemEnum(..) |
- hir::ItemStruct(..) |
- hir::ItemTrait(..) |
- hir::ItemUnion(..) => {
- let type_def_id = self.tcx.hir.local_def_id(item.id);
- self.check_for_overlapping_inherent_impls(type_def_id);
- }
- _ => {}
- }
- }
-
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
- }
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
- }
-}
-
-pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl,
- &mut InherentCollect { tcx });
- tcx.visit_all_item_likes_in_krate(DepNode::CoherenceOverlapCheckSpecial,
- &mut InherentOverlapChecker { tcx });
-}
--- /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.
+
+//! The code in this module gathers up all of the inherent impls in
+//! the current crate and organizes them in a map. It winds up
+//! touching the whole crate and thus must be recomputed completely
+//! for any change, but it is very cheap to compute. In practice, most
+//! code in the compiler never *directly* requests this map. Instead,
+//! it requests the inherent impls specific to some type (via
+//! `ty::queries::inherent_impls::get(def_id)`). That value, however,
+//! is computed by selecting an idea from this table.
+
+use rustc::dep_graph::DepNode;
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::hir;
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::ty::{self, CrateInherentImpls, TyCtxt};
+use rustc::util::nodemap::DefIdMap;
+
+use std::rc::Rc;
+use syntax::ast;
+use syntax_pos::{DUMMY_SP, Span};
+
+/// On-demand query: yields a map containing all types mapped to their inherent impls.
+pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ crate_num: CrateNum)
+ -> CrateInherentImpls {
+ assert_eq!(crate_num, LOCAL_CRATE);
+
+ let krate = tcx.hir.krate();
+ let mut collect = InherentCollect {
+ tcx,
+ impls_map: CrateInherentImpls {
+ inherent_impls: DefIdMap()
+ }
+ };
+ krate.visit_all_item_likes(&mut collect);
+ collect.impls_map
+}
+
+/// On-demand query: yields a vector of the inherent impls for a specific type.
+pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ ty_def_id: DefId)
+ -> Rc<Vec<DefId>> {
+ assert!(ty_def_id.is_local());
+
+ // NB. Until we adopt the red-green dep-tracking algorithm (see
+ // [the plan] for details on that), we do some hackery here to get
+ // the dependencies correct. Basically, we use a `with_ignore` to
+ // read the result we want. If we didn't have the `with_ignore`,
+ // we would wind up with a dependency on the entire crate, which
+ // we don't want. Then we go and add dependencies on all the impls
+ // in the result (which is what we wanted).
+ //
+ // The result is a graph with an edge from `Hir(I)` for every impl
+ // `I` defined on some type `T` to `CoherentInherentImpls(T)`,
+ // thus ensuring that if any of those impls change, the set of
+ // inherent impls is considered dirty.
+ //
+ // [the plan]: https://github.com/rust-lang/rust-roadmap/issues/4
+
+ let result = tcx.dep_graph.with_ignore(|| {
+ let crate_map = ty::queries::crate_inherent_impls::get(tcx, DUMMY_SP, ty_def_id.krate);
+ match crate_map.inherent_impls.get(&ty_def_id) {
+ Some(v) => v.clone(),
+ None => Rc::new(vec![]),
+ }
+ });
+
+ for &impl_def_id in &result[..] {
+ tcx.dep_graph.read(DepNode::Hir(impl_def_id));
+ }
+
+ result
+}
+
+struct InherentCollect<'a, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ impls_map: CrateInherentImpls,
+}
+
+impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
+ fn visit_item(&mut self, item: &hir::Item) {
+ let (unsafety, ty) = match item.node {
+ hir::ItemImpl(unsafety, .., None, ref ty, _) => (unsafety, ty),
+ _ => return
+ };
+
+ match unsafety {
+ hir::Unsafety::Normal => {
+ // OK
+ }
+ hir::Unsafety::Unsafe => {
+ span_err!(self.tcx.sess,
+ item.span,
+ E0197,
+ "inherent impls cannot be declared as unsafe");
+ }
+ }
+
+ let def_id = self.tcx.hir.local_def_id(item.id);
+ let self_ty = self.tcx.item_type(def_id);
+ match self_ty.sty {
+ ty::TyAdt(def, _) => {
+ self.check_def_id(item, def.did);
+ }
+ ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
+ self.check_def_id(item, data.principal().unwrap().def_id());
+ }
+ ty::TyChar => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.char_impl(),
+ "char",
+ "char",
+ item.span);
+ }
+ ty::TyStr => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.str_impl(),
+ "str",
+ "str",
+ item.span);
+ }
+ ty::TySlice(_) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.slice_impl(),
+ "slice",
+ "[T]",
+ item.span);
+ }
+ ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.const_ptr_impl(),
+ "const_ptr",
+ "*const T",
+ item.span);
+ }
+ ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.mut_ptr_impl(),
+ "mut_ptr",
+ "*mut T",
+ item.span);
+ }
+ ty::TyInt(ast::IntTy::I8) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.i8_impl(),
+ "i8",
+ "i8",
+ item.span);
+ }
+ ty::TyInt(ast::IntTy::I16) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.i16_impl(),
+ "i16",
+ "i16",
+ item.span);
+ }
+ ty::TyInt(ast::IntTy::I32) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.i32_impl(),
+ "i32",
+ "i32",
+ item.span);
+ }
+ ty::TyInt(ast::IntTy::I64) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.i64_impl(),
+ "i64",
+ "i64",
+ item.span);
+ }
+ ty::TyInt(ast::IntTy::I128) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.i128_impl(),
+ "i128",
+ "i128",
+ item.span);
+ }
+ ty::TyInt(ast::IntTy::Is) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.isize_impl(),
+ "isize",
+ "isize",
+ item.span);
+ }
+ ty::TyUint(ast::UintTy::U8) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.u8_impl(),
+ "u8",
+ "u8",
+ item.span);
+ }
+ ty::TyUint(ast::UintTy::U16) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.u16_impl(),
+ "u16",
+ "u16",
+ item.span);
+ }
+ ty::TyUint(ast::UintTy::U32) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.u32_impl(),
+ "u32",
+ "u32",
+ item.span);
+ }
+ ty::TyUint(ast::UintTy::U64) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.u64_impl(),
+ "u64",
+ "u64",
+ item.span);
+ }
+ ty::TyUint(ast::UintTy::U128) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.u128_impl(),
+ "u128",
+ "u128",
+ item.span);
+ }
+ ty::TyUint(ast::UintTy::Us) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.usize_impl(),
+ "usize",
+ "usize",
+ item.span);
+ }
+ ty::TyFloat(ast::FloatTy::F32) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.f32_impl(),
+ "f32",
+ "f32",
+ item.span);
+ }
+ ty::TyFloat(ast::FloatTy::F64) => {
+ self.check_primitive_impl(def_id,
+ self.tcx.lang_items.f64_impl(),
+ "f64",
+ "f64",
+ item.span);
+ }
+ ty::TyError => {
+ return;
+ }
+ _ => {
+ struct_span_err!(self.tcx.sess,
+ ty.span,
+ E0118,
+ "no base type found for inherent implementation")
+ .span_label(ty.span, &format!("impl requires a base type"))
+ .note(&format!("either implement a trait on it or create a newtype \
+ to wrap it instead"))
+ .emit();
+ return;
+ }
+ }
+ }
+
+ fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+ }
+
+ fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+ }
+}
+
+impl<'a, 'tcx> InherentCollect<'a, 'tcx> {
+ fn check_def_id(&mut self, item: &hir::Item, def_id: DefId) {
+ if def_id.is_local() {
+ // Add the implementation to the mapping from implementation to base
+ // type def ID, if there is a base type for this implementation and
+ // the implementation does not have any associated traits.
+ let impl_def_id = self.tcx.hir.local_def_id(item.id);
+ let mut rc_vec = self.impls_map.inherent_impls
+ .entry(def_id)
+ .or_insert_with(|| Rc::new(vec![]));
+
+ // At this point, there should not be any clones of the
+ // `Rc`, so we can still safely push into it in place:
+ Rc::get_mut(&mut rc_vec).unwrap().push(impl_def_id);
+ } else {
+ struct_span_err!(self.tcx.sess,
+ item.span,
+ E0116,
+ "cannot define inherent `impl` for a type outside of the crate \
+ where the type is defined")
+ .span_label(item.span,
+ &format!("impl for type defined outside of crate."))
+ .note("define and implement a trait or new type instead")
+ .emit();
+ }
+ }
+
+ fn check_primitive_impl(&self,
+ impl_def_id: DefId,
+ lang_def_id: Option<DefId>,
+ lang: &str,
+ ty: &str,
+ span: Span) {
+ match lang_def_id {
+ Some(lang_def_id) if lang_def_id == impl_def_id => {
+ // OK
+ }
+ _ => {
+ struct_span_err!(self.tcx.sess,
+ span,
+ E0390,
+ "only a single inherent implementation marked with `#[lang = \
+ \"{}\"]` is allowed for the `{}` primitive",
+ lang,
+ ty)
+ .span_help(span, "consider using a trait to implement these methods")
+ .emit();
+ }
+ }
+ }
+}
+
--- /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::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::hir;
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::lint;
+use rustc::traits::{self, Reveal};
+use rustc::ty::{self, TyCtxt};
+
+use syntax_pos::DUMMY_SP;
+
+pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ crate_num: CrateNum) {
+ assert_eq!(crate_num, LOCAL_CRATE);
+ let krate = tcx.hir.krate();
+ krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
+}
+
+struct InherentOverlapChecker<'a, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>
+}
+
+impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
+ fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) {
+ #[derive(Copy, Clone, PartialEq)]
+ enum Namespace {
+ Type,
+ Value,
+ }
+
+ let name_and_namespace = |def_id| {
+ let item = self.tcx.associated_item(def_id);
+ (item.name, match item.kind {
+ ty::AssociatedKind::Type => Namespace::Type,
+ ty::AssociatedKind::Const |
+ ty::AssociatedKind::Method => Namespace::Value,
+ })
+ };
+
+ let impl_items1 = self.tcx.associated_item_def_ids(impl1);
+ let impl_items2 = self.tcx.associated_item_def_ids(impl2);
+
+ for &item1 in &impl_items1[..] {
+ let (name, namespace) = name_and_namespace(item1);
+
+ for &item2 in &impl_items2[..] {
+ if (name, namespace) == name_and_namespace(item2) {
+ let msg = format!("duplicate definitions with name `{}`", name);
+ let node_id = self.tcx.hir.as_local_node_id(item1).unwrap();
+ self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
+ node_id,
+ self.tcx.span_of_impl(item1).unwrap(),
+ msg);
+ }
+ }
+ }
+ }
+
+ fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
+ let impls = ty::queries::inherent_impls::get(self.tcx, DUMMY_SP, ty_def_id);
+
+ for (i, &impl1_def_id) in impls.iter().enumerate() {
+ for &impl2_def_id in &impls[(i + 1)..] {
+ self.tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
+ if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
+ self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
+ }
+ });
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> {
+ fn visit_item(&mut self, item: &'v hir::Item) {
+ match item.node {
+ hir::ItemEnum(..) |
+ hir::ItemStruct(..) |
+ hir::ItemTrait(..) |
+ hir::ItemUnion(..) => {
+ let type_def_id = self.tcx.hir.local_def_id(item.id);
+ self.check_for_overlapping_inherent_impls(type_def_id);
+ }
+ _ => {}
+ }
+ }
+
+ fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+ }
+
+ fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+ }
+}
+
use syntax_pos::DUMMY_SP;
mod builtin;
-mod inherent;
+mod inherent_impls;
+mod inherent_impls_overlap;
mod orphan;
mod overlap;
mod unsafety;
}
pub fn provide(providers: &mut Providers) {
+ use self::builtin::coerce_unsized_info;
+ use self::inherent_impls::{crate_inherent_impls, inherent_impls};
+ use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
+
*providers = Providers {
coherent_trait,
- coherent_inherent_impls,
+ crate_inherent_impls,
+ inherent_impls,
+ crate_inherent_impls_overlap_check,
+ coerce_unsized_info,
..*providers
};
}
builtin::check_trait(tcx, def_id);
}
-fn coherent_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _: CrateNum) {
- inherent::check(tcx);
-}
-
pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let _task = tcx.dep_graph.in_task(DepNode::Coherence);
for &trait_def_id in tcx.hir.krate().trait_impls.keys() {
orphan::check(tcx);
overlap::check_default_impls(tcx);
- ty::queries::coherent_inherent_impls::get(tcx, DUMMY_SP, LOCAL_CRATE);
+ // these queries are executed for side-effects (error reporting):
+ ty::queries::crate_inherent_impls::get(tcx, DUMMY_SP, LOCAL_CRATE);
+ ty::queries::crate_inherent_impls_overlap_check::get(tcx, DUMMY_SP, LOCAL_CRATE);
}
and [RFC 809] for more details.
[RFC 470]: https://github.com/rust-lang/rfcs/pull/470
-[RFC 809]: https://github.com/rust-lang/rfcs/pull/809
+[RFC 809]: https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md
"##,
E0067: r##"
```
Note that type parameters for enum-variant constructors go after the variant,
-not after the enum (Option::None::<u32>, not Option::<u32>::None).
+not after the enum (`Option::None::<u32>`, not `Option::<u32>::None`).
"##,
E0110: r##"
For information on the design of the orphan rules, see [RFC 1023].
-[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
+[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
"##,
E0118: r##"
E0192: r##"
Negative impls are only allowed for traits with default impls. For more
-information see the [opt-in builtin traits RFC](https://github.com/rust-lang/
-rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
+information see the [opt-in builtin traits RFC][RFC 19].
+
+[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
"##,
E0193: r##"
Inherent associated types were part of [RFC 195] but are not yet implemented.
See [the tracking issue][iss8995] for the status of this implementation.
-[RFC 195]: https://github.com/rust-lang/rfcs/pull/195
+[RFC 195]: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md
[iss8995]: https://github.com/rust-lang/rust/issues/8995
"##,
For information on the design of the orphan rules, see [RFC 1023].
-[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
+[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
"##,
/*
E0318: r##"
Default impls for a trait must be located in the same crate where the trait was
-defined. For more information see the [opt-in builtin traits RFC](https://github
-.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
+defined. For more information see the [opt-in builtin traits RFC][RFC 19].
+
+[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
"##,
E0321: r##"
```
If you are defining your own smart pointer type and would like to enable
-conversion from a sized to an unsized type with the [DST coercion system]
-(https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md), use
-[`CoerceUnsized`](https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html)
-instead.
+conversion from a sized to an unsized type with the
+[DST coercion system][RFC 982], use [`CoerceUnsized`] instead.
```
#![feature(coerce_unsized)]
impl<T, U> CoerceUnsized<MyType<U>> for MyType<T>
where T: CoerceUnsized<U> {}
```
+
+[RFC 982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
+[`CoerceUnsized`]: https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html
"##,
E0329: r##"
E0380: r##"
Default impls are only allowed for traits with no methods or associated items.
-For more information see the [opt-in builtin traits RFC](https://github.com/rust
--lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
+For more information see the [opt-in builtin traits RFC][RFC 19].
+
+[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
"##,
E0390: r##"
authors = ["The Rust Project Developers"]
name = "rustdoc"
version = "0.0.0"
-build = "build.rs"
[lib]
name = "rustdoc"
[dependencies]
arena = { path = "../libarena" }
+env_logger = { version = "0.4", default-features = false }
+log = "0.3"
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_const_eval = { path = "../librustc_const_eval" }
-rustc_driver = { path = "../librustc_driver" }
rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_driver = { path = "../librustc_driver" }
rustc_errors = { path = "../librustc_errors" }
rustc_lint = { path = "../librustc_lint" }
rustc_metadata = { path = "../librustc_metadata" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
-log = { path = "../liblog" }
+pulldown-cmark = { version = "0.0.14", default-features = false }
[build-dependencies]
build_helper = { path = "../build_helper" }
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-extern crate build_helper;
-extern crate gcc;
-
-fn main() {
- let src_dir = std::path::Path::new("../rt/hoedown/src");
- build_helper::rerun_if_changed_anything_in_dir(src_dir);
- let mut cfg = gcc::Config::new();
- cfg.file("../rt/hoedown/src/autolink.c")
- .file("../rt/hoedown/src/buffer.c")
- .file("../rt/hoedown/src/document.c")
- .file("../rt/hoedown/src/escape.c")
- .file("../rt/hoedown/src/html.c")
- .file("../rt/hoedown/src/html_blocks.c")
- .file("../rt/hoedown/src/html_smartypants.c")
- .file("../rt/hoedown/src/stack.c")
- .file("../rt/hoedown/src/version.c")
- .include(src_dir)
- .compile("libhoedown.a");
-}
pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
let tcx = cx.tcx;
- tcx.populate_inherent_implementations_for_type_if_necessary(DUMMY_SP, did);
let mut impls = Vec::new();
- if let Some(i) = tcx.maps.inherent_impls.borrow().get(&did) {
- for &did in i.iter() {
- build_impl(cx, did, &mut impls);
- }
+ for &did in ty::queries::inherent_impls::get(tcx, DUMMY_SP, did).iter() {
+ build_impl(cx, did, &mut impls);
}
+
// If this is the first time we've inlined something from another crate, then
// we inline *all* impls from all the crates into this crate. Note that there's
// currently no way for us to filter this based on type, and we likely need
use rustc::dep_graph::DepGraph;
use rustc::session::{self, config};
use rustc::hir::def_id::DefId;
-use rustc::hir::def::{Def, ExportMap};
+use rustc::hir::def::Def;
use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt, GlobalArenas};
use rustc::hir::map as hir_map;
pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>,
/// Table node id of lifetime parameter definition -> substituted lifetime
pub lt_substs: RefCell<FxHashMap<ast::NodeId, clean::Lifetime>>,
- pub export_map: ExportMap,
}
impl<'a, 'tcx> DocContext<'a, 'tcx> {
sess.fatal("Compilation failed, aborting rustdoc");
}
- let ty::CrateAnalysis { access_levels, export_map, .. } = analysis;
+ let ty::CrateAnalysis { access_levels, .. } = analysis;
// Convert from a NodeId set to a DefId set since we don't always have easy access
// to the map from defid -> nodeid
let access_levels = AccessLevels {
- map: access_levels.map.into_iter()
- .map(|(k, v)| (tcx.hir.local_def_id(k), v))
+ map: access_levels.map.iter()
+ .map(|(&k, &v)| (tcx.hir.local_def_id(k), v))
.collect()
};
renderinfo: Default::default(),
ty_substs: Default::default(),
lt_substs: Default::default(),
- export_map: export_map,
};
debug!("crate: {:?}", tcx.hir.krate());
//! Markdown formatting for rustdoc
//!
-//! This module implements markdown formatting through the hoedown C-library
-//! (bundled into the rust runtime). This module self-contains the C bindings
-//! and necessary legwork to render markdown, and exposes all of the
+//! This module implements markdown formatting through the pulldown-cmark
+//! rust-library. This module exposes all of the
//! functionality through a unit-struct, `Markdown`, which has an implementation
//! of `fmt::Display`. Example usage:
//!
//! ```rust,ignore
-//! use rustdoc::html::markdown::Markdown;
+//! use rustdoc::html::markdown::{Markdown, MarkdownOutputStyle};
//!
//! let s = "My *markdown* _text_";
-//! let html = format!("{}", Markdown(s));
+//! let html = format!("{}", Markdown(s, MarkdownOutputStyle::Fancy));
//! // ... something using html
//! ```
#![allow(non_camel_case_types)]
-use libc;
use std::ascii::AsciiExt;
use std::cell::RefCell;
use std::default::Default;
-use std::ffi::CString;
use std::fmt::{self, Write};
-use std::slice;
use std::str;
use syntax::feature_gate::UnstableFeatures;
use syntax::codemap::Span;
use html::escape::Escape;
use test;
+use pulldown_cmark::{self, Event, Parser, Tag};
+
+#[derive(Copy, Clone)]
+pub enum MarkdownOutputStyle {
+ Compact,
+ Fancy,
+}
+
+impl MarkdownOutputStyle {
+ pub fn is_compact(&self) -> bool {
+ match *self {
+ MarkdownOutputStyle::Compact => true,
+ _ => false,
+ }
+ }
+
+ pub fn is_fancy(&self) -> bool {
+ match *self {
+ MarkdownOutputStyle::Fancy => true,
+ _ => false,
+ }
+ }
+}
+
/// A unit struct which has the `fmt::Display` trait implemented. When
/// formatted, this struct will emit the HTML corresponding to the rendered
/// version of the contained markdown string.
-pub struct Markdown<'a>(pub &'a str);
+// The second parameter is whether we need a shorter version or not.
+pub struct Markdown<'a>(pub &'a str, pub MarkdownOutputStyle);
/// A unit struct like `Markdown`, that renders the markdown with a
/// table of contents.
pub struct MarkdownWithToc<'a>(pub &'a str);
/// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
pub struct MarkdownHtml<'a>(pub &'a str);
-const DEF_OUNIT: libc::size_t = 64;
-const HOEDOWN_EXT_NO_INTRA_EMPHASIS: libc::c_uint = 1 << 11;
-const HOEDOWN_EXT_TABLES: libc::c_uint = 1 << 0;
-const HOEDOWN_EXT_FENCED_CODE: libc::c_uint = 1 << 1;
-const HOEDOWN_EXT_AUTOLINK: libc::c_uint = 1 << 3;
-const HOEDOWN_EXT_STRIKETHROUGH: libc::c_uint = 1 << 4;
-const HOEDOWN_EXT_SUPERSCRIPT: libc::c_uint = 1 << 8;
-const HOEDOWN_EXT_FOOTNOTES: libc::c_uint = 1 << 2;
-const HOEDOWN_HTML_ESCAPE: libc::c_uint = 1 << 1;
-
-const HOEDOWN_EXTENSIONS: libc::c_uint =
- HOEDOWN_EXT_NO_INTRA_EMPHASIS | HOEDOWN_EXT_TABLES |
- HOEDOWN_EXT_FENCED_CODE | HOEDOWN_EXT_AUTOLINK |
- HOEDOWN_EXT_STRIKETHROUGH | HOEDOWN_EXT_SUPERSCRIPT |
- HOEDOWN_EXT_FOOTNOTES;
-
-enum hoedown_document {}
-
-type blockcodefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_buffer, *const hoedown_renderer_data,
- libc::size_t);
-
-type blockquotefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data, libc::size_t);
-
-type headerfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- libc::c_int, *const hoedown_renderer_data,
- libc::size_t);
-
-type blockhtmlfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data, libc::size_t);
-
-type codespanfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data, libc::size_t) -> libc::c_int;
-
-type linkfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data, libc::size_t) -> libc::c_int;
-
-type entityfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data, libc::size_t);
-
-type normaltextfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data, libc::size_t);
-
-#[repr(C)]
-struct hoedown_renderer_data {
- opaque: *mut libc::c_void,
-}
-
-#[repr(C)]
-struct hoedown_renderer {
- opaque: *mut libc::c_void,
-
- blockcode: Option<blockcodefn>,
- blockquote: Option<blockquotefn>,
- header: Option<headerfn>,
-
- other_block_level_callbacks: [libc::size_t; 11],
-
- blockhtml: Option<blockhtmlfn>,
-
- /* span level callbacks - NULL or return 0 prints the span verbatim */
- autolink: libc::size_t, // unused
- codespan: Option<codespanfn>,
- other_span_level_callbacks_1: [libc::size_t; 7],
- link: Option<linkfn>,
- other_span_level_callbacks_2: [libc::size_t; 6],
-
- /* low level callbacks - NULL copies input directly into the output */
- entity: Option<entityfn>,
- normal_text: Option<normaltextfn>,
-
- /* header and footer */
- other_callbacks: [libc::size_t; 2],
-}
-
-#[repr(C)]
-struct hoedown_html_renderer_state {
- opaque: *mut libc::c_void,
- toc_data: html_toc_data,
- flags: libc::c_uint,
- link_attributes: Option<extern "C" fn(*mut hoedown_buffer,
- *const hoedown_buffer,
- *const hoedown_renderer_data)>,
-}
-
-#[repr(C)]
-struct html_toc_data {
- header_count: libc::c_int,
- current_level: libc::c_int,
- level_offset: libc::c_int,
- nesting_level: libc::c_int,
-}
-
-struct MyOpaque {
- dfltblk: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_buffer, *const hoedown_renderer_data,
- libc::size_t),
- toc_builder: Option<TocBuilder>,
-}
-
-#[repr(C)]
-struct hoedown_buffer {
- data: *const u8,
- size: libc::size_t,
- asize: libc::size_t,
- unit: libc::size_t,
-}
-
-extern {
- fn hoedown_html_renderer_new(render_flags: libc::c_uint,
- nesting_level: libc::c_int)
- -> *mut hoedown_renderer;
- fn hoedown_html_renderer_free(renderer: *mut hoedown_renderer);
-
- fn hoedown_document_new(rndr: *const hoedown_renderer,
- extensions: libc::c_uint,
- max_nesting: libc::size_t) -> *mut hoedown_document;
- fn hoedown_document_render(doc: *mut hoedown_document,
- ob: *mut hoedown_buffer,
- document: *const u8,
- doc_size: libc::size_t);
- fn hoedown_document_free(md: *mut hoedown_document);
-
- fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer;
- fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const libc::c_char,
- n: libc::size_t);
- fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char);
- fn hoedown_buffer_free(b: *mut hoedown_buffer);
-
-}
-
-// hoedown_buffer helpers
-impl hoedown_buffer {
- fn as_bytes(&self) -> &[u8] {
- unsafe { slice::from_raw_parts(self.data, self.size as usize) }
- }
-}
-
/// Returns Some(code) if `s` is a line that should be stripped from
/// documentation but used in example code. `code` is the portion of
/// `s` that should be used in tests. (None for lines that should be
RefCell::new(None)
});
+macro_rules! event_loop_break {
+ ($parser:expr, $toc_builder:expr, $shorter:expr, $buf:expr, $escape:expr, $id:expr,
+ $($end_event:pat)|*) => {{
+ fn inner(id: &mut Option<&mut String>, s: &str) {
+ if let Some(ref mut id) = *id {
+ id.push_str(s);
+ }
+ }
+ while let Some(event) = $parser.next() {
+ match event {
+ $($end_event)|* => break,
+ Event::Text(ref s) => {
+ inner($id, s);
+ if $escape {
+ $buf.push_str(&format!("{}", Escape(s)));
+ } else {
+ $buf.push_str(s);
+ }
+ }
+ Event::SoftBreak | Event::HardBreak if !$buf.is_empty() => {
+ $buf.push(' ');
+ }
+ x => {
+ looper($parser, &mut $buf, Some(x), $toc_builder, $shorter, $id);
+ }
+ }
+ }
+ }}
+}
pub fn render(w: &mut fmt::Formatter,
s: &str,
print_toc: bool,
- html_flags: libc::c_uint) -> fmt::Result {
- extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer,
- lang: *const hoedown_buffer, data: *const hoedown_renderer_data,
- line: libc::size_t) {
- unsafe {
- if orig_text.is_null() { return }
-
- let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
- let my_opaque: &MyOpaque = &*((*opaque).opaque as *const MyOpaque);
- let text = (*orig_text).as_bytes();
- let origtext = str::from_utf8(text).unwrap();
- let origtext = origtext.trim_left();
- debug!("docblock: ==============\n{:?}\n=======", text);
- let rendered = if lang.is_null() || origtext.is_empty() {
- false
- } else {
- let rlang = (*lang).as_bytes();
- let rlang = str::from_utf8(rlang).unwrap();
- if !LangString::parse(rlang).rust {
- (my_opaque.dfltblk)(ob, orig_text, lang,
- opaque as *const hoedown_renderer_data,
- line);
- true
- } else {
- false
+ shorter: MarkdownOutputStyle) -> fmt::Result {
+ fn code_block(parser: &mut Parser, buffer: &mut String, lang: &str) {
+ let mut origtext = String::new();
+ while let Some(event) = parser.next() {
+ match event {
+ Event::End(Tag::CodeBlock(_)) => break,
+ Event::Text(ref s) => {
+ origtext.push_str(s);
}
- };
+ _ => {}
+ }
+ }
+ let origtext = origtext.trim_left();
+ debug!("docblock: ==============\n{:?}\n=======", origtext);
- let lines = origtext.lines().filter(|l| {
- stripped_filtered_line(*l).is_none()
- });
- let text = lines.collect::<Vec<&str>>().join("\n");
- if rendered { return }
- PLAYGROUND.with(|play| {
- // insert newline to clearly separate it from the
- // previous block so we can shorten the html output
- let mut s = String::from("\n");
- let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| {
- if url.is_empty() {
- return None;
- }
- let test = origtext.lines().map(|l| {
- stripped_filtered_line(l).unwrap_or(l)
- }).collect::<Vec<&str>>().join("\n");
- let krate = krate.as_ref().map(|s| &**s);
- let test = test::maketest(&test, krate, false,
- &Default::default());
- let channel = if test.contains("#![feature(") {
- "&version=nightly"
+ let lines = origtext.lines().filter(|l| {
+ stripped_filtered_line(*l).is_none()
+ });
+ let text = lines.collect::<Vec<&str>>().join("\n");
+ let block_info = if lang.is_empty() {
+ LangString::all_false()
+ } else {
+ LangString::parse(lang)
+ };
+ if !block_info.rust {
+ buffer.push_str(&format!("<pre><code class=\"language-{}\">{}</code></pre>",
+ lang, text));
+ return
+ }
+ PLAYGROUND.with(|play| {
+ // insert newline to clearly separate it from the
+ // previous block so we can shorten the html output
+ buffer.push('\n');
+ let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| {
+ if url.is_empty() {
+ return None;
+ }
+ let test = origtext.lines().map(|l| {
+ stripped_filtered_line(l).unwrap_or(l)
+ }).collect::<Vec<&str>>().join("\n");
+ let krate = krate.as_ref().map(|s| &**s);
+ let test = test::maketest(&test, krate, false,
+ &Default::default());
+ let channel = if test.contains("#![feature(") {
+ "&version=nightly"
+ } else {
+ ""
+ };
+ // These characters don't need to be escaped in a URI.
+ // FIXME: use a library function for percent encoding.
+ fn dont_escape(c: u8) -> bool {
+ (b'a' <= c && c <= b'z') ||
+ (b'A' <= c && c <= b'Z') ||
+ (b'0' <= c && c <= b'9') ||
+ c == b'-' || c == b'_' || c == b'.' ||
+ c == b'~' || c == b'!' || c == b'\'' ||
+ c == b'(' || c == b')' || c == b'*'
+ }
+ let mut test_escaped = String::new();
+ for b in test.bytes() {
+ if dont_escape(b) {
+ test_escaped.push(char::from(b));
} else {
- ""
- };
- // These characters don't need to be escaped in a URI.
- // FIXME: use a library function for percent encoding.
- fn dont_escape(c: u8) -> bool {
- (b'a' <= c && c <= b'z') ||
- (b'A' <= c && c <= b'Z') ||
- (b'0' <= c && c <= b'9') ||
- c == b'-' || c == b'_' || c == b'.' ||
- c == b'~' || c == b'!' || c == b'\'' ||
- c == b'(' || c == b')' || c == b'*'
+ write!(test_escaped, "%{:02X}", b).unwrap();
}
- let mut test_escaped = String::new();
- for b in test.bytes() {
- if dont_escape(b) {
- test_escaped.push(char::from(b));
- } else {
- write!(test_escaped, "%{:02X}", b).unwrap();
- }
- }
- Some(format!(
- r#"<a class="test-arrow" target="_blank" href="{}?code={}{}">Run</a>"#,
- url, test_escaped, channel
- ))
- });
- s.push_str(&highlight::render_with_highlighting(
- &text,
- Some("rust-example-rendered"),
- None,
- playground_button.as_ref().map(String::as_str)));
- let output = CString::new(s).unwrap();
- hoedown_buffer_puts(ob, output.as_ptr());
- })
- }
+ }
+ Some(format!(
+ r#"<a class="test-arrow" target="_blank" href="{}?code={}{}">Run</a>"#,
+ url, test_escaped, channel
+ ))
+ });
+ buffer.push_str(&highlight::render_with_highlighting(
+ &text,
+ Some("rust-example-rendered"),
+ None,
+ playground_button.as_ref().map(String::as_str)));
+ });
}
- extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
- level: libc::c_int, data: *const hoedown_renderer_data,
- _: libc::size_t) {
- // hoedown does this, we may as well too
- unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); }
+ fn heading(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle, level: i32) {
+ let mut ret = String::new();
+ let mut id = String::new();
+ event_loop_break!(parser, toc_builder, shorter, ret, true, &mut Some(&mut id),
+ Event::End(Tag::Header(_)));
+ ret = ret.trim_right().to_owned();
- // Extract the text provided
- let s = if text.is_null() {
- "".to_owned()
- } else {
- let s = unsafe { (*text).as_bytes() };
- str::from_utf8(&s).unwrap().to_owned()
- };
-
- // Discard '<em>', '<code>' tags and some escaped characters,
- // transform the contents of the header into a hyphenated string
- // without non-alphanumeric characters other than '-' and '_'.
- //
- // This is a terrible hack working around how hoedown gives us rendered
- // html for text rather than the raw text.
- let mut id = s.clone();
- let repl_sub = vec!["<em>", "</em>", "<code>", "</code>",
- "<strong>", "</strong>",
- "<", ">", "&", "'", """];
- for sub in repl_sub {
- id = id.replace(sub, "");
- }
let id = id.chars().filter_map(|c| {
if c.is_alphanumeric() || c == '-' || c == '_' {
if c.is_ascii() {
}
}).collect::<String>();
- let opaque = unsafe { (*data).opaque as *mut hoedown_html_renderer_state };
- let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
-
let id = derive_id(id);
- let sec = opaque.toc_builder.as_mut().map_or("".to_owned(), |builder| {
- format!("{} ", builder.push(level as u32, s.clone(), id.clone()))
+ let sec = toc_builder.as_mut().map_or("".to_owned(), |builder| {
+ format!("{} ", builder.push(level as u32, ret.clone(), id.clone()))
});
// Render the HTML
- let text = format!("<h{lvl} id='{id}' class='section-header'>\
- <a href='#{id}'>{sec}{}</a></h{lvl}>",
- s, lvl = level, id = id, sec = sec);
-
- let text = CString::new(text).unwrap();
- unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
- }
-
- extern fn codespan(
- ob: *mut hoedown_buffer,
- text: *const hoedown_buffer,
- _: *const hoedown_renderer_data,
- _: libc::size_t
- ) -> libc::c_int {
- let content = if text.is_null() {
- "".to_owned()
- } else {
- let bytes = unsafe { (*text).as_bytes() };
- let s = str::from_utf8(bytes).unwrap();
- collapse_whitespace(s)
- };
+ buffer.push_str(&format!("<h{lvl} id=\"{id}\" class=\"section-header\">\
+ <a href=\"#{id}\">{sec}{}</a></h{lvl}>",
+ ret, lvl = level, id = id, sec = sec));
+ }
- let content = format!("<code>{}</code>", Escape(&content));
- let element = CString::new(content).unwrap();
- unsafe { hoedown_buffer_puts(ob, element.as_ptr()); }
- // Return anything except 0, which would mean "also print the code span verbatim".
- 1
+ fn inline_code(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) {
+ let mut content = String::new();
+ event_loop_break!(parser, toc_builder, shorter, content, false, id, Event::End(Tag::Code));
+ buffer.push_str(&format!("<code>{}</code>",
+ Escape(&collapse_whitespace(content.trim_right()))));
}
- unsafe {
- let ob = hoedown_buffer_new(DEF_OUNIT);
- let renderer = hoedown_html_renderer_new(html_flags, 0);
- let mut opaque = MyOpaque {
- dfltblk: (*renderer).blockcode.unwrap(),
- toc_builder: if print_toc {Some(TocBuilder::new())} else {None}
- };
- (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
- = &mut opaque as *mut _ as *mut libc::c_void;
- (*renderer).blockcode = Some(block);
- (*renderer).header = Some(header);
- (*renderer).codespan = Some(codespan);
+ fn link(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle, url: &str, mut title: String,
+ id: &mut Option<&mut String>) {
+ event_loop_break!(parser, toc_builder, shorter, title, true, id,
+ Event::End(Tag::Link(_, _)));
+ buffer.push_str(&format!("<a href=\"{}\">{}</a>", url, title));
+ }
- let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
- hoedown_document_render(document, ob, s.as_ptr(),
- s.len() as libc::size_t);
- hoedown_document_free(document);
+ fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) {
+ let mut content = String::new();
+ event_loop_break!(parser, toc_builder, shorter, content, true, id,
+ Event::End(Tag::Paragraph));
+ buffer.push_str(&format!("<p>{}</p>", content.trim_right()));
+ }
- hoedown_html_renderer_free(renderer);
+ fn table_cell(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle) {
+ let mut content = String::new();
+ event_loop_break!(parser, toc_builder, shorter, content, true, &mut None,
+ Event::End(Tag::TableHead) |
+ Event::End(Tag::Table(_)) |
+ Event::End(Tag::TableRow) |
+ Event::End(Tag::TableCell));
+ buffer.push_str(&format!("<td>{}</td>", content.trim()));
+ }
- let mut ret = opaque.toc_builder.map_or(Ok(()), |builder| {
- write!(w, "<nav id=\"TOC\">{}</nav>", builder.into_toc())
- });
+ fn table_row(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle) {
+ let mut content = String::new();
+ while let Some(event) = parser.next() {
+ match event {
+ Event::End(Tag::TableHead) |
+ Event::End(Tag::Table(_)) |
+ Event::End(Tag::TableRow) => break,
+ Event::Start(Tag::TableCell) => {
+ table_cell(parser, &mut content, toc_builder, shorter);
+ }
+ x => {
+ looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
+ }
+ }
+ }
+ buffer.push_str(&format!("<tr>{}</tr>", content));
+ }
- if ret.is_ok() {
- let buf = (*ob).as_bytes();
- ret = w.write_str(str::from_utf8(buf).unwrap());
+ fn table_head(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle) {
+ let mut content = String::new();
+ while let Some(event) = parser.next() {
+ match event {
+ Event::End(Tag::TableHead) | Event::End(Tag::Table(_)) => break,
+ Event::Start(Tag::TableCell) => {
+ table_cell(parser, &mut content, toc_builder, shorter);
+ }
+ x => {
+ looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
+ }
+ }
+ }
+ if !content.is_empty() {
+ buffer.push_str(&format!("<thead><tr>{}</tr></thead>", content.replace("td>", "th>")));
}
- hoedown_buffer_free(ob);
- ret
}
-}
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) {
- extern fn block(_ob: *mut hoedown_buffer,
- text: *const hoedown_buffer,
- lang: *const hoedown_buffer,
- data: *const hoedown_renderer_data,
- line: libc::size_t) {
- unsafe {
- if text.is_null() { return }
- let block_info = if lang.is_null() {
- LangString::all_false()
- } else {
- let lang = (*lang).as_bytes();
- let s = str::from_utf8(lang).unwrap();
- LangString::parse(s)
- };
- if !block_info.rust { return }
- let text = (*text).as_bytes();
- let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
- let tests = &mut *((*opaque).opaque as *mut ::test::Collector);
- let text = str::from_utf8(text).unwrap();
- let lines = text.lines().map(|l| {
- stripped_filtered_line(l).unwrap_or(l)
- });
- let text = lines.collect::<Vec<&str>>().join("\n");
- let line = tests.get_line() + line;
- let filename = tests.get_filename();
- tests.add_test(text.to_owned(),
- block_info.should_panic, block_info.no_run,
- block_info.ignore, block_info.test_harness,
- block_info.compile_fail, block_info.error_codes,
- line, filename);
+ fn table(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle) {
+ let mut content = String::new();
+ let mut rows = String::new();
+ while let Some(event) = parser.next() {
+ match event {
+ Event::End(Tag::Table(_)) => break,
+ Event::Start(Tag::TableHead) => {
+ table_head(parser, &mut content, toc_builder, shorter);
+ }
+ Event::Start(Tag::TableRow) => {
+ table_row(parser, &mut rows, toc_builder, shorter);
+ }
+ _ => {}
+ }
}
+ buffer.push_str(&format!("<table>{}{}</table>",
+ content,
+ if shorter.is_compact() || rows.is_empty() {
+ String::new()
+ } else {
+ format!("<tbody>{}</tbody>", rows)
+ }));
}
- extern fn header(_ob: *mut hoedown_buffer,
- text: *const hoedown_buffer,
- level: libc::c_int, data: *const hoedown_renderer_data,
- _: libc::size_t) {
- unsafe {
- let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
- let tests = &mut *((*opaque).opaque as *mut ::test::Collector);
- if text.is_null() {
- tests.register_header("", level as u32);
- } else {
- let text = (*text).as_bytes();
- let text = str::from_utf8(text).unwrap();
- tests.register_header(text, level as u32);
+ fn blockquote(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle) {
+ let mut content = String::new();
+ event_loop_break!(parser, toc_builder, shorter, content, true, &mut None,
+ Event::End(Tag::BlockQuote));
+ buffer.push_str(&format!("<blockquote>{}</blockquote>", content.trim_right()));
+ }
+
+ fn list_item(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle) {
+ let mut content = String::new();
+ while let Some(event) = parser.next() {
+ match event {
+ Event::End(Tag::Item) => break,
+ Event::Text(ref s) => {
+ content.push_str(&format!("{}", Escape(s)));
+ }
+ x => {
+ looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
+ }
+ }
+ }
+ buffer.push_str(&format!("<li>{}</li>", content));
+ }
+
+ fn list(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle) {
+ let mut content = String::new();
+ while let Some(event) = parser.next() {
+ match event {
+ Event::End(Tag::List(_)) => break,
+ Event::Start(Tag::Item) => {
+ list_item(parser, &mut content, toc_builder, shorter);
+ }
+ x => {
+ looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
+ }
+ }
+ }
+ buffer.push_str(&format!("<ul>{}</ul>", content));
+ }
+
+ fn emphasis(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) {
+ let mut content = String::new();
+ event_loop_break!(parser, toc_builder, shorter, content, false, id,
+ Event::End(Tag::Emphasis));
+ buffer.push_str(&format!("<em>{}</em>", content));
+ }
+
+ fn strong(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+ shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) {
+ let mut content = String::new();
+ event_loop_break!(parser, toc_builder, shorter, content, false, id,
+ Event::End(Tag::Strong));
+ buffer.push_str(&format!("<strong>{}</strong>", content));
+ }
+
+ fn looper<'a>(parser: &'a mut Parser, buffer: &mut String, next_event: Option<Event<'a>>,
+ toc_builder: &mut Option<TocBuilder>, shorter: MarkdownOutputStyle,
+ id: &mut Option<&mut String>) -> bool {
+ if let Some(event) = next_event {
+ match event {
+ Event::Start(Tag::CodeBlock(lang)) => {
+ code_block(parser, buffer, &*lang);
+ }
+ Event::Start(Tag::Header(level)) => {
+ heading(parser, buffer, toc_builder, shorter, level);
+ }
+ Event::Start(Tag::Code) => {
+ inline_code(parser, buffer, toc_builder, shorter, id);
+ }
+ Event::Start(Tag::Paragraph) => {
+ paragraph(parser, buffer, toc_builder, shorter, id);
+ }
+ Event::Start(Tag::Link(ref url, ref t)) => {
+ link(parser, buffer, toc_builder, shorter, url, t.as_ref().to_owned(), id);
+ }
+ Event::Start(Tag::Table(_)) => {
+ table(parser, buffer, toc_builder, shorter);
+ }
+ Event::Start(Tag::BlockQuote) => {
+ blockquote(parser, buffer, toc_builder, shorter);
+ }
+ Event::Start(Tag::List(_)) => {
+ list(parser, buffer, toc_builder, shorter);
+ }
+ Event::Start(Tag::Emphasis) => {
+ emphasis(parser, buffer, toc_builder, shorter, id);
+ }
+ Event::Start(Tag::Strong) => {
+ strong(parser, buffer, toc_builder, shorter, id);
+ }
+ Event::Html(h) | Event::InlineHtml(h) => {
+ buffer.push_str(&*h);
+ }
+ _ => {}
}
+ shorter.is_fancy()
+ } else {
+ false
+ }
+ }
+
+ let mut toc_builder = if print_toc {
+ Some(TocBuilder::new())
+ } else {
+ None
+ };
+ let mut buffer = String::new();
+ let mut parser = Parser::new_ext(s, pulldown_cmark::OPTION_ENABLE_TABLES);
+ loop {
+ let next_event = parser.next();
+ if !looper(&mut parser, &mut buffer, next_event, &mut toc_builder, shorter, &mut None) {
+ break
}
}
+ let mut ret = toc_builder.map_or(Ok(()), |builder| {
+ write!(w, "<nav id=\"TOC\">{}</nav>", builder.into_toc())
+ });
+
+ if ret.is_ok() {
+ ret = w.write_str(&buffer);
+ }
+ ret
+}
+pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) {
tests.set_position(position);
- unsafe {
- let ob = hoedown_buffer_new(DEF_OUNIT);
- let renderer = hoedown_html_renderer_new(0, 0);
- (*renderer).blockcode = Some(block);
- (*renderer).header = Some(header);
- (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
- = tests as *mut _ as *mut libc::c_void;
-
- let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
- hoedown_document_render(document, ob, doc.as_ptr(),
- doc.len() as libc::size_t);
- hoedown_document_free(document);
-
- hoedown_html_renderer_free(renderer);
- hoedown_buffer_free(ob);
+
+ let mut parser = Parser::new(doc);
+ let mut prev_offset = 0;
+ let mut nb_lines = 0;
+ let mut register_header = None;
+ 'main: while let Some(event) = parser.next() {
+ match event {
+ Event::Start(Tag::CodeBlock(s)) => {
+ let block_info = if s.is_empty() {
+ LangString::all_false()
+ } else {
+ LangString::parse(&*s)
+ };
+ if !block_info.rust {
+ continue
+ }
+ let mut test_s = String::new();
+ let mut offset = None;
+ loop {
+ let event = parser.next();
+ if let Some(event) = event {
+ match event {
+ Event::End(Tag::CodeBlock(_)) => break,
+ Event::Text(ref s) => {
+ test_s.push_str(s);
+ if offset.is_none() {
+ offset = Some(parser.get_offset());
+ }
+ }
+ _ => {}
+ }
+ } else {
+ break 'main;
+ }
+ }
+ let offset = offset.unwrap_or(0);
+ let lines = test_s.lines().map(|l| {
+ stripped_filtered_line(l).unwrap_or(l)
+ });
+ let text = lines.collect::<Vec<&str>>().join("\n");
+ nb_lines += doc[prev_offset..offset].lines().count();
+ let line = tests.get_line() + (nb_lines - 1);
+ let filename = tests.get_filename();
+ tests.add_test(text.to_owned(),
+ block_info.should_panic, block_info.no_run,
+ block_info.ignore, block_info.test_harness,
+ block_info.compile_fail, block_info.error_codes,
+ line, filename);
+ prev_offset = offset;
+ }
+ Event::Start(Tag::Header(level)) => {
+ register_header = Some(level as u32);
+ }
+ Event::Text(ref s) if register_header.is_some() => {
+ let level = register_header.unwrap();
+ if s.is_empty() {
+ tests.register_header("", level);
+ } else {
+ tests.register_header(s, level);
+ }
+ register_header = None;
+ }
+ _ => {}
+ }
}
}
impl<'a> fmt::Display for Markdown<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- let Markdown(md) = *self;
+ let Markdown(md, shorter) = *self;
// This is actually common enough to special-case
if md.is_empty() { return Ok(()) }
- render(fmt, md, false, 0)
+ render(fmt, md, false, shorter)
}
}
impl<'a> fmt::Display for MarkdownWithToc<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let MarkdownWithToc(md) = *self;
- render(fmt, md, true, 0)
+ render(fmt, md, true, MarkdownOutputStyle::Fancy)
}
}
let MarkdownHtml(md) = *self;
// This is actually common enough to special-case
if md.is_empty() { return Ok(()) }
- render(fmt, md, false, HOEDOWN_HTML_ESCAPE)
+ render(fmt, md, false, MarkdownOutputStyle::Fancy)
}
}
pub fn plain_summary_line(md: &str) -> String {
- extern fn link(_ob: *mut hoedown_buffer,
- _link: *const hoedown_buffer,
- _title: *const hoedown_buffer,
- content: *const hoedown_buffer,
- data: *const hoedown_renderer_data,
- _: libc::size_t) -> libc::c_int
- {
- unsafe {
- if !content.is_null() && (*content).size > 0 {
- let ob = (*data).opaque as *mut hoedown_buffer;
- hoedown_buffer_put(ob, (*content).data as *const libc::c_char,
- (*content).size);
- }
- }
- 1
- }
-
- extern fn normal_text(_ob: *mut hoedown_buffer,
- text: *const hoedown_buffer,
- data: *const hoedown_renderer_data,
- _: libc::size_t)
- {
- unsafe {
- let ob = (*data).opaque as *mut hoedown_buffer;
- hoedown_buffer_put(ob, (*text).data as *const libc::c_char,
- (*text).size);
- }
+ struct ParserWrapper<'a> {
+ inner: Parser<'a>,
+ is_in: isize,
+ is_first: bool,
}
- unsafe {
- let ob = hoedown_buffer_new(DEF_OUNIT);
- let mut plain_renderer: hoedown_renderer = ::std::mem::zeroed();
- let renderer: *mut hoedown_renderer = &mut plain_renderer;
- (*renderer).opaque = ob as *mut libc::c_void;
- (*renderer).link = Some(link);
- (*renderer).normal_text = Some(normal_text);
+ impl<'a> Iterator for ParserWrapper<'a> {
+ type Item = String;
- let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
- hoedown_document_render(document, ob, md.as_ptr(),
- md.len() as libc::size_t);
- hoedown_document_free(document);
- let plain_slice = (*ob).as_bytes();
- let plain = str::from_utf8(plain_slice).unwrap_or("").to_owned();
- hoedown_buffer_free(ob);
- plain
+ fn next(&mut self) -> Option<String> {
+ let next_event = self.inner.next();
+ if next_event.is_none() {
+ return None
+ }
+ let next_event = next_event.unwrap();
+ let (ret, is_in) = match next_event {
+ Event::Start(Tag::Paragraph) => (None, 1),
+ Event::Start(Tag::Link(_, ref t)) if !self.is_first => {
+ (Some(t.as_ref().to_owned()), 1)
+ }
+ Event::Start(Tag::Code) => (Some("`".to_owned()), 1),
+ Event::End(Tag::Code) => (Some("`".to_owned()), -1),
+ Event::Start(Tag::Header(_)) => (None, 1),
+ Event::Text(ref s) if self.is_in > 0 => (Some(s.as_ref().to_owned()), 0),
+ Event::End(Tag::Link(_, ref t)) => (Some(t.as_ref().to_owned()), -1),
+ Event::End(Tag::Paragraph) | Event::End(Tag::Header(_)) => (None, -1),
+ _ => (None, 0),
+ };
+ if is_in > 0 || (is_in < 0 && self.is_in > 0) {
+ self.is_in += is_in;
+ }
+ if ret.is_some() {
+ self.is_first = false;
+ ret
+ } else {
+ Some(String::new())
+ }
+ }
+ }
+ let mut s = String::with_capacity(md.len() * 3 / 2);
+ let mut p = ParserWrapper {
+ inner: Parser::new(md),
+ is_in: 0,
+ is_first: true,
+ };
+ while let Some(t) = p.next() {
+ if !t.is_empty() {
+ s.push_str(&t);
+ }
}
+ s
}
#[cfg(test)]
mod tests {
- use super::{LangString, Markdown, MarkdownHtml};
+ use super::{LangString, Markdown, MarkdownHtml, MarkdownOutputStyle};
use super::plain_summary_line;
use html::render::reset_ids;
#[test]
fn issue_17736() {
let markdown = "# title";
- format!("{}", Markdown(markdown));
+ format!("{}", Markdown(markdown, MarkdownOutputStyle::Fancy));
reset_ids(true);
}
#[test]
fn test_header() {
fn t(input: &str, expect: &str) {
- let output = format!("{}", Markdown(input));
- assert_eq!(output, expect);
+ let output = format!("{}", Markdown(input, MarkdownOutputStyle::Fancy));
+ assert_eq!(output, expect, "original: {}", input);
reset_ids(true);
}
- t("# Foo bar", "\n<h1 id='foo-bar' class='section-header'>\
- <a href='#foo-bar'>Foo bar</a></h1>");
- t("## Foo-bar_baz qux", "\n<h2 id='foo-bar_baz-qux' class=\'section-\
- header'><a href='#foo-bar_baz-qux'>Foo-bar_baz qux</a></h2>");
+ t("# Foo bar", "<h1 id=\"foo-bar\" class=\"section-header\">\
+ <a href=\"#foo-bar\">Foo bar</a></h1>");
+ t("## Foo-bar_baz qux", "<h2 id=\"foo-bar_baz-qux\" class=\"section-\
+ header\"><a href=\"#foo-bar_baz-qux\">Foo-bar_baz qux</a></h2>");
t("### **Foo** *bar* baz!?!& -_qux_-%",
- "\n<h3 id='foo-bar-baz--_qux_-' class='section-header'>\
- <a href='#foo-bar-baz--_qux_-'><strong>Foo</strong> \
- <em>bar</em> baz!?!& -_qux_-%</a></h3>");
- t("####**Foo?** & \\*bar?!* _`baz`_ ❤ #qux",
- "\n<h4 id='foo--bar--baz--qux' class='section-header'>\
- <a href='#foo--bar--baz--qux'><strong>Foo?</strong> & *bar?!* \
+ "<h3 id=\"foo-bar-baz--qux-\" class=\"section-header\">\
+ <a href=\"#foo-bar-baz--qux-\"><strong>Foo</strong> \
+ <em>bar</em> baz!?!& -<em>qux</em>-%</a></h3>");
+ t("#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux",
+ "<h4 id=\"foo--bar--baz--qux\" class=\"section-header\">\
+ <a href=\"#foo--bar--baz--qux\"><strong>Foo?</strong> & *bar?!* \
<em><code>baz</code></em> ❤ #qux</a></h4>");
}
#[test]
fn test_header_ids_multiple_blocks() {
fn t(input: &str, expect: &str) {
- let output = format!("{}", Markdown(input));
- assert_eq!(output, expect);
+ let output = format!("{}", Markdown(input, MarkdownOutputStyle::Fancy));
+ assert_eq!(output, expect, "original: {}", input);
}
let test = || {
- t("# Example", "\n<h1 id='example' class='section-header'>\
- <a href='#example'>Example</a></h1>");
- t("# Panics", "\n<h1 id='panics' class='section-header'>\
- <a href='#panics'>Panics</a></h1>");
- t("# Example", "\n<h1 id='example-1' class='section-header'>\
- <a href='#example-1'>Example</a></h1>");
- t("# Main", "\n<h1 id='main-1' class='section-header'>\
- <a href='#main-1'>Main</a></h1>");
- t("# Example", "\n<h1 id='example-2' class='section-header'>\
- <a href='#example-2'>Example</a></h1>");
- t("# Panics", "\n<h1 id='panics-1' class='section-header'>\
- <a href='#panics-1'>Panics</a></h1>");
+ t("# Example", "<h1 id=\"example\" class=\"section-header\">\
+ <a href=\"#example\">Example</a></h1>");
+ t("# Panics", "<h1 id=\"panics\" class=\"section-header\">\
+ <a href=\"#panics\">Panics</a></h1>");
+ t("# Example", "<h1 id=\"example-1\" class=\"section-header\">\
+ <a href=\"#example-1\">Example</a></h1>");
+ t("# Main", "<h1 id=\"main-1\" class=\"section-header\">\
+ <a href=\"#main-1\">Main</a></h1>");
+ t("# Example", "<h1 id=\"example-2\" class=\"section-header\">\
+ <a href=\"#example-2\">Example</a></h1>");
+ t("# Panics", "<h1 id=\"panics-1\" class=\"section-header\">\
+ <a href=\"#panics-1\">Panics</a></h1>");
};
test();
reset_ids(true);
fn test_plain_summary_line() {
fn t(input: &str, expect: &str) {
let output = plain_summary_line(input);
- assert_eq!(output, expect);
+ assert_eq!(output, expect, "original: {}", input);
}
t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)");
fn test_markdown_html_escape() {
fn t(input: &str, expect: &str) {
let output = format!("{}", MarkdownHtml(input));
- assert_eq!(output, expect);
+ assert_eq!(output, expect, "original: {}", input);
}
- t("`Struct<'a, T>`", "<p><code>Struct<'a, T></code></p>\n");
- t("Struct<'a, T>", "<p>Struct<'a, T></p>\n");
+ t("`Struct<'a, T>`", "<p><code>Struct<'a, T></code></p>");
+ t("Struct<'a, T>", "<p>Struct<'a, T></p>");
}
}
use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
use html::format::fmt_impl_for_trait_page;
use html::item_type::ItemType;
-use html::markdown::{self, Markdown, MarkdownHtml};
+use html::markdown::{self, Markdown, MarkdownHtml, MarkdownOutputStyle};
use html::{highlight, layout};
/// A pair of name and its optional document.
} else {
format!("{}", &plain_summary_line(Some(s)))
};
- write!(w, "<div class='docblock'>{}</div>", Markdown(&markdown))?;
+ write!(w, "<div class='docblock'>{}</div>",
+ Markdown(&markdown, MarkdownOutputStyle::Fancy))?;
}
Ok(())
}
fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
if let Some(s) = get_doc_value(item) {
write!(w, "<div class='docblock'>{}</div>",
- Markdown(&format!("{}{}", md_render_assoc_item(item), s)))?;
+ Markdown(&format!("{}{}", md_render_assoc_item(item), s),
+ MarkdownOutputStyle::Fancy))?;
}
Ok(())
}
</tr>",
name = *myitem.name.as_ref().unwrap(),
stab_docs = stab_docs,
- docs = shorter(Some(&Markdown(doc_value).to_string())),
+ docs = shorter(Some(&Markdown(doc_value,
+ MarkdownOutputStyle::Compact).to_string())),
class = myitem.type_(),
stab = myitem.stability_class().unwrap_or("".to_string()),
unsafety_flag = unsafety_flag,
if attr.is_word() {
Some(format!("{}", name))
} else if let Some(v) = attr.value_str() {
- Some(format!("{} = {:?}", name, &v.as_str()[..]))
+ Some(format!("{} = {:?}", name, v.as_str()))
} else if let Some(values) = attr.meta_item_list() {
let display: Vec<_> = values.iter().filter_map(|attr| {
attr.meta_item().and_then(|mi| render_attribute(mi))
for attr in &it.attrs.other_attrs {
let name = attr.name().unwrap();
- if !ATTRIBUTE_WHITELIST.contains(&&name.as_str()[..]) {
+ if !ATTRIBUTE_WHITELIST.contains(&&*name.as_str()) {
continue;
}
if let Some(s) = render_attribute(&attr.meta().unwrap()) {
write!(w, "</span>")?;
write!(w, "</h3>\n")?;
if let Some(ref dox) = i.impl_item.doc_value() {
- write!(w, "<div class='docblock'>{}</div>", Markdown(dox))?;
+ write!(w, "<div class='docblock'>{}</div>", Markdown(dox, MarkdownOutputStyle::Fancy))?;
}
}
// except according to those terms.
#![crate_name = "rustdoc"]
-#![unstable(feature = "rustdoc", issue = "27812")]
+#![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",
extern crate arena;
extern crate getopts;
+extern crate env_logger;
extern crate libc;
extern crate rustc;
extern crate rustc_const_eval;
extern crate std_unicode;
#[macro_use] extern crate log;
extern crate rustc_errors as errors;
+extern crate pulldown_cmark;
extern crate serialize as rustc_serialize; // used by deriving
pub fn main() {
const STACK_SIZE: usize = 32_000_000; // 32MB
+ env_logger::init().unwrap();
let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || {
let s = env::args().collect::<Vec<_>>();
main_args(&s)
use html::render::reset_ids;
use html::escape::Escape;
use html::markdown;
-use html::markdown::{Markdown, MarkdownWithToc, find_testable_code};
+use html::markdown::{Markdown, MarkdownWithToc, MarkdownOutputStyle, find_testable_code};
use test::{TestOptions, Collector};
-/// Separate any lines at the start of the file that begin with `%`.
+/// Separate any lines at the start of the file that begin with `# ` or `%`.
fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
let mut metadata = Vec::new();
let mut count = 0;
+
for line in s.lines() {
- if line.starts_with("%") {
- // remove %<whitespace>
+ if line.starts_with("# ") || line.starts_with("%") {
+ // trim the whitespace after the symbol
metadata.push(line[1..].trim_left());
count += line.len() + 1;
} else {
return (metadata, &s[count..]);
}
}
- // if we're here, then all lines were metadata % lines.
+
+ // if we're here, then all lines were metadata `# ` or `%` lines.
(metadata, "")
}
if metadata.is_empty() {
let _ = writeln!(
&mut io::stderr(),
- "rustdoc: invalid markdown file: expecting initial line with `% ...TITLE...`"
+ "rustdoc: invalid markdown file: no initial lines starting with `# ` or `%`"
);
return 5;
}
let rendered = if include_toc {
format!("{}", MarkdownWithToc(text))
} else {
- format!("{}", Markdown(text))
+ format!("{}", Markdown(text, MarkdownOutputStyle::Fancy))
};
let err = write!(
self.visit_item(item, None, &mut om);
}
self.inside_public_path = orig_inside_public_path;
- if let Some(exports) = self.cx.export_map.get(&id) {
+ if let Some(exports) = self.cx.tcx.export_map.get(&id) {
for export in exports {
if let Def::Macro(def_id, ..) = export.def {
if def_id.krate == LOCAL_CRATE {
use ops::Range;
use iter::FusedIterator;
-/// Extension methods for ASCII-subset only operations on string slices.
+/// Extension methods for ASCII-subset only operations.
///
/// Be aware that operations on seemingly non-ASCII characters can sometimes
/// have unexpected results. Consider this example:
///
/// let ascii = 'a';
/// let utf8 = '❤';
+ /// let int_ascii = 97;
///
/// assert!(ascii.is_ascii());
/// assert!(!utf8.is_ascii());
+ /// assert!(int_ascii.is_ascii());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn is_ascii(&self) -> bool;
- /// Makes a copy of the string in ASCII upper case.
+ /// Makes a copy of the value in its ASCII upper case equivalent.
///
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged.
///
- /// To uppercase the string in-place, use [`make_ascii_uppercase`].
+ /// To uppercase the value in-place, use [`make_ascii_uppercase`].
///
/// To uppercase ASCII characters in addition to non-ASCII characters, use
/// [`str::to_uppercase`].
///
/// let ascii = 'a';
/// let utf8 = '❤';
+ /// let int_ascii = 97;
///
/// assert_eq!('A', ascii.to_ascii_uppercase());
/// assert_eq!('❤', utf8.to_ascii_uppercase());
+ /// assert_eq!(65, int_ascii.to_ascii_uppercase());
/// ```
///
/// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
#[stable(feature = "rust1", since = "1.0.0")]
fn to_ascii_uppercase(&self) -> Self::Owned;
- /// Makes a copy of the string in ASCII lower case.
+ /// Makes a copy of the value in its ASCII lower case equivalent.
///
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
/// but non-ASCII letters are unchanged.
///
- /// To lowercase the string in-place, use [`make_ascii_lowercase`].
+ /// To lowercase the value in-place, use [`make_ascii_lowercase`].
///
/// To lowercase ASCII characters in addition to non-ASCII characters, use
/// [`str::to_lowercase`].
///
/// let ascii = 'A';
/// let utf8 = '❤';
+ /// let int_ascii = 65;
///
/// assert_eq!('a', ascii.to_ascii_lowercase());
/// assert_eq!('❤', utf8.to_ascii_lowercase());
+ /// assert_eq!(97, int_ascii.to_ascii_lowercase());
/// ```
///
/// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
#[stable(feature = "rust1", since = "1.0.0")]
fn to_ascii_lowercase(&self) -> Self::Owned;
- /// Checks that two strings are an ASCII case-insensitive match.
+ /// Checks that two values are an ASCII case-insensitive match.
///
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
- /// but without allocating and copying temporary strings.
+ /// but without allocating and copying temporaries.
///
/// # Examples
///
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged.
///
- /// To return a new uppercased string without modifying the existing one, use
+ /// To return a new uppercased value without modifying the existing one, use
/// [`to_ascii_uppercase`].
///
/// # Examples
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
/// but non-ASCII letters are unchanged.
///
- /// To return a new lowercased string without modifying the existing one, use
+ /// To return a new lowercased value without modifying the existing one, use
/// [`to_ascii_lowercase`].
///
/// # Examples
impl<T> Cursor<T> {
/// Creates a new cursor wrapping the provided underlying I/O object.
///
+ /// Cursor initial position is `0` even if underlying object (e.
+ /// g. `Vec`) is not empty. So writing to cursor starts with
+ /// overwriting `Vec` content, not with appending to it.
+ ///
/// # Examples
///
/// ```
/// If an I/O error is encountered then all bytes read so far will be
/// present in `buf` and its length will have been adjusted appropriately.
///
- /// # Examples
- ///
- /// A locked standard input implements `BufRead`. In this example, we'll
- /// read from standard input until we see an `a` byte.
- ///
/// [`fill_buf`]: #tymethod.fill_buf
/// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted
///
- /// ```
- /// use std::io;
- /// use std::io::prelude::*;
+ /// # Examples
///
- /// fn foo() -> io::Result<()> {
- /// let stdin = io::stdin();
- /// let mut stdin = stdin.lock();
- /// let mut buffer = Vec::new();
+ /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
+ /// this example, we use [`Cursor`] to read all the bytes in a byte slice
+ /// in hyphen delimited segments:
///
- /// stdin.read_until(b'a', &mut buffer)?;
+ /// [`Cursor`]: struct.Cursor.html
///
- /// println!("{:?}", buffer);
- /// # Ok(())
- /// # }
+ /// ```
+ /// use std::io::{self, BufRead};
+ ///
+ /// let mut cursor = io::Cursor::new(b"lorem-ipsum");
+ /// let mut buf = vec![];
+ ///
+ /// // cursor is at 'l'
+ /// let num_bytes = cursor.read_until(b'-', &mut buf)
+ /// .expect("reading from cursor won't fail");
+ /// assert_eq!(num_bytes, 6);
+ /// assert_eq!(buf, b"lorem-");
+ /// buf.clear();
+ ///
+ /// // cursor is at 'i'
+ /// let num_bytes = cursor.read_until(b'-', &mut buf)
+ /// .expect("reading from cursor won't fail");
+ /// assert_eq!(num_bytes, 5);
+ /// assert_eq!(buf, b"ipsum");
+ /// buf.clear();
+ ///
+ /// // cursor is at EOF
+ /// let num_bytes = cursor.read_until(b'-', &mut buf)
+ /// .expect("reading from cursor won't fail");
+ /// assert_eq!(num_bytes, 0);
+ /// assert_eq!(buf, b"");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
///
/// # Examples
///
- /// A locked standard input implements `BufRead`. In this example, we'll
- /// read all of the lines from standard input. If we were to do this in
- /// an actual project, the [`lines`] method would be easier, of
- /// course.
+ /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
+ /// this example, we use [`Cursor`] to read all the lines in a byte slice:
///
- /// [`lines`]: #method.lines
- /// [`read_until`]: #method.read_until
+ /// [`Cursor`]: struct.Cursor.html
///
/// ```
- /// use std::io;
- /// use std::io::prelude::*;
- ///
- /// let stdin = io::stdin();
- /// let mut stdin = stdin.lock();
- /// let mut buffer = String::new();
- ///
- /// while stdin.read_line(&mut buffer).unwrap() > 0 {
- /// // work with buffer
- /// println!("{:?}", buffer);
- ///
- /// buffer.clear();
- /// }
+ /// use std::io::{self, BufRead};
+ ///
+ /// let mut cursor = io::Cursor::new(b"foo\nbar");
+ /// let mut buf = String::new();
+ ///
+ /// // cursor is at 'f'
+ /// let num_bytes = cursor.read_line(&mut buf)
+ /// .expect("reading from cursor won't fail");
+ /// assert_eq!(num_bytes, 4);
+ /// assert_eq!(buf, "foo\n");
+ /// buf.clear();
+ ///
+ /// // cursor is at 'b'
+ /// let num_bytes = cursor.read_line(&mut buf)
+ /// .expect("reading from cursor won't fail");
+ /// assert_eq!(num_bytes, 3);
+ /// assert_eq!(buf, "bar");
+ /// buf.clear();
+ ///
+ /// // cursor is at EOF
+ /// let num_bytes = cursor.read_line(&mut buf)
+ /// .expect("reading from cursor won't fail");
+ /// assert_eq!(num_bytes, 0);
+ /// assert_eq!(buf, "");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read_line(&mut self, buf: &mut String) -> Result<usize> {
/// This function will yield errors whenever [`read_until`] would have
/// also yielded an error.
///
- /// # Examples
- ///
- /// A locked standard input implements `BufRead`. In this example, we'll
- /// read some input from standard input, splitting on commas.
- ///
/// [`io::Result`]: type.Result.html
/// [`Vec<u8>`]: ../vec/struct.Vec.html
/// [`read_until`]: #method.read_until
///
+ /// # Examples
+ ///
+ /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
+ /// this example, we use [`Cursor`] to iterate over all hyphen delimited
+ /// segments in a byte slice
+ ///
+ /// [`Cursor`]: struct.Cursor.html
+ ///
/// ```
- /// use std::io;
- /// use std::io::prelude::*;
+ /// use std::io::{self, BufRead};
///
- /// let stdin = io::stdin();
+ /// let cursor = io::Cursor::new(b"lorem-ipsum-dolor");
///
- /// for content in stdin.lock().split(b',') {
- /// println!("{:?}", content.unwrap());
- /// }
+ /// let mut split_iter = cursor.split(b'-').map(|l| l.unwrap());
+ /// assert_eq!(split_iter.next(), Some(b"lorem".to_vec()));
+ /// assert_eq!(split_iter.next(), Some(b"ipsum".to_vec()));
+ /// assert_eq!(split_iter.next(), Some(b"dolor".to_vec()));
+ /// assert_eq!(split_iter.next(), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn split(self, byte: u8) -> Split<Self> where Self: Sized {
///
/// # Examples
///
- /// A locked standard input implements `BufRead`:
+ /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
+ /// this example, we use [`Cursor`] to iterate over all the lines in a byte
+ /// slice.
+ ///
+ /// [`Cursor`]: struct.Cursor.html
///
/// ```
- /// use std::io;
- /// use std::io::prelude::*;
+ /// use std::io::{self, BufRead};
///
- /// let stdin = io::stdin();
+ /// let cursor = io::Cursor::new(b"lorem\nipsum\r\ndolor");
///
- /// for line in stdin.lock().lines() {
- /// println!("{}", line.unwrap());
- /// }
+ /// let mut lines_iter = cursor.lines().map(|l| l.unwrap());
+ /// assert_eq!(lines_iter.next(), Some(String::from("lorem")));
+ /// assert_eq!(lines_iter.next(), Some(String::from("ipsum")));
+ /// assert_eq!(lines_iter.next(), Some(String::from("dolor")));
+ /// assert_eq!(lines_iter.next(), None);
/// ```
///
/// # Errors
use iter;
use slice;
-/// Representation of a socket address for networking applications.
+/// An internet socket address, either IPv4 or IPv6.
///
-/// A socket address can either represent the IPv4 or IPv6 protocol and is
-/// paired with at least a port number as well. Each protocol may have more
-/// specific information about the address available to it as well.
+/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
+/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
+/// [`SocketAddrV6`]'s respective documentation for more details.
+///
+/// [IP address]: ../../std/net/enum.IpAddr.html
+/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+///
+/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.port(), 8080);
+/// assert_eq!(socket.is_ipv4(), true);
+/// ```
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum SocketAddr {
- /// An IPv4 socket address which is a (ip, port) combination.
+ /// An IPv4 socket address.
#[stable(feature = "rust1", since = "1.0.0")]
V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
/// An IPv6 socket address.
V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
}
-/// An IPv4 socket address which is a (ip, port) combination.
+/// An IPv4 socket address.
+///
+/// IPv4 socket addresses consist of an [IPv4 address] and a 16-bit port number, as
+/// stated in [IETF RFC 793].
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
+/// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
+/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv4Addr, SocketAddrV4};
+///
+/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
#[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SocketAddrV4 { inner: c::sockaddr_in }
/// An IPv6 socket address.
+///
+/// IPv6 socket addresses consist of an [Ipv6 address], a 16-bit port number, as well
+/// as fields containing the traffic class, the flow label, and a scope identifier
+/// (see [IETF RFC 2553, Section 3.3] for more details).
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+/// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv6Addr, SocketAddrV6};
+///
+/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+///
+/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
#[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SocketAddrV6 { inner: c::sockaddr_in6 }
impl SocketAddr {
- /// Creates a new socket address from the (ip, port) pair.
+ /// Creates a new socket address from an [IP address] and a port number.
+ ///
+ /// [IP address]: ../../std/net/enum.IpAddr.html
///
/// # Examples
///
}
}
- /// Change the IP address associated with this socket address.
+ /// Changes the IP address associated with this socket address.
///
/// # Examples
///
}
}
- /// Change the port number associated with this socket address.
+ /// Changes the port number associated with this socket address.
///
/// # Examples
///
}
}
- /// Returns true if the IP in this `SocketAddr` is a valid IPv4 address,
- /// false if it's a valid IPv6 address.
+ /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+ /// [IPv4 address], and [`false`] otherwise.
+ ///
+ /// [`true`]: ../../std/primitive.bool.html
+ /// [`false`]: ../../std/primitive.bool.html
+ /// [IP address]: ../../std/net/enum.IpAddr.html
+ /// [IPv4 address]: ../../std/net/enum.IpAddr.html#variant.V4
///
/// # Examples
///
}
}
- /// Returns true if the IP in this `SocketAddr` is a valid IPv6 address,
- /// false if it's a valid IPv4 address.
+ /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+ /// [IPv6 address], and [`false`] otherwise.
+ ///
+ /// [`true`]: ../../std/primitive.bool.html
+ /// [`false`]: ../../std/primitive.bool.html
+ /// [IP address]: ../../std/net/enum.IpAddr.html
+ /// [IPv6 address]: ../../std/net/enum.IpAddr.html#variant.V6
///
/// # Examples
///
}
impl SocketAddrV4 {
- /// Creates a new socket address from the (ip, port) pair.
+ /// Creates a new socket address from an [IPv4 address] and a port number.
+ ///
+ /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
///
/// # Examples
///
}
}
- /// Change the IP address associated with this socket address.
+ /// Changes the IP address associated with this socket address.
///
/// # Examples
///
ntoh(self.inner.sin_port)
}
- /// Change the port number associated with this socket address.
+ /// Changes the port number associated with this socket address.
///
/// # Examples
///
}
impl SocketAddrV6 {
- /// Creates a new socket address from the ip/port/flowinfo/scope_id
- /// components.
+ /// Creates a new socket address from an [IPv6 address], a 16-bit port number,
+ /// and the `flowinfo` and `scope_id` fields.
+ ///
+ /// For more information on the meaning and layout of the `flowinfo` and `scope_id`
+ /// parameters, see [IETF RFC 2553, Section 3.3].
+ ///
+ /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+ /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
///
/// # Examples
///
}
}
- /// Change the IP address associated with this socket address.
+ /// Changes the IP address associated with this socket address.
///
/// # Examples
///
ntoh(self.inner.sin6_port)
}
- /// Change the port number associated with this socket address.
+ /// Changes the port number associated with this socket address.
///
/// # Examples
///
self.inner.sin6_port = hton(new_port);
}
- /// Returns the flow information associated with this address,
- /// corresponding to the `sin6_flowinfo` field in C.
+ /// Returns the flow information associated with this address.
+ ///
+ /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`,
+ /// as specified in [IETF RFC 2553, Section 3.3].
+ /// It combines information about the flow label and the traffic class as specified
+ /// in [IETF RFC 2460], respectively [Section 6] and [Section 7].
+ ///
+ /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+ /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460
+ /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6
+ /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7
///
/// # Examples
///
self.inner.sin6_flowinfo
}
- /// Change the flow information associated with this socket address.
+ /// Changes the flow information associated with this socket address.
+ ///
+ /// See the [`flowinfo`] method's documentation for more details.
+ ///
+ /// [`flowinfo`]: #method.flowinfo
///
/// # Examples
///
self.inner.sin6_flowinfo = new_flowinfo;
}
- /// Returns the scope ID associated with this address,
- /// corresponding to the `sin6_scope_id` field in C.
+ /// Returns the scope ID associated with this address.
+ ///
+ /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`,
+ /// as specified in [IETF RFC 2553, Section 3.3].
+ ///
+ /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
///
/// # Examples
///
/// Change the scope ID associated with this socket address.
///
+ /// See the [`scope_id`] method's documentation for more details.
+ ///
+ /// [`scope_id`]: #method.scope_id
+ ///
/// # Examples
///
/// ```
}
/// A trait for objects which can be converted or resolved to one or more
-/// `SocketAddr` values.
+/// [`SocketAddr`] values.
///
/// This trait is used for generic address resolution when constructing network
/// objects. By default it is implemented for the following types:
///
-/// * `SocketAddr`, `SocketAddrV4`, `SocketAddrV6` - `to_socket_addrs` is
-/// identity function.
+/// * [`SocketAddr`]: [`to_socket_addrs`] is the identity function.
///
-/// * `(IpvNAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially.
+/// * [`SocketAddrV4`], [`SocketAddrV6`], `(`[`IpAddr`]`, `[`u16`]`)`,
+/// `(`[`Ipv4Addr`]`, `[`u16`]`)`, `(`[`Ipv6Addr`]`, `[`u16`]`)`:
+/// [`to_socket_addrs`] constructs a [`SocketAddr`] trivially.
///
-/// * `(&str, u16)` - the string should be either a string representation of an
-/// IP address expected by `FromStr` implementation for `IpvNAddr` or a host
+/// * `(`[`&str`]`, `[`u16`]`)`: the string should be either a string representation
+/// of an [`IpAddr`] address as expected by [`FromStr`] implementation or a host
/// name.
///
-/// * `&str` - the string should be either a string representation of a
-/// `SocketAddr` as expected by its `FromStr` implementation or a string like
-/// `<host_name>:<port>` pair where `<port>` is a `u16` value.
+/// * [`&str`]: the string should be either a string representation of a
+/// [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like
+/// `<host_name>:<port>` pair where `<port>` is a [`u16`] value.
///
-/// This trait allows constructing network objects like `TcpStream` or
-/// `UdpSocket` easily with values of various types for the bind/connection
+/// This trait allows constructing network objects like [`TcpStream`] or
+/// [`UdpSocket`] easily with values of various types for the bind/connection
/// address. It is needed because sometimes one type is more appropriate than
/// the other: for simple uses a string like `"localhost:12345"` is much nicer
-/// than manual construction of the corresponding `SocketAddr`, but sometimes
-/// `SocketAddr` value is *the* main source of the address, and converting it to
+/// than manual construction of the corresponding [`SocketAddr`], but sometimes
+/// [`SocketAddr`] value is *the* main source of the address, and converting it to
/// some other type (e.g. a string) just for it to be converted back to
-/// `SocketAddr` in constructor methods is pointless.
+/// [`SocketAddr`] in constructor methods is pointless.
///
/// Addresses returned by the operating system that are not IP addresses are
/// silently ignored.
///
-/// Some examples:
+/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
+/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
+/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+/// [`&str`]: ../../std/primitive.str.html
+/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+/// [`to_socket_addrs`]: #tymethod.to_socket_addrs
+/// [`UdpSocket`]: ../../std/net/struct.UdpSocket.html
+/// [`u16`]: ../../std/primitive.u16.html
+///
+/// # Examples
///
/// ```no_run
/// use std::net::{SocketAddrV4, TcpStream, UdpSocket, TcpListener, Ipv4Addr};
///
/// Note that this function may block the current thread while resolution is
/// performed.
- ///
- /// # Errors
- ///
- /// Any errors encountered during resolution will be returned as an `Err`.
#[stable(feature = "rust1", since = "1.0.0")]
fn to_socket_addrs(&self) -> io::Result<Self::Iter>;
}
use sys::net::netc as c;
use sys_common::{AsInner, FromInner};
-/// An IP address, either an IPv4 or IPv6 address.
+/// An IP address, either IPv4 or IPv6.
///
-/// # Examples
+/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
+/// respective documentation for more details.
///
-/// Constructing an IPv4 address:
+/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
+/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
///
-/// ```
-/// use std::net::{IpAddr, Ipv4Addr};
+/// # Examples
///
-/// IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
/// ```
+/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
-/// Constructing an IPv6 address:
+/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
+/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
///
-/// ```
-/// use std::net::{IpAddr, Ipv6Addr};
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
+/// assert_eq!("::1".parse(), Ok(localhost_v6));
///
-/// IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+/// assert_eq!(localhost_v4.is_ipv6(), false);
+/// assert_eq!(localhost_v4.is_ipv4(), true);
/// ```
#[stable(feature = "ip_addr", since = "1.7.0")]
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub enum IpAddr {
- /// Representation of an IPv4 address.
+ /// An IPv4 address.
#[stable(feature = "ip_addr", since = "1.7.0")]
V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
- /// Representation of an IPv6 address.
+ /// An IPv6 address.
#[stable(feature = "ip_addr", since = "1.7.0")]
V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
}
-/// Representation of an IPv4 address.
+/// An IPv4 address.
+///
+/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
+/// They are usually represented as four octets.
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
+/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+///
+/// # Textual representation
+///
+/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
+/// notation, divided by `.` (this is called "dot-decimal notation").
+///
+/// [`FromStr`]: ../../std/str/trait.FromStr.html
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv4Addr;
+///
+/// let localhost = Ipv4Addr::new(127, 0, 0, 1);
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// ```
#[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Ipv4Addr {
inner: c::in_addr,
}
-/// Representation of an IPv6 address.
+/// An IPv6 address.
+///
+/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
+/// They are usually represented as eight 16-bit segments.
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+///
+/// # Textual representation
+///
+/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
+/// an IPv6 address in text, but in general, each segments is written in hexadecimal
+/// notation, and segments are separated by `:`. For more information, see
+/// [IETF RFC 5952].
+///
+/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv6Addr;
+///
+/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+/// assert_eq!("::1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// ```
#[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Ipv6Addr {
}
impl IpAddr {
- /// Returns true for the special 'unspecified' address ([IPv4], [IPv6]).
+ /// Returns [`true`] for the special 'unspecified' address.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_unspecified`][IPv4] and
+ /// [`Ipv6Addr::is_unspecified`][IPv6] for more details.
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
}
}
- /// Returns true if this is a loopback address ([IPv4], [IPv6]).
+ /// Returns [`true`] if this is a loopback address.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_loopback`][IPv4] and
+ /// [`Ipv6Addr::is_loopback`][IPv6] for more details.
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
}
}
- /// Returns true if the address appears to be globally routable ([IPv4], [IPv6]).
+ /// Returns [`true`] if the address appears to be globally routable.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_global`][IPv4] and
+ /// [`Ipv6Addr::is_global`][IPv6] for more details.
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
}
}
- /// Returns true if this is a multicast address ([IPv4], [IPv6]).
+ /// Returns [`true`] if this is a multicast address.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_multicast`][IPv4] and
+ /// [`Ipv6Addr::is_multicast`][IPv6] for more details.
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
}
}
- /// Returns true if this address is in a range designated for documentation ([IPv4], [IPv6]).
+ /// Returns [`true`] if this address is in a range designated for documentation.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_documentation`][IPv4] and
+ /// [`Ipv6Addr::is_documentation`][IPv6] for more details.
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
}
}
- /// Returns true if this address is a valid IPv4 address, false if it's a valid IPv6 address.
+ /// Returns [`true`] if this address is an [IPv4 address], and [`false`] otherwise.
+ ///
+ /// [`true`]: ../../std/primitive.bool.html
+ /// [`false`]: ../../std/primitive.bool.html
+ /// [IPv4 address]: #variant.V4
///
/// # Examples
///
}
}
- /// Returns true if this address is a valid IPv6 address, false if it's a valid IPv4 address.
+ /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
+ ///
+ /// [`true`]: ../../std/primitive.bool.html
+ /// [`false`]: ../../std/primitive.bool.html
+ /// [IPv6 address]: #variant.V6
///
/// # Examples
///
[(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
}
- /// Returns true for the special 'unspecified' address (0.0.0.0).
+ /// Returns [`true`] for the special 'unspecified' address (0.0.0.0).
///
/// This property is defined in _UNIX Network Programming, Second Edition_,
/// W. Richard Stevens, p. 891; see also [ip7].
///
/// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
self.inner.s_addr == 0
}
- /// Returns true if this is a loopback address (127.0.0.0/8).
+ /// Returns [`true`] if this is a loopback address (127.0.0.0/8).
///
- /// This property is defined by [RFC 1122].
+ /// This property is defined by [IETF RFC 1122].
///
- /// [RFC 1122]: https://tools.ietf.org/html/rfc1122
+ /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
self.octets()[0] == 127
}
- /// Returns true if this is a private address.
+ /// Returns [`true`] if this is a private address.
///
- /// The private address ranges are defined in [RFC 1918] and include:
+ /// The private address ranges are defined in [IETF RFC 1918] and include:
///
/// - 10.0.0.0/8
/// - 172.16.0.0/12
/// - 192.168.0.0/16
///
- /// [RFC 1918]: https://tools.ietf.org/html/rfc1918
+ /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
}
}
- /// Returns true if the address is link-local (169.254.0.0/16).
+ /// Returns [`true`] if the address is link-local (169.254.0.0/16).
///
- /// This property is defined by [RFC 3927].
+ /// This property is defined by [IETF RFC 3927].
///
- /// [RFC 3927]: https://tools.ietf.org/html/rfc3927
+ /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
self.octets()[0] == 169 && self.octets()[1] == 254
}
- /// Returns true if the address appears to be globally routable.
+ /// Returns [`true`] if the address appears to be globally routable.
/// See [iana-ipv4-special-registry][ipv4-sr].
///
/// The following return false:
/// - the unspecified address (0.0.0.0)
///
/// [ipv4-sr]: http://goo.gl/RaZ7lg
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
!self.is_broadcast() && !self.is_documentation() && !self.is_unspecified()
}
- /// Returns true if this is a multicast address (224.0.0.0/4).
+ /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
///
/// Multicast addresses have a most significant octet between 224 and 239,
- /// and is defined by [RFC 5771].
+ /// and is defined by [IETF RFC 5771].
///
- /// [RFC 5771]: https://tools.ietf.org/html/rfc5771
+ /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
self.octets()[0] >= 224 && self.octets()[0] <= 239
}
- /// Returns true if this is a broadcast address (255.255.255.255).
+ /// Returns [`true`] if this is a broadcast address (255.255.255.255).
///
- /// A broadcast address has all octets set to 255 as defined in [RFC 919].
+ /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
///
- /// [RFC 919]: https://tools.ietf.org/html/rfc919
+ /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
self.octets()[2] == 255 && self.octets()[3] == 255
}
- /// Returns true if this address is in a range designated for documentation.
+ /// Returns [`true`] if this address is in a range designated for documentation.
///
- /// This is defined in [RFC 5737]:
+ /// This is defined in [IETF RFC 5737]:
///
/// - 192.0.2.0/24 (TEST-NET-1)
/// - 198.51.100.0/24 (TEST-NET-2)
/// - 203.0.113.0/24 (TEST-NET-3)
///
- /// [RFC 5737]: https://tools.ietf.org/html/rfc5737
+ /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
}
}
- /// Converts this address to an IPv4-compatible IPv6 address.
+ /// Converts this address to an IPv4-compatible [IPv6 address].
///
/// a.b.c.d becomes ::a.b.c.d
///
+ /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+ ///
/// # Examples
///
/// ```
((self.octets()[2] as u16) << 8) | self.octets()[3] as u16)
}
- /// Converts this address to an IPv4-mapped IPv6 address.
+ /// Converts this address to an IPv4-mapped [IPv6 address].
///
/// a.b.c.d becomes ::ffff:a.b.c.d
///
+ /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+ ///
/// # Examples
///
/// ```
]
}
- /// Returns true for the special 'unspecified' address (::).
+ /// Returns [`true`] for the special 'unspecified' address (::).
///
- /// This property is defined in [RFC 4291].
+ /// This property is defined in [IETF RFC 4291].
///
- /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
}
- /// Returns true if this is a loopback address (::1).
+ /// Returns [`true`] if this is a loopback address (::1).
///
- /// This property is defined in [RFC 4291].
+ /// This property is defined in [IETF RFC 4291].
///
- /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
}
- /// Returns true if the address appears to be globally routable.
+ /// Returns [`true`] if the address appears to be globally routable.
///
- /// The following return false:
+ /// The following return [`false`]:
///
/// - the loopback address
/// - link-local, site-local, and unique local unicast addresses
/// - interface-, link-, realm-, admin- and site-local multicast addresses
///
+ /// [`true`]: ../../std/primitive.bool.html
+ /// [`false`]: ../../std/primitive.bool.html
+ ///
/// # Examples
///
/// ```
}
}
- /// Returns true if this is a unique local address (fc00::/7).
+ /// Returns [`true`] if this is a unique local address (fc00::/7).
///
- /// This property is defined in [RFC 4193].
+ /// This property is defined in [IETF RFC 4193].
///
- /// [RFC 4193]: https://tools.ietf.org/html/rfc4193
+ /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
(self.segments()[0] & 0xfe00) == 0xfc00
}
- /// Returns true if the address is unicast and link-local (fe80::/10).
+ /// Returns [`true`] if the address is unicast and link-local (fe80::/10).
///
- /// This property is defined in [RFC 4291].
+ /// This property is defined in [IETF RFC 4291].
///
- /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
(self.segments()[0] & 0xffc0) == 0xfe80
}
- /// Returns true if this is a deprecated unicast site-local address
+ /// Returns [`true`] if this is a deprecated unicast site-local address
/// (fec0::/10).
///
+ /// [`true`]: ../../std/primitive.bool.html
+ ///
/// # Examples
///
/// ```
(self.segments()[0] & 0xffc0) == 0xfec0
}
- /// Returns true if this is an address reserved for documentation
+ /// Returns [`true`] if this is an address reserved for documentation
/// (2001:db8::/32).
///
- /// This property is defined in [RFC 3849].
+ /// This property is defined in [IETF RFC 3849].
///
- /// [RFC 3849]: https://tools.ietf.org/html/rfc3849
+ /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
}
- /// Returns true if the address is a globally routable unicast address.
+ /// Returns [`true`] if the address is a globally routable unicast address.
///
/// The following return false:
///
/// - the unspecified address
/// - the address range reserved for documentation
///
+ /// [`true`]: ../../std/primitive.bool.html
+ ///
/// # Examples
///
/// ```
}
}
- /// Returns true if this is a multicast address (ff00::/8).
+ /// Returns [`true`] if this is a multicast address (ff00::/8).
+ ///
+ /// This property is defined by [IETF RFC 4291].
///
- /// This property is defined by [RFC 4291].
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [`true`]: ../../std/primitive.bool.html
///
- /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
/// # Examples
///
/// ```
(self.segments()[0] & 0xff00) == 0xff00
}
- /// Converts this address to an IPv4 address. Returns None if this address is
+ /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
/// neither IPv4-compatible or IPv4-mapped.
///
/// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
///
+ /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
+ /// [`None`]: ../../std/option/enum.Option.html#variant.None
+ ///
+ /// # Examples
+ ///
/// ```
/// use std::net::{Ipv4Addr, Ipv6Addr};
///
// except according to those terms.
//! Networking primitives for TCP/UDP communication.
+//!
+//! This module provides networking functionality for the Transmission Control and User
+//! Datagram Protocols, as well as types for IP and socket addresses.
+//!
+//! # Organization
+//!
+//! * [`TcpListener`] and [`TcpStream`] provide functionality for communication over TCP
+//! * [`UdpSocket`] provides functionality for communication over UDP
+//! * [`IpAddr`] represents IP addresses of either IPv4 or IPv6; [`Ipv4Addr`] and
+//! [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses
+//! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`]
+//! and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses
+//! * [`ToSocketAddrs`] is a trait that used for generic address resolution when interacting
+//! with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`]
+//! * Other types are return or parameter types for various methods in this module
+//!
+//! [`IpAddr`]: ../../std/net/enum.IpAddr.html
+//! [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
+//! [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
+//! [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+//! [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+//! [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+//! [`TcpListener`]: ../../std/net/struct.TcpListener.html
+//! [`TcpStream`]: ../../std/net/struct.TcpStream.html
+//! [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
+//! [`UdpSocket`]: ../../std/net/struct.UdpSocket.html
#![stable(feature = "rust1", since = "1.0.0")]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Shutdown {
- /// Indicates that the reading portion of this stream/socket should be shut
- /// down. All currently blocked and future reads will return `Ok(0)`.
+ /// The reading portion of the [`TcpStream`] should be shut down.
+ ///
+ /// All currently blocked and future [reads] will return [`Ok(0)`].
+ ///
+ /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+ /// [reads]: ../../std/io/trait.Read.html
+ /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
#[stable(feature = "rust1", since = "1.0.0")]
Read,
- /// Indicates that the writing portion of this stream/socket should be shut
- /// down. All currently blocked and future writes will return an error.
+ /// The writing portion of the [`TcpStream`] should be shut down.
+ ///
+ /// All currently blocked and future [writes] will return an error.
+ ///
+ /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+ /// [writes]: ../../std/io/trait.Write.html
#[stable(feature = "rust1", since = "1.0.0")]
Write,
- /// Shut down both the reading and writing portions of this stream.
+ /// Both the reading and the writing portions of the [`TcpStream`] should be shut down.
+ ///
+ /// See [`Shutdown::Read`] and [`Shutdown::Write`] for more information.
///
- /// See `Shutdown::Read` and `Shutdown::Write` for more information.
+ /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+ /// [`Shutdown::Read`]: #variant.Read
+ /// [`Shutdown::Write`]: #variant.Write
#[stable(feature = "rust1", since = "1.0.0")]
Both,
}
}
}
-/// An error returned when parsing an IP address or a socket address.
+/// An error which can be returned when parsing an IP address or a socket address.
+///
+/// This error is used as the error type for the [`FromStr`] implementation for
+/// [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`], [`SocketAddr`], [`SocketAddrV4`], and
+/// [`SocketAddrV6`].
+///
+/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
+/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
+/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddrParseError(());
use sys_common::{AsInner, FromInner, IntoInner};
use time::Duration;
-/// A structure which represents a TCP stream between a local socket and a
-/// remote socket.
+/// A TCP stream between a local and a remote socket.
///
-/// The socket will be closed when the value is dropped.
+/// After creating a `TcpStream` by either [`connect`]ing to a remote host or
+/// [`accept`]ing a connection on a [`TcpListener`], data can be transmitted
+/// by [reading] and [writing] to it.
+///
+/// The connection will be closed when the value is dropped. The reading and writing
+/// portions of the connection can also be shut down individually with the [`shutdown`]
+/// method.
+///
+/// The Transmission Control Protocol is specified in [IETF RFC 793].
+///
+/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
+/// [`connect`]: #method.connect
+/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
+/// [reading]: ../../std/io/trait.Read.html
+/// [`shutdown`]: #method.shutdown
+/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
+/// [writing]: ../../std/io/trait.Write.html
///
/// # Examples
///
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TcpStream(net_imp::TcpStream);
-/// A structure representing a socket server.
+/// A TCP socket server, listening for connections.
+///
+/// After creating a `TcpListener` by [`bind`]ing it to a socket address, it listens
+/// for incoming TCP connections. These can be accepted by calling [`accept`] or by
+/// iterating over the [`Incoming`] iterator returned by [`incoming`].
+///
+/// The socket will be closed when the value is dropped.
+///
+/// The Transmission Control Protocol is specified in [IETF RFC 793].
+///
+/// [`accept`]: #method.accept
+/// [`bind`]: #method.bind
+/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
+/// [`Incoming`]: ../../std/net/struct.Incoming.html
+/// [`incoming`]: #method.incoming
///
/// # Examples
///
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TcpListener(net_imp::TcpListener);
-/// An infinite iterator over the connections from a `TcpListener`.
-///
-/// This iterator will infinitely yield [`Some`] of the accepted connections. It
-/// is equivalent to calling `accept` in a loop.
+/// An iterator that infinitely [`accept`]s connections on a [`TcpListener`].
///
/// This `struct` is created by the [`incoming`] method on [`TcpListener`].
+/// See its documentation for more.
///
-/// [`Some`]: ../../std/option/enum.Option.html#variant.Some
-/// [`incoming`]: struct.TcpListener.html#method.incoming
-/// [`TcpListener`]: struct.TcpListener.html
+/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
+/// [`incoming`]: ../../std/net/struct.TcpListener.html#method.incoming
+/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Incoming<'a> { listener: &'a TcpListener }
/// Opens a TCP connection to a remote host.
///
/// `addr` is an address of the remote host. Anything which implements
- /// `ToSocketAddrs` trait can be supplied for the address; see this trait
+ /// [`ToSocketAddrs`] trait can be supplied for the address; see this trait
/// documentation for concrete examples.
- /// In case `ToSocketAddrs::to_socket_addrs()` returns more than one entry,
+ /// In case [`ToSocketAddrs::to_socket_addrs()`] returns more than one entry,
/// then the first valid and reachable address is used.
///
+ /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
+ /// [`ToSocketAddrs::to_socket_addrs()`]:
+ /// ../../std/net/trait.ToSocketAddrs.html#tymethod.to_socket_addrs
+ ///
/// # Examples
///
/// ```no_run
///
/// Binding with a port number of 0 will request that the OS assigns a port
/// to this listener. The port allocated can be queried via the
- /// `local_addr` method.
+ /// [`local_addr`] method.
///
- /// The address type can be any implementor of `ToSocketAddrs` trait. See
+ /// The address type can be any implementor of [`ToSocketAddrs`] trait. See
/// its documentation for concrete examples.
///
+ /// [`local_addr`]: #method.local_addr
+ /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
+ ///
/// # Examples
///
/// ```no_run
/// Creates a new independently owned handle to the underlying socket.
///
- /// The returned `TcpListener` is a reference to the same socket that this
+ /// The returned [`TcpListener`] is a reference to the same socket that this
/// object references. Both handles can be used to accept incoming
/// connections and options set on one listener will affect the other.
///
+ /// [`TcpListener`]: ../../std/net/struct.TcpListener.html
+ ///
/// # Examples
///
/// ```no_run
/// Accept a new incoming connection from this listener.
///
/// This function will block the calling thread until a new TCP connection
- /// is established. When established, the corresponding `TcpStream` and the
+ /// is established. When established, the corresponding [`TcpStream`] and the
/// remote peer's address will be returned.
///
+ /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+ ///
/// # Examples
///
/// ```no_run
/// listener.
///
/// The returned iterator will never return [`None`] and will also not yield
- /// the peer's [`SocketAddr`] structure.
+ /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
+ /// calling [`accept`] in a loop.
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+ /// [`accept`]: #method.accept
///
/// # Examples
///
use sys_common::{AsInner, FromInner, IntoInner};
use time::Duration;
-/// A User Datagram Protocol socket.
+/// A UDP socket.
///
-/// This is an implementation of a bound UDP socket. This supports both IPv4 and
-/// IPv6 addresses, and there is no corresponding notion of a server because UDP
-/// is a datagram protocol.
+/// After creating a `UdpSocket` by [`bind`]ing it to a socket address, data can be
+/// [sent to] and [received from] any other socket address.
+///
+/// Although UDP is a connectionless protocol, this implementation provides an interface
+/// to set an address where data should be sent and received from. After setting a remote
+/// address with [`connect`], data can be sent to and received from that address with
+/// [`send`] and [`recv`].
+///
+/// As stated in the User Datagram Protocol's specification in [IETF RFC 768], UDP is
+/// an unordered, unreliable protocol; refer to [`TcpListener`] and [`TcpStream`] for TCP
+/// primitives.
+///
+/// [`bind`]: #method.bind
+/// [`connect`]: #method.connect
+/// [IETF RFC 768]: https://tools.ietf.org/html/rfc768
+/// [`recv`]: #method.recv
+/// [received from]: #method.recv_from
+/// [`send`]: #method.send
+/// [sent to]: #method.send_to
+/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
+/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
///
/// # Examples
///
/// Receives data on the socket from the remote address to which it is
/// connected.
///
- /// The `connect` method will connect this socket to a remote address. This
+ /// The [`connect`] method will connect this socket to a remote address. This
/// method will fail if the socket is not connected.
///
+ /// [`connect`]: #method.connect
+ ///
/// # Examples
///
/// ```no_run
use fmt;
-#[cfg(any(target_os = "android",
- target_os = "emscripten",
+#[cfg(any(target_os = "emscripten",
all(target_os = "linux", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "s390x")),
+ all(target_os = "android", any(target_arch = "aarch64",
+ target_arch = "arm")),
all(target_os = "fuchsia", target_arch = "aarch64")))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
-#[cfg(not(any(target_os = "android",
- target_os = "emscripten",
+#[cfg(not(any(target_os = "emscripten",
all(target_os = "linux", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "s390x")),
+ all(target_os = "android", any(target_arch = "aarch64",
+ target_arch = "arm")),
all(target_os = "fuchsia", target_arch = "aarch64"))))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
let (addr, len) = sockaddr_un(path)?;
- cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len))?;
+ cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?;
cvt(libc::listen(*inner.as_inner(), 128))?;
Ok(UnixListener(inner))
let socket = UnixDatagram::unbound()?;
let (addr, len) = sockaddr_un(path)?;
- cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len))?;
+ cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?;
Ok(socket)
}
}
}
+ // Android with api less than 21 define sig* functions inline, so it is not
+ // available for dynamic link. Implementing sigemptyset and sigaddset allow us
+ // to support older Android version (independent of libc version).
+ // The following implementations are based on https://git.io/vSkNf
+
#[cfg(not(target_os = "android"))]
extern {
+ #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")]
+ fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int;
+
#[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")]
fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int;
}
+ #[cfg(target_os = "android")]
+ unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
+ libc::memset(set as *mut _, 0, mem::size_of::<libc::sigset_t>());
+ return 0;
+ }
+
#[cfg(target_os = "android")]
unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
use slice;
let mut set: libc::sigset_t = mem::uninitialized();
let mut old_set: libc::sigset_t = mem::uninitialized();
- t!(cvt(libc::sigemptyset(&mut set)));
+ t!(cvt(sigemptyset(&mut set)));
t!(cvt(sigaddset(&mut set, libc::SIGINT)));
t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set)));
// need to clean things up now to avoid confusing the program
// we're about to run.
let mut set: libc::sigset_t = mem::uninitialized();
- t!(cvt(libc::sigemptyset(&mut set)));
+ if cfg!(target_os = "android") {
+ // Implementing sigemptyset allow us to support older Android
+ // versions. See the comment about Android and sig* functions in
+ // process_common.rs
+ libc::memset(&mut set as *mut _ as *mut _,
+ 0,
+ mem::size_of::<libc::sigset_t>());
+ } else {
+ t!(cvt(libc::sigemptyset(&mut set)));
+ }
t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set,
ptr::null_mut())));
let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
// INVALID_HANDLE_VALUE.
Stdio::Inherit => {
match stdio::get(stdio_id) {
- Ok(io) => io.handle().duplicate(0, true,
- c::DUPLICATE_SAME_ACCESS),
+ Ok(io) => {
+ let io = Handle::new(io.handle());
+ let ret = io.duplicate(0, true,
+ c::DUPLICATE_SAME_ACCESS);
+ io.into_raw();
+ return ret
+ }
Err(..) => Ok(Handle::new(c::INVALID_HANDLE_VALUE)),
}
}
use sys::handle::Handle;
use sys_common::io::read_to_end_uninitialized;
-pub struct NoClose(Option<Handle>);
-
pub enum Output {
- Console(NoClose),
- Pipe(NoClose),
+ Console(c::HANDLE),
+ Pipe(c::HANDLE),
}
pub struct Stdin {
- handle: Output,
utf8: Mutex<io::Cursor<Vec<u8>>>,
}
-pub struct Stdout(Output);
-pub struct Stderr(Output);
+pub struct Stdout;
+pub struct Stderr;
pub fn get(handle: c::DWORD) -> io::Result<Output> {
let handle = unsafe { c::GetStdHandle(handle) };
if handle == c::INVALID_HANDLE_VALUE {
Err(io::Error::last_os_error())
} else if handle.is_null() {
- Err(io::Error::new(io::ErrorKind::Other,
- "no stdio handle available for this process"))
+ Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32))
} else {
- let ret = NoClose::new(handle);
let mut out = 0;
match unsafe { c::GetConsoleMode(handle, &mut out) } {
- 0 => Ok(Output::Pipe(ret)),
- _ => Ok(Output::Console(ret)),
+ 0 => Ok(Output::Pipe(handle)),
+ _ => Ok(Output::Console(handle)),
}
}
}
-fn write(out: &Output, data: &[u8]) -> io::Result<usize> {
- let handle = match *out {
- Output::Console(ref c) => c.get().raw(),
- Output::Pipe(ref p) => return p.get().write(data),
+fn write(handle: c::DWORD, data: &[u8]) -> io::Result<usize> {
+ let handle = match try!(get(handle)) {
+ Output::Console(c) => c,
+ Output::Pipe(p) => {
+ let handle = Handle::new(p);
+ let ret = handle.write(data);
+ handle.into_raw();
+ return ret
+ }
};
+
// As with stdin on windows, stdout often can't handle writes of large
// sizes. For an example, see #14940. For this reason, don't try to
// write the entire output buffer on windows.
impl Stdin {
pub fn new() -> io::Result<Stdin> {
- get(c::STD_INPUT_HANDLE).map(|handle| {
- Stdin {
- handle: handle,
- utf8: Mutex::new(Cursor::new(Vec::new())),
- }
+ Ok(Stdin {
+ utf8: Mutex::new(Cursor::new(Vec::new())),
})
}
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
- let handle = match self.handle {
- Output::Console(ref c) => c.get().raw(),
- Output::Pipe(ref p) => return p.get().read(buf),
+ let handle = match try!(get(c::STD_INPUT_HANDLE)) {
+ Output::Console(c) => c,
+ Output::Pipe(p) => {
+ let handle = Handle::new(p);
+ let ret = handle.read(buf);
+ handle.into_raw();
+ return ret
+ }
};
let mut utf8 = self.utf8.lock().unwrap();
// Read more if the buffer is empty
Ok(utf8) => utf8.into_bytes(),
Err(..) => return Err(invalid_encoding()),
};
- if let Output::Console(_) = self.handle {
- if let Some(&last_byte) = data.last() {
- if last_byte == CTRL_Z {
- data.pop();
- }
+ if let Some(&last_byte) = data.last() {
+ if last_byte == CTRL_Z {
+ data.pop();
}
}
*utf8 = Cursor::new(data);
impl Stdout {
pub fn new() -> io::Result<Stdout> {
- get(c::STD_OUTPUT_HANDLE).map(Stdout)
+ Ok(Stdout)
}
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
- write(&self.0, data)
+ write(c::STD_OUTPUT_HANDLE, data)
}
pub fn flush(&self) -> io::Result<()> {
impl Stderr {
pub fn new() -> io::Result<Stderr> {
- get(c::STD_ERROR_HANDLE).map(Stderr)
+ Ok(Stderr)
}
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
- write(&self.0, data)
+ write(c::STD_ERROR_HANDLE, data)
}
pub fn flush(&self) -> io::Result<()> {
}
}
-impl NoClose {
- fn new(handle: c::HANDLE) -> NoClose {
- NoClose(Some(Handle::new(handle)))
- }
-
- fn get(&self) -> &Handle { self.0.as_ref().unwrap() }
-}
-
-impl Drop for NoClose {
- fn drop(&mut self) {
- self.0.take().unwrap().into_raw();
- }
-}
-
impl Output {
- pub fn handle(&self) -> &Handle {
- let nc = match *self {
- Output::Console(ref c) => c,
- Output::Pipe(ref c) => c,
- };
- nc.0.as_ref().unwrap()
+ pub fn handle(&self) -> c::HANDLE {
+ match *self {
+ Output::Console(c) => c,
+ Output::Pipe(c) => c,
+ }
}
}
// Bind our new socket
let (addrp, len) = addr.into_inner();
- cvt(unsafe { c::bind(*sock.as_inner(), addrp, len) })?;
+ cvt(unsafe { c::bind(*sock.as_inner(), addrp, len as _) })?;
// Start listening
cvt(unsafe { c::listen(*sock.as_inner(), 128) })?;
let sock = Socket::new(addr, c::SOCK_DGRAM)?;
let (addrp, len) = addr.into_inner();
- cvt(unsafe { c::bind(*sock.as_inner(), addrp, len) })?;
+ cvt(unsafe { c::bind(*sock.as_inner(), addrp, len as _) })?;
Ok(UdpSocket { inner: sock })
}
/// Returns an iterator that yields the uppercase equivalent of a `char`
/// as one or more `char`s.
///
- /// If a character does not have a uppercase equivalent, the same character
+ /// If a character does not have an uppercase equivalent, the same character
/// will be returned back by the iterator.
///
/// This performs complex unconditional mappings with no tailoring: it maps
- /// one Unicode character to its lowercase equivalent according to the
+ /// one Unicode character to its uppercase equivalent according to the
/// [Unicode database] and the additional complex mappings
/// [`SpecialCasing.txt`]. Conditional mappings (based on context or
/// language) are not considered here.
[dependencies]
serialize = { path = "../libserialize" }
-log = { path = "../liblog" }
+log = "0.3"
rustc_bitflags = { path = "../librustc_bitflags" }
syntax_pos = { path = "../libsyntax_pos" }
rustc_errors = { path = "../librustc_errors" }
impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
match item.node {
- ast::ItemKind::Mac(ref mac) if !mac.node.path.segments.is_empty() => {}
ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
+ ast::ItemKind::MacroDef(_) => return SmallVector::one(item),
_ => {}
}
};
let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), false);
p.root_module_name = cx.current_expansion.module.mod_path.last()
- .map(|id| (*id.name.as_str()).to_owned());
+ .map(|id| id.name.as_str().to_string());
p.check_unknown_macro_variable();
// Let the context choose how to interpret the result.
impl GatedCfg {
pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
- let name = &*cfg.name().as_str();
+ let name = cfg.name().as_str();
GATED_CFGS.iter()
.position(|info| info.0 == name)
.map(|idx| {
impl<'a> Context<'a> {
fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
debug!("check_attribute(attr = {:?})", attr);
- let name = unwrap_or!(attr.name(), return);
-
+ let name = unwrap_or!(attr.name(), return).as_str();
for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
if name == n {
if let &Gated(_, ref name, ref desc, ref has_feature) = gateage {
return;
}
}
- if name.as_str().starts_with("rustc_") {
+ if name.starts_with("rustc_") {
gate_feature!(self, rustc_attrs, attr.span,
"unless otherwise specified, attributes \
with the prefix `rustc_` \
are reserved for internal compiler diagnostics");
- } else if name.as_str().starts_with("derive_") {
+ } else if name.starts_with("derive_") {
gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
} else if !attr::is_known(attr) {
// Only run the custom attribute lint during regular
fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") {
- self.directory.path.push(&*path.as_str());
+ self.directory.path.push(&path.as_str());
self.directory.ownership = DirectoryOwnership::Owned;
} else {
- self.directory.path.push(&*id.name.as_str());
+ self.directory.path.push(&id.name.as_str());
}
}
pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> {
- attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&*d.as_str()))
+ attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str()))
}
/// Returns either a path to a module, or .
}
}
-impl<'a> PartialEq<&'a str> for Symbol {
- fn eq(&self, other: &&str) -> bool {
- *self.as_str() == **other
+impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
+ fn eq(&self, other: &T) -> bool {
+ self.as_str() == other.deref()
}
}
/// destroyed. In particular, they must not access string contents. This can
/// be fixed in the future by just leaking all strings until thread death
/// somehow.
-#[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
+#[derive(Clone, Hash, PartialOrd, Eq, Ord)]
pub struct InternedString {
string: &'static str,
}
+impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
+ fn as_ref(&self) -> &U {
+ self.string.as_ref()
+ }
+}
+
+impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
+ fn eq(&self, other: &T) -> bool {
+ self.string == other.deref()
+ }
+}
+
+impl ::std::cmp::PartialEq<InternedString> for str {
+ fn eq(&self, other: &InternedString) -> bool {
+ self == other.string
+ }
+}
+
+impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
+ fn eq(&self, other: &InternedString) -> bool {
+ *self == other.string
+ }
+}
+
+impl ::std::cmp::PartialEq<InternedString> for String {
+ fn eq(&self, other: &InternedString) -> bool {
+ self == other.string
+ }
+}
+
+impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
+ fn eq(&self, other: &InternedString) -> bool {
+ *self == other.string
+ }
+}
+
impl !Send for InternedString { }
impl ::std::ops::Deref for InternedString {
fn is_test_crate(krate: &ast::Crate) -> bool {
match attr::find_crate_name(&krate.attrs) {
- Some(s) if "test" == &*s.as_str() => true,
+ Some(s) if "test" == s.as_str() => true,
_ => false
}
}
[dependencies]
fmt_macros = { path = "../libfmt_macros" }
-log = { path = "../liblog" }
+log = "0.3"
proc_macro = { path = "../libproc_macro" }
rustc_errors = { path = "../librustc_errors" }
syntax = { path = "../libsyntax" }
+++ /dev/null
-Subproject commit da282f1bb7277b4d30fa1599ee29ad8eb4dd2a92
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(rustdoc)]
+#![feature(rustc_private)]
extern crate rustdoc;
--- /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.
+
+// aux-build:two_macros.rs
+
+#![feature(use_extern_macros)]
+
+mod foo {
+ extern crate two_macros;
+ pub use self::two_macros::m as panic;
+}
+
+mod m1 {
+ use foo::panic; // ok
+ fn f() { panic!(); }
+}
+
+mod m2 {
+ use foo::*; //~ NOTE `panic` could refer to the name imported here
+ fn f() { panic!(); } //~ ERROR ambiguous
+ //~| NOTE `panic` is also a builtin macro
+ //~| NOTE consider adding an explicit import of `panic` to disambiguate
+}
+
+mod m3 {
+ ::two_macros::m!(use foo::panic;); //~ NOTE `panic` could refer to the name imported here
+ //~| NOTE in this expansion
+ fn f() { panic!(); } //~ ERROR ambiguous
+ //~| NOTE `panic` is also a builtin macro
+ //~| NOTE macro-expanded macro imports do not shadow
+}
+
+mod m4 {
+ macro_rules! panic { () => {} } // ok
+ panic!();
+}
+
+mod m5 {
+ macro_rules! m { () => {
+ macro_rules! panic { () => {} } //~ ERROR `panic` is already in scope
+ //~| NOTE macro-expanded `macro_rules!`s may not shadow existing macros
+ } }
+ m!(); //~ NOTE in this expansion
+ //~| NOTE in this expansion
+ panic!();
+}
+
+#[macro_use(n)] //~ NOTE `n` could also refer to the name imported here
+extern crate two_macros;
+mod bar {
+ pub use two_macros::m as n;
+}
+
+mod m6 {
+ use bar::n; // ok
+ n!();
+}
+
+mod m7 {
+ use bar::*; //~ NOTE `n` could refer to the name imported here
+ n!(); //~ ERROR ambiguous
+ //~| NOTE consider adding an explicit import of `n` to disambiguate
+}
+
+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.
+
+#![feature(closure_to_fn_coercion)]
+
+fn main() {
+ let bar: fn(&mut u32) = |_| {}; //~ ERROR mismatched types
+ //~| expected concrete lifetime, found bound lifetime parameter
+
+ fn foo(x: Box<Fn(&i32)>) {}
+ let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>;
+ foo(bar); //~ ERROR mismatched types
+ //~| expected concrete lifetime, found bound lifetime parameter
+}
--- /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() {
+ [0; ..10];
+ //~^ ERROR mismatched types
+ //~| expected type `usize`
+ //~| found type `std::ops::RangeTo<{integer}>`
+}
--- /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 T { m!(); } //~ ERROR cannot find macro `m!` in this scope
+
+struct S;
+impl S { m!(); } //~ ERROR cannot find macro `m!` in this scope
+
+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.
+
+fn f<'a: 'static>(_: &'a i32) {} //~WARN unnecessary lifetime parameter `'a`
+
+fn main() {
+ let x = 0;
+ f(&x); //~ERROR does not live long enough
+}
+++ /dev/null
-// Copyright 2013-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.
-
-#![feature(rustc_private)]
-
-#[macro_use] extern crate log;
-
-pub fn foo<T>() {
- fn death() -> isize { panic!() }
- debug!("{}", (||{ death() })());
-}
+++ /dev/null
-// Copyright 2012-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.
-
-// compile-flags: -C debug-assertions=no
-// exec-env:RUST_LOG=conditional-debug-macro-off=4
-
-
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-pub fn main() {
- // only panics if println! evaluates its argument.
- debug!("{:?}", { if true { panic!() } });
-}
+++ /dev/null
-// Copyright 2013-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.
-
-// compile-flags:-C debug-assertions=no
-// exec-env:RUST_LOG=logging-enabled-debug=debug
-
-
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-pub fn main() {
- if log_enabled!(log::DEBUG) {
- panic!("what?! debugging?");
- }
-}
+++ /dev/null
-// Copyright 2013-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.
-
-// exec-env:RUST_LOG=logging_enabled=info
-// ignore-emscripten: FIXME(#31622)
-
-
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-pub fn main() {
- if log_enabled!(log::DEBUG) {
- panic!("what?! debugging?");
- }
- if !log_enabled!(log::INFO) {
- panic!("what?! no info?");
- }
-}
+++ /dev/null
-// Copyright 2013-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.
-
-// aux-build:logging_right_crate.rs
-// exec-env:RUST_LOG=logging-right-crate=debug
-
-// This is a test for issue #3046 to make sure that when we monomorphize a
-// function from one crate to another the right top-level logging name is
-// preserved.
-//
-// It used to be the case that if logging were turned on for this crate, all
-// monomorphized functions from other crates had logging turned on (their
-// logging module names were all incorrect). This test ensures that this no
-// longer happens by enabling logging for *this* crate and then invoking a
-// function in an external crate which will panic when logging is enabled.
-
-// pretty-expanded FIXME #23616
-
-extern crate logging_right_crate;
-
-pub fn main() {
- // this function panicks if logging is turned on
- logging_right_crate::foo::<isize>();
-}
+++ /dev/null
-// Copyright 2013-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.
-
-// ignore-windows
-// exec-env:RUST_LOG=debug
-// compile-flags:-C debug-assertions=y
-// ignore-emscripten: FIXME(#31622)
-
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-use std::process::Command;
-use std::env;
-use std::str;
-
-fn main() {
- let args: Vec<String> = env::args().collect();
- if args.len() > 1 && args[1] == "child" {
- debug!("foo");
- debug!("bar");
- return
- }
-
- let p = Command::new(&args[0])
- .arg("child")
- .output().unwrap();
- assert!(p.status.success());
- let mut lines = str::from_utf8(&p.stderr).unwrap().lines();
- assert!(lines.next().unwrap().contains("foo"));
- assert!(lines.next().unwrap().contains("bar"));
-}
+++ /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.
-
-// exec-env:RUST_LOG=rust_log_filter/foo
-// ignore-emscripten no threads support
-
-#![allow(unknown_features)]
-#![feature(box_syntax, std_misc, rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-use std::sync::mpsc::{channel, Sender, Receiver};
-use std::thread;
-
-pub struct ChannelLogger {
- tx: Sender<String>
-}
-
-impl ChannelLogger {
- pub fn new() -> (Box<ChannelLogger>, Receiver<String>) {
- let (tx, rx) = channel();
- (box ChannelLogger { tx: tx }, rx)
- }
-}
-
-impl log::Logger for ChannelLogger {
- fn log(&mut self, record: &log::LogRecord) {
- self.tx.send(format!("{}", record.args)).unwrap();
- }
-}
-
-pub fn main() {
- let (logger, rx) = ChannelLogger::new();
-
- let t = thread::spawn(move|| {
- log::set_logger(logger);
-
- info!("foo");
- info!("bar");
- info!("foo bar");
- info!("bar foo");
- });
-
- assert_eq!(rx.recv().unwrap(), "foo");
- assert_eq!(rx.recv().unwrap(), "foo bar");
- assert_eq!(rx.recv().unwrap(), "bar foo");
- assert!(rx.recv().is_err());
-
- t.join();
-}
--- /dev/null
+// Copyright 2012-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.
+
+#![feature(rustc_private)]
+
+extern crate rustc_back;
+
+use std::fs::File;
+use std::io::{Read, Write};
+
+use rustc_back::tempdir::TempDir;
+
+#[cfg(unix)]
+fn switch_stdout_to(file: File) {
+ use std::os::unix::prelude::*;
+
+ extern {
+ fn dup2(old: i32, new: i32) -> i32;
+ }
+
+ unsafe {
+ assert_eq!(dup2(file.as_raw_fd(), 1), 1);
+ }
+}
+
+#[cfg(windows)]
+fn switch_stdout_to(file: File) {
+ use std::os::windows::prelude::*;
+
+ extern "system" {
+ fn SetStdHandle(nStdHandle: u32, handle: *mut u8) -> i32;
+ }
+
+ const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32;
+
+ unsafe {
+ let rc = SetStdHandle(STD_OUTPUT_HANDLE,
+ file.into_raw_handle() as *mut _);
+ assert!(rc != 0);
+ }
+}
+
+fn main() {
+ let td = TempDir::new("foo").unwrap();
+ let path = td.path().join("bar");
+ let f = File::create(&path).unwrap();
+
+ println!("foo");
+ std::io::stdout().flush().unwrap();
+ switch_stdout_to(f);
+ println!("bar");
+ std::io::stdout().flush().unwrap();
+
+ let mut contents = String::new();
+ File::open(&path).unwrap().read_to_string(&mut contents).unwrap();
+ assert_eq!(contents, "bar\n");
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// exec-env:RUST_LOG=conditional-debug-macro-on=4
-
pub fn main() {
// exits early if println! evaluates its arguments, otherwise it
// will hit the panic.
--- /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.
+
+macro_rules! m {
+ ($e:expr) => {
+ macro_rules! n { () => { $e } }
+ }
+}
+
+fn main() {
+ m!(foo!());
+}
[dependencies]
log = "0.3"
-env_logger = { version = "0.3.5", default-features = false }
+env_logger = { version = "0.4", default-features = false }
rustc-serialize = "0.3"
filetime = "0.1"
let mut cmd = Command::new(prog);
cmd.args(args)
.stdout(Stdio::piped())
- .stderr(Stdio::piped());
-
- // Why oh why do we sometimes make a pipe and sometimes inherit the stdin
- // stream, well that's an excellent question! In theory it should suffice to
- // always create a pipe here and be done with it. Unfortunately though
- // there's apparently something odd with the gdb that comes with gcc 6.3.0
- // on MinGW. Tracked at rust-lang/rust#40184 when stdin is piped here
- // (unconditionally) then all gdb tests will fail on MinGW when using gcc
- // 6.3.0. WHen using an inherited stdin though they happen to all work!
- //
- // As to why this fixes the issue, well, I have no idea. If you can remove
- // this branch and unconditionally use `piped` and it gets past @bors please
- // feel free to send a PR!
- if input.is_some() || !cfg!(windows) {
- cmd.stdin(Stdio::piped());
- } else {
- cmd.stdin(Stdio::inherit());
- }
+ .stderr(Stdio::piped())
+ .stdin(Stdio::piped());
add_target_env(&mut cmd, lib_path, aux_path);
for (key, val) in env {
use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata};
-use rustdoc::html::markdown::{Markdown, PLAYGROUND};
+use rustdoc::html::markdown::{Markdown, MarkdownOutputStyle, PLAYGROUND};
use rustc_serialize::json;
enum OutputFormat {
// Description rendered as markdown.
match info.description {
- Some(ref desc) => write!(output, "{}", Markdown(desc))?,
+ Some(ref desc) => write!(output, "{}", Markdown(desc, MarkdownOutputStyle::Fancy))?,
None => write!(output, "<p>No description.</p>\n")?,
}