Remove function invokation parens from documentation links.
This was never established as a convention we should follow in the 'More
API Documentation Conventions' RFC:
https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md
SRC=.
RUSTC_RETRY_LINKER_ON_SEGFAULT=1
SCCACHE_ERROR_LOG=/tmp/sccache.log
- RUST_LOG=sccache
+ RUST_LOG=sccache=debug
os: osx
osx_image: xcode8.2
install: &osx_install_sccache >
SRC=.
RUSTC_RETRY_LINKER_ON_SEGFAULT=1
SCCACHE_ERROR_LOG=/tmp/sccache.log
- RUST_LOG=sccache
+ RUST_LOG=sccache=debug
os: osx
osx_image: xcode8.2
install: *osx_install_sccache
DEPLOY=1
RUSTC_RETRY_LINKER_ON_SEGFAULT=1
SCCACHE_ERROR_LOG=/tmp/sccache.log
- RUST_LOG=sccache
+ RUST_LOG=sccache=debug
os: osx
osx_image: xcode8.2
install: >
DEPLOY=1
RUSTC_RETRY_LINKER_ON_SEGFAULT=1
SCCACHE_ERROR_LOG=/tmp/sccache.log
- RUST_LOG=sccache
+ RUST_LOG=sccache=debug
os: osx
osx_image: xcode8.2
install: *osx_install_sccache
DEPLOY_ALT=1
RUSTC_RETRY_LINKER_ON_SEGFAULT=1
SCCACHE_ERROR_LOG=/tmp/sccache.log
- RUST_LOG=sccache
+ RUST_LOG=sccache=debug
os: osx
osx_image: xcode8.2
install: *osx_install_sccache
- handle.exe -accepteula -help
# Attempt to debug sccache failures
- - set RUST_LOG=sccache
+ - set RUST_LOG=sccache=debug
- set SCCACHE_ERROR_LOG=%CD%/sccache.log
test_script:
- cat %CD%/sccache.log
cache:
- - "build/i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-auto-clean-trigger"
- - "build/x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-auto-clean-trigger"
- - "i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-auto-clean-trigger"
- - "x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-auto-clean-trigger"
+ - "build/i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
+ - "build/x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
+ - "i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
+ - "x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
branches:
only:
opt local-rebuild 0 "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version"
opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
opt llvm-link-shared 0 "prefer shared linking to LLVM (llvm-config --link-shared)"
+opt llvm-clean-rebuild 0 "delete LLVM build directory on rebuild"
opt rpath 1 "build rpaths into rustc itself"
opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0"
# This is used by the automation to produce single-target nightlies
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
opt codegen-tests 1 "run the src/test/codegen tests"
+opt save-analysis 0 "save API analysis data"
opt option-checking 1 "complain about unrecognized options in this configure script"
opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)"
opt locked-deps 0 "force Cargo.lock to be up to date"
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.43 (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.20 (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)",
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (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)",
dependencies = [
"env_logger 0.3.5 (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.6 (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.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
-version = "0.4.0"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.4 (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)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "lazy_static"
-version = "0.2.2"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
[[package]]
name = "libc"
-version = "0.2.20"
+version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
[[package]]
name = "log"
-version = "0.3.6"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mdbook"
-version = "0.0.17"
+version = "0.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.4.0 (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)",
- "log 0.3.6 (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)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
-version = "0.1.36"
+version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.0"
dependencies = [
"clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "mdbook 0.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "serde"
-version = "0.9.7"
+version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_json"
-version = "0.9.7"
+version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "toml"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"checksum cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "e1acc68a3f714627af38f9f5d09706a28584ba60dfe2cca68f40bf779f941b25"
"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.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99971fb1b635fe7a0ee3c4d065845bb93cca80a23b5613b5613391ece5de4144"
+"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.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
"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 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.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
-"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
-"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
-"checksum mdbook 0.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dbba458ca886cb082d026afd704eeeeb0531f7e4ffd6c619f72dc309c1c18fe4"
+"checksum lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7291b1dd97d331f752620b02dfdbc231df7fc01bf282a00769e1cdb963c460dc"
+"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 memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
-"checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"
+"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
"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 regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
-"checksum serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0ed773960f90a78567fcfbe935284adf50c5d7cf119aa2cf43bb0b4afa69bb"
-"checksum serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb96d30e4e6f9fc52e08f51176d078b6f79b981dc3ed4134f7b850be9f446a8"
+"checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f"
+"checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
-"checksum toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08272367dd2e766db3fa38f068067d17aa6a9dfd7259af24b3927db92f1e0c2f"
+"checksum toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3474f3c6eaf32eedb4f4a66a26214f020f828a6d96c37e38a35e3a379bbcfd11"
"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
impl GitInfo {
pub fn new(dir: &Path) -> GitInfo {
- if !dir.join(".git").is_dir() {
+ // See if this even begins to look like a git dir
+ if !dir.join(".git").exists() {
return GitInfo { inner: None }
}
+
+ // Make sure git commands work
+ let out = Command::new("git")
+ .arg("rev-parse")
+ .current_dir(dir)
+ .output()
+ .expect("failed to spawn git");
+ if !out.status.success() {
+ return GitInfo { inner: None }
+ }
+
+ // Ok, let's scrape some info
let ver_date = output(Command::new("git").current_dir(dir)
.arg("log").arg("-1")
.arg("--date=short")
pub llvm_link_shared: bool,
pub llvm_targets: Option<String>,
pub llvm_link_jobs: Option<u32>,
+ pub llvm_clean_rebuild: bool,
// rust codegen options
pub rust_optimize: bool,
pub rustc_default_ar: Option<String>,
pub rust_optimize_tests: bool,
pub rust_debuginfo_tests: bool,
+ pub rust_save_analysis: bool,
pub rust_dist_src: bool,
pub build: String,
static_libstdcpp: Option<bool>,
targets: Option<String>,
link_jobs: Option<u32>,
+ clean_rebuild: Option<bool>,
}
#[derive(RustcDecodable, Default, Clone)]
optimize_tests: Option<bool>,
debuginfo_tests: Option<bool>,
codegen_tests: Option<bool>,
+ save_analysis: Option<bool>,
}
/// TOML representation of how each build target is configured.
set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
set(&mut config.llvm_version_check, llvm.version_check);
set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
+ set(&mut config.llvm_clean_rebuild, llvm.clean_rebuild);
config.llvm_targets = llvm.targets.clone();
config.llvm_link_jobs = llvm.link_jobs;
}
set(&mut config.rust_optimize_tests, rust.optimize_tests);
set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
set(&mut config.codegen_tests, rust.codegen_tests);
+ set(&mut config.rust_save_analysis, rust.save_analysis);
set(&mut config.rust_rpath, rust.rpath);
set(&mut config.debug_jemalloc, rust.debug_jemalloc);
set(&mut config.use_jemalloc, rust.use_jemalloc);
("LLVM_VERSION_CHECK", self.llvm_version_check),
("LLVM_STATIC_STDCPP", self.llvm_static_stdcpp),
("LLVM_LINK_SHARED", self.llvm_link_shared),
+ ("LLVM_CLEAN_REBUILD", self.llvm_clean_rebuild),
("OPTIMIZE", self.rust_optimize),
("DEBUG_ASSERTIONS", self.rust_debug_assertions),
("DEBUGINFO", self.rust_debuginfo),
("LOCAL_REBUILD", self.local_rebuild),
("NINJA", self.ninja),
("CODEGEN_TESTS", self.codegen_tests),
+ ("SAVE_ANALYSIS", self.rust_save_analysis),
("LOCKED_DEPS", self.locked_deps),
("VENDOR", self.vendor),
("FULL_BOOTSTRAP", self.full_bootstrap),
# controlled by rustbuild's -j parameter.
#link-jobs = 0
+# Delete LLVM build directory on LLVM rebuild.
+# This option defaults to `false` for local development, but CI may want to
+# always perform clean full builds (possibly accelerated by (s)ccache).
+#clean-rebuild = false
+
# =============================================================================
# General build configuration options
# =============================================================================
# saying that the FileCheck executable is missing, you may want to disable this.
#codegen-tests = true
+# Flag indicating whether the API analysis data should be saved.
+#save-analysis = false
+
# =============================================================================
# Options for specific targets
#
/// Creates a tarball of save-analysis metadata, if available.
pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
+ if !build.config.rust_save_analysis {
+ return
+ }
+
println!("Dist analysis");
- if build.config.channel != "nightly" {
- println!("\tskipping - not on nightly channel");
- return;
- }
if compiler.host != build.config.build {
- println!("\tskipping - not a build host");
- return
- }
- if compiler.stage != 2 {
- println!("\tskipping - not stage2");
+ println!("\tskipping, not a build host");
return
}
// We don't want to build docs for internal std dependencies unless
// in compiler-docs mode. When not in that mode, we whitelist the crates
// for which docs must be built.
- if build.config.compiler_docs {
- cargo.arg("-p").arg("std");
- } else {
+ if !build.config.compiler_docs {
cargo.arg("--no-deps");
for krate in &["alloc", "collections", "core", "std", "std_unicode"] {
cargo.arg("-p").arg(krate);
.arg(build.src.join("src/rustc/Cargo.toml"))
.arg("--features").arg(build.rustc_features());
- // Like with libstd above if compiler docs aren't enabled then we're not
- // documenting internal dependencies, so we have a whitelist.
- if !build.config.compiler_docs {
+ if build.config.compiler_docs {
+ // src/rustc/Cargo.toml contains bin crates called rustc and rustdoc
+ // which would otherwise overwrite the docs for the real rustc and
+ // rustdoc lib crates.
+ cargo.arg("-p").arg("rustc_driver")
+ .arg("-p").arg("rustdoc");
+ } else {
+ // Like with libstd above if compiler docs aren't enabled then we're not
+ // documenting internal dependencies, so we have a whitelist.
cargo.arg("--no-deps");
for krate in &["proc_macro"] {
cargo.arg("-p").arg(krate);
install_sh(&build, "docs", "rust-docs", stage, host, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
}
+ if build.config.rust_save_analysis {
+ install_sh(&build, "analysis", "rust-analysis", stage, host, &prefix,
+ &docdir, &libdir, &mandir, &empty_dir);
+ }
install_sh(&build, "std", "rust-std", stage, host, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
install_sh(&build, "rustc", "rustc", stage, host, &prefix,
None => false,
};
let rust_info = channel::GitInfo::new(&src);
- let cargo_info = channel::GitInfo::new(&src.join("src/tools/cargo"));
+ let cargo_info = channel::GitInfo::new(&src.join("cargo"));
Build {
flags: flags,
.env(format!("CFLAGS_{}", target), self.cflags(target).join(" "));
}
- if self.config.channel == "nightly" && compiler.is_final_stage(self) {
+ if self.config.rust_save_analysis && compiler.is_final_stage(self) {
cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string());
}
}
}
- let clean_trigger = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
- let mut clean_trigger_contents = String::new();
- t!(t!(File::open(&clean_trigger)).read_to_string(&mut clean_trigger_contents));
+ let rebuild_trigger = build.src.join("src/rustllvm/llvm-rebuild-trigger");
+ let mut rebuild_trigger_contents = String::new();
+ t!(t!(File::open(&rebuild_trigger)).read_to_string(&mut rebuild_trigger_contents));
let out_dir = build.llvm_out(target);
let done_stamp = out_dir.join("llvm-finished-building");
let mut done_contents = String::new();
t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents));
- // LLVM was already built previously.
- // We don't track changes in LLVM sources, so we need to choose between reusing
- // what was built previously, or cleaning the directory and doing a fresh build.
- // The choice depends on contents of the clean-trigger file.
- // If the contents are the same as during the previous build, then no action is required.
- // If the contents differ from the previous build, then cleaning is triggered.
- if done_contents == clean_trigger_contents {
+ // If LLVM was already built previously and contents of the rebuild-trigger file
+ // didn't change from the previous build, then no action is required.
+ if done_contents == rebuild_trigger_contents {
return
- } else {
- t!(fs::remove_dir_all(&out_dir));
}
}
+ if build.config.llvm_clean_rebuild {
+ drop(fs::remove_dir_all(&out_dir));
+ }
println!("Building LLVM for {}", target);
let _time = util::timeit();
// tools and libs on all platforms.
cfg.build();
- t!(t!(File::create(&done_stamp)).write_all(clean_trigger_contents.as_bytes()));
+ t!(t!(File::create(&done_stamp)).write_all(rebuild_trigger_contents.as_bytes()));
}
fn check_llvm_version(build: &Build, llvm_config: &Path) {
for (krate, path, default) in krates("test") {
rules.doc(&krate.doc_step, path)
.dep(|s| s.name("libtest-link"))
+ // Needed so rustdoc generates relative links to std.
+ .dep(|s| s.name("doc-crate-std"))
.default(default && build.config.compiler_docs)
.run(move |s| doc::test(build, s.stage, s.target));
}
for (krate, path, default) in krates("rustc-main") {
rules.doc(&krate.doc_step, path)
.dep(|s| s.name("librustc-link"))
+ // Needed so rustdoc generates relative links to std.
+ .dep(|s| s.name("doc-crate-std"))
.host(true)
.default(default && build.config.docs)
.run(move |s| doc::rustc(build, s.stage, s.target));
name: "std".to_string(),
deps: Vec::new(),
path: cwd.join("src/std"),
- doc_step: "doc-std".to_string(),
+ doc_step: "doc-crate-std".to_string(),
build_step: "build-crate-std".to_string(),
- test_step: "test-std".to_string(),
- bench_step: "bench-std".to_string(),
+ test_step: "test-crate-std".to_string(),
+ bench_step: "bench-crate-std".to_string(),
version: String::new(),
});
build.crates.insert("test".to_string(), ::Crate {
name: "test".to_string(),
deps: Vec::new(),
path: cwd.join("src/test"),
- doc_step: "doc-test".to_string(),
+ doc_step: "doc-crate-test".to_string(),
build_step: "build-crate-test".to_string(),
- test_step: "test-test".to_string(),
- bench_step: "bench-test".to_string(),
+ test_step: "test-crate-test".to_string(),
+ bench_step: "bench-crate-test".to_string(),
version: String::new(),
});
build.crates.insert("rustc-main".to_string(), ::Crate {
deps: Vec::new(),
version: String::new(),
path: cwd.join("src/rustc-main"),
- doc_step: "doc-rustc-main".to_string(),
+ doc_step: "doc-crate-rustc-main".to_string(),
build_step: "build-crate-rustc-main".to_string(),
- test_step: "test-rustc-main".to_string(),
- bench_step: "bench-rustc-main".to_string(),
+ test_step: "test-crate-rustc-main".to_string(),
+ bench_step: "bench-crate-rustc-main".to_string(),
});
return build
}
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-locked-deps"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-openssl-static"
+RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-clean-rebuild"
if [ "$DIST_SRC" = "" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src"
if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=nightly"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
+ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-save-analysis"
if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions"
------------------------
+The `concat_idents` feature adds a macro for concatenating multiple identifiers
+into one identifier.
+## Examples
+```rust
+#![feature(concat_idents)]
+
+fn main() {
+ fn foobar() -> u32 { 23 }
+ let f = concat_idents!(foo, bar);
+ assert_eq!(f(), 23);
+}
+```
\ No newline at end of file
------------------------
+The `conservative_impl_trait` feature allows a conservative form of abstract
+return types.
+Abstract return types allow a function to hide a concrete return type behind a
+trait interface similar to trait objects, while still generating the same
+statically dispatched code as with concrete types.
+## Examples
+
+```rust
+#![feature(conservative_impl_trait)]
+
+fn even_iter() -> impl Iterator<Item=u32> {
+ (0..).map(|n| n * 2)
+}
+
+fn main() {
+ let first_four_even_numbers = even_iter().take(4).collect::<Vec<_>>();
+ assert_eq!(first_four_even_numbers, vec![0, 2, 4, 6]);
+}
+```
+
+## Background
+
+In today's Rust, you can write function signatures like:
+
+````rust,ignore
+fn consume_iter_static<I: Iterator<u8>>(iter: I) { }
+
+fn consume_iter_dynamic(iter: Box<Iterator<u8>>) { }
+````
+
+In both cases, the function does not depend on the exact type of the argument.
+The type held is "abstract", and is assumed only to satisfy a trait bound.
+
+* In the `_static` version using generics, each use of the function is
+ specialized to a concrete, statically-known type, giving static dispatch,
+ inline layout, and other performance wins.
+* In the `_dynamic` version using trait objects, the concrete argument type is
+ only known at runtime using a vtable.
+
+On the other hand, while you can write:
+
+````rust,ignore
+fn produce_iter_dynamic() -> Box<Iterator<u8>> { }
+````
+
+...but you _cannot_ write something like:
+
+````rust,ignore
+fn produce_iter_static() -> Iterator<u8> { }
+````
+
+That is, in today's Rust, abstract return types can only be written using trait
+objects, which can be a significant performance penalty. This RFC proposes
+"unboxed abstract types" as a way of achieving signatures like
+`produce_iter_static`. Like generics, unboxed abstract types guarantee static
+dispatch and inline data layout.
------------------------
+The `const_fn` feature allows marking free functions and inherent methods as
+`const`, enabling them to be called in constants contexts, with constant
+arguments.
+## Examples
+```rust
+#![feature(const_fn)]
+
+const fn double(x: i32) -> i32 {
+ x * 2
+}
+
+const FIVE: i32 = 5;
+const TEN: i32 = double(FIVE);
+
+fn main() {
+ assert_eq!(5, FIVE);
+ assert_eq!(10, TEN);
+}
+```
------------------------
+The `const_indexing` feature allows the constant evaluation of index operations
+on constant arrays and repeat expressions.
+## Examples
+```rust
+#![feature(const_indexing)]
+
+const ARR: [usize; 5] = [1, 2, 3, 4, 5];
+const ARR2: [usize; ARR[1]] = [42, 99];
+```
\ No newline at end of file
------------------------
+The `i128_type` feature adds support for 128 bit signed and unsigned integer
+types.
+```rust
+#![feature(i128_type)]
+
+fn main() {
+ assert_eq!(1u128 + 1u128, 2u128);
+ assert_eq!(u128::min_value(), 0);
+ assert_eq!(u128::max_value(), 340282366920938463463374607431768211455);
+
+ assert_eq!(1i128 - 2i128, -1i128);
+ assert_eq!(i128::min_value(), -170141183460469231731687303715884105728);
+ assert_eq!(i128::max_value(), 170141183460469231731687303715884105727);
+}
+```
------------------------
+The `non_ascii_idents` feature adds support for non-ASCII identifiers.
+## Examples
+```rust
+#![feature(non_ascii_idents)]
+
+const ε: f64 = 0.00001f64;
+const Î : f64 = 3.14f64;
+```
\ No newline at end of file
}
}
+// note: test pulls in libstd, which causes errors here
+#[cfg(not(test))]
+#[stable(feature = "string_from_box", since = "1.17.0")]
+impl From<Box<str>> for String {
+ fn from(s: Box<str>) -> String {
+ s.into_string()
+ }
+}
+
+#[stable(feature = "box_from_str", since = "1.17.0")]
+impl Into<Box<str>> for String {
+ fn into(self) -> Box<str> {
+ self.into_boxed_str()
+ }
+}
+
#[stable(feature = "string_from_cow_str", since = "1.14.0")]
impl<'a> From<Cow<'a, str>> for String {
fn from(s: Cow<'a, str>) -> String {
}
}
+// note: test pulls in libstd, which causes errors here
+#[cfg(not(test))]
+#[stable(feature = "vec_from_box", since = "1.17.0")]
+impl<T> From<Box<[T]>> for Vec<T> {
+ fn from(s: Box<[T]>) -> Vec<T> {
+ s.into_vec()
+ }
+}
+
+#[stable(feature = "box_from_vec", since = "1.17.0")]
+impl<T> Into<Box<[T]>> for Vec<T> {
+ fn into(self) -> Box<[T]> {
+ self.into_boxed_slice()
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&'a str> for Vec<u8> {
fn from(s: &'a str) -> Vec<u8> {
#![feature(test)]
#![feature(unboxed_closures)]
#![feature(unicode)]
+#![feature(utf8_error_error_len)]
extern crate collections;
extern crate test;
}
}
+#[test]
+fn from_utf8_error() {
+ macro_rules! test {
+ ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
+ let error = from_utf8($input).unwrap_err();
+ assert_eq!(error.valid_up_to(), $expected_valid_up_to);
+ assert_eq!(error.error_len(), $expected_error_len);
+ }
+ }
+ test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
+ test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xC1", 4, Some(1));
+ test!(b"A\xC3\xA9 \xC2", 4, None);
+ test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
+ test!(b"A\xC3\xA9 \xE0", 4, None);
+ test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
+ test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
+ test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
+ test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
+ test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xF1", 4, None);
+ test!(b"A\xC3\xA9 \xF1\x80", 4, None);
+ test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
+ test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
+ test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
+}
+
#[test]
fn test_as_bytes() {
// no null
mod sources;
mod traits;
-/// An double-ended iterator with the direction inverted.
+/// A double-ended iterator with the direction inverted.
///
/// This `struct` is created by the [`rev`] method on [`Iterator`]. See its
/// documentation for more.
/// allocations or resources, so care must be taken not to overwrite an object
/// that should be dropped.
///
-/// It does not immediately drop the contents of `src` either; it is rather
-/// *moved* into the memory location `dst` and will be dropped whenever that
-/// location goes out of scope.
+/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
+/// location pointed to by `dst`.
///
/// This is appropriate for initializing uninitialized memory, or overwriting
/// memory that has previously been `read` from.
/// allocations or resources, so care must be taken not to overwrite an object
/// that should be dropped.
///
+/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
+/// location pointed to by `dst`.
+///
/// This is appropriate for initializing uninitialized memory, or overwriting
/// memory that has previously been `read` from.
///
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Utf8Error {
valid_up_to: usize,
+ error_len: Option<u8>,
}
impl Utf8Error {
/// Returns the index in the given string up to which valid UTF-8 was
/// verified.
///
- /// It is the maximum index such that `from_utf8(input[..index])`
+ /// It is the maximum index such that `from_utf8(&input[..index])`
/// would return `Ok(_)`.
///
/// # Examples
/// ```
#[stable(feature = "utf8_error", since = "1.5.0")]
pub fn valid_up_to(&self) -> usize { self.valid_up_to }
+
+ /// Provide more information about the failure:
+ ///
+ /// * `None`: the end of the input was reached unexpectedly.
+ /// `self.valid_up_to()` is 1 to 3 bytes from the end of the input.
+ /// If a byte stream (such as a file or a network socket) is being decoded incrementally,
+ /// this could be a valid `char` whose UTF-8 byte sequence is spanning multiple chunks.
+ ///
+ /// * `Some(len)`: an unexpected byte was encountered.
+ /// The length provided is that of the invalid byte sequence
+ /// that starts at the index given by `valid_up_to()`.
+ /// Decoding should resume after that sequence
+ /// (after inserting a U+FFFD REPLACEMENT CHARACTER) in case of lossy decoding.
+ #[unstable(feature = "utf8_error_error_len", reason ="new", issue = "40494")]
+ pub fn error_len(&self) -> Option<usize> {
+ self.error_len.map(|len| len as usize)
+ }
}
/// Converts a slice of bytes to a string slice.
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Utf8Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "invalid utf-8: invalid byte near index {}", self.valid_up_to)
+ if let Some(error_len) = self.error_len {
+ write!(f, "invalid utf-8 sequence of {} bytes from index {}",
+ error_len, self.valid_up_to)
+ } else {
+ write!(f, "incomplete utf-8 byte sequence from index {}", self.valid_up_to)
+ }
}
}
while index < len {
let old_offset = index;
- macro_rules! err { () => {{
- return Err(Utf8Error {
- valid_up_to: old_offset
- })
- }}}
+ macro_rules! err {
+ ($error_len: expr) => {
+ return Err(Utf8Error {
+ valid_up_to: old_offset,
+ error_len: $error_len,
+ })
+ }
+ }
macro_rules! next { () => {{
index += 1;
// we needed data, but there was none: error!
if index >= len {
- err!()
+ err!(None)
}
v[index]
}}}
let first = v[index];
if first >= 128 {
let w = UTF8_CHAR_WIDTH[first as usize];
- let second = next!();
// 2-byte encoding is for codepoints \u{0080} to \u{07ff}
// first C2 80 last DF BF
// 3-byte encoding is for codepoints \u{0800} to \u{ffff}
// UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
// %xF4 %x80-8F 2( UTF8-tail )
match w {
- 2 => if second & !CONT_MASK != TAG_CONT_U8 {err!()},
+ 2 => if next!() & !CONT_MASK != TAG_CONT_U8 {
+ err!(Some(1))
+ },
3 => {
- match (first, second, next!() & !CONT_MASK) {
- (0xE0 , 0xA0 ... 0xBF, TAG_CONT_U8) |
- (0xE1 ... 0xEC, 0x80 ... 0xBF, TAG_CONT_U8) |
- (0xED , 0x80 ... 0x9F, TAG_CONT_U8) |
- (0xEE ... 0xEF, 0x80 ... 0xBF, TAG_CONT_U8) => {}
- _ => err!()
+ match (first, next!()) {
+ (0xE0 , 0xA0 ... 0xBF) |
+ (0xE1 ... 0xEC, 0x80 ... 0xBF) |
+ (0xED , 0x80 ... 0x9F) |
+ (0xEE ... 0xEF, 0x80 ... 0xBF) => {}
+ _ => err!(Some(1))
+ }
+ if next!() & !CONT_MASK != TAG_CONT_U8 {
+ err!(Some(2))
}
}
4 => {
- match (first, second, next!() & !CONT_MASK, next!() & !CONT_MASK) {
- (0xF0 , 0x90 ... 0xBF, TAG_CONT_U8, TAG_CONT_U8) |
- (0xF1 ... 0xF3, 0x80 ... 0xBF, TAG_CONT_U8, TAG_CONT_U8) |
- (0xF4 , 0x80 ... 0x8F, TAG_CONT_U8, TAG_CONT_U8) => {}
- _ => err!()
+ match (first, next!()) {
+ (0xF0 , 0x90 ... 0xBF) |
+ (0xF1 ... 0xF3, 0x80 ... 0xBF) |
+ (0xF4 , 0x80 ... 0x8F) => {}
+ _ => err!(Some(1))
+ }
+ if next!() & !CONT_MASK != TAG_CONT_U8 {
+ err!(Some(2))
+ }
+ if next!() & !CONT_MASK != TAG_CONT_U8 {
+ err!(Some(3))
}
}
- _ => err!()
+ _ => err!(Some(1))
}
index += 1;
} else {
#![crate_type = "dylib"]
#![deny(warnings)]
#![deny(missing_docs)]
+#![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/",
+ issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
+ test(no_crate_inject, attr(deny(warnings))),
+ test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
#![feature(rustc_private)]
#![feature(staged_api)]
trait_impls: BTreeMap<DefId, Vec<NodeId>>,
trait_default_impl: BTreeMap<DefId, NodeId>,
+ catch_scopes: Vec<NodeId>,
loop_scopes: Vec<NodeId>,
is_in_loop_condition: bool,
trait_impls: BTreeMap::new(),
trait_default_impl: BTreeMap::new(),
exported_macros: Vec::new(),
+ catch_scopes: Vec::new(),
loop_scopes: Vec::new(),
is_in_loop_condition: false,
type_def_lifetime_params: DefIdMap(),
span
}
+ fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
+ where F: FnOnce(&mut LoweringContext) -> T
+ {
+ let len = self.catch_scopes.len();
+ self.catch_scopes.push(catch_id);
+
+ let result = f(self);
+ assert_eq!(len + 1, self.catch_scopes.len(),
+ "catch scopes should be added and removed in stack order");
+
+ self.catch_scopes.pop().unwrap();
+
+ result
+ }
+
fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
where F: FnOnce(&mut LoweringContext) -> T
{
result
}
- fn with_new_loop_scopes<T, F>(&mut self, f: F) -> T
+ fn with_new_scopes<T, F>(&mut self, f: F) -> T
where F: FnOnce(&mut LoweringContext) -> T
{
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = false;
+ let catch_scopes = mem::replace(&mut self.catch_scopes, Vec::new());
let loop_scopes = mem::replace(&mut self.loop_scopes, Vec::new());
let result = f(self);
- mem::replace(&mut self.loop_scopes, loop_scopes);
+ self.catch_scopes = catch_scopes;
+ self.loop_scopes = loop_scopes;
self.is_in_loop_condition = was_in_loop_condition;
self.record_body(value, None))
}
ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
- self.with_new_loop_scopes(|this| {
+ self.with_new_scopes(|this| {
let body = this.lower_block(body);
let body = this.expr_block(body, ThinVec::new());
let body_id = this.record_body(body, Some(decl));
this.lower_opt_sp_ident(opt_ident),
hir::LoopSource::Loop))
}
+ ExprKind::Catch(ref body) => {
+ // FIXME(cramertj): Add catch to HIR
+ self.with_catch_scope(e.id, |this| hir::ExprBlock(this.lower_block(body)))
+ }
ExprKind::Match(ref expr, ref arms) => {
hir::ExprMatch(P(self.lower_expr(expr)),
arms.iter().map(|x| self.lower_arm(x)).collect(),
hir::MatchSource::Normal)
}
ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
- self.with_new_loop_scopes(|this| {
+ self.with_new_scopes(|this| {
this.with_parent_def(e.id, |this| {
let expr = this.lower_expr(body);
hir::ExprClosure(this.lower_capture_clause(capture_clause),
// Err(err) => #[allow(unreachable_code)]
// return Carrier::from_error(From::from(err)),
// }
+
+ // FIXME(cramertj): implement breaking to catch
+ if !self.catch_scopes.is_empty() {
+ bug!("`?` in catch scopes is unimplemented")
+ }
+
let unstable_span = self.allow_internal_unstable("?", e.span);
// Carrier::translate(<expr>)
Allow <foo>
-D <foo> Deny <foo>
-F <foo> Forbid <foo> \
- (deny, and deny all overrides)
+ (deny <foo> and all attempts to override)
");
// Trait paths in bounds or impls.
Trait,
// Expression paths `path`, with optional parent context.
- Expr(Option<&'a ExprKind>),
+ Expr(Option<&'a Expr>),
// Paths in path patterns `Path`.
Pat,
// Paths in struct expressions and patterns `Path { .. }`.
ValueNS => "method or associated constant",
MacroNS => bug!("associated macro"),
},
- PathSource::Expr(parent) => match parent {
+ PathSource::Expr(parent) => match parent.map(|p| &p.node) {
// "function" here means "anything callable" rather than `Def::Fn`,
// this is not precise but usually more helpful than just "value".
Some(&ExprKind::Call(..)) => "function",
source: PathSource)
-> PathResolution {
let segments = &path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>();
- self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
+ let ident_span = path.segments.last().map_or(path.span, |seg| seg.span);
+ self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source)
}
fn smart_resolve_path_fragment(&mut self,
qself: Option<&QSelf>,
path: &[Ident],
span: Span,
+ ident_span: Span,
source: PathSource)
-> PathResolution {
let ns = source.namespace();
let expected = source.descr_expected();
let path_str = names_to_string(path);
let code = source.error_code(def.is_some());
- let (base_msg, fallback_label) = if let Some(def) = def {
+ let (base_msg, fallback_label, base_span) = if let Some(def) = def {
(format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
- format!("not a {}", expected))
+ format!("not a {}", expected), span)
} else {
let item_str = path[path.len() - 1];
let (mod_prefix, mod_str) = if path.len() == 1 {
(mod_prefix, format!("`{}`", names_to_string(mod_path)))
};
(format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
- format!("not found in {}", mod_str))
+ format!("not found in {}", mod_str), ident_span)
};
- let mut err = this.session.struct_span_err_with_code(span, &base_msg, code);
+ let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
// Emit special messages for unresolved `Self` and `self`.
if is_self_type(path, ns) {
err.span_label(span, &format!("type aliases cannot be used for traits"));
return err;
}
- (Def::Mod(..), PathSource::Expr(Some(parent))) => match *parent {
+ (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
ExprKind::Field(_, ident) => {
- err.span_label(span, &format!("did you mean `{}::{}`?",
- path_str, ident.node));
+ err.span_label(parent.span, &format!("did you mean `{}::{}`?",
+ path_str, ident.node));
return err;
}
ExprKind::MethodCall(ident, ..) => {
- err.span_label(span, &format!("did you mean `{}::{}(...)`?",
- path_str, ident.node));
+ err.span_label(parent.span, &format!("did you mean `{}::{}(...)`?",
+ path_str, ident.node));
return err;
}
_ => {}
// Try Levenshtein if nothing else worked.
if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) {
- err.span_label(span, &format!("did you mean `{}`?", candidate));
+ err.span_label(ident_span, &format!("did you mean `{}`?", candidate));
return err;
}
// Fallback label.
- err.span_label(span, &fallback_label);
+ err.span_label(base_span, &fallback_label);
err
};
let report_errors = |this: &mut Self, def: Option<Def>| {
// Make sure `A::B` in `<T as A>::B::C` is a trait item.
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
- span, PathSource::TraitItem(ns));
+ span, span, PathSource::TraitItem(ns));
return Some(PathResolution::with_unresolved_segments(
res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
));
path: &[Ident],
ns: Namespace,
filter_fn: FilterFn)
- -> Option<String>
+ -> Option<Symbol>
where FilterFn: Fn(Def) -> bool
{
let add_module_candidates = |module: Module, names: &mut Vec<Name>| {
};
let mut names = Vec::new();
- let prefix_str = if path.len() == 1 {
+ if path.len() == 1 {
// Search in lexical scope.
// Walk backwards up the ribs in scope and collect candidates.
for rib in self.ribs[ns].iter().rev() {
names.push(*name);
}
}
- String::new()
} else {
// Search in module.
let mod_path = &path[..path.len() - 1];
if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) {
add_module_candidates(module, &mut names);
}
- names_to_string(mod_path) + "::"
- };
+ }
let name = path[path.len() - 1].name;
// Make sure error reporting is deterministic.
names.sort_by_key(|name| name.as_str());
match find_best_match_for_name(names.iter(), &name.as_str(), None) {
- Some(found) if found != name => Some(format!("{}{}", prefix_str, found)),
+ Some(found) if found != name => Some(found),
_ => None,
}
}
self.with_resolved_label(label, id, |this| this.visit_block(block));
}
- fn resolve_expr(&mut self, expr: &Expr, parent: Option<&ExprKind>) {
+ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
// First, record candidate traits for this expression if it could
// result in the invocation of a method call.
// Equivalent to `visit::walk_expr` + passing some context to children.
ExprKind::Field(ref subexpression, _) => {
- self.resolve_expr(subexpression, Some(&expr.node));
+ self.resolve_expr(subexpression, Some(expr));
}
ExprKind::MethodCall(_, ref types, ref arguments) => {
let mut arguments = arguments.iter();
- self.resolve_expr(arguments.next().unwrap(), Some(&expr.node));
+ self.resolve_expr(arguments.next().unwrap(), Some(expr));
for argument in arguments {
self.resolve_expr(argument, None);
}
});
}
ExprKind::Call(ref callee, ref arguments) => {
- self.resolve_expr(callee, Some(&expr.node));
+ self.resolve_expr(callee, Some(expr));
for argument in arguments {
self.resolve_expr(argument, None);
}
if ident.name == lookup_name && ns == namespace {
if filter_fn(name_binding.def()) {
// create the path
- let span = name_binding.span;
let mut segms = path_segments.clone();
- segms.push(ident.into());
+ segms.push(ast::PathSegment::from_ident(ident, name_binding.span));
let path = Path {
- span: span,
+ span: name_binding.span,
segments: segms,
};
// the entity is accessible in the following cases:
if let Some(module) = name_binding.module() {
// form the path
let mut path_segments = path_segments.clone();
- path_segments.push(ident.into());
+ path_segments.push(ast::PathSegment::from_ident(ident, name_binding.span));
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
// add the module to the lookup
path.segments[0].identifier.name = keywords::CrateRoot.name();
let module = self.0.resolve_crate_var(ident.ctxt);
if !module.is_local() {
+ let span = path.segments[0].span;
path.segments.insert(1, match module.kind {
- ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name).into(),
+ ModuleKind::Def(_, name) => ast::PathSegment::from_ident(
+ ast::Ident::with_empty_ctxt(name), span
+ ),
_ => unreachable!(),
})
}
};
let ident = Ident::from_str(name);
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
- .as_ref().map(|s| Symbol::intern(s))
});
if let Some(suggestion) = suggestion {
self.trans_lvalue(bcx, dest)
};
if fn_ret_ty.is_indirect() {
- llargs.push(dest.llval);
- ReturnDest::Nothing
+ match dest.alignment {
+ Alignment::AbiAligned => {
+ llargs.push(dest.llval);
+ ReturnDest::Nothing
+ },
+ Alignment::Packed => {
+ // Currently, MIR code generation does not create calls
+ // that store directly to fields of packed structs (in
+ // fact, the calls it creates write only to temps),
+ //
+ // If someone changes that, please update this code path
+ // to create a temporary.
+ span_bug!(self.mir.span, "can't directly store to unaligned value");
+ }
+ }
} else {
ReturnDest::Store(dest.llval)
}
bcx.store(base::from_immediate(bcx, s), lldest, align);
}
OperandValue::Pair(a, b) => {
+ let f_align = match *bcx.ccx.layout_of(operand.ty) {
+ Layout::Univariant { ref variant, .. } if variant.packed => {
+ Some(1)
+ }
+ _ => align
+ };
+
let a = base::from_immediate(bcx, a);
let b = base::from_immediate(bcx, b);
- bcx.store(a, bcx.struct_gep(lldest, 0), align);
- bcx.store(b, bcx.struct_gep(lldest, 1), align);
+ bcx.store(a, bcx.struct_gep(lldest, 0), f_align);
+ bcx.store(b, bcx.struct_gep(lldest, 1), f_align);
}
}
}
// going on). If they're in different crates then the crate defining
// the trait will be interested in our implementation.
if imp.def_id.krate == did.krate { continue }
- write!(implementors, r#""{}","#, imp.impl_).unwrap();
+ write!(implementors, "{},", as_json(&imp.impl_.to_string())).unwrap();
}
implementors.push_str("];");
use hash::{Hash, Hasher, BuildHasher, SipHasher13};
use iter::{FromIterator, FusedIterator};
use mem::{self, replace};
-use ops::{Deref, Index};
+use ops::{Deref, Index, InPlace, Place, Placer};
use rand::{self, Rng};
+use ptr;
use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash};
use super::table::BucketState::{Empty, Full};
mut hash: SafeHash,
mut key: K,
mut val: V)
- -> &'a mut V {
+ -> FullBucketMut<'a, K, V> {
let start_index = bucket.index();
let size = bucket.table().size();
// Save the *starting point*.
// bucket, which is a FullBucket on top of a
// FullBucketMut, into just one FullBucketMut. The "table"
// refers to the inner FullBucketMut in this context.
- return bucket.into_table().into_mut_refs().1;
+ return bucket.into_table();
}
Full(bucket) => bucket,
};
}
}
+/// A place for insertion to a `Entry`.
+///
+/// See [`HashMap::entry`](struct.HashMap.html#method.entry) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+ reason = "struct name and placement protocol is subject to change",
+ issue = "30172")]
+pub struct EntryPlace<'a, K: 'a, V: 'a> {
+ bucket: FullBucketMut<'a, K, V>,
+}
+
+#[unstable(feature = "collection_placement",
+ reason = "struct name and placement protocol is subject to change",
+ issue = "30172")]
+impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for EntryPlace<'a, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("EntryPlace")
+ .field("key", self.bucket.read().0)
+ .field("value", self.bucket.read().1)
+ .finish()
+ }
+}
+
+#[unstable(feature = "collection_placement",
+ reason = "struct name and placement protocol is subject to change",
+ issue = "30172")]
+impl<'a, K, V> Drop for EntryPlace<'a, K, V> {
+ fn drop(&mut self) {
+ // Inplacement insertion failed. Only key need to drop.
+ // The value is failed to insert into map.
+ unsafe { self.bucket.remove_key() };
+ }
+}
+
+#[unstable(feature = "collection_placement",
+ reason = "placement protocol is subject to change",
+ issue = "30172")]
+impl<'a, K, V> Placer<V> for Entry<'a, K, V> {
+ type Place = EntryPlace<'a, K, V>;
+
+ fn make_place(self) -> EntryPlace<'a, K, V> {
+ let b = match self {
+ Occupied(mut o) => {
+ unsafe { ptr::drop_in_place(o.elem.read_mut().1); }
+ o.elem
+ }
+ Vacant(v) => {
+ unsafe { v.insert_key() }
+ }
+ };
+ EntryPlace { bucket: b }
+ }
+}
+
+#[unstable(feature = "collection_placement",
+ reason = "placement protocol is subject to change",
+ issue = "30172")]
+impl<'a, K, V> Place<V> for EntryPlace<'a, K, V> {
+ fn pointer(&mut self) -> *mut V {
+ self.bucket.read_mut().1
+ }
+}
+
+#[unstable(feature = "collection_placement",
+ reason = "placement protocol is subject to change",
+ issue = "30172")]
+impl<'a, K, V> InPlace<V> for EntryPlace<'a, K, V> {
+ type Owner = ();
+
+ unsafe fn finalize(self) {
+ mem::forget(self);
+ }
+}
+
impl<'a, K, V> Entry<'a, K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
/// Ensures a value is in the entry by inserting the default if empty, and returns
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn insert(self, value: V) -> &'a mut V {
- match self.elem {
+ let b = match self.elem {
NeqElem(mut bucket, disp) => {
if disp >= DISPLACEMENT_THRESHOLD {
bucket.table_mut().set_tag(true);
if disp >= DISPLACEMENT_THRESHOLD {
bucket.table_mut().set_tag(true);
}
- bucket.put(self.hash, self.key, value).into_mut_refs().1
+ bucket.put(self.hash, self.key, value)
+ },
+ };
+ b.into_mut_refs().1
+ }
+
+ // Only used for InPlacement insert. Avoid unnecessary value copy.
+ // The value remains uninitialized.
+ unsafe fn insert_key(self) -> FullBucketMut<'a, K, V> {
+ match self.elem {
+ NeqElem(mut bucket, disp) => {
+ if disp >= DISPLACEMENT_THRESHOLD {
+ bucket.table_mut().set_tag(true);
+ }
+ let uninit = mem::uninitialized();
+ robin_hood(bucket, disp, self.hash, self.key, uninit)
+ },
+ NoElem(mut bucket, disp) => {
+ if disp >= DISPLACEMENT_THRESHOLD {
+ bucket.table_mut().set_tag(true);
+ }
+ bucket.put_key(self.hash, self.key)
},
}
}
use super::RandomState;
use cell::RefCell;
use rand::{thread_rng, Rng};
+ use panic;
#[test]
fn test_zero_capacities() {
}
panic!("Adaptive early resize failed");
}
+
+ #[test]
+ fn test_placement_in() {
+ let mut map = HashMap::new();
+ map.extend((0..10).map(|i| (i, i)));
+
+ map.entry(100) <- 100;
+ assert_eq!(map[&100], 100);
+
+ map.entry(0) <- 10;
+ assert_eq!(map[&0], 10);
+
+ assert_eq!(map.len(), 11);
+ }
+
+ #[test]
+ fn test_placement_panic() {
+ let mut map = HashMap::new();
+ map.extend((0..10).map(|i| (i, i)));
+
+ fn mkpanic() -> usize { panic!() }
+
+ // modify existing key
+ // when panic happens, previous key is removed.
+ let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(0) <- mkpanic(); }));
+ assert_eq!(map.len(), 9);
+ assert!(!map.contains_key(&0));
+
+ // add new key
+ let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(100) <- mkpanic(); }));
+ assert_eq!(map.len(), 9);
+ assert!(!map.contains_key(&100));
+ }
+
+ #[test]
+ fn test_placement_drop() {
+ // correctly drop
+ struct TestV<'a>(&'a mut bool);
+ impl<'a> Drop for TestV<'a> {
+ fn drop(&mut self) {
+ if !*self.0 { panic!("value double drop!"); } // no double drop
+ *self.0 = false;
+ }
+ }
+
+ fn makepanic<'a>() -> TestV<'a> { panic!() }
+
+ let mut can_drop = true;
+ let mut hm = HashMap::new();
+ hm.insert(0, TestV(&mut can_drop));
+ let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { hm.entry(0) <- makepanic(); }));
+ assert_eq!(hm.len(), 0);
+ }
}
table: self.table,
}
}
+
+ /// Puts given key, remain value uninitialized.
+ /// It is only used for inplacement insertion.
+ pub unsafe fn put_key(mut self, hash: SafeHash, key: K) -> FullBucket<K, V, M> {
+ *self.raw.hash = hash.inspect();
+ let pair_mut = self.raw.pair as *mut (K, V);
+ ptr::write(&mut (*pair_mut).0, key);
+
+ self.table.borrow_table_mut().size += 1;
+
+ FullBucket {
+ raw: self.raw,
+ idx: self.idx,
+ table: self.table,
+ }
+ }
}
impl<K, V, M: Deref<Target = RawTable<K, V>>> FullBucket<K, V, M> {
v)
}
}
+
+ /// Remove this bucket's `key` from the hashtable.
+ /// Only used for inplacement insertion.
+ /// NOTE: `Value` is uninitialized when this function is called, don't try to drop the `Value`.
+ pub unsafe fn remove_key(&mut self) {
+ self.table.size -= 1;
+
+ *self.raw.hash = EMPTY_BUCKET;
+ let pair_mut = self.raw.pair as *mut (K, V);
+ ptr::drop_in_place(&mut (*pair_mut).0); // only drop key
+ }
}
// This use of `Put` is misleading and restrictive, but safe and sufficient for our use cases
}
/// Converts this `CString` into a boxed `CStr`.
- #[unstable(feature = "into_boxed_c_str", issue = "0")]
+ #[unstable(feature = "into_boxed_c_str", issue = "40380")]
pub fn into_boxed_c_str(self) -> Box<CStr> {
unsafe { mem::transmute(self.into_inner()) }
}
}
}
+#[stable(feature = "c_string_from_box", since = "1.17.0")]
+impl From<Box<CStr>> for CString {
+ fn from(s: Box<CStr>) -> CString {
+ s.into_c_string()
+ }
+}
+
+#[stable(feature = "box_from_c_string", since = "1.17.0")]
+impl Into<Box<CStr>> for CString {
+ fn into(self) -> Box<CStr> {
+ self.into_boxed_c_str()
+ }
+}
+
#[stable(feature = "default_box_extra", since = "1.17.0")]
impl Default for Box<CStr> {
fn default() -> Box<CStr> {
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(self.to_bytes())
}
+
+ /// Converts a `Box<CStr>` into a `CString` without copying or allocating.
+ #[unstable(feature = "into_boxed_c_str", issue = "40380")]
+ pub fn into_c_string(self: Box<CStr>) -> CString {
+ unsafe { mem::transmute(self) }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
fn into_boxed() {
let orig: &[u8] = b"Hello, world!\0";
let cstr = CStr::from_bytes_with_nul(orig).unwrap();
- let cstring = cstr.to_owned();
- let box1: Box<CStr> = Box::from(cstr);
- let box2 = cstring.into_boxed_c_str();
- assert_eq!(cstr, &*box1);
- assert_eq!(box1, box2);
- assert_eq!(&*box2, cstr);
+ let boxed: Box<CStr> = Box::from(cstr);
+ let cstring = cstr.to_owned().into_boxed_c_str().into_c_string();
+ assert_eq!(cstr, &*boxed);
+ assert_eq!(&*boxed, &*cstring);
+ assert_eq!(&*cstring, cstr);
}
#[test]
}
/// Converts this `OsString` into a boxed `OsStr`.
- #[unstable(feature = "into_boxed_os_str", issue = "0")]
+ #[unstable(feature = "into_boxed_os_str", issue = "40380")]
pub fn into_boxed_os_str(self) -> Box<OsStr> {
unsafe { mem::transmute(self.inner.into_box()) }
}
self.inner.inner.len()
}
+ /// Converts a `Box<OsStr>` into an `OsString` without copying or allocating.
+ #[unstable(feature = "into_boxed_os_str", issue = "40380")]
+ pub fn into_os_string(self: Box<OsStr>) -> OsString {
+ let inner: Box<Slice> = unsafe { mem::transmute(self) };
+ OsString { inner: Buf::from_box(inner) }
+ }
+
/// Gets the underlying byte representation.
///
/// Note: it is *crucial* that this API is private, to avoid
}
}
+#[stable(feature = "os_string_from_box", since = "1.17.0")]
+impl<'a> From<Box<OsStr>> for OsString {
+ fn from(boxed: Box<OsStr>) -> OsString {
+ boxed.into_os_string()
+ }
+}
+
+#[stable(feature = "box_from_c_string", since = "1.17.0")]
+impl Into<Box<OsStr>> for OsString {
+ fn into(self) -> Box<OsStr> {
+ self.into_boxed_os_str()
+ }
+}
+
#[stable(feature = "box_default_extra", since = "1.17.0")]
impl Default for Box<OsStr> {
fn default() -> Box<OsStr> {
fn into_boxed() {
let orig = "Hello, world!";
let os_str = OsStr::new(orig);
- let os_string = os_str.to_owned();
- let box1: Box<OsStr> = Box::from(os_str);
- let box2 = os_string.into_boxed_os_str();
- assert_eq!(os_str, &*box1);
- assert_eq!(box1, box2);
- assert_eq!(&*box2, os_str);
+ let boxed: Box<OsStr> = Box::from(os_str);
+ let os_string = os_str.to_owned().into_boxed_os_str().into_os_string();
+ assert_eq!(os_str, &*boxed);
+ assert_eq!(&*boxed, &*os_string);
+ assert_eq!(&*os_string, os_str);
}
#[test]
#![feature(panic_unwind)]
#![feature(peek)]
#![feature(placement_in_syntax)]
+#![feature(placement_new_protocol)]
#![feature(prelude_import)]
#![feature(pub_restricted)]
#![feature(rand)]
}
/// Converts this `PathBuf` into a boxed `Path`.
- #[unstable(feature = "into_boxed_path", issue = "0")]
+ #[unstable(feature = "into_boxed_path", issue = "40380")]
pub fn into_boxed_path(self) -> Box<Path> {
unsafe { mem::transmute(self.inner.into_boxed_os_str()) }
}
}
}
+#[stable(feature = "path_buf_from_box", since = "1.17.0")]
+impl<'a> From<Box<Path>> for PathBuf {
+ fn from(boxed: Box<Path>) -> PathBuf {
+ boxed.into_path_buf()
+ }
+}
+
+#[stable(feature = "box_from_path_buf", since = "1.17.0")]
+impl Into<Box<Path>> for PathBuf {
+ fn into(self) -> Box<Path> {
+ self.into_boxed_path()
+ }
+}
+
#[stable(feature = "box_default_extra", since = "1.17.0")]
impl Default for Box<Path> {
fn default() -> Box<Path> {
pub fn is_dir(&self) -> bool {
fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
}
+
+ /// Converts a `Box<Path>` into a `PathBuf` without copying or allocating.
+ #[unstable(feature = "into_boxed_path", issue = "40380")]
+ pub fn into_path_buf(self: Box<Path>) -> PathBuf {
+ let inner: Box<OsStr> = unsafe { mem::transmute(self) };
+ PathBuf { inner: OsString::from(inner) }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
fn into_boxed() {
let orig: &str = "some/sort/of/path";
let path = Path::new(orig);
- let path_buf = path.to_owned();
- let box1: Box<Path> = Box::from(path);
- let box2 = path_buf.into_boxed_path();
- assert_eq!(path, &*box1);
- assert_eq!(box1, box2);
- assert_eq!(&*box2, path);
+ let boxed: Box<Path> = Box::from(path);
+ let path_buf = path.to_owned().into_boxed_path().into_path_buf();
+ assert_eq!(path, &*boxed);
+ assert_eq!(&*boxed, &*path_buf);
+ assert_eq!(&*path_buf, path);
}
#[test]
pub fn into_box(self) -> Box<Slice> {
unsafe { mem::transmute(self.inner.into_boxed_slice()) }
}
+
+ #[inline]
+ pub fn from_box(boxed: Box<Slice>) -> Buf {
+ let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
+ Buf { inner: inner.into_vec() }
+ }
}
impl Slice {
pub fn into_box(self) -> Box<Slice> {
unsafe { mem::transmute(self.inner.into_boxed_slice()) }
}
+
+ #[inline]
+ pub fn from_box(boxed: Box<Slice>) -> Buf {
+ let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
+ Buf { inner: inner.into_vec() }
+ }
}
impl Slice {
pub fn into_box(self) -> Box<Slice> {
unsafe { mem::transmute(self.inner.into_box()) }
}
+
+ #[inline]
+ pub fn from_box(boxed: Box<Slice>) -> Buf {
+ let inner: Box<Wtf8> = unsafe { mem::transmute(boxed) };
+ Buf { inner: Wtf8Buf::from_box(inner) }
+ }
}
impl Slice {
pub fn into_box(self) -> Box<Wtf8> {
unsafe { mem::transmute(self.bytes.into_boxed_slice()) }
}
+
+ /// Converts a `Box<Wtf8>` into a `Wtf8Buf`.
+ pub fn from_box(boxed: Box<Wtf8>) -> Wtf8Buf {
+ let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) };
+ Wtf8Buf { bytes: bytes.into_vec() }
+ }
}
/// Create a new WTF-8 string from an iterator of code points.
pub fn from_ident(s: Span, identifier: Ident) -> Path {
Path {
span: s,
- segments: vec![identifier.into()],
+ segments: vec![PathSegment::from_ident(identifier, s)],
}
}
pub struct PathSegment {
/// The identifier portion of this path segment.
pub identifier: Ident,
+ /// Span of the segment identifier.
+ pub span: Span,
/// Type/lifetime parameters attached to this path. They come in
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
pub parameters: Option<P<PathParameters>>,
}
-impl From<Ident> for PathSegment {
- fn from(id: Ident) -> Self {
- PathSegment { identifier: id, parameters: None }
- }
-}
-
impl PathSegment {
+ pub fn from_ident(ident: Ident, span: Span) -> Self {
+ PathSegment { identifier: ident, span: span, parameters: None }
+ }
pub fn crate_root() -> Self {
PathSegment {
identifier: keywords::CrateRoot.ident(),
+ span: DUMMY_SP,
parameters: None,
}
}
Closure(CaptureBy, P<FnDecl>, P<Expr>, Span),
/// A block (`{ ... }`)
Block(P<Block>),
+ /// A catch block (`catch { ... }`)
+ Catch(P<Block>),
/// An assignment (`a = foo()`)
Assign(P<Expr>, P<Expr>),
fn qpath(&self, self_type: P<ast::Ty>,
trait_path: ast::Path,
- ident: ast::Ident)
+ ident: ast::SpannedIdent)
-> (ast::QSelf, ast::Path);
fn qpath_all(&self, self_type: P<ast::Ty>,
trait_path: ast::Path,
- ident: ast::Ident,
+ ident: ast::SpannedIdent,
lifetimes: Vec<ast::Lifetime>,
types: Vec<P<ast::Ty>>,
bindings: Vec<ast::TypeBinding>)
segments.push(ast::PathSegment::crate_root());
}
- segments.extend(idents.into_iter().map(Into::into));
+ segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, sp)));
let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
None
} else {
bindings: bindings,
})))
};
- segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
+ segments.push(ast::PathSegment {
+ identifier: last_identifier,
+ span: sp,
+ parameters: parameters
+ });
ast::Path {
span: sp,
segments: segments,
fn qpath(&self,
self_type: P<ast::Ty>,
trait_path: ast::Path,
- ident: ast::Ident)
+ ident: ast::SpannedIdent)
-> (ast::QSelf, ast::Path) {
self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
}
fn qpath_all(&self,
self_type: P<ast::Ty>,
trait_path: ast::Path,
- ident: ast::Ident,
+ ident: ast::SpannedIdent,
lifetimes: Vec<ast::Lifetime>,
types: Vec<P<ast::Ty>>,
bindings: Vec<ast::TypeBinding>)
bindings: bindings,
};
path.segments.push(ast::PathSegment {
- identifier: ident,
+ identifier: ident.node,
+ span: ident.span,
parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
});
// `extern "x86-interrupt" fn()`
(active, abi_x86_interrupt, "1.17.0", Some(40180)),
+
+ // Allows the `catch {...}` expression
+ (active, catch_expr, "1.17.0", Some(31436)),
);
declare_features! (
}
}
}
+ ast::ExprKind::Catch(_) => {
+ gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
+ }
_ => {}
}
visit::walk_expr(self, e);
pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path {
Path {
- segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
+ segments: segments.move_map(|PathSegment {identifier, span, parameters}| PathSegment {
identifier: fld.fold_ident(identifier),
+ span: fld.new_span(span),
parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
}),
span: fld.new_span(span)
};
}
ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)),
+ ExprKind::Catch(body) => ExprKind::Catch(folder.fold_block(body)),
},
id: folder.new_id(id),
span: folder.new_span(span),
Span {lo: BytePos(a), hi: BytePos(b), expn_id: NO_EXPANSION}
}
+ fn str2seg(s: &str, lo: u32, hi: u32) -> ast::PathSegment {
+ ast::PathSegment::from_ident(Ident::from_str(s), sp(lo, hi))
+ }
+
#[test] fn path_exprs_1() {
assert!(string_to_expr("a".to_string()) ==
P(ast::Expr{
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, ast::Path {
span: sp(0, 1),
- segments: vec![Ident::from_str("a").into()],
+ segments: vec![str2seg("a", 0, 1)],
}),
span: sp(0, 1),
attrs: ThinVec::new(),
node: ast::ExprKind::Path(None, ast::Path {
span: sp(0, 6),
segments: vec![ast::PathSegment::crate_root(),
- Ident::from_str("a").into(),
- Ident::from_str("b").into()]
+ str2seg("a", 2, 3),
+ str2seg("b", 5, 6)]
}),
span: sp(0, 6),
attrs: ThinVec::new(),
id: ast::DUMMY_NODE_ID,
node:ast::ExprKind::Path(None, ast::Path{
span: sp(7, 8),
- segments: vec![Ident::from_str("d").into()],
+ segments: vec![str2seg("d", 7, 8)],
}),
span:sp(7,8),
attrs: ThinVec::new(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, ast::Path {
span:sp(0,1),
- segments: vec![Ident::from_str("b").into()],
+ segments: vec![str2seg("b", 0, 1)],
}),
span: sp(0,1),
attrs: ThinVec::new()})),
ty: P(ast::Ty{id: ast::DUMMY_NODE_ID,
node: ast::TyKind::Path(None, ast::Path{
span:sp(10,13),
- segments: vec![Ident::from_str("i32").into()],
+ segments: vec![str2seg("i32", 10, 13)],
}),
span:sp(10,13)
}),
node: ast::ExprKind::Path(None,
ast::Path{
span:sp(17,18),
- segments: vec![Ident::from_str("b").into()],
+ segments: vec![str2seg("b", 17, 18)],
}),
span: sp(17,18),
attrs: ThinVec::new()})),
use ast::MacStmtStyle;
use ast::Mac_;
use ast::{MutTy, Mutability};
-use ast::{Pat, PatKind};
+use ast::{Pat, PatKind, PathSegment};
use ast::{PolyTraitRef, QSelf};
use ast::{Stmt, StmtKind};
use ast::{VariantData, StructField};
};
if is_global {
- segments.insert(0, ast::PathSegment::crate_root());
+ segments.insert(0, PathSegment::crate_root());
}
// Assemble the span.
/// - `a::b<T,U>::c<V,W>`
/// - `a::b<T,U>::c(V) -> W`
/// - `a::b<T,U>::c(V)`
- pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> {
+ pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<PathSegment>> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
let identifier = self.parse_path_segment_ident()?;
+ let ident_span = self.prev_span;
if self.check(&token::ModSep) && self.look_ahead(1, |t| *t == token::Lt) {
self.bump();
};
// Assemble and push the result.
- segments.push(ast::PathSegment { identifier: identifier, parameters: parameters });
+ segments.push(PathSegment {
+ identifier: identifier,
+ span: ident_span,
+ parameters: parameters
+ });
// Continue only if we see a `::`
if !self.eat(&token::ModSep) {
/// Examples:
/// - `a::b::<T,U>::c`
- pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> {
+ pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<PathSegment>> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
let identifier = self.parse_path_segment_ident()?;
+ let ident_span = self.prev_span;
// If we do not see a `::`, stop.
if !self.eat(&token::ModSep) {
- segments.push(identifier.into());
+ segments.push(PathSegment::from_ident(identifier, ident_span));
return Ok(segments);
}
// Consumed `a::b::<`, go look for types
let (lifetimes, types, bindings) = self.parse_generic_args()?;
self.expect_gt()?;
- segments.push(ast::PathSegment {
+ segments.push(PathSegment {
identifier: identifier,
+ span: ident_span,
parameters: ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: types,
}
} else {
// Consumed `a::`, go look for `b`
- segments.push(identifier.into());
+ segments.push(PathSegment::from_ident(identifier, ident_span));
}
}
}
/// Examples:
/// - `a::b::c`
pub fn parse_path_segments_without_types(&mut self)
- -> PResult<'a, Vec<ast::PathSegment>> {
+ -> PResult<'a, Vec<PathSegment>> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
let identifier = self.parse_path_segment_ident()?;
// Assemble and push the result.
- segments.push(identifier.into());
+ segments.push(PathSegment::from_ident(identifier, self.prev_span));
// If we do not see a `::` or see `::{`/`::*`, stop.
if !self.check(&token::ModSep) || self.is_import_coupler() {
BlockCheckMode::Unsafe(ast::UserProvided),
attrs);
}
+ if self.is_catch_expr() {
+ assert!(self.eat_keyword(keywords::Do));
+ assert!(self.eat_keyword(keywords::Catch));
+ let lo = self.prev_span.lo;
+ return self.parse_catch_expr(lo, attrs);
+ }
if self.eat_keyword(keywords::Return) {
if self.token.can_begin_expr() {
let e = self.parse_expr()?;
Ok(self.mk_expr(span_lo, hi, ExprKind::Loop(body, opt_ident), attrs))
}
+ /// Parse a `do catch {...}` expression (`do catch` token already eaten)
+ pub fn parse_catch_expr(&mut self, span_lo: BytePos, mut attrs: ThinVec<Attribute>)
+ -> PResult<'a, P<Expr>>
+ {
+ let (iattrs, body) = self.parse_inner_attrs_and_block()?;
+ attrs.extend(iattrs);
+ let hi = body.span.hi;
+ Ok(self.mk_expr(span_lo, hi, ExprKind::Catch(body), attrs))
+ }
+
// `match` token already eaten
fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
let match_span = self.prev_span;
})
}
+ fn is_catch_expr(&mut self) -> bool {
+ self.token.is_keyword(keywords::Do) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
+ self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) &&
+
+ // prevent `while catch {} {}`, `if catch {} {} else {}`, etc.
+ !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL)
+ }
+
fn is_union_item(&self) -> bool {
self.token.is_keyword(keywords::Union) &&
self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword())
/// Parse struct Foo { ... }
fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
let class_name = self.parse_ident()?;
+
let mut generics = self.parse_generics()?;
// There is a special case worth noting here, as reported in issue #17904.
/// Parse union Foo { ... }
fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
let class_name = self.parse_ident()?;
+
let mut generics = self.parse_generics()?;
let vdata = if self.token.is_keyword(keywords::Where) {
// `{foo, bar}`, `::{foo, bar}`, `*`, or `::*`.
self.eat(&token::ModSep);
let prefix = ast::Path {
- segments: vec![ast::PathSegment::crate_root()],
+ segments: vec![PathSegment::crate_root()],
span: mk_sp(lo, self.span.hi),
};
let view_path_kind = if self.eat(&token::BinOp(token::Star)) {
!ident_token.is_any_keyword() ||
ident_token.is_path_segment_keyword() ||
[
+ keywords::Do.name(),
keywords::Box.name(),
keywords::Break.name(),
keywords::Continue.name(),
self.print_expr(e)?;
word(&mut self.s, "?")?
}
+ ast::ExprKind::Catch(ref blk) => {
+ self.head("do catch")?;
+ space(&mut self.s)?;
+ self.print_block_with_attrs(&blk, attrs)?
+ }
}
self.ann.post(self, NodeExpr(expr))?;
self.end()
vis: ast::Visibility::Inherited,
node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| {
- ast::Ident::from_str(name).into()
+ ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP)
}).collect(),
span: span,
})))),
(53, Default, "default")
(54, StaticLifetime, "'static")
(55, Union, "union")
+ (56, Catch, "catch")
// A virtual keyword that resolves to the crate root when used in a lexical scope.
- (56, CrateRoot, "{{root}}")
+ (57, CrateRoot, "{{root}}")
}
// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
fn path_node(ids: Vec<Ident>) -> ast::Path {
ast::Path {
span: DUMMY_SP,
- segments: ids.into_iter().map(Into::into).collect(),
+ segments: ids.into_iter().map(|id| ast::PathSegment::from_ident(id, DUMMY_SP)).collect(),
}
}
ExprKind::Try(ref subexpression) => {
visitor.visit_expr(subexpression)
}
+ ExprKind::Catch(ref body) => {
+ visitor.visit_block(body)
+ }
}
visitor.visit_expr_post(expression)
fn path(&self) -> ast::Path {
ast::Path {
span: self.span,
- segments: vec![self.ident.into()],
+ segments: vec![ast::PathSegment::from_ident(self.ident, self.span)],
}
}
}
+++ /dev/null
-# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
-# The actual contents of this file do not matter, but to trigger a change on the
-# build bots then the contents should be changed so git updates the mtime.
-2017-03-04
--- /dev/null
+# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
+# The actual contents of this file do not matter, but to trigger a change on the
+# build bots then the contents should be changed so git updates the mtime.
+2017-03-04
pkd.data = 42;
result
}
+
+pub struct Array([i32; 8]);
+#[repr(packed)]
+pub struct BigPacked {
+ dealign: u8,
+ data: Array
+}
+
+// CHECK-LABEL: @call_pkd
+#[no_mangle]
+pub fn call_pkd(f: fn() -> Array) -> BigPacked {
+// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
+// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 1, i1 false)
+ // check that calls whose destination is a field of a packed struct
+ // go through an alloca rather than calling the function with an
+ // unaligned destination.
+ BigPacked { dealign: 0, data: f() }
+}
+
+#[repr(packed)]
+#[derive(Copy, Clone)]
+pub struct PackedPair(u8, u32);
+
+// CHECK-LABEL: @pkd_pair
+#[no_mangle]
+pub fn pkd_pair(pair1: &mut PackedPair, pair2: &mut PackedPair) {
+ // CHECK: [[V1:%[a-z0-9]+]] = load i8, i8* %{{.*}}, align 1
+ // CHECK: [[V2:%[a-z0-9]+]] = load i32, i32* %{{.*}}, align 1
+ // CHECK: store i8 [[V1]], i8* {{.*}}, align 1
+ // CHECK: store i32 [[V2]], i32* {{.*}}, align 1
+ *pair2 = *pair1;
+}
--- /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(catch_expr)]
+
+fn main() {
+ match do catch { false } { _ => {} } //~ ERROR expected expression, found reserved keyword `do`
+}
--- /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(catch_expr)]
+
+fn main() {
+ while do catch { false } {} //~ ERROR expected expression, found reserved keyword `do`
+}
--- /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.
+
+pub fn main() {
+ let catch_result = do catch { //~ ERROR `catch` expression is experimental
+ let x = 5;
+ x
+ };
+ assert_eq!(catch_result, 5);
+}
--- /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(catch_expr)]
+
+struct catch {}
+
+pub fn main() {
+ let catch_result = do catch {
+ let x = 5;
+ x
+ };
+ assert_eq!(catch_result, 5);
+
+ let mut catch = true;
+ while catch { catch = false; }
+ assert_eq!(catch, false);
+
+ catch = if catch { false } else { true };
+ assert_eq!(catch, true);
+
+ match catch {
+ _ => {}
+ };
+}
error[E0425]: cannot find value `A` in module `namespaced_enums`
- --> $DIR/enums-are-namespaced-xc.rs:15:13
+ --> $DIR/enums-are-namespaced-xc.rs:15:31
|
15 | let _ = namespaced_enums::A;
- | ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums`
+ | ^ not found in `namespaced_enums`
|
= help: possible candidate is found in another module, you can import it into scope:
`use namespaced_enums::Foo::A;`
error[E0425]: cannot find function `B` in module `namespaced_enums`
- --> $DIR/enums-are-namespaced-xc.rs:18:13
+ --> $DIR/enums-are-namespaced-xc.rs:18:31
|
18 | let _ = namespaced_enums::B(10);
- | ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums`
+ | ^ not found in `namespaced_enums`
|
= help: possible candidate is found in another module, you can import it into scope:
`use namespaced_enums::Foo::B;`
error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums`
- --> $DIR/enums-are-namespaced-xc.rs:21:13
+ --> $DIR/enums-are-namespaced-xc.rs:21:31
|
21 | let _ = namespaced_enums::C { a: 10 };
- | ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums`
+ | ^ not found in `namespaced_enums`
|
= help: possible candidate is found in another module, you can import it into scope:
`use namespaced_enums::Foo::C;`
--> $DIR/levenshtein.rs:20:10
|
20 | type B = Opiton<u8>; // Misspelled type name from the prelude.
- | ^^^^^^^^^^ did you mean `Option`?
+ | ^^^^^^ did you mean `Option`?
error[E0412]: cannot find type `Baz` in this scope
--> $DIR/levenshtein.rs:23:14
| ^^^^^^ did you mean `foo_bar`?
error[E0412]: cannot find type `first` in module `m`
- --> $DIR/levenshtein.rs:32:12
+ --> $DIR/levenshtein.rs:32:15
|
32 | let b: m::first = m::second; // Misspelled item in module.
- | ^^^^^^^^ did you mean `m::First`?
+ | ^^^^^ did you mean `First`?
error[E0425]: cannot find value `second` in module `m`
- --> $DIR/levenshtein.rs:32:23
+ --> $DIR/levenshtein.rs:32:26
|
32 | let b: m::first = m::second; // Misspelled item in module.
- | ^^^^^^^^^ did you mean `m::Second`?
+ | ^^^^^^ did you mean `Second`?
error: aborting due to 8 previous errors
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5
|
27 | a.I
- | ^ did you mean `a::I`?
+ | ^--
+ | |
+ | did you mean `a::I`?
error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:33:5
|
33 | a.g()
- | ^ did you mean `a::g(...)`?
+ | ^----
+ | |
+ | did you mean `a::g(...)`?
error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:39:5
|
39 | a.b.J
- | ^ did you mean `a::b`?
+ | ^--
+ | |
+ | did you mean `a::b`?
error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
|
45 | a::b.J
- | ^^^^ did you mean `a::b::J`?
+ | ^^^^--
+ | |
+ | did you mean `a::b::J`?
error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:51:5
|
51 | a.b.f();
- | ^ did you mean `a::b`?
+ | ^--
+ | |
+ | did you mean `a::b`?
error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:12
|
55 | v.push(a::b);
- | ^^^^ did you mean `a::I`?
+ | ^^^-
+ | |
+ | did you mean `I`?
error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:61:5
|
61 | a::b.f()
- | ^^^^ did you mean `a::b::f(...)`?
+ | ^^^^----
+ | |
+ | did you mean `a::b::f(...)`?
error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:67:5
|
67 | a::b
- | ^^^^ did you mean `a::I`?
+ | ^^^-
+ | |
+ | did you mean `I`?
error[E0423]: expected function, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:73:5
|
73 | a::b()
- | ^^^^ did you mean `a::I`?
+ | ^^^-
+ | |
+ | did you mean `I`?
error: main function not found
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:11:8
|
11 | fn f<F:Nonexist(isize) -> isize>(x: F) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+ | ^^^^^^^^ not found in this scope
error[E0404]: expected trait, found type alias `Typedef`
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:17:8
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+
+trait Tr {
+ const C: Self;
+}
+
+fn main() {
+ let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied
+}
--- /dev/null
+error[E0277]: the trait bound `u8: Tr` is not satisfied
+ --> $DIR/issue-29595.rs:18:17
+ |
+18 | let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied
+ | ^^^^^ the trait `Tr` is not implemented for `u8`
+ |
+ = note: required by `Tr::C`
+
+error: aborting due to previous error
+
let mut components = Vec::new();
let mut extensions = Vec::new();
- // rustc/rust-std/cargo are all required, and so is rust-mingw if it's
- // available for the target.
+ // rustc/rust-std/cargo/docs are all required, and so is rust-mingw
+ // if it's available for the target.
components.extend(vec![
Component { pkg: "rustc".to_string(), target: host.to_string() },
Component { pkg: "rust-std".to_string(), target: host.to_string() },
Component { pkg: "cargo".to_string(), target: host.to_string() },
+ Component { pkg: "rust-docs".to_string(), target: host.to_string() },
]);
if host.contains("pc-windows-gnu") {
components.push(Component {
});
}
- // Docs, other standard libraries, and the source package are all
- // optional.
- extensions.push(Component {
- pkg: "rust-docs".to_string(),
- target: host.to_string(),
- });
for target in TARGETS {
if target != host {
extensions.push(Component {
clap = "2.19.3"
[dependencies.mdbook]
-version = "0.0.17"
+version = "0.0.18"
default-features = false