[submodule "src/binaryen"]
path = src/binaryen
url = https://github.com/alexcrichton/binaryen.git
+[submodule "src/doc/rust-by-example"]
+ path = src/doc/rust-by-example
+ url = https://github.com/rust-lang/rust-by-example
if: branch = auto
- env: IMAGE=dist-armv7-linux DEPLOY=1
if: branch = auto
- - env: IMAGE=dist-i586-gnu-i686-musl DEPLOY=1
+ - env: IMAGE=dist-i586-gnu-i586-i686-musl DEPLOY=1
if: branch = auto
- env: IMAGE=dist-i686-freebsd DEPLOY=1
if: branch = auto
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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.5 (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 = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"libgit2-sys 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
"socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz-sys 0.1.10 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (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 = [
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"libgit2-sys 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "jobserver"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
-version = "0.2.34"
+version = "0.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.2 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.0 (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 = [
"fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
dependencies = [
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
]
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fmt_macros 0.0.0",
"graphviz 0.0.0",
- "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_apfloat 0.0.0",
"rustc_back 0.0.0",
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.25 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5"
"checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
-"checksum jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "931b04e5e57d88cc909528f0d701db36a870b72a052648ded8baf80f9f445e0f"
+"checksum jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "565f6106bd87b394398f813bea4e5ecad6d6b0f6aa077592d088f882a506481d"
"checksum json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)" = "39ebf0fac977ee3a4a3242b6446004ff64514889e3e2730bbd4f764a67a2e483"
"checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
-"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
+"checksum libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "96264e9b293e95d25bfcbbf8a88ffd1aedc85b754eba8b7d78012f638ba220eb"
"checksum libgit2-sys 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "82fc20bd8beefe7c9f98aae2d3cff78e57f544cdd83d58fe181ec37a5fbe0c77"
"checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16"
fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
- let libdir = env::var_os("RUSTC_LIBDIR").expect("RUSTC_LIBDIR was not set");
+ let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set");
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
+ use std::str::FromStr;
+
+ let verbose = match env::var("RUSTC_VERBOSE") {
+ Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
+ Err(_) => 0,
+ };
+
let mut dylib_path = bootstrap::util::dylib_path();
dylib_path.insert(0, PathBuf::from(libdir));
cmd.arg("--deny-render-differences");
}
+ if verbose > 1 {
+ eprintln!("rustdoc command: {:?}", cmd);
+ }
+
std::process::exit(match cmd.status() {
Ok(s) => s.code().unwrap_or(1),
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
Kind::Bench => describe!(check::Crate, check::CrateLibrustc),
Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
- doc::Reference, doc::Rustdoc, doc::CargoBook),
+ doc::Reference, doc::Rustdoc, doc::RustByExample, doc::CargoBook),
Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts,
dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo,
dist::Rls, dist::Rustfmt, dist::Extended, dist::HashSign,
fn run(self, builder: &Builder) -> Interned<PathBuf> {
let compiler = self.compiler;
- let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() {
- builder.build.config.libdir_relative.clone().unwrap()
+ let lib = if compiler.stage >= 1 && builder.build.config.libdir.is_some() {
+ builder.build.config.libdir.clone().unwrap()
} else {
PathBuf::from("lib")
};
let compiler = self.compiler(self.top_stage, host);
cmd.env("RUSTC_STAGE", compiler.stage.to_string())
.env("RUSTC_SYSROOT", self.sysroot(compiler))
- .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
+ .env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
.env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
.env("RUSTDOC_REAL", self.rustdoc(host))
.env("RUSTDOC_CRATE_VERSION", self.build.rust_version())
if let Some(target_linker) = self.build.linker(target) {
cargo.env("RUSTC_TARGET_LINKER", target_linker);
}
+ if cmd != "build" {
+ cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.build.build)));
+ }
if mode != Mode::Tool {
// Tools don't get debuginfo right now, e.g. cargo and rls don't
}
Mode::Librustc => {
builder.ensure(compile::Rustc { compiler, target });
- compile::rustc_cargo(build, &compiler, target, &mut cargo);
+ compile::rustc_cargo(build, target, &mut cargo);
("librustc", "rustc-main")
}
_ => panic!("can only test libraries"),
build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
- rustc_cargo(build, &compiler, target, &mut cargo);
+ rustc_cargo(build, target, &mut cargo);
run_cargo(build,
&mut cargo,
&librustc_stamp(build, compiler, target));
/// Same as `std_cargo`, but for libtest
pub fn rustc_cargo(build: &Build,
- compiler: &Compiler,
target: Interned<String>,
cargo: &mut Command) {
cargo.arg("--features").arg(build.rustc_features())
.env("CFG_VERSION", build.rust_version())
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
- if compiler.stage == 0 {
- cargo.env("CFG_LIBDIR_RELATIVE", "lib");
- } else {
- let libdir_relative =
- build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib"));
- cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
- }
+ let libdir_relative =
+ build.config.libdir.clone().unwrap_or(PathBuf::from("lib"));
+ cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
// If we're not building a compiler with debugging information then remove
// these two env vars which would be set otherwise.
pub docdir: Option<PathBuf>,
pub bindir: Option<PathBuf>,
pub libdir: Option<PathBuf>,
- pub libdir_relative: Option<PathBuf>,
pub mandir: Option<PathBuf>,
pub codegen_tests: bool,
pub nodejs: Option<PathBuf>,
"MUSL root installation directory (deprecated)")
v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root",
"x86_64-unknown-linux-musl install directory")
+v("musl-root-i586", "target.i586-unknown-linux-musl.musl-root",
+ "i586-unknown-linux-musl install directory")
v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root",
"i686-unknown-linux-musl install directory")
v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root",
//!
//! This module implements generation for all bits and pieces of documentation
//! for the Rust project. This notably includes suites like the rust book, the
-//! nomicon, standalone documentation, etc.
+//! nomicon, rust by example, standalone documentation, etc.
//!
//! Everything here is basically just a shim around calling either `rustbook` or
//! `rustdoc`.
Nomicon, "src/doc/nomicon", "nomicon";
Reference, "src/doc/reference", "reference";
Rustdoc, "src/doc/rustdoc", "rustdoc";
+ RustByExample, "src/doc/rust-by-example", "rust-by-example";
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
t!(symlink_dir_force(&my_out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
- compile::rustc_cargo(build, &compiler, target, &mut cargo);
+ compile::rustc_cargo(build, target, &mut cargo);
if build.config.compiler_docs {
// src/rustc/Cargo.toml contains a bin crate called rustc which
"arm-unknown-linux-gnueabihf" => "linux-armv4",
"armv7-linux-androideabi" => "android-armv7",
"armv7-unknown-linux-gnueabihf" => "linux-armv4",
+ "i586-unknown-linux-gnu" => "linux-elf",
+ "i586-unknown-linux-musl" => "linux-elf",
"i686-apple-darwin" => "darwin-i386-cc",
"i686-linux-android" => "android-x86",
"i686-unknown-freebsd" => "BSD-x86-elf",
--- /dev/null
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ g++-multilib \
+ make \
+ file \
+ curl \
+ ca-certificates \
+ python2.7 \
+ git \
+ cmake \
+ xz-utils \
+ sudo \
+ gdb \
+ patch \
+ libssl-dev \
+ pkg-config
+
+WORKDIR /build/
+COPY scripts/musl.sh /build/
+RUN CC=gcc CFLAGS="-m32 -fPIC -Wa,-mrelax-relocations=no" \
+ CXX=g++ CXXFLAGS="-m32 -Wa,-mrelax-relocations=no" \
+ bash musl.sh i686 --target=i686 && \
+ CC=gcc CFLAGS="-march=pentium -m32 -fPIC -Wa,-mrelax-relocations=no" \
+ CXX=g++ CXXFLAGS="-march=pentium -m32 -Wa,-mrelax-relocations=no" \
+ bash musl.sh i586 --target=i586 && \
+ rm -rf /build
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV RUST_CONFIGURE_ARGS \
+ --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
+ --musl-root-i586=/musl-i586 \
+ --musl-root-i686=/musl-i686 \
+ --enable-extended
+
+# Newer binutils broke things on some vms/distros (i.e., linking against
+# unknown relocs disabled by the following flag), so we need to go out of our
+# way to produce "super compatible" binaries.
+#
+# See: https://github.com/rust-lang/rust/issues/34978
+ENV CFLAGS_i686_unknown_linux_musl=-Wa,-mrelax-relocations=no
+ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
+# FIXME remove -Wl,-melf_i386 after cc is updated to include
+# https://github.com/alexcrichton/cc-rs/pull/281
+ENV CFLAGS_i586_unknown_linux_musl="-Wa,-mrelax-relocations=no -Wl,-melf_i386"
+
+ENV TARGETS=i586-unknown-linux-gnu
+ENV TARGETS=$TARGETS,i686-unknown-linux-musl
+
+ENV SCRIPT \
+ python2.7 ../x.py test --target $TARGETS && \
+ python2.7 ../x.py dist --target $TARGETS,i586-unknown-linux-musl
+++ /dev/null
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- g++-multilib \
- make \
- file \
- curl \
- ca-certificates \
- python2.7 \
- git \
- cmake \
- xz-utils \
- sudo \
- gdb \
- patch \
- libssl-dev \
- pkg-config
-
-WORKDIR /build/
-COPY scripts/musl.sh /build/
-RUN CC=gcc CFLAGS="-m32 -fPIC -Wa,-mrelax-relocations=no" \
- CXX=g++ CXXFLAGS="-m32 -Wa,-mrelax-relocations=no" \
- bash musl.sh i686 --target=i686 && \
- rm -rf /build
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-ENV RUST_CONFIGURE_ARGS \
- --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
- --musl-root-i686=/musl-i686 \
- --enable-extended
-
-# Newer binutils broke things on some vms/distros (i.e., linking against
-# unknown relocs disabled by the following flag), so we need to go out of our
-# way to produce "super compatible" binaries.
-#
-# See: https://github.com/rust-lang/rust/issues/34978
-ENV CFLAGS_i686_unknown_linux_musl=-Wa,-mrelax-relocations=no
-ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
-
-ENV SCRIPT \
- python2.7 ../x.py test \
- --target i686-unknown-linux-musl \
- --target i586-unknown-linux-gnu \
- && \
- python2.7 ../x.py dist \
- --target i686-unknown-linux-musl \
- --target i586-unknown-linux-gnu
TAG=$1
shift
-MUSL=musl-1.1.17
+MUSL=musl-1.1.18
# may have been downloaded in a previous run
if [ ! -d $MUSL ]; then
cd $MUSL
./configure --disable-shared --prefix=/musl-$TAG $@
-if [ "$TAG" = "i686" ]; then
+if [ "$TAG" = "i586" -o "$TAG" = "i686" ]; then
hide_output make -j$(nproc) AR=ar RANLIB=ranlib
else
hide_output make -j$(nproc)
--- /dev/null
+Subproject commit 4ebb8169dfe569b3dcbeab560607800bb717978a
* except according to those terms.
*/
@font-face {
- font-family: 'Fira Sans';
- font-style: normal;
- font-weight: 400;
- src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
+ font-family: 'Fira Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
}
@font-face {
- font-family: 'Fira Sans';
- font-style: normal;
- font-weight: 500;
- src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
+ font-family: 'Fira Sans';
+ font-style: normal;
+ font-weight: 500;
+ src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
}
@font-face {
- font-family: 'Source Serif Pro';
- font-style: normal;
- font-weight: 400;
- src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff');
+ font-family: 'Source Serif Pro';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff');
}
@font-face {
- font-family: 'Source Serif Pro';
- font-style: italic;
- font-weight: 400;
- src: url("Heuristica-Italic.woff") format('woff');
+ font-family: 'Source Serif Pro';
+ font-style: italic;
+ font-weight: 400;
+ src: url("Heuristica-Italic.woff") format('woff');
}
@font-face {
- font-family: 'Source Serif Pro';
- font-style: normal;
- font-weight: 700;
- src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff');
+ font-family: 'Source Serif Pro';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff');
}
@font-face {
- font-family: 'Source Code Pro';
- font-style: normal;
- font-weight: 400;
- /* Avoid using locally installed font because bad versions are in circulation:
- * see https://github.com/rust-lang/rust/issues/24355 */
- src: url("SourceCodePro-Regular.woff") format('woff');
+ font-family: 'Source Code Pro';
+ font-style: normal;
+ font-weight: 400;
+ /* Avoid using locally installed font because bad versions are in circulation:
+ * see https://github.com/rust-lang/rust/issues/24355 */
+ src: url("SourceCodePro-Regular.woff") format('woff');
}
*:not(body) {
-webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
}
/* General structure */
body {
- background-color: white;
- margin: 0 auto;
- padding: 0 15px;
- font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
- font-size: 18px;
- color: #333;
- line-height: 1.428571429;
-
- -webkit-font-feature-settings: "kern", "liga";
- -moz-font-feature-settings: "kern", "liga";
- font-feature-settings: "kern", "liga";
+ background-color: white;
+ margin: 0 auto;
+ padding: 0 15px;
+ font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
+ font-size: 18px;
+ color: #333;
+ line-height: 1.428571429;
+
+ -webkit-font-feature-settings: "kern", "liga";
+ -moz-font-feature-settings: "kern", "liga";
+ font-feature-settings: "kern", "liga";
}
@media (min-width: 768px) {
- body {
- max-width: 750px;
- }
+ body {
+ max-width: 750px;
+ }
}
h1, h2, h3, h4, h5, h6, nav, #versioninfo {
- font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
h1, h2, h3, h4, h5, h6 {
- color: black;
- font-weight: 400;
- line-height: 1.1;
+ color: black;
+ font-weight: 400;
+ line-height: 1.1;
}
h1, h2, h3 {
- margin-top: 20px;
- margin-bottom: 15px;
+ margin-top: 20px;
+ margin-bottom: 15px;
}
h1 {
- margin-bottom: 20px;
+ margin-bottom: 20px;
}
h4, h5, h6 {
- margin-top: 12px;
- margin-bottom: 10px;
- padding: 5px 10px;
+ margin-top: 12px;
+ margin-bottom: 10px;
+ padding: 5px 10px;
}
h5, h6 {
- text-decoration: underline;
+ text-decoration: underline;
}
h1 {
- font-size: 28px;
- font-weight: 500;
- padding: .1em .4em;
- border-bottom: 2px solid #ddd;
+ font-size: 28px;
+ font-weight: 500;
+ padding: .1em .4em;
+ border-bottom: 2px solid #ddd;
}
h1.title {
- line-height: 1.5em;
+ line-height: 1.5em;
}
h2 {
- font-size: 26px;
- padding: .2em .5em;
- border-bottom: 1px solid #ddd;
+ font-size: 26px;
+ padding: .2em .5em;
+ border-bottom: 1px solid #ddd;
}
h3 {
- font-size: 24px;
- padding: .2em .7em;
- border-bottom: 1px solid #DDE8FC;
+ font-size: 24px;
+ padding: .2em .7em;
+ border-bottom: 1px solid #DDE8FC;
}
h4 {
- font-size: 22px;
+ font-size: 22px;
}
h5 {
- font-size: 20px;
+ font-size: 20px;
}
h6 {
- font-size: 18px;
+ font-size: 18px;
}
@media (min-width: 992px) {
- h1 {
- font-size: 36px;
- }
- h2 {
- font-size: 30px;
- }
- h3 {
- font-size: 26px;
- }
+ h1 {
+ font-size: 36px;
+ }
+ h2 {
+ font-size: 30px;
+ }
+ h3 {
+ font-size: 26px;
+ }
}
nav {
- column-count: 2;
- -moz-column-count: 2;
- -webkit-column-count: 2;
- font-size: 15px;
- margin: 0 0 1em 0;
+ column-count: 2;
+ -moz-column-count: 2;
+ -webkit-column-count: 2;
+ font-size: 15px;
+ margin: 0 0 1em 0;
}
p {
- margin: 0 0 1em 0;
+ margin: 0 0 1em 0;
}
strong {
- font-weight: bold;
+ font-weight: bold;
}
em {
- font-style: italic;
+ font-style: italic;
}
footer {
- border-top: 1px solid #ddd;
- font-size: 14px;
- font-style: italic;
- padding-top: 5px;
- margin-top: 3em;
- margin-bottom: 1em;
+ border-top: 1px solid #ddd;
+ font-size: 14px;
+ font-style: italic;
+ padding-top: 5px;
+ margin-top: 3em;
+ margin-bottom: 1em;
}
/* Links layout */
a {
- text-decoration: none;
- color: #428BCA;
- background: transparent;
+ text-decoration: none;
+ color: #428BCA;
+ background: transparent;
}
a:hover, a:focus {
- color: #2A6496;
- text-decoration: underline;
+ color: #2A6496;
+ text-decoration: underline;
}
a:focus {
- outline: thin dotted #333;
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
+ outline: thin dotted #333;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
}
a:hover, a:active {
- outline: 0;
+ outline: 0;
}
h1 a:link, h1 a:visited, h2 a:link, h2 a:visited,
/* Code */
pre, code {
- font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace;
- word-wrap: break-word;
+ font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace;
+ word-wrap: break-word;
}
pre {
- border-left: 2px solid #eee;
- white-space: pre-wrap;
- padding: 14px;
- padding-right: 0;
- margin: 20px 0;
- font-size: 13px;
- word-break: break-all;
+ border-left: 2px solid #eee;
+ white-space: pre-wrap;
+ padding: 14px;
+ padding-right: 0;
+ margin: 20px 0;
+ font-size: 15px;
+ word-break: break-all;
}
code {
- padding: 0 2px;
- color: #8D1A38;
+ padding: 0 2px;
+ color: #8D1A38;
}
pre code {
- padding: 0;
- font-size: inherit;
- color: inherit;
+ padding: 0;
+ font-size: inherit;
+ color: inherit;
}
a > code {
- color: #428BCA;
+ color: #428BCA;
}
.section-header > a > code {
- color: #8D1A38;
+ color: #8D1A38;
}
/* Code highlighting */
/* The rest */
#versioninfo {
- text-align: center;
- margin: 0.5em;
- font-size: 1.1em;
+ text-align: center;
+ margin: 0.5em;
+ font-size: 1.1em;
}
@media (min-width: 992px) {
- #versioninfo {
- font-size: 0.8em;
- position: fixed;
- bottom: 0px;
- right: 0px;
- }
- .white-sticker {
- background-color: #fff;
- margin: 2px;
- padding: 0 2px;
- border-radius: .2em;
- }
+ #versioninfo {
+ font-size: 0.8em;
+ position: fixed;
+ bottom: 0px;
+ right: 0px;
+ }
+ .white-sticker {
+ background-color: #fff;
+ margin: 2px;
+ padding: 0 2px;
+ border-radius: .2em;
+ }
}
#versioninfo a.hash {
- color: gray;
- font-size: 80%;
+ color: gray;
+ font-size: 80%;
}
blockquote {
- color: #000;
- margin: 20px 0;
- padding: 15px 20px;
- background-color: #f2f7f9;
- border-top: .1em solid #e5eef2;
- border-bottom: .1em solid #e5eef2;
+ color: #000;
+ margin: 20px 0;
+ padding: 15px 20px;
+ background-color: #f2f7f9;
+ border-top: .1em solid #e5eef2;
+ border-bottom: .1em solid #e5eef2;
}
blockquote p {
- font-size: 17px;
- font-weight: 300;
- line-height: 1.4;
+ font-size: 17px;
+ font-weight: 300;
+ line-height: 1.4;
}
blockquote p:last-child {
- margin-bottom: 0;
+ margin-bottom: 0;
}
ul, ol {
- padding-left: 25px;
+ padding-left: 25px;
}
ul ul, ol ul, ul ol, ol ol {
- margin-bottom: 0;
+ margin-bottom: 0;
}
dl {
- margin-bottom: 20px;
+ margin-bottom: 20px;
}
dd {
- margin-left: 0;
+ margin-left: 0;
}
nav ul {
- list-style-type: none;
- margin: 0;
- padding-left: 0px;
+ list-style-type: none;
+ margin: 0;
+ padding-left: 0px;
}
/* Only display one level of hierarchy in the TOC */
nav ul ul {
- display: none;
+ display: none;
}
sub,
sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
}
hr {
- margin-top: 20px;
- margin-bottom: 20px;
- border: 0;
- border-top: 1px solid #eeeeee;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 0;
+ border-top: 1px solid #eeeeee;
}
table {
- border-collapse: collapse;
- border-spacing: 0;
- overflow-x: auto;
- display: block;
+ border-collapse: collapse;
+ border-spacing: 0;
+ overflow-x: auto;
+ display: block;
}
table tr.odd {
- background: #eee;
+ background: #eee;
}
table td,
table th {
- border: 1px solid #ddd;
- padding: 5px;
+ border: 1px solid #ddd;
+ padding: 5px;
}
/* Code snippets */
pre.rust { position: relative; }
a.test-arrow {
- background-color: rgba(78, 139, 202, 0.2);
- display: inline-block;
- position: absolute;
- color: #f5f5f5;
- padding: 5px 10px 5px 10px;
- border-radius: 5px;
- font-size: 130%;
- top: 5px;
- right: 5px;
+ background-color: rgba(78, 139, 202, 0.2);
+ display: inline-block;
+ position: absolute;
+ color: #f5f5f5;
+ padding: 5px 10px 5px 10px;
+ border-radius: 5px;
+ font-size: 130%;
+ top: 5px;
+ right: 5px;
}
a.test-arrow:hover{
- background-color: #4e8bca;
- text-decoration: none;
+ background-color: #4e8bca;
+ text-decoration: none;
}
.unstable-feature {
- border: 2px solid red;
- padding: 5px;
+ border: 2px solid red;
+ padding: 5px;
}
@media (min-width: 1170px) {
- pre {
- font-size: 15px;
- }
+ pre {
+ font-size: 15px;
+ }
}
@media print {
- * {
- text-shadow: none !important;
- color: #000 !important;
- background: transparent !important;
- box-shadow: none !important;
- }
- a, a:visited {
- text-decoration: underline;
- }
- p a[href]:after {
- content: " (" attr(href) ")";
- }
- footer a[href]:after {
- content: "";
- }
- a[href^="javascript:"]:after, a[href^="#"]:after {
- content: "";
- }
- pre, blockquote {
- border: 1px solid #999;
- page-break-inside: avoid;
- }
- @page {
- margin: 2cm .5cm;
- }
- h1:not(.title), h2, h3 {
- border-bottom: 0px none;
- }
- p, h2, h3 {
- orphans: 3;
- widows: 3;
- }
- h2, h3 {
- page-break-after: avoid;
- }
- table {
- border-collapse: collapse !important;
- }
- table td, table th {
- background-color: #fff !important;
- }
+ * {
+ text-shadow: none !important;
+ color: #000 !important;
+ background: transparent !important;
+ box-shadow: none !important;
+ }
+ a, a:visited {
+ text-decoration: underline;
+ }
+ p a[href]:after {
+ content: " (" attr(href) ")";
+ }
+ footer a[href]:after {
+ content: "";
+ }
+ a[href^="javascript:"]:after, a[href^="#"]:after {
+ content: "";
+ }
+ pre, blockquote {
+ border: 1px solid #999;
+ page-break-inside: avoid;
+ }
+ @page {
+ margin: 2cm .5cm;
+ }
+ h1:not(.title), h2, h3 {
+ border-bottom: 0px none;
+ }
+ p, h2, h3 {
+ orphans: 3;
+ widows: 3;
+ }
+ h2, h3 {
+ page-break-after: avoid;
+ }
+ table {
+ border-collapse: collapse !important;
+ }
+ table td, table th {
+ background-color: #fff !important;
+ }
}
#keyword-table-marker + table thead { display: none; }
#keyword-table-marker + table td { border: none; }
#keyword-table-marker + table {
- margin-left: 2em;
- margin-bottom: 1em;
+ margin-left: 2em;
+ margin-bottom: 1em;
+}
+
+.error-described {
+ position: relative;
+}
+
+.information {
+ position: absolute;
+ left: -25px;
+ margin-top: 7px;
+ z-index: 1;
+}
+
+.tooltip {
+ position: relative;
+ display: inline-block;
+ cursor: pointer;
+}
+
+.tooltip .tooltiptext {
+ width: 120px;
+ display: none;
+ text-align: center;
+ padding: 5px 3px;
+ border-radius: 6px;
+ margin-left: 5px;
+ top: -5px;
+ left: 105%;
+ z-index: 1;
+}
+
+.tooltip:hover .tooltiptext {
+ display: inline;
+}
+
+.tooltip .tooltiptext::after {
+ content: " ";
+ position: absolute;
+ top: 50%;
+ left: 13px;
+ margin-top: -5px;
+ border-width: 5px;
+ border-style: solid;
}
fn $name(b: &mut Bencher) {
let size = mem::size_of_val(&$gen(1)[0]);
let mut v = $gen($len * 8 / size);
- b.iter(|| black_box(&mut v).rotate(($mid*8+size-1)/size));
+ b.iter(|| black_box(&mut v).rotate_left(($mid*8+size-1)/size));
b.bytes = (v.len() * size) as u64;
}
}
#![feature(unsize)]
#![feature(allocator_internals)]
#![feature(on_unimplemented)]
+#![feature(exact_chunks)]
#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))]
#![cfg_attr(test, feature(test, box_heap))]
pub use core::slice::{from_ref, from_ref_mut};
#[unstable(feature = "slice_get_slice", issue = "35729")]
pub use core::slice::SliceIndex;
+#[unstable(feature = "exact_chunks", issue = "47115")]
+pub use core::slice::{ExactChunks, ExactChunksMut};
////////////////////////////////////////////////////////////////////////////////
// Basic slice extension methods
/// not divide the length of the slice, then the last chunk will
/// not have length `chunk_size`.
///
+ /// See [`exact_chunks`] for a variant of this iterator that returns chunks
+ /// of always exactly `chunk_size` elements.
+ ///
/// # Panics
///
/// Panics if `chunk_size` is 0.
core_slice::SliceExt::chunks(self, chunk_size)
}
+ /// Returns an iterator over `chunk_size` elements of the slice at a
+ /// time. The chunks are slices and do not overlap. If `chunk_size` does
+ /// not divide the length of the slice, then the last up to `chunk_size-1`
+ /// elements will be omitted.
+ ///
+ /// Due to each chunk having exactly `chunk_size` elements, the compiler
+ /// can often optimize the resulting code better than in the case of
+ /// [`chunks`].
+ ///
+ /// # Panics
+ ///
+ /// Panics if `chunk_size` is 0.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(exact_chunks)]
+ ///
+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
+ /// let mut iter = slice.exact_chunks(2);
+ /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+ /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+ /// assert!(iter.next().is_none());
+ /// ```
+ #[unstable(feature = "exact_chunks", issue = "47115")]
+ #[inline]
+ pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
+ core_slice::SliceExt::exact_chunks(self, chunk_size)
+ }
+
/// Returns an iterator over `chunk_size` elements of the slice at a time.
/// The chunks are mutable slices, and do not overlap. If `chunk_size` does
/// not divide the length of the slice, then the last chunk will not
/// have length `chunk_size`.
///
+ /// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks
+ /// of always exactly `chunk_size` elements.
+ ///
/// # Panics
///
/// Panics if `chunk_size` is 0.
core_slice::SliceExt::chunks_mut(self, chunk_size)
}
+ /// Returns an iterator over `chunk_size` elements of the slice at a time.
+ /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
+ /// not divide the length of the slice, then the last up to `chunk_size-1`
+ /// elements will be omitted.
+ ///
+ ///
+ /// Due to each chunk having exactly `chunk_size` elements, the compiler
+ /// can often optimize the resulting code better than in the case of
+ /// [`chunks_mut`].
+ ///
+ /// # Panics
+ ///
+ /// Panics if `chunk_size` is 0.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(exact_chunks)]
+ ///
+ /// let v = &mut [0, 0, 0, 0, 0];
+ /// let mut count = 1;
+ ///
+ /// for chunk in v.exact_chunks_mut(2) {
+ /// for elem in chunk.iter_mut() {
+ /// *elem += count;
+ /// }
+ /// count += 1;
+ /// }
+ /// assert_eq!(v, &[1, 1, 2, 2, 0]);
+ /// ```
+ #[unstable(feature = "exact_chunks", issue = "47115")]
+ #[inline]
+ pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
+ core_slice::SliceExt::exact_chunks_mut(self, chunk_size)
+ }
+
/// Divides one slice into two at an index.
///
/// The first will contain all indices from `[0, mid)` (excluding
core_slice::SliceExt::sort_unstable_by_key(self, f);
}
- /// Permutes the slice in-place such that `self[mid..]` moves to the
- /// beginning of the slice while `self[..mid]` moves to the end of the
- /// slice. Equivalently, rotates the slice `mid` places to the left
- /// or `k = self.len() - mid` places to the right.
+ /// Rotates the slice in-place such that the first `mid` elements of the
+ /// slice move to the end while the last `self.len() - mid` elements move to
+ /// the front. After calling `rotate_left`, the element previously at index
+ /// `mid` will become the first element in the slice.
///
- /// This is a "k-rotation", a permutation in which item `i` moves to
- /// position `i + k`, modulo the length of the slice. See _Elements
- /// of Programming_ [§10.4][eop].
+ /// # Panics
///
- /// Rotation by `mid` and rotation by `k` are inverse operations.
+ /// This function will panic if `mid` is greater than the length of the
+ /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op
+ /// rotation.
///
- /// [eop]: https://books.google.com/books?id=CO9ULZGINlsC&pg=PA178&q=k-rotation
+ /// # Complexity
+ ///
+ /// Takes linear (in `self.len()`) time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_rotate)]
+ ///
+ /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+ /// a.rotate_left(2);
+ /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
+ /// ```
+ ///
+ /// Rotating a subslice:
+ ///
+ /// ```
+ /// #![feature(slice_rotate)]
+ ///
+ /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+ /// a[1..5].rotate_left(1);
+ /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
+ /// ```
+ #[unstable(feature = "slice_rotate", issue = "41891")]
+ pub fn rotate_left(&mut self, mid: usize) {
+ core_slice::SliceExt::rotate_left(self, mid);
+ }
+
+ #[unstable(feature = "slice_rotate", issue = "41891")]
+ #[rustc_deprecated(since = "", reason = "renamed to `rotate_left`")]
+ pub fn rotate(&mut self, mid: usize) {
+ core_slice::SliceExt::rotate_left(self, mid);
+ }
+
+ /// Rotates the slice in-place such that the first `self.len() - k`
+ /// elements of the slice move to the end while the last `k` elements move
+ /// to the front. After calling `rotate_right`, the element previously at
+ /// index `self.len() - k` will become the first element in the slice.
///
/// # Panics
///
- /// This function will panic if `mid` is greater than the length of the
- /// slice. (Note that `mid == self.len()` does _not_ panic; it's a nop
- /// rotation with `k == 0`, the inverse of a rotation with `mid == 0`.)
+ /// This function will panic if `k` is greater than the length of the
+ /// slice. Note that `k == self.len()` does _not_ panic and is a no-op
+ /// rotation.
///
/// # Complexity
///
/// ```
/// #![feature(slice_rotate)]
///
- /// let mut a = [1, 2, 3, 4, 5, 6, 7];
- /// let mid = 2;
- /// a.rotate(mid);
- /// assert_eq!(&a, &[3, 4, 5, 6, 7, 1, 2]);
- /// let k = a.len() - mid;
- /// a.rotate(k);
- /// assert_eq!(&a, &[1, 2, 3, 4, 5, 6, 7]);
- ///
- /// use std::ops::Range;
- /// fn slide<T>(slice: &mut [T], range: Range<usize>, to: usize) {
- /// if to < range.start {
- /// slice[to..range.end].rotate(range.start-to);
- /// } else if to > range.end {
- /// slice[range.start..to].rotate(range.end-range.start);
- /// }
- /// }
- /// let mut v: Vec<_> = (0..10).collect();
- /// slide(&mut v, 1..4, 7);
- /// assert_eq!(&v, &[0, 4, 5, 6, 1, 2, 3, 7, 8, 9]);
- /// slide(&mut v, 6..8, 1);
- /// assert_eq!(&v, &[0, 3, 7, 4, 5, 6, 1, 2, 8, 9]);
+ /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+ /// a.rotate_right(2);
+ /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
+ /// ```
+ ///
+ /// Rotate a subslice:
+ ///
+ /// ```
+ /// #![feature(slice_rotate)]
+ ///
+ /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+ /// a[1..5].rotate_right(1);
+ /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
/// ```
#[unstable(feature = "slice_rotate", issue = "41891")]
- pub fn rotate(&mut self, mid: usize) {
- core_slice::SliceExt::rotate(self, mid);
+ pub fn rotate_right(&mut self, k: usize) {
+ core_slice::SliceExt::rotate_right(self, k);
}
/// Copies the elements from `src` into `self`.
/// let x = s.to_vec();
/// // Here, `s` and `x` can be modified independently.
/// ```
+ #[rustc_conversion_suggestion]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_vec(&self) -> Vec<T>
///
/// assert_eq!(five, i.to_string());
/// ```
+ #[rustc_conversion_suggestion]
#[stable(feature = "rust1", since = "1.0.0")]
fn to_string(&self) -> String;
}
#![feature(string_retain)]
#![feature(unboxed_closures)]
#![feature(unicode)]
+#![feature(exact_chunks)]
extern crate alloc_system;
extern crate std_unicode;
}
#[test]
-fn test_rotate() {
+fn test_rotate_left() {
let expected: Vec<_> = (0..13).collect();
let mut v = Vec::new();
// no-ops
v.clone_from(&expected);
- v.rotate(0);
+ v.rotate_left(0);
assert_eq!(v, expected);
- v.rotate(expected.len());
+ v.rotate_left(expected.len());
assert_eq!(v, expected);
let mut zst_array = [(), (), ()];
- zst_array.rotate(2);
+ zst_array.rotate_left(2);
// happy path
v = (5..13).chain(0..5).collect();
- v.rotate(8);
+ v.rotate_left(8);
assert_eq!(v, expected);
let expected: Vec<_> = (0..1000).collect();
// small rotations in large slice, uses ptr::copy
v = (2..1000).chain(0..2).collect();
- v.rotate(998);
+ v.rotate_left(998);
assert_eq!(v, expected);
v = (998..1000).chain(0..998).collect();
- v.rotate(2);
+ v.rotate_left(2);
assert_eq!(v, expected);
// non-small prime rotation, has a few rounds of swapping
v = (389..1000).chain(0..389).collect();
- v.rotate(1000-389);
+ v.rotate_left(1000-389);
+ assert_eq!(v, expected);
+}
+
+#[test]
+fn test_rotate_right() {
+ let expected: Vec<_> = (0..13).collect();
+ let mut v = Vec::new();
+
+ // no-ops
+ v.clone_from(&expected);
+ v.rotate_right(0);
+ assert_eq!(v, expected);
+ v.rotate_right(expected.len());
+ assert_eq!(v, expected);
+ let mut zst_array = [(), (), ()];
+ zst_array.rotate_right(2);
+
+ // happy path
+ v = (5..13).chain(0..5).collect();
+ v.rotate_right(5);
+ assert_eq!(v, expected);
+
+ let expected: Vec<_> = (0..1000).collect();
+
+ // small rotations in large slice, uses ptr::copy
+ v = (2..1000).chain(0..2).collect();
+ v.rotate_right(2);
+ assert_eq!(v, expected);
+ v = (998..1000).chain(0..998).collect();
+ v.rotate_right(998);
+ assert_eq!(v, expected);
+
+ // non-small prime rotation, has a few rounds of swapping
+ v = (389..1000).chain(0..389).collect();
+ v.rotate_right(389);
assert_eq!(v, expected);
}
let _it = v.chunks(0);
}
+#[test]
+fn test_exact_chunksator() {
+ let v = &[1, 2, 3, 4, 5];
+
+ assert_eq!(v.exact_chunks(2).len(), 2);
+
+ let chunks: &[&[_]] = &[&[1, 2], &[3, 4]];
+ assert_eq!(v.exact_chunks(2).collect::<Vec<_>>(), chunks);
+ let chunks: &[&[_]] = &[&[1, 2, 3]];
+ assert_eq!(v.exact_chunks(3).collect::<Vec<_>>(), chunks);
+ let chunks: &[&[_]] = &[];
+ assert_eq!(v.exact_chunks(6).collect::<Vec<_>>(), chunks);
+
+ let chunks: &[&[_]] = &[&[3, 4], &[1, 2]];
+ assert_eq!(v.exact_chunks(2).rev().collect::<Vec<_>>(), chunks);
+}
+
+#[test]
+#[should_panic]
+fn test_exact_chunksator_0() {
+ let v = &[1, 2, 3, 4];
+ let _it = v.exact_chunks(0);
+}
+
#[test]
fn test_reverse_part() {
let mut values = [1, 2, 3, 4, 5];
}
}
let result = [0, 0, 0, 1, 1, 1, 2];
- assert!(v == result);
+ assert_eq!(v, result);
}
#[test]
}
}
let result = [2, 2, 2, 1, 1, 1, 0];
- assert!(v == result);
+ assert_eq!(v, result);
}
#[test]
let _it = v.chunks_mut(0);
}
+#[test]
+fn test_mut_exact_chunks() {
+ let mut v = [0, 1, 2, 3, 4, 5, 6];
+ assert_eq!(v.exact_chunks_mut(2).len(), 3);
+ for (i, chunk) in v.exact_chunks_mut(3).enumerate() {
+ for x in chunk {
+ *x = i as u8;
+ }
+ }
+ let result = [0, 0, 0, 1, 1, 1, 6];
+ assert_eq!(v, result);
+}
+
+#[test]
+fn test_mut_exact_chunks_rev() {
+ let mut v = [0, 1, 2, 3, 4, 5, 6];
+ for (i, chunk) in v.exact_chunks_mut(3).rev().enumerate() {
+ for x in chunk {
+ *x = i as u8;
+ }
+ }
+ let result = [1, 1, 1, 0, 0, 0, 6];
+ assert_eq!(v, result);
+}
+
+#[test]
+#[should_panic]
+fn test_mut_exact_chunks_0() {
+ let mut v = [1, 2, 3, 4];
+ let _it = v.exact_chunks_mut(0);
+}
+
#[test]
fn test_mut_last() {
let mut x = [1, 2, 3, 4, 5];
impl<T> TypedArenaChunk<T> {
#[inline]
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
- TypedArenaChunk { storage: RawVec::with_capacity(capacity) }
+ TypedArenaChunk {
+ storage: RawVec::with_capacity(capacity),
+ }
}
/// Destroys this arena chunk.
unsafe {
if mem::size_of::<T>() == 0 {
- self.ptr.set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T);
+ self.ptr
+ .set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1)
+ as *mut T);
let ptr = mem::align_of::<T>() as *mut T;
// Don't drop the object. This `write` is equivalent to `forget`.
ptr::write(ptr, object);
/// - Zero-length slices
#[inline]
pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
- where T: Copy {
+ where
+ T: Copy,
+ {
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
let (chunk, mut new_capacity);
if let Some(last_chunk) = chunks.last_mut() {
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
- if last_chunk.storage.reserve_in_place(used_bytes, needed_bytes) {
+ if last_chunk
+ .storage
+ .reserve_in_place(used_bytes, needed_bytes)
+ {
self.end.set(last_chunk.end());
return;
} else {
let ptr = self.ptr.get();
// Set the pointer past ourselves
- self.ptr.set(intrinsics::arith_offset(
- self.ptr.get(), mem::size_of::<T>() as isize
- ) as *mut u8);
+ self.ptr.set(
+ intrinsics::arith_offset(self.ptr.get(), mem::size_of::<T>() as isize) as *mut u8,
+ );
// Write into uninitialized memory.
ptr::write(ptr as *mut T, object);
&mut *(ptr as *mut T)
/// - Zero-length slices
#[inline]
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
- where T: Copy {
+ where
+ T: Copy,
+ {
assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
unsafe {
let arena_slice = slice::from_raw_parts_mut(self.ptr.get() as *mut T, slice.len());
self.ptr.set(intrinsics::arith_offset(
- self.ptr.get(), (slice.len() * mem::size_of::<T>()) as isize
+ self.ptr.get(),
+ (slice.len() * mem::size_of::<T>()) as isize,
) as *mut u8);
arena_slice.copy_from_slice(slice);
arena_slice
let arena = Wrap(TypedArena::new());
- let result =
- arena.alloc_outer(|| Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) });
+ let result = arena.alloc_outer(|| Outer {
+ inner: arena.alloc_inner(|| Inner { value: 10 }),
+ });
assert_eq!(result.inner.value, 10);
}
/// some other means.
///
/// An important thing to remember is that the type `fmt::Error` should not be
-/// confused with `std::io::Error` or `std::error::Error`, which you may also
+/// confused with [`std::io::Error`] or [`std::error::Error`], which you may also
/// have in scope.
///
+/// [`std::io::Error`]: ../../std/io/struct.Error.html
+/// [`std::error::Error`]: ../../std/error/trait.Error.html
+///
/// # Examples
///
/// ```rust
self.start = self.end.clone();
None
}
+
+ #[inline]
+ fn last(mut self) -> Option<A> {
+ self.next_back()
+ }
+
+ #[inline]
+ fn min(mut self) -> Option<A> {
+ self.next()
+ }
+
+ #[inline]
+ fn max(mut self) -> Option<A> {
+ self.next_back()
+ }
}
// These macros generate `ExactSizeIterator` impls for various range types.
self.end.replace_zero();
None
}
+
+ #[inline]
+ fn last(mut self) -> Option<A> {
+ self.next_back()
+ }
+
+ #[inline]
+ fn min(mut self) -> Option<A> {
+ self.next()
+ }
+
+ #[inline]
+ fn max(mut self) -> Option<A> {
+ self.next_back()
+ }
}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
/// [ub]: ../../reference/behavior-considered-undefined.html
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
-pub unsafe trait Send {
+pub unsafe auto trait Send {
// empty.
}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-unsafe impl Send for .. { }
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Send for *const T { }
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
-pub unsafe trait Sync {
+pub unsafe auto trait Sync {
// Empty
}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-unsafe impl Sync for .. { }
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Sync for *const T { }
#[stable(feature = "rust1", since = "1.0.0")]
/// This affects, for example, whether a `static` of that type is
/// placed in read-only static memory or writable static memory.
#[lang = "freeze"]
-unsafe trait Freeze {}
-
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-unsafe impl Freeze for .. {}
+unsafe auto trait Freeze {}
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
#[stable(feature = "core", since = "1.6.0")]
fn chunks(&self, size: usize) -> Chunks<Self::Item>;
+ #[unstable(feature = "exact_chunks", issue = "47115")]
+ fn exact_chunks(&self, size: usize) -> ExactChunks<Self::Item>;
+
#[stable(feature = "core", since = "1.6.0")]
fn get<I>(&self, index: I) -> Option<&I::Output>
where I: SliceIndex<Self>;
#[stable(feature = "core", since = "1.6.0")]
fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<Self::Item>;
+ #[unstable(feature = "exact_chunks", issue = "47115")]
+ fn exact_chunks_mut(&mut self, size: usize) -> ExactChunksMut<Self::Item>;
+
#[stable(feature = "core", since = "1.6.0")]
fn swap(&mut self, a: usize, b: usize);
fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
#[unstable(feature = "slice_rotate", issue = "41891")]
- fn rotate(&mut self, mid: usize);
+ fn rotate_left(&mut self, mid: usize);
+
+ #[unstable(feature = "slice_rotate", issue = "41891")]
+ fn rotate_right(&mut self, k: usize);
#[stable(feature = "clone_from_slice", since = "1.7.0")]
fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone;
Chunks { v: self, chunk_size: chunk_size }
}
+ #[inline]
+ fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
+ assert!(chunk_size != 0);
+ let rem = self.len() % chunk_size;
+ let len = self.len() - rem;
+ ExactChunks { v: &self[..len], chunk_size: chunk_size}
+ }
+
#[inline]
fn get<I>(&self, index: I) -> Option<&I::Output>
where I: SliceIndex<[T]>
ChunksMut { v: self, chunk_size: chunk_size }
}
+ #[inline]
+ fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
+ assert!(chunk_size != 0);
+ let rem = self.len() % chunk_size;
+ let len = self.len() - rem;
+ ExactChunksMut { v: &mut self[..len], chunk_size: chunk_size}
+ }
+
#[inline]
fn swap(&mut self, a: usize, b: usize) {
unsafe {
self.binary_search_by(|p| p.cmp(x))
}
- fn rotate(&mut self, mid: usize) {
+ fn rotate_left(&mut self, mid: usize) {
assert!(mid <= self.len());
let k = self.len() - mid;
}
}
+ fn rotate_right(&mut self, k: usize) {
+ assert!(k <= self.len());
+ let mid = self.len() - k;
+
+ unsafe {
+ let p = self.as_mut_ptr();
+ rotate::ptr_rotate(mid, p.offset(mid as isize), k);
+ }
+ }
+
#[inline]
fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
assert!(self.len() == src.len(),
fn may_have_side_effect() -> bool { false }
}
+/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
+/// time).
+///
+/// When the slice len is not evenly divided by the chunk size, the last
+/// up to `chunk_size-1` elements will be omitted.
+///
+/// This struct is created by the [`exact_chunks`] method on [slices].
+///
+/// [`exact_chunks`]: ../../std/primitive.slice.html#method.exact_chunks
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug)]
+#[unstable(feature = "exact_chunks", issue = "47115")]
+pub struct ExactChunks<'a, T:'a> {
+ v: &'a [T],
+ chunk_size: usize
+}
+
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> Clone for ExactChunks<'a, T> {
+ fn clone(&self) -> ExactChunks<'a, T> {
+ ExactChunks {
+ v: self.v,
+ chunk_size: self.chunk_size,
+ }
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> Iterator for ExactChunks<'a, T> {
+ type Item = &'a [T];
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a [T]> {
+ if self.v.len() < self.chunk_size {
+ None
+ } else {
+ let (fst, snd) = self.v.split_at(self.chunk_size);
+ self.v = snd;
+ Some(fst)
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let n = self.v.len() / self.chunk_size;
+ (n, Some(n))
+ }
+
+ #[inline]
+ fn count(self) -> usize {
+ self.len()
+ }
+
+ #[inline]
+ fn nth(&mut self, n: usize) -> Option<Self::Item> {
+ let (start, overflow) = n.overflowing_mul(self.chunk_size);
+ if start >= self.v.len() || overflow {
+ self.v = &[];
+ None
+ } else {
+ let (_, snd) = self.v.split_at(start);
+ self.v = snd;
+ self.next()
+ }
+ }
+
+ #[inline]
+ fn last(mut self) -> Option<Self::Item> {
+ self.next_back()
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> DoubleEndedIterator for ExactChunks<'a, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a [T]> {
+ if self.v.len() < self.chunk_size {
+ None
+ } else {
+ let (fst, snd) = self.v.split_at(self.v.len() - self.chunk_size);
+ self.v = fst;
+ Some(snd)
+ }
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> ExactSizeIterator for ExactChunks<'a, T> {
+ fn is_empty(&self) -> bool {
+ self.v.is_empty()
+ }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for ExactChunks<'a, T> {}
+
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for ExactChunks<'a, T> {
+ unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
+ let start = i * self.chunk_size;
+ from_raw_parts(self.v.as_ptr().offset(start as isize), self.chunk_size)
+ }
+ fn may_have_side_effect() -> bool { false }
+}
+
+/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size`
+/// elements at a time). When the slice len is not evenly divided by the chunk
+/// size, the last up to `chunk_size-1` elements will be omitted.
+///
+/// This struct is created by the [`exact_chunks_mut`] method on [slices].
+///
+/// [`exact_chunks_mut`]: ../../std/primitive.slice.html#method.exact_chunks_mut
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug)]
+#[unstable(feature = "exact_chunks", issue = "47115")]
+pub struct ExactChunksMut<'a, T:'a> {
+ v: &'a mut [T],
+ chunk_size: usize
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> Iterator for ExactChunksMut<'a, T> {
+ type Item = &'a mut [T];
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a mut [T]> {
+ if self.v.len() < self.chunk_size {
+ None
+ } else {
+ let tmp = mem::replace(&mut self.v, &mut []);
+ let (head, tail) = tmp.split_at_mut(self.chunk_size);
+ self.v = tail;
+ Some(head)
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let n = self.v.len() / self.chunk_size;
+ (n, Some(n))
+ }
+
+ #[inline]
+ fn count(self) -> usize {
+ self.len()
+ }
+
+ #[inline]
+ fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
+ let (start, overflow) = n.overflowing_mul(self.chunk_size);
+ if start >= self.v.len() || overflow {
+ self.v = &mut [];
+ None
+ } else {
+ let tmp = mem::replace(&mut self.v, &mut []);
+ let (_, snd) = tmp.split_at_mut(start);
+ self.v = snd;
+ self.next()
+ }
+ }
+
+ #[inline]
+ fn last(mut self) -> Option<Self::Item> {
+ self.next_back()
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> DoubleEndedIterator for ExactChunksMut<'a, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a mut [T]> {
+ if self.v.len() < self.chunk_size {
+ None
+ } else {
+ let tmp = mem::replace(&mut self.v, &mut []);
+ let tmp_len = tmp.len();
+ let (head, tail) = tmp.split_at_mut(tmp_len - self.chunk_size);
+ self.v = head;
+ Some(tail)
+ }
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> ExactSizeIterator for ExactChunksMut<'a, T> {
+ fn is_empty(&self) -> bool {
+ self.v.is_empty()
+ }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {}
+
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> {
+ unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
+ let start = i * self.chunk_size;
+ from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), self.chunk_size)
+ }
+ fn may_have_side_effect() -> bool { false }
+}
+
//
// Free functions
//
assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX)));
}
+#[test]
+fn test_range_last_max() {
+ assert_eq!((0..20).last(), Some(19));
+ assert_eq!((-20..0).last(), Some(-1));
+ assert_eq!((5..5).last(), None);
+
+ assert_eq!((0..20).max(), Some(19));
+ assert_eq!((-20..0).max(), Some(-1));
+ assert_eq!((5..5).max(), None);
+}
+
+#[test]
+fn test_range_inclusive_last_max() {
+ assert_eq!((0..=20).last(), Some(20));
+ assert_eq!((-20..=0).last(), Some(0));
+ assert_eq!((5..=5).last(), Some(5));
+ let mut r = 10..=10;
+ r.next();
+ assert_eq!(r.last(), None);
+
+ assert_eq!((0..=20).max(), Some(20));
+ assert_eq!((-20..=0).max(), Some(0));
+ assert_eq!((5..=5).max(), Some(5));
+ let mut r = 10..=10;
+ r.next();
+ assert_eq!(r.max(), None);
+}
+
+#[test]
+fn test_range_min() {
+ assert_eq!((0..20).min(), Some(0));
+ assert_eq!((-20..0).min(), Some(-20));
+ assert_eq!((5..5).min(), None);
+}
+
+#[test]
+fn test_range_inclusive_min() {
+ assert_eq!((0..=20).min(), Some(0));
+ assert_eq!((-20..=0).min(), Some(-20));
+ assert_eq!((5..=5).min(), Some(5));
+ let mut r = 10..=10;
+ r.next();
+ assert_eq!(r.min(), None);
+}
+
#[test]
fn test_repeat() {
let mut it = repeat(42);
#![feature(try_from)]
#![feature(try_trait)]
#![feature(unique)]
+#![feature(exact_chunks)]
extern crate core;
extern crate test;
test_impl_from! { test_u32f64, u32, f64 }
// Float -> Float
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
#[test]
fn test_f32f64() {
use core::f32;
fn test_chunks_nth() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
let mut c = v.chunks(2);
- assert_eq!(c.nth(1).unwrap()[1], 3);
- assert_eq!(c.next().unwrap()[0], 4);
+ assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[4, 5]);
let v2: &[i32] = &[0, 1, 2, 3, 4];
let mut c2 = v2.chunks(3);
- assert_eq!(c2.nth(1).unwrap()[1], 4);
+ assert_eq!(c2.nth(1).unwrap(), &[3, 4]);
assert_eq!(c2.next(), None);
}
fn test_chunks_mut_nth() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let mut c = v.chunks_mut(2);
- assert_eq!(c.nth(1).unwrap()[1], 3);
- assert_eq!(c.next().unwrap()[0], 4);
+ assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[4, 5]);
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
let mut c2 = v2.chunks_mut(3);
- assert_eq!(c2.nth(1).unwrap()[1], 4);
+ assert_eq!(c2.nth(1).unwrap(), &[3, 4]);
assert_eq!(c2.next(), None);
}
fn test_chunks_mut_last() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let c = v.chunks_mut(2);
- assert_eq!(c.last().unwrap()[1], 5);
+ assert_eq!(c.last().unwrap(), &[4, 5]);
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
let c2 = v2.chunks_mut(2);
- assert_eq!(c2.last().unwrap()[0], 4);
+ assert_eq!(c2.last().unwrap(), &[4]);
}
#[test]
assert_eq!(v1, [13, 14, 19, 20, 14]);
}
+#[test]
+fn test_exact_chunks_count() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let c = v.exact_chunks(3);
+ assert_eq!(c.count(), 2);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let c2 = v2.exact_chunks(2);
+ assert_eq!(c2.count(), 2);
+
+ let v3: &[i32] = &[];
+ let c3 = v3.exact_chunks(2);
+ assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_exact_chunks_nth() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let mut c = v.exact_chunks(2);
+ assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[4, 5]);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
+ let mut c2 = v2.exact_chunks(3);
+ assert_eq!(c2.nth(1).unwrap(), &[3, 4, 5]);
+ assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_exact_chunks_last() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let c = v.exact_chunks(2);
+ assert_eq!(c.last().unwrap(), &[4, 5]);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let c2 = v2.exact_chunks(2);
+ assert_eq!(c2.last().unwrap(), &[2, 3]);
+}
+
+#[test]
+fn test_exact_chunks_zip() {
+ let v1: &[i32] = &[0, 1, 2, 3, 4];
+ let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+ let res = v1.exact_chunks(2)
+ .zip(v2.exact_chunks(2))
+ .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
+ .collect::<Vec<_>>();
+ assert_eq!(res, vec![14, 22]);
+}
+
+#[test]
+fn test_exact_chunks_mut_count() {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let c = v.exact_chunks_mut(3);
+ assert_eq!(c.count(), 2);
+
+ let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let c2 = v2.exact_chunks_mut(2);
+ assert_eq!(c2.count(), 2);
+
+ let v3: &mut [i32] = &mut [];
+ let c3 = v3.exact_chunks_mut(2);
+ assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_exact_chunks_mut_nth() {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let mut c = v.exact_chunks_mut(2);
+ assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[4, 5]);
+
+ let v2: &mut [i32] = &mut [0, 1, 2, 3, 4, 5, 6];
+ let mut c2 = v2.exact_chunks_mut(3);
+ assert_eq!(c2.nth(1).unwrap(), &[3, 4, 5]);
+ assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_exact_chunks_mut_last() {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let c = v.exact_chunks_mut(2);
+ assert_eq!(c.last().unwrap(), &[4, 5]);
+
+ let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let c2 = v2.exact_chunks_mut(2);
+ assert_eq!(c2.last().unwrap(), &[2, 3]);
+}
+
+#[test]
+fn test_exact_chunks_mut_zip() {
+ let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+ for (a, b) in v1.exact_chunks_mut(2).zip(v2.exact_chunks(2)) {
+ let sum = b.iter().sum::<i32>();
+ for v in a {
+ *v += sum;
+ }
+ }
+ assert_eq!(v1, [13, 14, 19, 20, 4]);
+}
+
#[test]
fn test_windows_count() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
}
#[test]
-fn test_rotate() {
+fn test_rotate_left() {
const N: usize = 600;
let a: &mut [_] = &mut [0; N];
for i in 0..N {
a[i] = i;
}
- a.rotate(42);
+ a.rotate_left(42);
let k = N - 42;
for i in 0..N {
- assert_eq!(a[(i+k)%N], i);
+ assert_eq!(a[(i + k) % N], i);
+ }
+}
+
+#[test]
+fn test_rotate_right() {
+ const N: usize = 600;
+ let a: &mut [_] = &mut [0; N];
+ for i in 0..N {
+ a[i] = i;
+ }
+
+ a.rotate_right(42);
+
+ for i in 0..N {
+ assert_eq!(a[(i + 42) % N], i);
}
}
-Subproject commit ef9eefb6df3f3a2cb989e8050519661faa7d7118
+Subproject commit 2b4cd1016bdba92becb4f982a4dcb18fe6653bc4
// notify the expansion info that it is unhygienic
let mark = Mark::fresh(mark);
mark.set_expn_info(expn_info);
- let span = call_site.with_ctxt(call_site.ctxt().apply_mark(mark));
+ let span = call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark));
let stream = parse::parse_stream_from_source_str(name, src, sess, Some(span));
Ok(__internal::token_stream_wrap(stream))
})
[] SuperPredicatesOfItem(DefId),
[] TraitDefOfItem(DefId),
[] AdtDefOfItem(DefId),
- [] IsAutoImpl(DefId),
[] ImplTraitRef(DefId),
[] ImplPolarity(DefId),
[] FnSignature(DefId),
[] Null,
[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
+
+ [input] TargetFeaturesWhitelist,
+ [] TargetFeaturesEnabled(DefId),
+
);
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
DepGraphQuery::new(&nodes[..], &edges[..])
}
- pub fn in_ignore<'graph>(&'graph self) -> Option<raii::IgnoreTask<'graph>> {
- self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.current))
+ pub fn assert_ignored(&self)
+ {
+ if let Some(ref data) = self.data {
+ match data.current.borrow().task_stack.last() {
+ Some(&OpenTask::Ignore) | None => {
+ // ignored
+ }
+ _ => panic!("expected an ignore context")
+ }
+ }
}
pub fn with_ignore<OP,R>(&self, op: OP) -> R
where OP: FnOnce() -> R
{
- let _task = self.in_ignore();
+ let _task = self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.current));
op()
}
//! conflicts between multiple such attributes attached to the same
//! item.
-use session::Session;
+use ty::TyCtxt;
-use syntax::ast;
-use syntax::visit;
-use syntax::visit::Visitor;
+use hir;
+use hir::intravisit::{self, Visitor, NestedVisitorMap};
#[derive(Copy, Clone, PartialEq)]
enum Target {
}
impl Target {
- fn from_item(item: &ast::Item) -> Target {
+ fn from_item(item: &hir::Item) -> Target {
match item.node {
- ast::ItemKind::Fn(..) => Target::Fn,
- ast::ItemKind::Struct(..) => Target::Struct,
- ast::ItemKind::Union(..) => Target::Union,
- ast::ItemKind::Enum(..) => Target::Enum,
+ hir::ItemFn(..) => Target::Fn,
+ hir::ItemStruct(..) => Target::Struct,
+ hir::ItemUnion(..) => Target::Union,
+ hir::ItemEnum(..) => Target::Enum,
_ => Target::Other,
}
}
}
-struct CheckAttrVisitor<'a> {
- sess: &'a Session,
+struct CheckAttrVisitor<'a, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
-impl<'a> CheckAttrVisitor<'a> {
+impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
/// Check any attribute.
- fn check_attributes(&self, item: &ast::Item, target: Target) {
+ fn check_attributes(&self, item: &hir::Item, target: Target) {
+ self.tcx.target_features_enabled(self.tcx.hir.local_def_id(item.id));
+
for attr in &item.attrs {
if let Some(name) = attr.name() {
if name == "inline" {
}
}
}
+
self.check_repr(item, target);
}
/// Check if an `#[inline]` is applied to a function.
- fn check_inline(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
+ fn check_inline(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
if target != Target::Fn {
- struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function")
+ struct_span_err!(self.tcx.sess,
+ attr.span,
+ E0518,
+ "attribute should be applied to function")
.span_label(item.span, "not a function")
.emit();
}
}
/// Check if the `#[repr]` attributes on `item` are valid.
- fn check_repr(&self, item: &ast::Item, target: Target) {
+ fn check_repr(&self, item: &hir::Item, target: Target) {
// Extract the names of all repr hints, e.g., [foo, bar, align] for:
// ```
// #[repr(foo)]
}
_ => continue,
};
- struct_span_err!(self.sess, hint.span, E0517,
+ struct_span_err!(self.tcx.sess, hint.span, E0517,
"attribute should be applied to {}", allowed_targets)
.span_label(item.span, format!("not {} {}", article, allowed_targets))
.emit();
if (int_reprs > 1)
|| (is_simd && is_c)
|| (int_reprs == 1 && is_c && is_c_like_enum(item)) {
- // Just point at all repr hints. This is not ideal, but tracking precisely which ones
- // are at fault is a huge hassle.
+ // Just point at all repr hints. This is not ideal, but tracking
+ // precisely which ones are at fault is a huge hassle.
let spans: Vec<_> = hints.iter().map(|hint| hint.span).collect();
- span_warn!(self.sess, spans, E0566,
+ span_warn!(self.tcx.sess, spans, E0566,
"conflicting representation hints");
}
}
}
-impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
- fn visit_item(&mut self, item: &'a ast::Item) {
+impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ NestedVisitorMap::None
+ }
+
+ fn visit_item(&mut self, item: &'tcx hir::Item) {
let target = Target::from_item(item);
self.check_attributes(item, target);
- visit::walk_item(self, item);
+ intravisit::walk_item(self, item);
}
}
-pub fn check_crate(sess: &Session, krate: &ast::Crate) {
- visit::walk_crate(&mut CheckAttrVisitor { sess: sess }, krate);
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+ let mut checker = CheckAttrVisitor { tcx };
+ tcx.hir.krate().visit_all_item_likes(&mut checker.as_deep_visitor());
}
-fn is_c_like_enum(item: &ast::Item) -> bool {
- if let ast::ItemKind::Enum(ref def, _) = item.node {
+fn is_c_like_enum(item: &hir::Item) -> bool {
+ if let hir::ItemEnum(ref def, _) = item.node {
for variant in &def.variants {
match variant.node.data {
- ast::VariantData::Unit(_) => { /* continue */ }
+ hir::VariantData::Unit(_) => { /* continue */ }
_ => { return false; }
}
}
/// particular definition. It should really be considered an interned
/// shorthand for a particular DefPath.
///
-/// At the moment we are allocating the numerical values of DefIndexes into two
-/// ranges: the "low" range (starting at zero) and the "high" range (starting at
-/// DEF_INDEX_HI_START). This allows us to allocate the DefIndexes of all
-/// item-likes (Items, TraitItems, and ImplItems) into one of these ranges and
+/// At the moment we are allocating the numerical values of DefIndexes from two
+/// address spaces: DefIndexAddressSpace::Low and DefIndexAddressSpace::High.
+/// This allows us to allocate the DefIndexes of all item-likes
+/// (Items, TraitItems, and ImplItems) into one of these spaces and
/// consequently use a simple array for lookup tables keyed by DefIndex and
/// known to be densely populated. This is especially important for the HIR map.
///
/// Since the DefIndex is mostly treated as an opaque ID, you probably
-/// don't have to care about these ranges.
-newtype_index!(DefIndex
- {
- ENCODABLE = custom
- DEBUG_FORMAT = custom,
+/// don't have to care about these address spaces.
- /// The start of the "high" range of DefIndexes.
- const DEF_INDEX_HI_START = 1 << 31,
+#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, Hash, Copy)]
+pub struct DefIndex(u32);
+
+/// The crate root is always assigned index 0 by the AST Map code,
+/// thanks to `NodeCollector::new`.
+pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
- /// The crate root is always assigned index 0 by the AST Map code,
- /// thanks to `NodeCollector::new`.
- const CRATE_DEF_INDEX = 0,
- });
impl fmt::Debug for DefIndex {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl DefIndex {
#[inline]
- pub fn from_u32(x: u32) -> DefIndex {
- DefIndex(x)
+ pub fn address_space(&self) -> DefIndexAddressSpace {
+ match self.0 & 1 {
+ 0 => DefIndexAddressSpace::Low,
+ 1 => DefIndexAddressSpace::High,
+ _ => unreachable!()
+ }
}
+ /// Converts this DefIndex into a zero-based array index.
+ /// This index is the offset within the given DefIndexAddressSpace.
#[inline]
- pub fn as_usize(&self) -> usize {
- self.0 as usize
+ pub fn as_array_index(&self) -> usize {
+ (self.0 >> 1) as usize
}
#[inline]
- pub fn as_u32(&self) -> u32 {
- self.0
+ pub fn from_array_index(i: usize, address_space: DefIndexAddressSpace) -> DefIndex {
+ DefIndex::from_raw_u32(((i << 1) | (address_space as usize)) as u32)
}
- #[inline]
- pub fn address_space(&self) -> DefIndexAddressSpace {
- if self.0 < DEF_INDEX_HI_START.0 {
- DefIndexAddressSpace::Low
- } else {
- DefIndexAddressSpace::High
- }
+ // Proc macros from a proc-macro crate have a kind of virtual DefIndex. This
+ // function maps the index of the macro within the crate (which is also the
+ // index of the macro in the CrateMetadata::proc_macros array) to the
+ // corresponding DefIndex.
+ pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
+ let def_index = DefIndex::from_array_index(proc_macro_index,
+ DefIndexAddressSpace::High);
+ assert!(def_index != CRATE_DEF_INDEX);
+ def_index
}
- /// Converts this DefIndex into a zero-based array index.
- /// This index is the offset within the given "range" of the DefIndex,
- /// that is, if the DefIndex is part of the "high" range, the resulting
- /// index will be (DefIndex - DEF_INDEX_HI_START).
- #[inline]
- pub fn as_array_index(&self) -> usize {
- (self.0 & !DEF_INDEX_HI_START.0) as usize
+ // This function is the reverse of from_proc_macro_index() above.
+ pub fn to_proc_macro_index(self: DefIndex) -> usize {
+ self.as_array_index()
}
- pub fn from_array_index(i: usize, address_space: DefIndexAddressSpace) -> DefIndex {
- DefIndex::new(address_space.start() + i)
+ // Don't use this if you don't know about the DefIndex encoding.
+ pub fn from_raw_u32(x: u32) -> DefIndex {
+ DefIndex(x)
+ }
+
+ // Don't use this if you don't know about the DefIndex encoding.
+ pub fn as_raw_u32(&self) -> u32 {
+ self.0
}
}
pub fn index(&self) -> usize {
*self as usize
}
-
- #[inline]
- pub fn start(&self) -> usize {
- self.index() * DEF_INDEX_HI_START.as_usize()
- }
}
/// A DefId identifies a particular *definition*, by combining a crate
// visit_enum_def() takes care of visiting the Item's NodeId
visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
}
- ItemAutoImpl(_, ref trait_ref) => {
- visitor.visit_id(item.id);
- visitor.visit_trait_ref(trait_ref)
- }
ItemImpl(.., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_item_refs) => {
visitor.visit_id(item.id);
visitor.visit_generics(type_parameters);
// We're constructing the HIR here; we don't care what we will
// read, since we haven't even constructed the *input* to
// incr. comp. yet.
- let _ignore = dep_graph.in_ignore();
+ dep_graph.assert_ignored();
LoweringContext {
crate_root: std_inject::injected_crate_name(),
fn_def_id: Option<DefId>,
impl_trait_return_allow: bool)
-> P<hir::FnDecl> {
- // NOTE: The two last paramters here have to do with impl Trait. If fn_def_id is Some,
- // then impl Trait arguments are lowered into generic paramters on the given
+ // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some,
+ // then impl Trait arguments are lowered into generic parameters on the given
// fn_def_id, otherwise impl Trait is disallowed. (for now)
//
// Furthermore, if impl_trait_return_allow is true, then impl Trait may be used in
let vdata = self.lower_variant_data(vdata);
hir::ItemUnion(vdata, self.lower_generics(generics))
}
- ItemKind::AutoImpl(unsafety, ref trait_ref) => {
- let trait_ref = self.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed);
-
- if let Def::Trait(def_id) = trait_ref.path.def {
- self.trait_auto_impl.insert(def_id, id);
- }
-
- hir::ItemAutoImpl(self.lower_unsafety(unsafety),
- trait_ref)
- }
ItemKind::Impl(unsafety,
polarity,
defaultness,
// Pick the def data. This need not be unique, but the more
// information we encapsulate into
let def_data = match i.node {
- ItemKind::AutoImpl(..) | ItemKind::Impl(..) =>
- DefPathData::Impl,
+ ItemKind::Impl(..) => DefPathData::Impl,
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
CRATE_DEF_INDEX};
use ich::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::{IndexVec};
use rustc_data_structures::stable_hasher::StableHasher;
use serialize::{Encodable, Decodable, Encoder, Decoder};
use session::CrateDisambiguator;
-> DefIndex {
let index = {
let index_to_key = &mut self.index_to_key[address_space.index()];
- let index = DefIndex::new(index_to_key.len() + address_space.start());
+ let index = DefIndex::from_array_index(index_to_key.len(), address_space);
debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
index_to_key.push(key);
index
pub fn add_def_path_hashes_to(&self,
cnum: CrateNum,
out: &mut FxHashMap<DefPathHash, DefId>) {
- for address_space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
- let start_index = address_space.start();
+ for &address_space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
out.extend(
(&self.def_path_hashes[address_space.index()])
.iter()
.map(|(index, &hash)| {
let def_id = DefId {
krate: cnum,
- index: DefIndex::new(index + start_index),
+ index: DefIndex::from_array_index(index, address_space),
};
(hash, def_id)
})
errors: vec![],
};
- hir_map.dep_graph.with_ignore(|| {
- hir_map.krate().visit_all_item_likes(&mut outer_visitor);
- if !outer_visitor.errors.is_empty() {
- let message = outer_visitor
- .errors
- .iter()
- .fold(String::new(), |s1, s2| s1 + "\n" + s2);
- bug!("{}", message);
- }
- });
+ hir_map.dep_graph.assert_ignored();
+
+ hir_map.krate().visit_all_item_likes(&mut outer_visitor);
+ if !outer_visitor.errors.is_empty() {
+ let message = outer_visitor
+ .errors
+ .iter()
+ .fold(String::new(), |s1, s2| s1 + "\n" + s2);
+ bug!("{}", message);
+ }
}
struct HirIdValidator<'a, 'hir: 'a> {
ItemTrait(..) => "trait",
ItemTraitAlias(..) => "trait alias",
ItemImpl(..) => "impl",
- ItemAutoImpl(..) => "default impl",
};
format!("{} {}{}", item_str, path_str(), id_str)
}
/// Represents a Trait Alias Declaration
ItemTraitAlias(Generics, TyParamBounds),
- /// Auto trait implementations
- ///
- /// `impl Trait for .. {}`
- ItemAutoImpl(Unsafety, TraitRef),
/// An implementation, eg `impl<A> Trait for Foo { .. }`
ItemImpl(Unsafety,
ImplPolarity,
ItemUnion(..) => "union",
ItemTrait(..) => "trait",
ItemTraitAlias(..) => "trait alias",
- ItemImpl(..) |
- ItemAutoImpl(..) => "item",
+ ItemImpl(..) => "item",
}
}
self.head(&visibility_qualified(&item.vis, "union"))?;
self.print_struct(struct_def, generics, item.name, item.span, true)?;
}
- hir::ItemAutoImpl(unsafety, ref trait_ref) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.print_unsafety(unsafety)?;
- self.word_nbsp("impl")?;
- self.print_trait_ref(trait_ref)?;
- self.s.space()?;
- self.word_space("for")?;
- self.word_space("..")?;
- self.bopen()?;
- self.bclose(item.span)?;
- }
hir::ItemImpl(unsafety,
polarity,
defaultness,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::mem;
use rustc_data_structures::stable_hasher;
+use serialize;
+use serialize::opaque::{EncodeResult, Encoder, Decoder};
-#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
pub struct Fingerprint(u64, u64);
impl Fingerprint {
format!("{:x}{:x}", self.0, self.1)
}
+ pub fn encode_opaque(&self, encoder: &mut Encoder) -> EncodeResult {
+ let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
+
+ encoder.emit_raw_bytes(&bytes)
+ }
+
+ pub fn decode_opaque<'a>(decoder: &mut Decoder<'a>) -> Result<Fingerprint, String> {
+ let mut bytes = [0; 16];
+
+ decoder.read_raw_bytes(&mut bytes)?;
+
+ let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) };
+
+ Ok(Fingerprint(u64::from_le(l), u64::from_le(r)))
+ }
}
impl ::std::fmt::Display for Fingerprint {
::std::hash::Hash::hash(self, hasher);
}
}
+
+impl serialize::UseSpecializedEncodable for Fingerprint { }
+
+impl serialize::UseSpecializedDecodable for Fingerprint { }
+
+impl<'a> serialize::SpecializedEncoder<Fingerprint> for serialize::opaque::Encoder<'a> {
+ fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+ f.encode_opaque(self)
+ }
+}
+
+impl<'a> serialize::SpecializedDecoder<Fingerprint> for serialize::opaque::Decoder<'a> {
+ fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+ Fingerprint::decode_opaque(self)
+ }
+}
ItemUnion(variant_data, generics),
ItemTrait(is_auto, unsafety, generics, bounds, item_refs),
ItemTraitAlias(generics, bounds),
- ItemAutoImpl(unsafety, trait_ref),
ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
});
.emit();
return Some(ErrorReported);
}
+
+ // This method returns whether the given Region is Named
+ pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool {
+ match *region {
+ ty::ReStatic => true,
+ ty::ReFree(ref free_region) => match free_region.bound_region {
+ ty::BrNamed(..) => true,
+ _ => false,
+ },
+ ty::ReEarlyBound(_) => true,
+ _ => false,
+ }
+ }
}
}
false
}
-
- // This method returns whether the given Region is Named
- pub(super) fn is_named_region(&self, region: Region<'tcx>) -> bool {
- match *region {
- ty::ReFree(ref free_region) => match free_region.bound_region {
- ty::BrNamed(..) => true,
- _ => false,
- },
- ty::ReEarlyBound(_) => true,
- _ => false,
- }
- }
}
use graphviz as dot;
use hir::def_id::DefIndex;
-use rustc_data_structures::indexed_vec::Idx;
use ty;
use middle::free_region::RegionRelations;
use middle::region;
}
let requested_node = env::var("RUST_REGION_GRAPH_NODE")
- .ok().and_then(|s| s.parse().map(DefIndex::new).ok());
+ .ok().and_then(|s| s.parse().map(DefIndex::from_raw_u32).ok());
if requested_node.is_some() && requested_node != Some(context.index) {
return;
let mut new_str = String::new();
for c in output_template.chars() {
if c == '%' {
- new_str.push_str(&context.index.as_usize().to_string());
+ new_str.push_str(&context.index.as_raw_u32().to_string());
} else {
new_str.push(c);
}
#![feature(drain_filter)]
#![feature(dyn_trait)]
#![feature(from_ref)]
+#![feature(fs_read_write)]
#![feature(i128)]
#![feature(i128_type)]
#![feature(inclusive_range)]
// calculated the lint levels for all AST nodes.
for (_id, lints) in cx.buffered.map {
for early_lint in lints {
- span_bug!(early_lint.span, "failed to process bufferd lint here");
+ span_bug!(early_lint.span, "failed to process buffered lint here");
}
}
}
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
live_symbols: Box<FxHashSet<ast::NodeId>>,
- struct_has_extern_repr: bool,
+ repr_has_repr_c: bool,
in_pat: bool,
inherited_pub_visibility: bool,
ignore_variant_stack: Vec<DefId>,
fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
match self.tables.expr_ty_adjusted(lhs).sty {
ty::TyAdt(def, _) => {
- self.insert_def_id(def.struct_variant().field_named(name).did);
+ self.insert_def_id(def.non_enum_variant().field_named(name).did);
}
_ => span_bug!(lhs.span, "named field access on non-ADT"),
}
fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
match self.tables.expr_ty_adjusted(lhs).sty {
ty::TyAdt(def, _) => {
- self.insert_def_id(def.struct_variant().fields[idx].did);
+ self.insert_def_id(def.non_enum_variant().fields[idx].did);
}
ty::TyTuple(..) => {}
_ => span_bug!(lhs.span, "numeric field access on non-ADT"),
}
fn visit_node(&mut self, node: &hir_map::Node<'tcx>) {
- let had_extern_repr = self.struct_has_extern_repr;
- self.struct_has_extern_repr = false;
+ let had_repr_c = self.repr_has_repr_c;
+ self.repr_has_repr_c = false;
let had_inherited_pub_visibility = self.inherited_pub_visibility;
self.inherited_pub_visibility = false;
match *node {
hir::ItemStruct(..) | hir::ItemUnion(..) => {
let def_id = self.tcx.hir.local_def_id(item.id);
let def = self.tcx.adt_def(def_id);
- self.struct_has_extern_repr = def.repr.c();
+ self.repr_has_repr_c = def.repr.c();
intravisit::walk_item(self, &item);
}
}
_ => ()
}
- self.struct_has_extern_repr = had_extern_repr;
+ self.repr_has_repr_c = had_repr_c;
self.inherited_pub_visibility = had_inherited_pub_visibility;
}
fn visit_variant_data(&mut self, def: &'tcx hir::VariantData, _: ast::Name,
_: &hir::Generics, _: ast::NodeId, _: syntax_pos::Span) {
- let has_extern_repr = self.struct_has_extern_repr;
+ let has_repr_c = self.repr_has_repr_c;
let inherited_pub_visibility = self.inherited_pub_visibility;
let live_fields = def.fields().iter().filter(|f| {
- has_extern_repr || inherited_pub_visibility || f.vis == hir::Public
+ has_repr_c || inherited_pub_visibility || f.vis == hir::Public
});
self.live_symbols.extend(live_fields.map(|f| f.id));
tcx,
tables: &ty::TypeckTables::empty(None),
live_symbols: box FxHashSet(),
- struct_has_extern_repr: false,
+ repr_has_repr_c: false,
in_pat: false,
inherited_pub_visibility: false,
ignore_variant_stack: vec![],
hir::ItemStruct(..) |
hir::ItemUnion(..) |
hir::ItemTrait(..) |
- hir::ItemAutoImpl(..) |
hir::ItemImpl(..) => self.tcx.sess.codemap().def_span(item.span),
_ => item.span,
};
match with_cmt.ty.sty {
ty::TyAdt(adt, substs) if adt.is_struct() => {
// Consume those fields of the with expression that are needed.
- for with_field in &adt.struct_variant().fields {
+ for with_field in &adt.non_enum_variant().fields {
if !contains_field_named(with_field, fields) {
let cmt_field = self.mc.cat_field(
&*with_expr,
Def::StructCtor(_, CtorKind::Fn) => {
match self.pat_ty(&pat)?.sty {
ty::TyAdt(adt_def, _) => {
- (cmt, adt_def.struct_variant().fields.len())
+ (cmt, adt_def.non_enum_variant().fields.len())
}
ref ty => {
span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
hir::ItemMod(..) | hir::ItemForeignMod(..) |
hir::ItemImpl(..) | hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
hir::ItemStruct(..) | hir::ItemEnum(..) |
- hir::ItemUnion(..) | hir::ItemAutoImpl(..) |
- hir::ItemGlobalAsm(..) => {}
+ hir::ItemUnion(..) | hir::ItemGlobalAsm(..) => {}
}
}
hir_map::NodeTraitItem(trait_method) => {
intravisit::walk_item(this, item);
});
}
+
hir::ItemExternCrate(_)
| hir::ItemUse(..)
| hir::ItemMod(..)
- | hir::ItemAutoImpl(..)
| hir::ItemForeignMod(..)
| hir::ItemGlobalAsm(..) => {
// These sorts of items have no lifetime parameters at all.
use syntax::symbol::InternedString;
use ty::Instance;
use util::nodemap::FxHashMap;
+use rustc_data_structures::base_n;
use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult,
StableHasher};
use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
+use std::hash::Hash;
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub enum MonoItem<'tcx> {
{
&mut self.items
}
+
+ pub fn mangle_name(human_readable_name: &str) -> String {
+ // We generate a 80 bit hash from the name. This should be enough to
+ // avoid collisions and is still reasonably short for filenames.
+ let mut hasher = StableHasher::new();
+ human_readable_name.hash(&mut hasher);
+ let hash: u128 = hasher.finish();
+ let hash = hash & ((1u128 << 80) - 1);
+ base_n::encode(hash, base_n::CASE_INSENSITIVE)
+ }
}
impl<'tcx> HashStable<StableHashingContext<'tcx>> for CodegenUnit<'tcx> {
"omit landing pads for unwinding"),
fewer_names: bool = (false, parse_bool, [TRACKED],
"reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR)"),
- debug_llvm: bool = (false, parse_bool, [UNTRACKED],
- "enable debug output from LLVM"),
meta_stats: bool = (false, parse_bool, [UNTRACKED],
"gather metadata statistics"),
print_link_args: bool = (false, parse_bool, [UNTRACKED],
"rewrite operators on i128 and u128 into lang item calls (typically provided \
by compiler-builtins) so translation doesn't need to support them,
overriding the default for the current target"),
+ human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
+ "generate human-readable, predictable names for codegen units"),
}
pub fn default_lib_output() -> CrateType {
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.borrowck_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
- opts.debugging_opts.debug_llvm = true;
- assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.meta_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_link_args = true;
index: DefIndex)
-> String {
format!("__rustc_plugin_registrar__{}_{}", disambiguator.to_fingerprint().to_hex(),
- index.as_usize())
+ index.to_proc_macro_index())
}
pub fn generate_derive_registrar_symbol(&self, disambiguator: CrateDisambiguator,
index: DefIndex)
-> String {
format!("__rustc_derive_registrar__{}_{}", disambiguator.to_fingerprint().to_hex(),
- index.as_usize())
+ index.to_proc_macro_index())
}
pub fn sysroot<'a>(&'a self) -> &'a Path {
VtableBuiltinData { nested: obligations }
}
- /// This handles the case where a `impl Foo for ..` impl is being used.
+ /// This handles the case where a `auto trait Foo` impl is being used.
/// The idea is that the impl applies to `X : Foo` if the following conditions are met:
///
/// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
/*!
* Creates a cause for obligations that are derived from
* `obligation` by a recursive search (e.g., for a builtin
- * bound, or eventually a `impl Foo for ..`). If `obligation`
+ * bound, or eventually a `auto trait Foo`). If `obligation`
* is itself a derived obligation, this is just a clone, but
* otherwise we create a "derived obligation" cause so as to
* keep track of the original root obligation for error
// Always use types for non-local impls, where types are always
// available, and filename/line-number is mostly uninteresting.
- let use_types = !self.is_auto_impl(impl_def_id) && (!impl_def_id.is_local() || {
+ let use_types = !impl_def_id.is_local() || {
// Otherwise, use filename/line-number if forced.
let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
!force_no_types
- });
+ };
if !use_types {
return self.push_impl_path_fallback(buffer, impl_def_id);
}, niche_start))
};
+ // Locals variables which live across yields are stored
+ // in the generator type as fields. These may be uninitialized
+ // so we don't look for niches there.
+ if let ty::TyGenerator(..) = self.ty.sty {
+ return Ok(None);
+ }
+
match self.abi {
Abi::Scalar(ref scalar) => {
return Ok(scalar_component(scalar, Size::from_bytes(0)));
}
}
+impl<'tcx> QueryDescription<'tcx> for queries::target_features_whitelist<'tcx> {
+ fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+ format!("looking up the whitelist of target features")
+ }
+}
+
macro_rules! impl_disk_cacheable_query(
($query_name:ident, |$key:tt| $cond:expr) => {
impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> {
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
[] fn is_foreign_item: IsForeignItem(DefId) -> bool,
- /// True if this is an auto impl (aka impl Foo for ..)
- [] fn is_auto_impl: IsAutoImpl(DefId) -> bool,
-
/// Get a map with the variance of every item; use `item_variance`
/// instead.
[] fn crate_variances: crate_variances(CrateNum) -> Rc<ty::CrateVariancesMap>,
[] fn substitute_normalize_and_test_predicates:
substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
+
+ [] fn target_features_whitelist:
+ target_features_whitelist_node(CrateNum) -> Rc<FxHashSet<String>>,
+ [] fn target_features_enabled: TargetFeaturesEnabled(DefId) -> Rc<Vec<String>>,
+
}
//////////////////////////////////////////////////////////////////////
-> DepConstructor<'tcx> {
DepConstructor::SubstituteNormalizeAndTestPredicates { key }
}
+
+fn target_features_whitelist_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+ DepConstructor::TargetFeaturesWhitelist
+}
use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId,
RESERVED_FOR_INCR_COMP_CACHE, LOCAL_CRATE};
use hir::map::definitions::DefPathHash;
-use ich::CachingCodemapView;
+use ich::{CachingCodemapView, Fingerprint};
use mir;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
where E: ty_codec::TyEncoder
{
// Serializing the DepGraph should not modify it:
- let _in_ignore = tcx.dep_graph.in_ignore();
-
- // Allocate FileMapIndices
- let (file_to_file_index, file_index_to_stable_id) = {
- let mut file_to_file_index = FxHashMap();
- let mut file_index_to_stable_id = FxHashMap();
-
- for (index, file) in tcx.sess.codemap().files().iter().enumerate() {
- let index = FileMapIndex(index as u32);
- let file_ptr: *const FileMap = &**file as *const _;
- file_to_file_index.insert(file_ptr, index);
- file_index_to_stable_id.insert(index, StableFilemapId::new(&file));
- }
-
- (file_to_file_index, file_index_to_stable_id)
- };
-
- let mut encoder = CacheEncoder {
- tcx,
- encoder,
- type_shorthands: FxHashMap(),
- predicate_shorthands: FxHashMap(),
- expn_info_shorthands: FxHashMap(),
- codemap: CachingCodemapView::new(tcx.sess.codemap()),
- file_to_file_index,
- };
-
- // Load everything into memory so we can write it out to the on-disk
- // cache. The vast majority of cacheable query results should already
- // be in memory, so this should be a cheap operation.
- tcx.dep_graph.exec_cache_promotions(tcx);
-
- // Encode query results
- let mut query_result_index = EncodedQueryResultIndex::new();
-
- {
- use ty::maps::queries::*;
- let enc = &mut encoder;
- let qri = &mut query_result_index;
-
- // Encode TypeckTables
- encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
- encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
- encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
- encode_query_results::<borrowck, _>(tcx, enc, qri)?;
- encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
- encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
- encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
- encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
- encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
- encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
- encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?;
- encode_query_results::<check_match, _>(tcx, enc, qri)?;
- }
+ tcx.dep_graph.with_ignore(|| {
+ // Allocate FileMapIndices
+ let (file_to_file_index, file_index_to_stable_id) = {
+ let mut file_to_file_index = FxHashMap();
+ let mut file_index_to_stable_id = FxHashMap();
+
+ for (index, file) in tcx.sess.codemap().files().iter().enumerate() {
+ let index = FileMapIndex(index as u32);
+ let file_ptr: *const FileMap = &**file as *const _;
+ file_to_file_index.insert(file_ptr, index);
+ file_index_to_stable_id.insert(index, StableFilemapId::new(&file));
+ }
- // Encode diagnostics
- let diagnostics_index = {
- let mut diagnostics_index = EncodedDiagnosticsIndex::new();
-
- for (dep_node_index, diagnostics) in self.current_diagnostics
- .borrow()
- .iter() {
- let pos = AbsoluteBytePos::new(encoder.position());
- // Let's make sure we get the expected type here:
- let diagnostics: &EncodedDiagnostics = diagnostics;
- let dep_node_index =
- SerializedDepNodeIndex::new(dep_node_index.index());
- encoder.encode_tagged(dep_node_index, diagnostics)?;
- diagnostics_index.push((dep_node_index, pos));
+ (file_to_file_index, file_index_to_stable_id)
+ };
+
+ let mut encoder = CacheEncoder {
+ tcx,
+ encoder,
+ type_shorthands: FxHashMap(),
+ predicate_shorthands: FxHashMap(),
+ expn_info_shorthands: FxHashMap(),
+ codemap: CachingCodemapView::new(tcx.sess.codemap()),
+ file_to_file_index,
+ };
+
+ // Load everything into memory so we can write it out to the on-disk
+ // cache. The vast majority of cacheable query results should already
+ // be in memory, so this should be a cheap operation.
+ tcx.dep_graph.exec_cache_promotions(tcx);
+
+ // Encode query results
+ let mut query_result_index = EncodedQueryResultIndex::new();
+
+ {
+ use ty::maps::queries::*;
+ let enc = &mut encoder;
+ let qri = &mut query_result_index;
+
+ // Encode TypeckTables
+ encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
+ encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
+ encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
+ encode_query_results::<borrowck, _>(tcx, enc, qri)?;
+ encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
+ encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
+ encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
+ encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
+ encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
+ encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
+ encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?;
+ encode_query_results::<check_match, _>(tcx, enc, qri)?;
}
- diagnostics_index
- };
+ // Encode diagnostics
+ let diagnostics_index = {
+ let mut diagnostics_index = EncodedDiagnosticsIndex::new();
+
+ for (dep_node_index, diagnostics) in self.current_diagnostics
+ .borrow()
+ .iter() {
+ let pos = AbsoluteBytePos::new(encoder.position());
+ // Let's make sure we get the expected type here:
+ let diagnostics: &EncodedDiagnostics = diagnostics;
+ let dep_node_index =
+ SerializedDepNodeIndex::new(dep_node_index.index());
+ encoder.encode_tagged(dep_node_index, diagnostics)?;
+ diagnostics_index.push((dep_node_index, pos));
+ }
- let sorted_cnums = sorted_cnums_including_local_crate(tcx);
- let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
- let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
- let crate_disambiguator = tcx.crate_disambiguator(cnum);
- (cnum.as_u32(), crate_name, crate_disambiguator)
- }).collect();
-
- // Encode the file footer
- let footer_pos = encoder.position() as u64;
- encoder.encode_tagged(TAG_FILE_FOOTER, &Footer {
- file_index_to_stable_id,
- prev_cnums,
- query_result_index,
- diagnostics_index,
- })?;
-
- // Encode the position of the footer as the last 8 bytes of the
- // file so we know where to look for it.
- IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
-
- // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
- // of the footer must be the last thing in the data stream.
-
- return Ok(());
-
- fn sorted_cnums_including_local_crate(tcx: TyCtxt) -> Vec<CrateNum> {
- let mut cnums = vec![LOCAL_CRATE];
- cnums.extend_from_slice(&tcx.crates()[..]);
- cnums.sort_unstable();
- // Just to be sure...
- cnums.dedup();
- cnums
- }
+ diagnostics_index
+ };
+
+ let sorted_cnums = sorted_cnums_including_local_crate(tcx);
+ let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
+ let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
+ let crate_disambiguator = tcx.crate_disambiguator(cnum);
+ (cnum.as_u32(), crate_name, crate_disambiguator)
+ }).collect();
+
+ // Encode the file footer
+ let footer_pos = encoder.position() as u64;
+ encoder.encode_tagged(TAG_FILE_FOOTER, &Footer {
+ file_index_to_stable_id,
+ prev_cnums,
+ query_result_index,
+ diagnostics_index,
+ })?;
+
+ // Encode the position of the footer as the last 8 bytes of the
+ // file so we know where to look for it.
+ IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
+
+ // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
+ // of the footer must be the last thing in the data stream.
+
+ return Ok(());
+
+ fn sorted_cnums_including_local_crate(tcx: TyCtxt) -> Vec<CrateNum> {
+ let mut cnums = vec![LOCAL_CRATE];
+ cnums.extend_from_slice(&tcx.crates()[..]);
+ cnums.sort_unstable();
+ // Just to be sure...
+ cnums.dedup();
+ cnums
+ }
+ })
}
/// Load a diagnostic emitted during the previous compilation session.
prev_cnums: &[(u32, String, CrateDisambiguator)])
-> IndexVec<CrateNum, Option<CrateNum>>
{
- let _in_ignore = tcx.dep_graph.in_ignore();
-
- let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
- let crate_name = tcx.original_crate_name(cnum)
- .as_str()
- .to_string();
- let crate_disambiguator = tcx.crate_disambiguator(cnum);
- ((crate_name, crate_disambiguator), cnum)
- }).collect::<FxHashMap<_,_>>();
-
- let map_size = prev_cnums.iter()
- .map(|&(cnum, ..)| cnum)
- .max()
- .unwrap_or(0) + 1;
- let mut map = IndexVec::new();
- map.resize(map_size as usize, None);
-
- for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
- let key = (crate_name.clone(), crate_disambiguator);
- map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
- }
+ tcx.dep_graph.with_ignore(|| {
+ let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
+ let crate_name = tcx.original_crate_name(cnum)
+ .as_str()
+ .to_string();
+ let crate_disambiguator = tcx.crate_disambiguator(cnum);
+ ((crate_name, crate_disambiguator), cnum)
+ }).collect::<FxHashMap<_,_>>();
+
+ let map_size = prev_cnums.iter()
+ .map(|&(cnum, ..)| cnum)
+ .max()
+ .unwrap_or(0) + 1;
+ let mut map = IndexVec::new();
+ map.resize(map_size as usize, None);
+
+ for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
+ let key = (crate_name.clone(), crate_disambiguator);
+ map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
+ }
- map[LOCAL_CRATE] = Some(LOCAL_CRATE);
- map
+ map[LOCAL_CRATE] = Some(LOCAL_CRATE);
+ map
+ })
}
}
}
}
+impl<'a, 'tcx, 'x> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx, 'x> {
+ fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+ Fingerprint::decode_opaque(&mut self.opaque)
+ }
+}
+
impl<'a, 'tcx, 'x, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
for CacheDecoder<'a, 'tcx, 'x> {
#[inline]
}
}
+impl<'enc, 'a, 'tcx> SpecializedEncoder<Fingerprint>
+for CacheEncoder<'enc, 'a, 'tcx, opaque::Encoder<'enc>>
+{
+ fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+ f.encode_opaque(&mut self.encoder)
+ }
+}
+
impl<'enc, 'a, 'tcx, E, T> SpecializedEncoder<mir::ClearCrossCrate<T>>
for CacheEncoder<'enc, 'a, 'tcx, E>
where E: 'enc + ty_codec::TyEncoder,
DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
- DepKind::IsAutoImpl => { force!(is_auto_impl, def_id!()); }
DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); }
DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); }
DepKind::FnSignature => { force!(fn_sig, def_id!()); }
}
DepKind::IsTranslatedFunction => { force!(is_translated_function, def_id!()); }
DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
+
+ DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
+ DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); }
}
true
for attr in tcx.get_attrs(did).iter() {
for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) {
flags.insert(match r {
- attr::ReprExtern => ReprFlags::IS_C,
+ attr::ReprC => ReprFlags::IS_C,
attr::ReprPacked => ReprFlags::IS_PACKED,
attr::ReprSimd => ReprFlags::IS_SIMD,
attr::ReprInt(i) => {
}
}
- // FIXME(eddyb) This is deprecated and should be removed.
- if tcx.has_attr(did, "simd") {
- flags.insert(ReprFlags::IS_SIMD);
- }
-
// This is here instead of layout because the choice must make it into metadata.
if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.item_path_str(did))) {
flags.insert(ReprFlags::IS_LINEAR);
self.destructor(tcx).is_some()
}
- /// Asserts this is a struct and returns the struct's unique
- /// variant.
- pub fn struct_variant(&self) -> &VariantDef {
- assert!(!self.is_enum());
+ /// Asserts this is a struct or union and returns its unique variant.
+ pub fn non_enum_variant(&self) -> &VariantDef {
+ assert!(self.is_struct() || self.is_union());
&self.variants[0]
}
match def {
Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
- Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.struct_variant(),
+ Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.non_enum_variant(),
_ => bug!("unexpected def {:?} in variant_of_def", def)
}
}
self.adt_def(enum_did).variant_with_id(did)
}
Def::Struct(did) | Def::Union(did) => {
- self.adt_def(did).struct_variant()
+ self.adt_def(did).non_enum_variant()
}
Def::StructCtor(ctor_did, ..) => {
let did = self.parent_def_id(ctor_did).expect("struct ctor has no parent");
- self.adt_def(did).struct_variant()
+ self.adt_def(did).non_enum_variant()
}
_ => bug!("expect_variant_def used with unexpected def {:?}", def)
}
}
/// Returns true if this is an `auto trait`.
- ///
- /// NB. For a limited time, also returns true if `impl Trait for .. { }` is in the code-base.
pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
self.trait_def(trait_def_id).has_auto_impl
}
pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
match self.sty {
TyAdt(def, substs) => {
- def.struct_variant().fields[0].ty(tcx, substs)
+ def.non_enum_variant().fields[0].ty(tcx, substs)
}
_ => bug!("simd_type called on invalid type")
}
pub fn simd_size(&self, _cx: TyCtxt) -> usize {
match self.sty {
- TyAdt(def, _) => def.struct_variant().fields.len(),
+ TyAdt(def, _) => def.non_enum_variant().fields.len(),
_ => bug!("simd_size called on invalid type")
}
}
adt.variant_with_id(vid).fields.get(i).map(|f| f.ty(self, substs))
}
(&TyAdt(adt, substs), None) => {
- // Don't use `struct_variant`, this may be a univariant enum.
+ // Don't use `non_enum_variant`, this may be a univariant enum.
adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
}
(&TyTuple(ref v, _), None) => v.get(i).cloned(),
adt.variant_with_id(vid).find_field_named(n).map(|f| f.ty(self, substs))
}
(&TyAdt(adt, substs), None) => {
- adt.struct_variant().find_field_named(n).map(|f| f.ty(self, substs))
+ adt.non_enum_variant().find_field_named(n).map(|f| f.ty(self, substs))
}
_ => return None
}
if !def.is_struct() {
break;
}
- match def.struct_variant().fields.last() {
+ match def.non_enum_variant().fields.last() {
Some(f) => ty = f.ty(self, substs),
None => break,
}
match (&a.sty, &b.sty) {
(&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs))
if a_def == b_def && a_def.is_struct() => {
- if let Some(f) = a_def.struct_variant().fields.last() {
+ if let Some(f) = a_def.non_enum_variant().fields.last() {
a = f.ty(self, a_substs);
b = f.ty(self, b_substs);
} else {
// Memory reporting
#[cfg(unix)]
fn get_resident() -> Option<usize> {
- use std::fs::File;
- use std::io::Read;
+ use std::fs;
let field = 1;
- let mut f = File::open("/proc/self/statm").ok()?;
- let mut contents = String::new();
- f.read_to_string(&mut contents).ok()?;
+ let contents = fs::read_string("/proc/self/statm").ok()?;
let s = contents.split_whitespace().nth(field)?;
let npages = s.parse::<usize>().ok()?;
Some(npages * 4096)
#![feature(box_syntax)]
#![feature(const_fn)]
+#![feature(fs_read_write)]
extern crate syntax;
extern crate rand;
--- /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 target::TargetResult;
+
+pub fn target() -> TargetResult {
+ let mut base = super::i686_unknown_linux_musl::target()?;
+ base.options.cpu = "pentium".to_string();
+ base.llvm_target = "i586-unknown-linux-musl".to_string();
+ Ok(base)
+}
use serialize::json::{Json, ToJson};
use std::collections::BTreeMap;
use std::default::Default;
-use std::io::prelude::*;
use syntax::abi::{Abi, lookup as lookup_abi};
use {LinkerFlavor, PanicStrategy, RelroLevel};
("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
+ ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
+
("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
("i686-unknown-linux-musl", i686_unknown_linux_musl),
+ ("i586-unknown-linux-musl", i586_unknown_linux_musl),
("mips-unknown-linux-musl", mips_unknown_linux_musl),
("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
+
("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
- ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
-
("i686-linux-android", i686_linux_android),
("x86_64-linux-android", x86_64_linux_android),
("arm-linux-androideabi", arm_linux_androideabi),
pub fn search(target: &str) -> Result<Target, String> {
use std::env;
use std::ffi::OsString;
- use std::fs::File;
+ use std::fs;
use std::path::{Path, PathBuf};
use serialize::json;
fn load_file(path: &Path) -> Result<Target, String> {
- let mut f = File::open(path).map_err(|e| e.to_string())?;
- let mut contents = Vec::new();
- f.read_to_end(&mut contents).map_err(|e| e.to_string())?;
+ let contents = fs::read(path).map_err(|e| e.to_string())?;
let obj = json::from_reader(&mut &contents[..])
.map_err(|e| e.to_string())?;
Target::from_json(obj)
ty::TyAdt(adt_def, _) if adt_def.is_union() => match result {
RestrictionResult::Safe => RestrictionResult::Safe,
RestrictionResult::SafeIf(base_lp, mut base_vec) => {
- for field in &adt_def.struct_variant().fields {
+ for field in &adt_def.non_enum_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
let field_ty = if field == interior {
cmt.ty
&move_data::Assignment) {
let mut err = self.cannot_reassign_immutable(span,
&self.loan_path_to_string(lp),
+ false,
Origin::Ast);
err.span_label(span, "cannot assign twice to immutable variable");
if span != assign.span {
err.span_label(assign.span, format!("first assignment to `{}`",
- self.loan_path_to_string(lp)));
+ self.loan_path_to_string(lp)));
}
err.emit();
}
if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior))
= (&base_lp.ty.sty, lp_elem) {
if adt_def.is_union() {
- for field in &adt_def.struct_variant().fields {
+ for field in &adt_def.non_enum_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
if field != interior {
let sibling_lp_kind =
if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
if adt_def.is_union() {
- for field in &adt_def.struct_variant().fields {
+ for field in &adt_def.non_enum_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
let field_ty = if field == interior {
lp.ty
let mut pcx = PatternContext::new(tcx, param_env_and_substs, tables);
let result = pcx.lower_pattern(pat);
if !pcx.errors.is_empty() {
- span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors)
+ let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
+ tcx.sess.delay_span_bug(pat.span, &msg);
}
debug!("Pattern::from_hir({:?}) = {:?}", pat, result);
result
use std::str;
-pub const MAX_BASE: u64 = 64;
-pub const ALPHANUMERIC_ONLY: u64 = 62;
+pub const MAX_BASE: usize = 64;
+pub const ALPHANUMERIC_ONLY: usize = 62;
+pub const CASE_INSENSITIVE: usize = 36;
const BASE_64: &'static [u8; MAX_BASE as usize] =
b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
#[inline]
-pub fn push_str(mut n: u64, base: u64, output: &mut String) {
+pub fn push_str(mut n: u128, base: usize, output: &mut String) {
debug_assert!(base >= 2 && base <= MAX_BASE);
- let mut s = [0u8; 64];
+ let mut s = [0u8; 128];
let mut index = 0;
+ let base = base as u128;
+
loop {
s[index] = BASE_64[(n % base) as usize];
index += 1;
}
#[inline]
-pub fn encode(n: u64, base: u64) -> String {
- let mut s = String::with_capacity(13);
+pub fn encode(n: u128, base: usize) -> String {
+ let mut s = String::new();
push_str(n, base, &mut s);
s
}
#[test]
fn test_encode() {
- fn test(n: u64, base: u64) {
- assert_eq!(Ok(n), u64::from_str_radix(&encode(n, base), base as u32));
+ fn test(n: u128, base: usize) {
+ assert_eq!(Ok(n), u128::from_str_radix(&encode(n, base), base as u32));
}
for base in 2..37 {
test(35, base);
test(36, base);
test(37, base);
- test(u64::max_value(), base);
+ test(u64::max_value() as u128, base);
+ test(u128::max_value(), base);
for i in 0 .. 1_000 {
test(i * 983, base);
|| hir_map::map_crate(sess, cstore, &mut hir_forest, &defs));
{
- let _ignore = hir_map.dep_graph.in_ignore();
+ hir_map.dep_graph.assert_ignored();
controller_entry_point!(after_hir_lowering,
sess,
CompileState::state_after_hir_lowering(input,
Ok(()));
}
- time(sess.time_passes(), "attribute checking", || {
- hir::check_attr::check_crate(sess, &expanded_crate);
- });
-
let opt_crate = if control.keep_ast {
Some(&expanded_crate)
} else {
|tcx, analysis, rx, result| {
{
// Eventually, we will want to track plugins.
- let _ignore = tcx.dep_graph.in_ignore();
-
- let mut state = CompileState::state_after_analysis(input,
- sess,
- outdir,
- output,
- opt_crate,
- tcx.hir.krate(),
- &analysis,
- tcx,
- &crate_name);
- (control.after_analysis.callback)(&mut state);
+ tcx.dep_graph.with_ignore(|| {
+ let mut state = CompileState::state_after_analysis(input,
+ sess,
+ outdir,
+ output,
+ opt_crate,
+ tcx.hir.krate(),
+ &analysis,
+ tcx,
+ &crate_name);
+ (control.after_analysis.callback)(&mut state);
+ });
if control.after_analysis.stop == Compilation::Stop {
return result.and_then(|_| Err(CompileIncomplete::Stopped));
let dep_graph = match future_dep_graph {
None => DepGraph::new_disabled(),
Some(future) => {
- let prev_graph = future
- .open()
- .expect("Could not join with background dep_graph thread")
- .open(sess);
+ let prev_graph = time(time_passes, "blocked while dep-graph loading finishes", || {
+ future.open()
+ .expect("Could not join with background dep_graph thread")
+ .open(sess)
+ });
DepGraph::new(prev_graph)
}
};
// tcx available.
rustc_incremental::dep_graph_tcx_init(tcx);
+ time(sess.time_passes(), "attribute checking", || {
+ hir::check_attr::check_crate(tcx)
+ });
+
time(time_passes,
"stability checking",
|| stability::check_unstable_api_usage(tcx));
pub use rustc_trans_utils::trans_crate::TranslatedCrate as CrateTranslation;
pub fn init(_sess: &Session) {}
- pub fn enable_llvm_debug() {}
pub fn print_version() {}
pub fn print_passes() {}
pub fn print(_req: PrintRequest, _sess: &Session) {}
let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
- if sopts.debugging_opts.debug_llvm {
- rustc_trans::enable_llvm_debug();
- }
-
let descriptions = diagnostics_registry();
do_or_return!(callbacks.early_callback(&matches,
tcx,
tables: Cell::new(&empty_tables)
};
- let _ignore = tcx.dep_graph.in_ignore();
- f(&annotation, hir_map.forest.krate())
+ tcx.dep_graph.with_ignore(|| {
+ f(&annotation, hir_map.forest.krate())
+ })
}),
sess)
}
hir::ItemUnion(..) |
hir::ItemTrait(..) |
hir::ItemTraitAlias(..) |
- hir::ItemImpl(..) |
- hir::ItemAutoImpl(..) => None,
+ hir::ItemImpl(..) => None,
hir::ItemMod(ref m) => search_mod(this, m, idx, names),
};
buffer.append(buffer_msg_line_offset,
&format!("{}:{}:{}",
loc.file.name,
- loc.line,
+ cm.doctest_offset_line(loc.line),
loc.col.0 + 1),
Style::LineAndColumn);
for _ in 0..max_line_num_len {
buffer.prepend(0,
&format!("{}:{}:{} - ",
loc.file.name,
- loc.line,
+ cm.doctest_offset_line(loc.line),
loc.col.0 + 1),
Style::LineAndColumn);
}
fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span>;
fn call_span_if_macro(&self, sp: Span) -> Span;
fn ensure_filemap_source_present(&self, file_map: Rc<FileMap>) -> bool;
+ fn doctest_offset_line(&self, line: usize) -> usize;
}
impl CodeSuggestion {
self.continue_after_error.set(continue_after_error);
}
- // NOTE: DO NOT call this function from rustc, as it relies on `err_count` being non-zero
- // if an error happened to avoid ICEs. This function should only be called from tools.
+ /// Resets the diagnostic error count as well as the cached emitted diagnostics.
+ ///
+ /// NOTE: DO NOT call this function from rustc. It is only meant to be called from external
+ /// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as
+ /// the overall count of emitted error diagnostics.
pub fn reset_err_count(&self) {
+ self.emitted_diagnostics.replace(FxHashSet());
self.err_count.store(0, SeqCst);
}
use rustc::ich::{ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED};
use graphviz::IntoCow;
use std::env;
-use std::fs::File;
+use std::fs::{self, File};
use std::io::Write;
use syntax::ast;
use syntax_pos::Span;
pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let _ignore = tcx.dep_graph.in_ignore();
-
- if tcx.sess.opts.debugging_opts.dump_dep_graph {
- dump_graph(tcx);
- }
-
- // if the `rustc_attrs` feature is not enabled, then the
- // attributes we are interested in cannot be present anyway, so
- // skip the walk.
- if !tcx.sess.features.borrow().rustc_attrs {
- return;
- }
+ tcx.dep_graph.with_ignore(|| {
+ if tcx.sess.opts.debugging_opts.dump_dep_graph {
+ dump_graph(tcx);
+ }
- // Find annotations supplied by user (if any).
- let (if_this_changed, then_this_would_need) = {
- let mut visitor = IfThisChanged { tcx,
- if_this_changed: vec![],
- then_this_would_need: vec![] };
- visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir.krate().attrs);
- tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
- (visitor.if_this_changed, visitor.then_this_would_need)
- };
+ // if the `rustc_attrs` feature is not enabled, then the
+ // attributes we are interested in cannot be present anyway, so
+ // skip the walk.
+ if !tcx.sess.features.borrow().rustc_attrs {
+ return;
+ }
- if !if_this_changed.is_empty() || !then_this_would_need.is_empty() {
- assert!(tcx.sess.opts.debugging_opts.query_dep_graph,
- "cannot use the `#[{}]` or `#[{}]` annotations \
- without supplying `-Z query-dep-graph`",
- ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED);
- }
+ // Find annotations supplied by user (if any).
+ let (if_this_changed, then_this_would_need) = {
+ let mut visitor = IfThisChanged { tcx,
+ if_this_changed: vec![],
+ then_this_would_need: vec![] };
+ visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir.krate().attrs);
+ tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+ (visitor.if_this_changed, visitor.then_this_would_need)
+ };
+
+ if !if_this_changed.is_empty() || !then_this_would_need.is_empty() {
+ assert!(tcx.sess.opts.debugging_opts.query_dep_graph,
+ "cannot use the `#[{}]` or `#[{}]` annotations \
+ without supplying `-Z query-dep-graph`",
+ ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED);
+ }
- // Check paths.
- check_paths(tcx, &if_this_changed, &then_this_would_need);
+ // Check paths.
+ check_paths(tcx, &if_this_changed, &then_this_would_need);
+ })
}
type Sources = Vec<(Span, DefId, DepNode)>;
let dot_path = format!("{}.dot", path);
let mut v = Vec::new();
dot::render(&GraphvizDepGraph(nodes, edges), &mut v).unwrap();
- File::create(&dot_path).and_then(|mut f| f.write_all(&v)).unwrap();
+ fs::write(dot_path, v).unwrap();
}
}
#![deny(warnings)]
#![feature(conservative_impl_trait)]
+#![feature(fs_read_write)]
#![feature(i128_type)]
#![feature(inclusive_range_syntax)]
#![feature(specialization)]
return;
}
- let _ignore = tcx.dep_graph.in_ignore();
- let krate = tcx.hir.krate();
- let mut dirty_clean_visitor = DirtyCleanVisitor {
- tcx,
- checked_attrs: FxHashSet(),
- };
- krate.visit_all_item_likes(&mut dirty_clean_visitor);
-
- let mut all_attrs = FindAllAttrs {
- tcx,
- attr_names: vec![ATTR_DIRTY, ATTR_CLEAN],
- found_attrs: vec![],
- };
- intravisit::walk_crate(&mut all_attrs, krate);
-
- // Note that we cannot use the existing "unused attribute"-infrastructure
- // here, since that is running before trans. This is also the reason why
- // all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
- all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
+ tcx.dep_graph.with_ignore(|| {
+ let krate = tcx.hir.krate();
+ let mut dirty_clean_visitor = DirtyCleanVisitor {
+ tcx,
+ checked_attrs: FxHashSet(),
+ };
+ krate.visit_all_item_likes(&mut dirty_clean_visitor);
+
+ let mut all_attrs = FindAllAttrs {
+ tcx,
+ attr_names: vec![ATTR_DIRTY, ATTR_CLEAN],
+ found_attrs: vec![],
+ };
+ intravisit::walk_crate(&mut all_attrs, krate);
+
+ // Note that we cannot use the existing "unused attribute"-infrastructure
+ // here, since that is running before trans. This is also the reason why
+ // all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
+ all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
+ })
}
pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
//
//HirItem::ItemTrait(..) => ("ItemTrait", LABELS_TRAIT),
- // `impl Trait for .. {}`
- HirItem::ItemAutoImpl(..) => ("ItemAutoImpl", LABELS_IMPL),
-
// An implementation, eg `impl<A> Trait for Foo { .. }`
HirItem::ItemImpl(..) => ("ItemImpl", LABELS_IMPL),
use std::io::{self, Read};
use std::path::Path;
-use std::fs::File;
+use std::fs;
use std::env;
use rustc::session::config::nightly_options;
return Ok(None);
}
- let mut file = File::open(path)?;
- let file_size = file.metadata()?.len() as usize;
-
- let mut data = Vec::with_capacity(file_size);
- file.read_to_end(&mut data)?;
+ let data = fs::read(path)?;
let mut file = io::Cursor::new(data);
// or hexadecimal numbers (we want short file and directory names). Since these
// numbers will be used in file names, we choose an encoding that is not
// case-sensitive (as opposed to base64, for example).
-const INT_ENCODE_BASE: u64 = 36;
+const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE;
pub fn dep_graph_path(sess: &Session) -> PathBuf {
in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME)
let mut new_sub_dir_name = String::from(&old_sub_dir_name[.. dash_indices[2] + 1]);
// Append the svh
- base_n::push_str(svh.as_u64(), INT_ENCODE_BASE, &mut new_sub_dir_name);
+ base_n::push_str(svh.as_u64() as u128, INT_ENCODE_BASE, &mut new_sub_dir_name);
// Create the full path
let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name);
let directory_name = format!("s-{}-{}-working",
timestamp,
- base_n::encode(random_number as u64,
+ base_n::encode(random_number as u128,
INT_ENCODE_BASE));
debug!("generate_session_dir_path: directory_name = {}", directory_name);
let directory_path = crate_dir.join(directory_name);
let duration = timestamp.duration_since(UNIX_EPOCH).unwrap();
let micros = duration.as_secs() * 1_000_000 +
(duration.subsec_nanos() as u64) / 1000;
- base_n::encode(micros, INT_ENCODE_BASE)
+ base_n::encode(micros as u128, INT_ENCODE_BASE)
}
fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
// The full crate disambiguator is really long. 64 bits of it should be
// sufficient.
let crate_disambiguator = crate_disambiguator.to_fingerprint().to_smaller_hash();
- let crate_disambiguator = base_n::encode(crate_disambiguator, INT_ENCODE_BASE);
+ let crate_disambiguator = base_n::encode(crate_disambiguator as u128,
+ INT_ENCODE_BASE);
let crate_name = format!("{}-{}", crate_name, crate_disambiguator);
incr_dir.join(crate_name)
use rustc_data_structures::fx::FxHashMap;
use rustc_serialize::Encodable as RustcEncodable;
use rustc_serialize::opaque::Encoder;
-use std::io::{self, Cursor, Write};
-use std::fs::{self, File};
+use std::io::{self, Cursor};
+use std::fs;
use std::path::PathBuf;
use super::data::*;
pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
debug!("save_dep_graph()");
- let _ignore = tcx.dep_graph.in_ignore();
- let sess = tcx.sess;
- if sess.opts.incremental.is_none() {
- return;
- }
-
- time(sess.time_passes(), "persist query result cache", || {
- save_in(sess,
- query_cache_path(sess),
- |e| encode_query_cache(tcx, e));
- });
+ tcx.dep_graph.with_ignore(|| {
+ let sess = tcx.sess;
+ if sess.opts.incremental.is_none() {
+ return;
+ }
- if tcx.sess.opts.debugging_opts.incremental_queries {
- time(sess.time_passes(), "persist dep-graph", || {
+ time(sess.time_passes(), "persist query result cache", || {
save_in(sess,
- dep_graph_path(sess),
- |e| encode_dep_graph(tcx, e));
+ query_cache_path(sess),
+ |e| encode_query_cache(tcx, e));
});
- }
- dirty_clean::check_dirty_clean_annotations(tcx);
+ if tcx.sess.opts.debugging_opts.incremental_queries {
+ time(sess.time_passes(), "persist dep-graph", || {
+ save_in(sess,
+ dep_graph_path(sess),
+ |e| encode_dep_graph(tcx, e));
+ });
+ }
+
+ dirty_clean::check_dirty_clean_annotations(tcx);
+ })
}
pub fn save_work_products(sess: &Session, dep_graph: &DepGraph) {
}
debug!("save_work_products()");
- let _ignore = dep_graph.in_ignore();
+ dep_graph.assert_ignored();
let path = work_products_path(sess);
save_in(sess, path, |e| encode_work_products(dep_graph, e));
// write the data out
let data = wr.into_inner();
- match File::create(&path_buf).and_then(|mut file| file.write_all(&data)) {
+ match fs::write(&path_buf, data) {
Ok(_) => {
debug!("save: data written to disk successfully");
}
let extension = match kind {
WorkProductFileKind::Object => "o",
WorkProductFileKind::Bytecode => "bc",
- WorkProductFileKind::BytecodeCompressed => "bc-compressed",
+ WorkProductFileKind::BytecodeCompressed => "bc.z",
};
- let file_name = format!("cgu-{}.{}", cgu_name, extension);
+ let file_name = format!("{}.{}", cgu_name, extension);
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
match link_or_copy(path, &path_in_incr_dir) {
Ok(_) => Some((kind, file_name)),
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes {
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
- let extern_repr_count = it.attrs
+ let has_repr_c = it.attrs
.iter()
- .filter(|attr| {
+ .any(|attr| {
attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr)
.iter()
- .any(|r| r == &attr::ReprExtern)
- })
- .count();
- let has_extern_repr = extern_repr_count > 0;
+ .any(|r| r == &attr::ReprC)
+ });
- if has_extern_repr {
+ if has_repr_c {
return;
}
// hardwired lints from librustc
pub use lint::builtin::*;
-declare_lint! {
- pub AUTO_IMPL,
- Deny,
- "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`"
-}
-
-#[derive(Copy, Clone)]
-pub struct AutoImpl;
-
-impl LintPass for AutoImpl {
- fn get_lints(&self) -> LintArray {
- lint_array!(AUTO_IMPL)
- }
-}
-
-impl EarlyLintPass for AutoImpl {
- fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) {
- let msg = "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`";
- match item.node {
- ast::ItemKind::AutoImpl(..) => cx.span_lint(AUTO_IMPL, item.span, msg),
- _ => ()
- }
- }
-}
-
declare_lint! {
WHILE_TRUE,
Warn,
// don't have anything to attach a symbol to
let msg = "const items should never be #[no_mangle]";
let mut err = cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
+
+ // account for "pub const" (#45562)
+ let start = cx.tcx.sess.codemap().span_to_snippet(it.span)
+ .map(|snippet| snippet.find("const").unwrap_or(0))
+ .unwrap_or(0) as u32;
// `const` is 5 chars
- let const_span = it.span.with_hi(BytePos(it.span.lo().0 + 5));
+ let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
err.span_suggestion(const_span,
"try a static value",
"pub static".to_owned());
AnonymousParameters,
IllegalFloatLiteralPattern,
UnusedDocComment,
- AutoImpl,
);
add_early_builtin_with_new!(sess,
// - Eventually, remove lint
store.register_future_incompatible(sess,
vec![
- FutureIncompatibleInfo {
- id: LintId::of(AUTO_IMPL),
- reference: "issue #13231 <https://github.com/rust-lang/rust/issues/13231>",
- },
FutureIncompatibleInfo {
id: LintId::of(PRIVATE_IN_PUBLIC),
reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
consider adding a #[repr(C)] attribute to the type");
}
- if def.struct_variant().fields.is_empty() {
+ if def.non_enum_variant().fields.is_empty() {
return FfiUnsafe("found zero-size struct in foreign module, consider \
adding a member to this struct");
}
// We can't completely trust repr(C) markings; make sure the
// fields are actually safe.
let mut all_phantom = true;
- for field in &def.struct_variant().fields {
+ for field in &def.non_enum_variant().fields {
let field_ty = cx.fully_normalize_associated_types_in(
&field.ty(cx, substs)
);
consider adding a #[repr(C)] attribute to the type");
}
- if def.struct_variant().fields.is_empty() {
+ if def.non_enum_variant().fields.is_empty() {
return FfiUnsafe("found zero-size union in foreign module, consider \
adding a member to this union");
}
let mut all_phantom = true;
- for field in &def.struct_variant().fields {
+ for field in &def.non_enum_variant().fields {
let field_ty = cx.fully_normalize_associated_types_in(
&field.ty(cx, substs)
);
ElementCount: c_uint,
Packed: Bool);
- /// Enables LLVM debug output.
- pub fn LLVMRustSetDebug(Enabled: c_int);
-
/// Prepares inline assembly.
pub fn LLVMRustInlineAsm(Ty: TypeRef,
AsmString: *const c_char,
pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool);
pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef, bc: *const c_char, len: size_t) -> bool;
- pub fn LLVMRustLinkInParsedExternalBitcode(M: ModuleRef, M: ModuleRef) -> bool;
pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t);
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
- pub fn LLVMRustWriteDebugLocToString(C: ContextRef, DL: DebugLocRef, s: RustStringRef);
-
pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef,
H: InlineAsmDiagHandler,
CX: *mut c_void);
build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
}
-pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
- build_string(|s| LLVMRustWriteDebugLocToString(c, tr, s))
- .expect("got a non-UTF8 DebugLoc from LLVM")
-}
-
pub fn initialize_available_targets() {
macro_rules! init_target(
($cfg:meta, $($method:ident),*) => { {
inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
is_const_fn => { cdata.is_const_fn(def_id.index) }
is_foreign_item => { cdata.is_foreign_item(def_id.index) }
- is_auto_impl => { cdata.is_auto_impl(def_id.index) }
describe_def => { cdata.get_def(def_id.index) }
def_span => { cdata.get_span(def_id.index, &tcx.sess) }
lookup_stability => {
fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
let data = self.get_crate_data(id.krate);
if let Some(ref proc_macros) = data.proc_macros {
- return LoadedMacro::ProcMacro(proc_macros[id.index.as_usize() - 1].1.clone());
+ return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
} else if data.name == "proc_macro" &&
self.get_crate_data(id.krate).item_name(id.index) == "quote" {
let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter));
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
ExternBodyNestedBodies};
use rustc::hir::def::{self, Def, CtorKind};
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
+ CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::ich::Fingerprint;
use rustc::middle::lang_items;
use rustc::mir;
use std::u32;
use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
-use rustc_data_structures::indexed_vec::Idx;
use syntax::attr;
use syntax::ast::{self, Ident};
use syntax::codemap;
impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
#[inline]
fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
- Ok(DefIndex::from_u32(self.read_u32()?))
+ Ok(DefIndex::from_raw_u32(self.read_u32()?))
}
}
}
}
+impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+ Fingerprint::decode_opaque(&mut self.opaque)
+ }
+}
+
impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
for DecodeContext<'a, 'tcx> {
#[inline]
EntryKind::ForeignMod |
EntryKind::Impl(_) |
- EntryKind::AutoImpl(_) |
EntryKind::Field |
EntryKind::Generator(_) |
EntryKind::Closure(_) => return None,
if !self.is_proc_macro(index) {
self.entry(index).kind.to_def(self.local_def_id(index))
} else {
- let kind = self.proc_macros.as_ref().unwrap()[index.as_usize() - 1].1.kind();
+ let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind();
Some(Def::Macro(self.local_def_id(index), kind))
}
}
let def = Def::Macro(
DefId {
krate: self.cnum,
- index: DefIndex::new(id + 1)
+ index: DefIndex::from_proc_macro_index(id),
},
ext.kind()
);
}
continue;
}
- EntryKind::Impl(_) |
- EntryKind::AutoImpl(_) => continue,
+ EntryKind::Impl(_) => continue,
_ => {}
}
self.dllimport_foreign_items.contains(&id)
}
- pub fn is_auto_impl(&self, impl_id: DefIndex) -> bool {
- match self.entry(impl_id).kind {
- EntryKind::AutoImpl(_) => true,
- _ => false,
- }
- }
-
pub fn fn_sig(&self,
id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
use rustc::hir::def::CtorKind;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
use rustc::hir::map::definitions::DefPathTable;
+use rustc::ich::Fingerprint;
use rustc::middle::dependency_format::Linkage;
use rustc::middle::lang_items;
use rustc::mir;
impl<'a, 'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'a, 'tcx> {
#[inline]
fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> {
- self.emit_u32(def_index.as_u32())
+ self.emit_u32(def_index.as_raw_u32())
}
}
}
}
+impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'a, 'tcx> {
+ fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+ f.encode_opaque(&mut self.opaque)
+ }
+}
+
impl<'a, 'tcx, T: Encodable> SpecializedEncoder<mir::ClearCrossCrate<T>>
for EncodeContext<'a, 'tcx> {
fn specialized_encode(&mut self,
debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
let tcx = self.tcx;
let adt_def = tcx.adt_def(adt_def_id);
- let variant = adt_def.struct_variant();
+ let variant = adt_def.non_enum_variant();
let data = VariantData {
ctor_kind: variant.ctor_kind,
fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId)
-> LazySeq<ast::Name> {
- let _ignore = self.tcx.dep_graph.in_ignore();
- let body = self.tcx.hir.body(body_id);
- self.lazy_seq(body.arguments.iter().map(|arg| {
- match arg.pat.node {
- PatKind::Binding(_, _, name, _) => name.node,
- _ => Symbol::intern("")
- }
- }))
+ self.tcx.dep_graph.with_ignore(|| {
+ let body = self.tcx.hir.body(body_id);
+ self.lazy_seq(body.arguments.iter().map(|arg| {
+ match arg.pat.node {
+ PatKind::Binding(_, _, name, _) => name.node,
+ _ => Symbol::intern("")
+ }
+ }))
+ })
}
fn encode_fn_arg_names(&mut self, names: &[Spanned<ast::Name>])
hir::ItemTy(..) => EntryKind::Type,
hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
hir::ItemStruct(ref struct_def, _) => {
- let variant = tcx.adt_def(def_id).struct_variant();
+ let variant = tcx.adt_def(def_id).non_enum_variant();
// Encode def_ids for each field and method
// for methods, write all the stuff get_trait_method
}), repr_options)
}
hir::ItemUnion(..) => {
- let variant = tcx.adt_def(def_id).struct_variant();
+ let variant = tcx.adt_def(def_id).non_enum_variant();
let repr_options = get_repr_options(&tcx, def_id);
EntryKind::Union(self.lazy(&VariantData {
ctor_sig: None,
}), repr_options)
}
- hir::ItemAutoImpl(..) => {
- let data = ImplData {
- polarity: hir::ImplPolarity::Positive,
- defaultness: hir::Defaultness::Final,
- parent_impl: None,
- coerce_unsized_info: None,
- trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
- };
-
- EntryKind::AutoImpl(self.lazy(&data))
- }
hir::ItemImpl(_, polarity, defaultness, ..) => {
let trait_ref = tcx.impl_trait_ref(def_id);
let parent = if let Some(trait_ref) = trait_ref {
hir::ItemStruct(..) |
hir::ItemUnion(..) => {
let def = self.tcx.adt_def(def_id);
- self.lazy_seq(def.struct_variant().fields.iter().map(|f| {
+ self.lazy_seq(def.non_enum_variant().fields.iter().map(|f| {
assert!(f.did.is_local());
f.did.index
}))
hir::ItemGlobalAsm(..) |
hir::ItemExternCrate(..) |
hir::ItemUse(..) |
- hir::ItemAutoImpl(..) |
hir::ItemTy(..) |
hir::ItemTraitAlias(..) => {
// no sub-item recording needed in these cases
#[inline(never)]
pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
let words = &bytes_to_words(&bytes[self.position..])[..self.len];
- let index = def_index.as_usize();
debug!("Index::lookup: index={:?} words.len={:?}",
- index,
+ def_index,
words.len());
let positions = match def_index.address_space() {
where DATA: DepGraphRead
{
assert!(id.is_local());
- let tcx: TyCtxt<'b, 'tcx, 'tcx> = self.ecx.tcx;
// We don't track this since we are explicitly computing the incr. comp.
// hashes anyway. In theory we could do some tracking here and use it to
// avoid rehashing things (and instead cache the hashes) but it's
// unclear whether that would be a win since hashing is cheap enough.
- let _task = tcx.dep_graph.in_ignore();
+ self.ecx.tcx.dep_graph.with_ignore(move || {
+ let mut entry_builder = IsolatedEncoder::new(self.ecx);
+ let entry = op(&mut entry_builder, data);
+ let entry = entry_builder.lazy(&entry);
- let mut entry_builder = IsolatedEncoder::new(self.ecx);
- let entry = op(&mut entry_builder, data);
- let entry = entry_builder.lazy(&entry);
-
- self.items.record(id, entry);
+ self.items.record(id, entry);
+ })
}
pub fn into_items(self) -> Index {
#![feature(box_patterns)]
#![feature(conservative_impl_trait)]
+#![feature(fs_read_write)]
#![feature(i128_type)]
#![feature(libc)]
#![feature(proc_macro_internals)]
use std::cmp;
use std::fmt;
-use std::fs::{self, File};
+use std::fs;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::time::Instant;
}
}
CrateFlavor::Rmeta => {
- let mut file = File::open(filename).map_err(|_|
- format!("could not open file: '{}'", filename.display()))?;
- let mut buf = vec![];
- file.read_to_end(&mut buf).map_err(|_|
+ let buf = fs::read(filename).map_err(|_|
format!("failed to read rmeta metadata: '{}'", filename.display()))?;
OwningRef::new(buf).map_owner_box().erase_owner()
}
Generator(Lazy<GeneratorData<'tcx>>),
Trait(Lazy<TraitData<'tcx>>),
Impl(Lazy<ImplData<'tcx>>),
- AutoImpl(Lazy<ImplData<'tcx>>),
Method(Lazy<MethodData<'tcx>>),
AssociatedType(AssociatedContainer),
AssociatedConst(AssociatedContainer, u8),
EntryKind::Trait(ref trait_data) => {
trait_data.hash_stable(hcx, hasher);
}
- EntryKind::AutoImpl(ref impl_data) |
EntryKind::Impl(ref impl_data) => {
impl_data.hash_stable(hcx, hasher);
}
use syntax_pos::Span;
use rustc::middle::region::ScopeTree;
-use rustc::mir::{BorrowKind, Field, Local, Location, Operand};
+use rustc::mir::{BorrowKind, Field, Local, LocalKind, Location, Operand};
use rustc::mir::{Place, ProjectionElem, Rvalue, Statement, StatementKind};
use rustc::ty::{self, RegionKind};
use rustc_data_structures::indexed_vec::Idx;
(place, span): (&Place<'tcx>, Span),
assigned_span: Span,
) {
+ let is_arg = if let Place::Local(local) = place {
+ if let LocalKind::Arg = self.mir.local_kind(*local) {
+ true
+ } else {
+ false
+ }
+ } else {
+ false
+ };
+
let mut err = self.tcx.cannot_reassign_immutable(
span,
&self.describe_place(place).unwrap_or("_".to_owned()),
+ is_arg,
Origin::Mir,
);
- err.span_label(span, "cannot assign twice to immutable variable");
+ let msg = if is_arg {
+ "cannot assign to immutable argument"
+ } else {
+ "cannot assign twice to immutable variable"
+ };
if span != assigned_span {
- let value_msg = match self.describe_place(place) {
- Some(name) => format!("`{}`", name),
- None => "value".to_owned(),
- };
- err.span_label(assigned_span, format!("first assignment to {}", value_msg));
+ if is_arg {
+ err.span_label(assigned_span, "argument not declared as `mut`");
+ } else {
+ let value_msg = match self.describe_place(place) {
+ Some(name) => format!("`{}`", name),
+ None => "value".to_owned(),
+ };
+ err.span_label(assigned_span, format!("first assignment to {}", value_msg));
+ }
}
+ err.span_label(span, msg);
err.emit();
}
}
ty::TyAdt(def, _) => if def.is_enum() {
format!("{}", field.index())
} else {
- format!("{}", def.struct_variant().fields[field.index()].name)
+ format!("{}", def.non_enum_variant().fields[field.index()].name)
},
ty::TyTuple(_, _) => format!("{}", field.index()),
ty::TyRef(_, tnm) | ty::TyRawPtr(tnm) => {
// associated types here and possibly recursively process.
for ty in dtorck_types {
let ty = self.cx.normalize(&ty, location);
+ let ty = self.cx.infcx.resolve_type_and_region_vars_if_possible(&ty);
match ty.sty {
ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
let cause = Cause::DropVar(dropped_local, location);
use dot;
use dot::IntoCow;
-use std::fs::File;
+use std::fs;
use std::io;
use std::io::prelude::*;
use std::marker::PhantomData;
dot::render(&g, &mut v)?;
debug!("print_borrowck_graph_to path: {} node_id: {}",
path.display(), mbcx.node_id);
- File::create(path).and_then(|mut f| f.write_all(&v))
+ fs::write(path, v)
}
pub type Node = BasicBlock;
miri_place = ecx.place_downcast(miri_place, variant).unwrap();
&def.variants[variant]
} else {
- def.struct_variant()
+ def.non_enum_variant()
};
let vec = match ctfe {
ConstVal::Aggregate(Struct(v)) => v,
#![feature(core_intrinsics)]
#![feature(decl_macro)]
#![feature(dyn_trait)]
+#![feature(fs_read_write)]
#![feature(i128_type)]
#![feature(inclusive_range_syntax)]
#![feature(inclusive_range)]
CustomCoerceUnsized::Struct(i) => i
};
- let source_fields = &source_adt_def.struct_variant().fields;
- let target_fields = &target_adt_def.struct_variant().fields;
+ let source_fields = &source_adt_def.non_enum_variant().fields;
+ let target_fields = &target_adt_def.non_enum_variant().fields;
assert!(coerce_index < source_fields.len() &&
source_fields.len() == target_fields.len());
hir::ItemUse(..) |
hir::ItemForeignMod(..) |
hir::ItemTy(..) |
- hir::ItemAutoImpl(..) |
hir::ItemTrait(..) |
hir::ItemTraitAlias(..) |
hir::ItemMod(..) => {
}
// Anything we can't find a proper codegen unit for goes into this.
-const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
+fn fallback_cgu_name(tcx: TyCtxt) -> InternedString {
+ const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
+
+ if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+ Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str()
+ } else {
+ Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_str()
+ }
+}
+
pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
trans_items: I,
let codegen_unit_name = match characteristic_def_id {
Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile),
- None => Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str(),
+ None => fallback_cgu_name(tcx),
};
let make_codegen_unit = || {
// always ensure we have at least one CGU; otherwise, if we have a
// crate with just types (for example), we could wind up with no CGU
if codegen_units.is_empty() {
- let codegen_unit_name = Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str();
+ let codegen_unit_name = fallback_cgu_name(tcx);
codegen_units.insert(codegen_unit_name.clone(),
CodegenUnit::new(codegen_unit_name.clone()));
}
// Unfortunately we cannot just use the `ty::item_path` infrastructure here
// because we need paths to modules and the DefIds of those are not
// available anymore for external items.
- let mut mod_path = String::with_capacity(64);
+ let mut cgu_name = String::with_capacity(64);
let def_path = tcx.def_path(def_id);
- mod_path.push_str(&tcx.crate_name(def_path.krate).as_str());
+ cgu_name.push_str(&tcx.crate_name(def_path.krate).as_str());
for part in tcx.def_path(def_id)
.data
_ => false,
}
}) {
- mod_path.push_str("-");
- mod_path.push_str(&part.data.as_interned_str());
+ cgu_name.push_str("-");
+ cgu_name.push_str(&part.data.as_interned_str());
}
if volatile {
- mod_path.push_str(".volatile");
+ cgu_name.push_str(".volatile");
}
- return Symbol::intern(&mod_path[..]).as_str();
+ let cgu_name = if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+ cgu_name
+ } else {
+ CodegenUnit::mangle_name(&cgu_name)
+ };
+
+ Symbol::intern(&cgu_name[..]).as_str()
}
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
return_qualif: Option<Qualif>,
qualif: Qualif,
const_fn_arg_vars: BitVector,
- local_needs_drop: IndexVec<Local, Option<Span>>,
temp_promotion_state: IndexVec<Local, TempState>,
promotion_candidates: Vec<Candidate>
}
let mut rpo = traversal::reverse_postorder(mir);
let temps = promote_consts::collect_temps(mir, &mut rpo);
rpo.reset();
+
+ let param_env = tcx.param_env(def_id);
+
+ let mut temp_qualif = IndexVec::from_elem(None, &mir.local_decls);
+ for arg in mir.args_iter() {
+ let mut qualif = Qualif::NEEDS_DROP;
+ qualif.restrict(mir.local_decls[arg].ty, tcx, param_env);
+ temp_qualif[arg] = Some(qualif);
+ }
+
Qualifier {
mode,
span: mir.span,
mir,
rpo,
tcx,
- param_env: tcx.param_env(def_id),
- temp_qualif: IndexVec::from_elem(None, &mir.local_decls),
+ param_env,
+ temp_qualif,
return_qualif: None,
qualif: Qualif::empty(),
const_fn_arg_vars: BitVector::new(mir.local_decls.len()),
- local_needs_drop: IndexVec::from_elem(None, &mir.local_decls),
temp_promotion_state: temps,
promotion_candidates: vec![]
}
return;
}
- // When initializing a local, record whether the *value* being
- // stored in it needs dropping, which it may not, even if its
- // type does, e.g. `None::<String>`.
- if let Place::Local(local) = *dest {
- if qualif.intersects(Qualif::NEEDS_DROP) {
- self.local_needs_drop[local] = Some(self.span);
- }
- }
-
match *dest {
Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp => {
debug!("store to temp {:?}", index);
&local: &Local,
_: PlaceContext<'tcx>,
_: Location) {
- match self.mir.local_kind(local) {
+ let kind = self.mir.local_kind(local);
+ match kind {
LocalKind::ReturnPointer => {
self.not_const();
}
- LocalKind::Arg => {
- self.add(Qualif::FN_ARGUMENT);
- }
LocalKind::Var => {
self.add(Qualif::NOT_CONST);
}
+ LocalKind::Arg |
LocalKind::Temp => {
+ if let LocalKind::Arg = kind {
+ self.add(Qualif::FN_ARGUMENT);
+ }
+
if !self.temp_promotion_state[local].is_promotable() {
self.add(Qualif::NOT_PROMOTABLE);
}
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
match *operand {
- Operand::Copy(ref place) |
- Operand::Move(ref place) => {
+ Operand::Copy(_) |
+ Operand::Move(_) => {
self.nest(|this| {
this.super_operand(operand, location);
this.try_consume();
});
// Mark the consumed locals to indicate later drops are noops.
- if let Place::Local(local) = *place {
- self.local_needs_drop[local] = None;
+ if let Operand::Move(Place::Local(local)) = *operand {
+ self.temp_qualif[local] = self.temp_qualif[local].map(|q|
+ q - Qualif::NEEDS_DROP
+ );
}
}
Operand::Constant(ref constant) => {
// HACK(eddyb) Emulate a bit of dataflow analysis,
// conservatively, that drop elaboration will do.
let needs_drop = if let Place::Local(local) = *place {
- self.local_needs_drop[local]
+ if self.temp_qualif[local].map_or(true, |q| q.intersects(Qualif::NEEDS_DROP)) {
+ Some(self.mir.local_decls[local].source_info.span)
+ } else {
+ None
+ }
} else {
- None
+ Some(self.span)
};
if let Some(span) = needs_drop {
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_reassign_immutable(&self, span: Span, desc: &str, o: Origin)
+ fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Origin)
-> DiagnosticBuilder
{
+ let msg = if is_arg {
+ "to immutable argument"
+ } else {
+ "twice to immutable variable"
+ };
let err = struct_span_err!(self, span, E0384,
- "cannot assign twice to immutable variable `{}`{OGN}",
- desc, OGN=o);
+ "cannot assign {} `{}`{OGN}",
+ msg, desc, OGN=o);
self.cancel_if_wrong_origin(err, o)
}
fn visit_item(&mut self, item: &'a Item) {
match item.node {
- ItemKind::Impl(.., Some(..), _, ref impl_items) => {
+ ItemKind::Impl(unsafety, polarity, _, _, Some(..), ref ty, ref impl_items) => {
self.invalid_visibility(&item.vis, item.span, None);
+ if ty.node == TyKind::Err {
+ self.err_handler()
+ .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
+ .help("use `auto trait Trait {}` instead").emit();
+ }
+ if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
+ span_err!(self.session, item.span, E0198, "negative impls cannot be unsafe");
+ }
for impl_item in impl_items {
self.invalid_visibility(&impl_item.vis, impl_item.span, None);
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
}
}
}
- ItemKind::Impl(.., None, _, _) => {
+ ItemKind::Impl(unsafety, polarity, defaultness, _, None, _, _) => {
self.invalid_visibility(&item.vis,
item.span,
Some("place qualifiers on individual impl items instead"));
- }
- ItemKind::AutoImpl(..) => {
- self.invalid_visibility(&item.vis, item.span, None);
+ if unsafety == Unsafety::Unsafe {
+ span_err!(self.session, item.span, E0197, "inherent impls cannot be unsafe");
+ }
+ if polarity == ImplPolarity::Negative {
+ self.err_handler().span_err(item.span, "inherent impls cannot be negative");
+ }
+ if defaultness == Defaultness::Default {
+ self.err_handler().span_err(item.span, "inherent impls cannot be default");
+ }
}
ItemKind::ForeignMod(..) => {
self.invalid_visibility(&item.vis,
if is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
if generics.is_parameterized() {
- self.err_handler().span_err(item.span,
- "auto traits cannot have generics");
+ struct_span_err!(self.session, item.span, E0567,
+ "auto traits cannot have generic parameters").emit();
}
if !bounds.is_empty() {
- self.err_handler().span_err(item.span,
- "auto traits cannot have super traits");
+ struct_span_err!(self.session, item.span, E0568,
+ "auto traits cannot have super traits").emit();
}
if !trait_items.is_empty() {
- self.err_handler().span_err(item.span,
- "auto traits cannot contain items");
+ struct_span_err!(self.session, item.span, E0380,
+ "auto traits cannot have methods or associated items").emit();
}
}
self.no_questions_in_bounds(bounds, "supertraits", true);
```
"##,
+E0197: r##"
+Inherent implementations (one that do not implement a trait but provide
+methods associated with a type) are always safe because they are not
+implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
+implementation will resolve this error.
+
+```compile_fail,E0197
+struct Foo;
+
+// this will cause this error
+unsafe impl Foo { }
+// converting it to this will fix it
+impl Foo { }
+```
+"##,
+
+E0198: r##"
+A negative implementation is one that excludes a type from implementing a
+particular trait. Not being able to use a trait is always a safe operation,
+so negative implementations are always safe and never need to be marked as
+unsafe.
+
+```compile_fail
+#![feature(optin_builtin_traits)]
+
+struct Foo;
+
+// unsafe is unnecessary
+unsafe impl !Clone for Foo { }
+```
+
+This will compile:
+
+```ignore (ignore auto_trait future compatibility warning)
+#![feature(optin_builtin_traits)]
+
+struct Foo;
+
+auto trait Enterprise {}
+
+impl !Enterprise for Foo { }
+```
+
+Please note that negative impls are only allowed for auto traits.
+"##,
+
E0265: r##"
This error indicates that a static or constant references itself.
All statics and constants need to resolve to a value in an acyclic manner.
[RFC 911]: https://github.com/rust-lang/rfcs/pull/911
"##,
+E0380: r##"
+Auto traits cannot have methods or associated items.
+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
+"##,
+
E0449: r##"
A visibility qualifier was used when it was unnecessary. Erroneous code
examples:
E0226, // only a single explicit lifetime bound is permitted
E0472, // asm! is unsupported on this target
E0561, // patterns aren't allowed in function pointer types
+ E0567, // auto traits can not have generic parameters
+ E0568, // auto traits can not have super traits
E0642, // patterns aren't allowed in methods without bodies
}
let def_id = self.tcx.hir.local_def_id(item.id);
cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id))
}
- hir::ItemAutoImpl(..) => {
- let def_id = self.tcx.hir.local_def_id(item.id);
- self.impl_trait_level(def_id)
- }
// Foreign mods inherit level from parents
hir::ItemForeignMod(..) => {
self.prev_level
}
hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) | hir::ItemTraitAlias(..) |
- hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemAutoImpl(..) => {}
+ hir::ItemFn(..) | hir::ItemExternCrate(..) => {}
}
// Mark all items in interfaces of reachable items as reachable
// Reexports are handled in visit_mod
hir::ItemUse(..) => {}
// The interface is empty
- hir::ItemAutoImpl(..) => {}
- // The interface is empty
hir::ItemGlobalAsm(..) => {}
// Visit everything
hir::ItemConst(..) | hir::ItemStatic(..) |
self.check(field.id, min(item_visibility, field_visibility)).ty();
}
}
- // The interface is empty
- hir::ItemAutoImpl(..) => {}
// An inherent impl is public when its type is public
// Subitems of inherent impls have their own publicity
hir::ItemImpl(.., None, _, ref impl_item_refs) => {
// Disallow `use $crate;`
if source.name == keywords::DollarCrate.name() && path.segments.len() == 1 {
- let crate_root = self.resolve_crate_root(source.ctxt);
+ let crate_root = self.resolve_crate_root(source.ctxt, true);
let crate_name = match crate_root.kind {
ModuleKind::Def(_, name) => name,
ModuleKind::Block(..) => unreachable!(),
self.insert_field_names(item_def_id, field_names);
}
- ItemKind::AutoImpl(..) | ItemKind::Impl(..) => {}
+ ItemKind::Impl(..) => {}
ItemKind::Trait(..) => {
let def_id = self.definitions.local_def_id(item.id);
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
use syntax::codemap::{dummy_spanned, respan};
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext};
use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
use syntax::ext::base::SyntaxExtension;
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
result
}
- fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext) -> Module<'a> {
- let module = match ctxt.adjust(Mark::root()) {
+ fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext, legacy: bool) -> Module<'a> {
+ let mark = if legacy {
+ // When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
+ // we don't want to pretend that the `macro_rules!` definition is in the `macro`
+ // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
+ ctxt.marks().into_iter().find(|&mark| mark.kind() != MarkKind::Modern)
+ } else {
+ ctxt = ctxt.modern();
+ ctxt.adjust(Mark::root())
+ };
+ let module = match mark {
Some(def) => self.macro_def_scope(def),
None => return self.graph_root,
};
|this| visit::walk_item(this, item));
}
- ItemKind::AutoImpl(_, ref trait_ref) => {
- self.with_optional_trait_ref(Some(trait_ref), |this, _| {
- // Resolve type arguments in trait path
- visit::walk_trait_ref(this, trait_ref);
- });
- }
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
self.resolve_implementation(generics,
opt_trait_ref,
(i == 1 && name == keywords::Crate.name() &&
path[0].node.name == keywords::CrateRoot.name()) {
// `::a::b` or `::crate::a::b`
- module = Some(self.resolve_crate_root(ident.node.ctxt.modern()));
+ module = Some(self.resolve_crate_root(ident.node.ctxt, false));
continue
} else if i == 0 && name == keywords::DollarCrate.name() {
// `$crate::a::b`
- module = Some(self.resolve_crate_root(ident.node.ctxt));
+ module = Some(self.resolve_crate_root(ident.node.ctxt, true));
continue
} else if i == 1 && !token::Ident(ident.node).is_path_segment_keyword() {
let prev_name = path[0].node.name;
use Namespace::{self, MacroNS};
use build_reduced_graph::BuildReducedGraphVisitor;
use resolve_imports::ImportResolver;
-use rustc_data_structures::indexed_vec::Idx;
-use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
+use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex,
+ DefIndexAddressSpace};
use rustc::hir::def::{Def, Export};
use rustc::hir::map::{self, DefCollector};
use rustc::{ty, lint};
let ident = path.segments[0].identifier;
if ident.name == keywords::DollarCrate.name() {
path.segments[0].identifier.name = keywords::CrateRoot.name();
- let module = self.0.resolve_crate_root(ident.ctxt);
+ let module = self.0.resolve_crate_root(ident.ctxt, true);
if !module.is_local() {
let span = path.segments[0].span;
path.segments.insert(1, match module.kind {
fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
let def_id = DefId {
krate: BUILTIN_MACROS_CRATE,
- index: DefIndex::new(self.macro_map.len()),
+ index: DefIndex::from_array_index(self.macro_map.len(),
+ DefIndexAddressSpace::Low),
};
let kind = ext.kind();
self.macro_map.insert(def_id, ext);
"crate root imports need to be explicitly named: \
`use crate as name;`".to_string()));
} else {
- Some(self.resolve_crate_root(source.ctxt.modern()))
+ Some(self.resolve_crate_root(source.ctxt.modern(), false))
}
} else if is_extern && !token::Ident(source).is_path_segment_keyword() {
let crate_id =
root_item: &'l ast::Item,
prefix: &ast::Path) {
let path = &use_tree.prefix;
- let access = access_from!(self.save_ctxt, root_item);
+
+ // The access is calculated using the current tree ID, but with the root tree's visibility
+ // (since nested trees don't have their own visibility).
+ let access = Access {
+ public: root_item.vis == ast::Visibility::Public,
+ reachable: self.save_ctxt.analysis.access_levels.is_reachable(id),
+ };
// The parent def id of a given use tree is always the enclosing item.
let parent = self.save_ctxt.tcx.hir.opt_local_def_id(id)
if !self.span.filter_generated(sub_span, ex.span) {
let span =
self.span_from_span(sub_span.expect("No span found for var ref"));
+ let ref_id =
+ ::id_from_def_id(def.non_enum_variant().fields[idx.node].did);
self.dumper.dump_ref(Ref {
kind: RefKind::Variable,
span,
- ref_id: ::id_from_def_id(def.struct_variant().fields[idx.node].did),
+ ref_id,
});
}
}
};
match self.tables.expr_ty_adjusted(&hir_node).sty {
ty::TyAdt(def, _) if !def.is_enum() => {
- let f = def.struct_variant().field_named(ident.node.name);
+ let f = def.non_enum_variant().field_named(ident.node.name);
let sub_span = self.span_utils.span_for_last_ident(expr.span);
filter!(self.span_utils, sub_span, expr.span, None);
let span = self.span_from_span(sub_span.unwrap());
config: Option<Config>,
mut handler: H,
) {
- let _ignore = tcx.dep_graph.in_ignore();
+ tcx.dep_graph.with_ignore(|| {
+ assert!(analysis.glob_map.is_some());
- assert!(analysis.glob_map.is_some());
+ info!("Dumping crate {}", cratename);
- info!("Dumping crate {}", cratename);
-
- let save_ctxt = SaveContext {
- tcx,
- tables: &ty::TypeckTables::empty(None),
- analysis,
- span_utils: SpanUtils::new(&tcx.sess),
- config: find_config(config),
- };
+ let save_ctxt = SaveContext {
+ tcx,
+ tables: &ty::TypeckTables::empty(None),
+ analysis,
+ span_utils: SpanUtils::new(&tcx.sess),
+ config: find_config(config),
+ };
- handler.save(save_ctxt, krate, cratename)
+ handler.save(save_ctxt, krate, cratename)
+ })
}
fn find_config(supplied: Option<Config>) -> Config {
fn id_from_def_id(id: DefId) -> rls_data::Id {
rls_data::Id {
krate: id.krate.as_u32(),
- index: id.index.as_u32(),
+ index: id.index.as_raw_u32(),
}
}
Ok(sig)
}
- ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
- let mut text = String::new();
- if unsafety == ast::Unsafety::Unsafe {
- text.push_str("unsafe ");
- }
- text.push_str("impl ");
- let trait_sig = trait_ref.path.make(offset + text.len(), id, scx)?;
- text.push_str(&trait_sig.text);
- text.push_str(" for .. {}");
- Ok(replace_text(trait_sig, text))
- }
ast::ItemKind::Impl(
unsafety,
polarity,
//! perturb the reuse results.
use rustc::dep_graph::{DepNode, DepConstructor};
+use rustc::mir::mono::CodegenUnit;
use rustc::ty::TyCtxt;
use syntax::ast;
+use syntax_pos::symbol::Symbol;
use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_TRANSLATED};
const MODULE: &'static str = "module";
enum Disposition { Reused, Translated }
pub(crate) fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let _ignore = tcx.dep_graph.in_ignore();
-
- if tcx.sess.opts.incremental.is_none() {
- return;
- }
+ tcx.dep_graph.with_ignore(|| {
+ if tcx.sess.opts.incremental.is_none() {
+ return;
+ }
- let ams = AssertModuleSource { tcx };
- for attr in &tcx.hir.krate().attrs {
- ams.check_attr(attr);
- }
+ let ams = AssertModuleSource { tcx };
+ for attr in &tcx.hir.krate().attrs {
+ ams.check_attr(attr);
+ }
+ })
}
struct AssertModuleSource<'a, 'tcx: 'a> {
}
let mname = self.field(attr, MODULE);
+ let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
+ let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_str();
let dep_node = DepNode::new(self.tcx,
- DepConstructor::CompileCodegenUnit(mname.as_str()));
+ DepConstructor::CompileCodegenUnit(mangled_cgu_name));
if let Some(loaded_from_cache) = self.tcx.dep_graph.was_loaded_from_cache(&dep_node) {
match (disposition, loaded_from_cache) {
//! Set and unset common attributes on LLVM values.
use std::ffi::{CStr, CString};
+use std::rc::Rc;
+use rustc::hir::Unsafety;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::session::config::Sanitizer;
+use rustc::ty::TyCtxt;
+use rustc::ty::maps::Providers;
+use rustc_data_structures::fx::FxHashSet;
use llvm::{self, Attribute, ValueRef};
use llvm::AttributePlace::Function;
+use llvm_util;
pub use syntax::attr::{self, InlineAttr};
use syntax::ast;
use context::CrateContext;
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
/// attributes.
-pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
+pub fn from_fn_attrs(ccx: &CrateContext, llfn: ValueRef, id: DefId) {
use syntax::attr::*;
- inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
+ let attrs = ccx.tcx().get_attrs(id);
+ inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), &attrs));
set_frame_pointer_elimination(ccx, llfn);
set_probestack(ccx, llfn);
- let mut target_features = vec![];
- for attr in attrs {
- if attr.check_name("target_feature") {
- if let Some(val) = attr.value_str() {
- for feat in val.as_str().split(",").map(|f| f.trim()) {
- if !feat.is_empty() && !feat.contains('\0') {
- target_features.push(feat.to_string());
- }
- }
- }
- } else if attr.check_name("cold") {
+
+ for attr in attrs.iter() {
+ if attr.check_name("cold") {
Attribute::Cold.apply_llfn(Function, llfn);
} else if attr.check_name("naked") {
naked(llfn, true);
unwind(llfn, false);
}
}
+
+ let target_features = ccx.tcx().target_features_enabled(id);
if !target_features.is_empty() {
let val = CString::new(target_features.join(",")).unwrap();
llvm::AddFunctionAttrStringValue(
fn cstr(s: &'static str) -> &CStr {
CStr::from_bytes_with_nul(s.as_bytes()).expect("null-terminated string")
}
+
+pub fn provide(providers: &mut Providers) {
+ providers.target_features_whitelist = |tcx, cnum| {
+ assert_eq!(cnum, LOCAL_CRATE);
+ Rc::new(llvm_util::target_feature_whitelist(tcx.sess)
+ .iter()
+ .map(|c| c.to_str().unwrap().to_string())
+ .collect())
+ };
+
+ providers.target_features_enabled = |tcx, id| {
+ let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
+ let mut target_features = Vec::new();
+ for attr in tcx.get_attrs(id).iter() {
+ if !attr.check_name("target_feature") {
+ continue
+ }
+ if let Some(val) = attr.value_str() {
+ for feat in val.as_str().split(",").map(|f| f.trim()) {
+ if !feat.is_empty() && !feat.contains('\0') {
+ target_features.push(feat.to_string());
+ }
+ }
+ let msg = "#[target_feature = \"..\"] is deprecated and will \
+ eventually be removed, use \
+ #[target_feature(enable = \"..\")] instead";
+ tcx.sess.span_warn(attr.span, &msg);
+ continue
+ }
+
+ if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
+ let msg = "#[target_feature(..)] can only be applied to \
+ `unsafe` function";
+ tcx.sess.span_err(attr.span, msg);
+ }
+ from_target_feature(tcx, attr, &whitelist, &mut target_features);
+ }
+ Rc::new(target_features)
+ };
+}
+
+fn from_target_feature(
+ tcx: TyCtxt,
+ attr: &ast::Attribute,
+ whitelist: &FxHashSet<String>,
+ target_features: &mut Vec<String>,
+) {
+ let list = match attr.meta_item_list() {
+ Some(list) => list,
+ None => {
+ let msg = "#[target_feature] attribute must be of the form \
+ #[target_feature(..)]";
+ tcx.sess.span_err(attr.span, &msg);
+ return
+ }
+ };
+
+ for item in list {
+ if !item.check_name("enable") {
+ let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
+ currently";
+ tcx.sess.span_err(item.span, &msg);
+ continue
+ }
+ let value = match item.value_str() {
+ Some(list) => list,
+ None => {
+ let msg = "#[target_feature] attribute must be of the form \
+ #[target_feature(enable = \"..\")]";
+ tcx.sess.span_err(item.span, &msg);
+ continue
+ }
+ };
+ let value = value.as_str();
+ for feature in value.split(',') {
+ if whitelist.contains(feature) {
+ target_features.push(format!("+{}", feature));
+ continue
+ }
+
+ let msg = format!("the feature named `{}` is not valid for \
+ this target", feature);
+ let mut err = tcx.sess.struct_span_err(item.span, &msg);
+
+ if feature.starts_with("+") {
+ let valid = whitelist.contains(&feature[1..]);
+ if valid {
+ err.help("consider removing the leading `+` in the feature name");
+ }
+ }
+ err.emit();
+ }
+ }
+}
// The version number this compiler will write to bytecode objects in rlibs
pub const RLIB_BYTECODE_OBJECT_VERSION: u8 = 2;
-pub const RLIB_BYTECODE_EXTENSION: &str = "bytecode.encoded";
+pub const RLIB_BYTECODE_EXTENSION: &str = "bc.z";
pub fn encode(identifier: &str, bytecode: &[u8]) -> Vec<u8> {
let mut encoded = Vec::new();
fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, tmpdir: &TempDir)
-> PathBuf {
let out_filename = tmpdir.path().join(METADATA_FILENAME);
- let result = fs::File::create(&out_filename).and_then(|mut f| {
- f.write_all(&trans.metadata.raw_data)
- });
+ let result = fs::write(&out_filename, &trans.metadata.raw_data);
if let Err(e) = result {
sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
use std::any::Any;
use std::ffi::{CString, CStr};
-use std::fs::{self, File};
-use std::io;
-use std::io::{Read, Write};
+use std::fs;
+use std::io::{self, Write};
use std::mem;
use std::path::{Path, PathBuf};
use std::str;
timeline.record("make-bc");
if write_bc {
- if let Err(e) = File::create(&bc_out).and_then(|mut f| f.write_all(data)) {
+ if let Err(e) = fs::write(&bc_out, data) {
diag_handler.err(&format!("failed to write bytecode: {}", e));
}
timeline.record("write-bc");
if config.emit_bc_compressed {
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
let data = bytecode::encode(&mtrans.llmod_id, data);
- if let Err(e) = File::create(&dst).and_then(|mut f| f.write_all(&data)) {
+ if let Err(e) = fs::write(&dst, data) {
diag_handler.err(&format!("failed to write bytecode: {}", e));
}
timeline.record("compress-bc");
object: &Path) {
use rustc_binaryen::{Module, ModuleOptions};
- let input = File::open(&assembly).and_then(|mut f| {
- let mut contents = Vec::new();
- f.read_to_end(&mut contents)?;
+ let input = fs::read(&assembly).and_then(|contents| {
Ok(CString::new(contents)?)
});
let mut options = ModuleOptions::new();
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
});
let err = assembled.and_then(|binary| {
- File::create(&object).and_then(|mut f| f.write_all(binary.data()))
+ fs::write(&object, binary.data())
});
if let Err(e) = err {
handler.err(&format!("failed to run binaryen assembler: {}", e));
if instance.def.is_inline(tcx) {
attributes::inline(llfn, attributes::InlineAttr::Hint);
}
- let attrs = instance.def.attrs(ccx.tcx());
- attributes::from_fn_attrs(ccx, &attrs, llfn);
+ attributes::from_fn_attrs(ccx, llfn, instance.def.def_id());
let instance_def_id = instance.def_id();
let mut name = String::with_capacity(prefix.len() + 6);
name.push_str(prefix);
name.push_str(".");
- base_n::push_str(idx as u64, base_n::ALPHANUMERIC_ONLY, &mut name);
+ base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name);
name
}
let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
let (struct_def_id, variant) = match struct_type.sty {
- ty::TyAdt(def, _) => (def.did, def.struct_variant()),
+ ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
_ => bug!("prepare_struct_metadata on a non-ADT")
};
let union_name = compute_debuginfo_type_name(cx, union_type, false);
let (union_def_id, variant) = match union_type.sty {
- ty::TyAdt(def, _) => (def.did, def.struct_variant()),
+ ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
_ => bug!("prepare_union_metadata on a non-ADT")
};
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(custom_attribute)]
+#![feature(fs_read_write)]
#![allow(unused_attributes)]
#![feature(i128_type)]
#![feature(i128)]
use back::bytecode::RLIB_BYTECODE_EXTENSION;
pub use metadata::LlvmMetadataLoader;
-pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug};
+pub use llvm_util::{init, target_features, print_version, print_passes, print};
use std::any::Any;
use std::path::PathBuf;
back::symbol_names::provide(providers);
back::symbol_export::provide(providers);
base::provide(providers);
+ attributes::provide(providers);
}
fn provide_extern(providers: &mut ty::maps::Providers) {
use llvm;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
-use libc::{c_int, c_char};
-use std::ffi::CString;
+use libc::c_int;
+use std::ffi::{CStr, CString};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;
const MIPS_WHITELIST: &'static [&'static str] = &["msa\0"];
pub fn target_features(sess: &Session) -> Vec<Symbol> {
+ let whitelist = target_feature_whitelist(sess);
let target_machine = create_target_machine(sess);
+ let mut features = Vec::new();
+ for feat in whitelist {
+ if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr()) } {
+ features.push(Symbol::intern(feat.to_str().unwrap()));
+ }
+ }
+ features
+}
+pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
let whitelist = match &*sess.target.target.arch {
"arm" => ARM_WHITELIST,
"aarch64" => AARCH64_WHITELIST,
"powerpc" | "powerpc64" => POWERPC_WHITELIST,
_ => &[],
};
-
- let mut features = Vec::new();
- for feat in whitelist {
- assert_eq!(feat.chars().last(), Some('\0'));
- if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
- features.push(Symbol::intern(&feat[..feat.len() - 1]));
- }
- }
- features
+ whitelist.iter().map(|m| {
+ CStr::from_bytes_with_nul(m.as_bytes()).unwrap()
+ }).collect()
}
pub fn print_version() {
}
}
}
-
-pub fn enable_llvm_debug() {
- unsafe { llvm::LLVMRustSetDebug(1); }
-}
return;
}
- let _ignore = tcx.dep_graph.in_ignore();
- let mut visitor = SymbolNamesTest { tcx: tcx };
- // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
- tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+ tcx.dep_graph.with_ignore(|| {
+ let mut visitor = SymbolNamesTest { tcx: tcx };
+ // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
+ tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+ })
}
struct SymbolNamesTest<'a, 'tcx:'a> {
if instance.def.is_inline(ccx.tcx()) {
attributes::inline(lldecl, attributes::InlineAttr::Hint);
}
- attributes::from_fn_attrs(ccx, &attrs, lldecl);
+ attributes::from_fn_attrs(ccx, lldecl, instance.def.def_id());
ccx.instances().borrow_mut().insert(instance, lldecl);
}
use super::method::MethodCallee;
use rustc::infer::InferOk;
+use rustc::session::DiagnosticMessageId;
use rustc::traits;
use rustc::ty::{self, Ty, TraitRef};
use rustc::ty::{ToPredicate, TypeFoldable};
return Some((self.cur_ty, 0));
}
- if self.steps.len() == tcx.sess.recursion_limit.get() {
+ if self.steps.len() >= tcx.sess.recursion_limit.get() {
// We've reached the recursion limit, error gracefully.
let suggested_limit = tcx.sess.recursion_limit.get() * 2;
- struct_span_err!(tcx.sess,
- self.span,
- E0055,
- "reached the recursion limit while auto-dereferencing {:?}",
- self.cur_ty)
- .span_label(self.span, "deref recursion limit reached")
- .help(&format!(
- "consider adding a `#[recursion_limit=\"{}\"]` attribute to your crate",
+ let msg = format!("reached the recursion limit while auto-dereferencing {:?}",
+ self.cur_ty);
+ let error_id = (DiagnosticMessageId::ErrorId(55), Some(self.span), msg.clone());
+ let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+ if fresh {
+ struct_span_err!(tcx.sess,
+ self.span,
+ E0055,
+ "reached the recursion limit while auto-dereferencing {:?}",
+ self.cur_ty)
+ .span_label(self.span, "deref recursion limit reached")
+ .help(&format!(
+ "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
suggested_limit))
- .emit();
+ .emit();
+ }
return None;
}
ty::TyDynamic(ref tty, ..) =>
Some(PointerKind::Vtable(tty.principal().map(|p| p.def_id()))),
ty::TyAdt(def, substs) if def.is_struct() => {
- match def.struct_variant().fields.last() {
+ match def.non_enum_variant().fields.last() {
None => Some(PointerKind::Thin),
Some(f) => {
let field_ty = self.field_ty(span, f, substs);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::iter;
use check::FnCtxt;
use rustc::infer::InferOk;
if let Some((msg, suggestion)) = self.check_ref(expr, checked_ty, expected) {
err.span_suggestion(expr.span, msg, suggestion);
} else {
- let mode = probe::Mode::MethodCall;
- let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
- mode,
- expected,
- checked_ty,
- ast::DUMMY_NODE_ID);
- if suggestions.len() > 0 {
- err.help(&format!("here are some functions which \
- might fulfill your needs:\n{}",
- self.get_best_match(&suggestions).join("\n")));
+ let methods = self.get_conversion_methods(expected, checked_ty);
+ if let Ok(expr_text) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+ let suggestions = iter::repeat(expr_text).zip(methods.iter())
+ .map(|(receiver, method)| format!("{}.{}()", receiver, method.name))
+ .collect::<Vec<_>>();
+ if !suggestions.is_empty() {
+ err.span_suggestions(expr.span,
+ "try using a conversion method",
+ suggestions);
+ }
}
}
(expected, Some(err))
}
- fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
- format!("- .{}({})",
- method.name,
- if self.has_no_input_arg(method) {
- ""
- } else {
- "..."
- })
- }
-
- fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> Vec<String> {
- methods.iter()
- .take(5)
- .map(|method| self.format_method_suggestion(&*method))
- .collect::<Vec<String>>()
- }
+ fn get_conversion_methods(&self, expected: Ty<'tcx>, checked_ty: Ty<'tcx>)
+ -> Vec<AssociatedItem> {
+ let mut methods = self.probe_for_return_type(syntax_pos::DUMMY_SP,
+ probe::Mode::MethodCall,
+ expected,
+ checked_ty,
+ ast::DUMMY_NODE_ID);
+ methods.retain(|m| {
+ self.has_no_input_arg(m) &&
+ self.tcx.get_attrs(m.def_id).iter()
+ // This special internal attribute is used to whitelist
+ // "identity-like" conversion methods to be suggested here.
+ //
+ // FIXME (#46459 and #46460): ideally
+ // `std::convert::Into::into` and `std::borrow:ToOwned` would
+ // also be `#[rustc_conversion_suggestion]`, if not for
+ // method-probing false-positives and -negatives (respectively).
+ //
+ // FIXME? Other potential candidate methods: `as_ref` and
+ // `as_mut`?
+ .find(|a| a.check_name("rustc_conversion_suggestion")).is_some()
+ });
- fn get_best_match(&self, methods: &[AssociatedItem]) -> Vec<String> {
- let no_argument_methods: Vec<_> =
- methods.iter()
- .filter(|ref x| self.has_no_input_arg(&*x))
- .map(|x| x.clone())
- .collect();
- if no_argument_methods.len() > 0 {
- self.display_suggested_methods(&no_argument_methods)
- } else {
- self.display_suggested_methods(&methods)
- }
+ methods
}
// This function checks if the method isn't static and takes other arguments than `self`.
scope_expr_id);
let method_names =
self.probe_op(span, mode, None, Some(return_type), IsSuggestion(true),
- self_ty, scope_expr_id, ProbeScope::TraitsInScope,
+ self_ty, scope_expr_id, ProbeScope::AllTraits,
|probe_cx| Ok(probe_cx.candidate_method_names()))
.unwrap_or(vec![]);
method_names
self.probe_op(
span, mode, Some(method_name), Some(return_type),
IsSuggestion(true), self_ty, scope_expr_id,
- ProbeScope::TraitsInScope, |probe_cx| probe_cx.pick()
+ ProbeScope::AllTraits, |probe_cx| probe_cx.pick()
).ok().map(|pick| pick.item)
})
.collect()
for (ty, _) in self.autoderef(span, rcvr_ty) {
match ty.sty {
ty::TyAdt(def, substs) if !def.is_enum() => {
- if let Some(field) = def.struct_variant()
+ if let Some(field) = def.non_enum_variant()
.find_field_named(item_name) {
let snippet = tcx.sess.codemap().span_to_snippet(expr.span);
let expr_string = match snippet {
let t = tcx.type_of(def_id);
match t.sty {
ty::TyAdt(def, substs) if def.is_struct() => {
- let fields = &def.struct_variant().fields;
+ let fields = &def.non_enum_variant().fields;
if fields.is_empty() {
span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
return;
}
// push struct def_id before checking fields
stack.push(def_id);
- for field in &def.struct_variant().fields {
+ for field in &def.non_enum_variant().fields {
let f = field.ty(tcx, substs);
match f.sty {
ty::TyAdt(def, _) => {
adjusted_ty,
index_ty);
- // First, try built-in indexing.
- match (adjusted_ty.builtin_index(), &index_ty.sty) {
- (Some(ty), &ty::TyUint(ast::UintTy::Usize)) |
- (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
- debug!("try_index_step: success, using built-in indexing");
- let adjustments = autoderef.adjust_steps(lvalue_pref);
- self.apply_adjustments(base_expr, adjustments);
- return Some((self.tcx.types.usize, ty));
- }
- _ => {}
- }
-
for &unsize in &[false, true] {
let mut self_ty = adjusted_ty;
if unsize {
debug!("struct named {:?}", base_t);
let (ident, def_scope) =
self.tcx.adjust(field.node, base_def.did, self.body_id);
- let fields = &base_def.struct_variant().fields;
+ let fields = &base_def.non_enum_variant().fields;
if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
let field_ty = self.field_ty(expr.span, field, substs);
if field.vis.is_accessible_from(def_scope, self.tcx) {
match expr_t.sty {
ty::TyAdt(def, _) if !def.is_enum() => {
if let Some(suggested_field_name) =
- Self::suggest_field_name(def.struct_variant(), field, vec![]) {
+ Self::suggest_field_name(def.non_enum_variant(), field, vec![]) {
err.span_label(field.span,
format!("did you mean `{}`?", suggested_field_name));
} else {
err.span_label(field.span, "unknown field");
- let struct_variant_def = def.struct_variant();
+ let struct_variant_def = def.non_enum_variant();
let field_names = self.available_field_names(struct_variant_def);
if !field_names.is_empty() {
err.note(&format!("available fields are: {}",
while let Some((base_t, _)) = autoderef.next() {
let field = match base_t.sty {
ty::TyAdt(base_def, substs) if base_def.is_struct() => {
- tuple_like = base_def.struct_variant().ctor_kind == CtorKind::Fn;
+ tuple_like = base_def.non_enum_variant().ctor_kind == CtorKind::Fn;
if !tuple_like { continue }
debug!("tuple struct named {:?}", base_t);
};
let (ident, def_scope) =
self.tcx.adjust_ident(ident, base_def.did, self.body_id);
- let fields = &base_def.struct_variant().fields;
+ let fields = &base_def.non_enum_variant().fields;
if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
let field_ty = self.field_ty(expr.span, field, substs);
if field.vis.is_accessible_from(def_scope, self.tcx) {
Def::AssociatedTy(..) | Def::SelfTy(..) => {
match ty.sty {
ty::TyAdt(adt, substs) if !adt.is_enum() => {
- Some((adt.struct_variant(), adt.did, substs))
+ Some((adt.non_enum_variant(), adt.did, substs))
}
_ => None,
}
self.check_expr_has_type_or_error(base_expr, struct_ty);
match struct_ty.sty {
ty::TyAdt(adt, substs) if adt.is_struct() => {
- let fru_field_types = adt.struct_variant().fields.iter().map(|f| {
+ let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| {
self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs))
}).collect();
//
// won't be allowed unless there's an *explicit* implementation of `Send`
// for `T`
- hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _,
- ref trait_ref, ref self_ty, _) => {
- self.check_impl(item, self_ty, trait_ref);
- }
- hir::ItemImpl(_, hir::ImplPolarity::Negative, _, _, Some(_), ..) => {
- // FIXME(#27579) what amount of WF checking do we need for neg impls?
-
- let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
- if !tcx.trait_is_auto(trait_ref.def_id) {
- error_192(tcx, item.span);
+ hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
+ let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
+ .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
+ if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
+ tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
+ }
+ if polarity == hir::ImplPolarity::Positive {
+ self.check_impl(item, self_ty, trait_ref);
+ } else {
+ // FIXME(#27579) what amount of WF checking do we need for neg impls?
+ if trait_ref.is_some() && !is_auto {
+ span_err!(tcx.sess, item.span, E0192,
+ "negative impls are only allowed for \
+ auto traits (e.g., `Send` and `Sync`)")
+ }
}
}
hir::ItemFn(..) => {
}
hir::ItemStruct(ref struct_def, ref ast_generics) => {
self.check_type_defn(item, false, |fcx| {
- vec![fcx.struct_variant(struct_def)]
+ vec![fcx.non_enum_variant(struct_def)]
});
self.check_variances_for_type_defn(item, ast_generics);
}
hir::ItemUnion(ref struct_def, ref ast_generics) => {
self.check_type_defn(item, true, |fcx| {
- vec![fcx.struct_variant(struct_def)]
+ vec![fcx.non_enum_variant(struct_def)]
});
self.check_variances_for_type_defn(item, ast_generics);
});
}
- fn check_auto_trait(&mut self, trait_def_id: DefId, span: Span) {
- // We want to ensure:
- //
- // 1) that there are no items contained within
- // the trait definition
- //
- // 2) that the definition doesn't violate the no-super trait rule
- // for auto traits.
- //
- // 3) that the trait definition does not have any type parameters
-
- let predicates = self.tcx.predicates_of(trait_def_id);
-
- // We must exclude the Self : Trait predicate contained by all
- // traits.
- let has_predicates =
- predicates.predicates.iter().any(|predicate| {
- match predicate {
- &ty::Predicate::Trait(ref poly_trait_ref) => {
- let self_ty = poly_trait_ref.0.self_ty();
- !(self_ty.is_self() && poly_trait_ref.def_id() == trait_def_id)
- },
- _ => true,
- }
- });
-
- let has_ty_params = self.tcx.generics_of(trait_def_id).types.len() > 1;
-
- // We use an if-else here, since the generics will also trigger
- // an extraneous error message when we find predicates like
- // `T : Sized` for a trait like: `trait Magic<T>`.
- //
- // We also put the check on the number of items here,
- // as it seems confusing to report an error about
- // extraneous predicates created by things like
- // an associated type inside the trait.
- let mut err = None;
- if !self.tcx.associated_item_def_ids(trait_def_id).is_empty() {
- error_380(self.tcx, span);
- } else if has_ty_params {
- err = Some(struct_span_err!(self.tcx.sess, span, E0567,
- "traits with auto impls (`e.g. impl \
- Trait for ..`) can not have type parameters"));
- } else if has_predicates {
- err = Some(struct_span_err!(self.tcx.sess, span, E0568,
- "traits with auto impls (`e.g. impl \
- Trait for ..`) cannot have predicates"));
- }
-
- // Finally if either of the above conditions apply we should add a note
- // indicating that this error is the result of a recent soundness fix.
- match err {
- None => {},
- Some(mut e) => {
- e.note("the new auto trait rules are the result of a \
- recent soundness fix; see #29859 for more details");
- e.emit();
- }
- }
- }
-
fn check_trait(&mut self, item: &hir::Item) {
let trait_def_id = self.tcx.hir.local_def_id(item.id);
-
- if self.tcx.trait_is_auto(trait_def_id) {
- self.check_auto_trait(trait_def_id, item.span);
- }
-
self.for_item(item).with_fcx(|fcx, this| {
let predicates = fcx.tcx.predicates_of(trait_def_id).instantiate_identity(fcx.tcx);
let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
}
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
- fn struct_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
+ fn non_enum_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
let fields =
struct_def.fields().iter()
.map(|field| {
fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec<AdtVariant<'tcx>> {
enum_def.variants.iter()
- .map(|variant| self.struct_variant(&variant.node.data))
+ .map(|variant| self.non_enum_variant(&variant.node.data))
.collect()
}
}
}
-fn error_192(tcx: TyCtxt, span: Span) {
- span_err!(tcx.sess, span, E0192,
- "negative impls are only allowed for traits with \
- default impls (e.g., `Send` and `Sync`)")
-}
-
-fn error_380(tcx: TyCtxt, span: Span) {
- span_err!(tcx.sess, span, E0380,
- "traits with default impls (`e.g. impl \
- Trait for ..`) must have no methods or associated items")
-}
-
fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name)
-> DiagnosticBuilder<'tcx> {
let mut err = struct_span_err!(tcx.sess, span, E0392,
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::infer::InferCtxt;
use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::adjustment::{Adjust, Adjustment};
use rustc::ty::fold::{TypeFoldable, TypeFolder};
use rustc::util::nodemap::DefIdSet;
use syntax::ast;
_ => {}
}
}
+
+ // Similar to operators, indexing is always assumed to be overloaded
+ // Here, correct cases where an indexing expression can be simplified
+ // to use builtin indexing because the index type is known to be
+ // usize-ish
+ fn fix_index_builtin_expr(&mut self, e: &hir::Expr) {
+ if let hir::ExprIndex(ref base, ref index) = e.node {
+ let mut tables = self.fcx.tables.borrow_mut();
+
+ match tables.expr_ty_adjusted(&base).sty {
+ // All valid indexing looks like this
+ ty::TyRef(_, ty::TypeAndMut { ty: ref base_ty, .. }) => {
+ let index_ty = tables.expr_ty_adjusted(&index);
+ let index_ty = self.fcx.resolve_type_vars_if_possible(&index_ty);
+
+ if base_ty.builtin_index().is_some()
+ && index_ty == self.fcx.tcx.types.usize {
+ // Remove the method call record
+ tables.type_dependent_defs_mut().remove(e.hir_id);
+ tables.node_substs_mut().remove(e.hir_id);
+
+ tables.adjustments_mut().get_mut(base.hir_id).map(|a| {
+ // Discard the need for a mutable borrow
+ match a.pop() {
+ // Extra adjustment made when indexing causes a drop
+ // of size information - we need to get rid of it
+ // Since this is "after" the other adjustment to be
+ // discarded, we do an extra `pop()`
+ Some(Adjustment { kind: Adjust::Unsize, .. }) => {
+ // So the borrow discard actually happens here
+ a.pop();
+ },
+ _ => {}
+ }
+ });
+ }
+ },
+ // Might encounter non-valid indexes at this point, so there
+ // has to be a fall-through
+ _ => {},
+ }
+ }
+ }
}
+
///////////////////////////////////////////////////////////////////////////
// Impl of Visitor for Resolver
//
fn visit_expr(&mut self, e: &'gcx hir::Expr) {
self.fix_scalar_builtin_expr(e);
+ self.fix_index_builtin_expr(e);
self.visit_node_id(e.span, e.hir_id);
// conversion). This will work out because `U:
// Unsize<V>`, and we have a builtin rule that `*mut
// U` can be coerced to `*mut V` if `U: Unsize<V>`.
- let fields = &def_a.struct_variant().fields;
+ let fields = &def_a.non_enum_variant().fields;
let diff_fields = fields.iter()
.enumerate()
.filter_map(|(i, f)| {
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),
+ let ty = match item.node {
+ hir::ItemImpl(.., None, ref ty, _) => 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.type_of(def_id);
let lang_items = self.tcx.lang_items();
// mappings. That mapping code resides here.
use hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::traits;
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc::ty::maps::Providers;
mod inherent_impls;
mod inherent_impls_overlap;
mod orphan;
-mod overlap;
mod unsafety;
fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
check_impl(tcx, impl_id);
}
for &impl_id in impls {
- overlap::check_impl(tcx, impl_id);
+ check_impl_overlap(tcx, impl_id);
}
builtin::check_trait(tcx, def_id);
}
unsafety::check(tcx);
orphan::check(tcx);
- overlap::check_auto_impls(tcx);
// these queries are executed for side-effects (error reporting):
ty::maps::queries::crate_inherent_impls::ensure(tcx, LOCAL_CRATE);
ty::maps::queries::crate_inherent_impls_overlap_check::ensure(tcx, LOCAL_CRATE);
}
+
+/// Overlap: No two impls for the same trait are implemented for the
+/// same type. Likewise, no two inherent impls for a given type
+/// constructor provide a method with the same name.
+fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
+ let impl_def_id = tcx.hir.local_def_id(node_id);
+ let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+ let trait_def_id = trait_ref.def_id;
+
+ if trait_ref.references_error() {
+ debug!("coherence: skipping impl {:?} with error {:?}",
+ impl_def_id, trait_ref);
+ return
+ }
+
+ // Trigger building the specialization graph for the trait of this impl.
+ // This will detect any overlap errors.
+ tcx.specialization_graph_of(trait_def_id);
+
+ // check for overlap with the automatic `impl Trait for Trait`
+ if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
+ // This is something like impl Trait1 for Trait2. Illegal
+ // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
+
+ if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
+ // This is an error, but it will be reported by wfcheck. Ignore it here.
+ // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
+ } else {
+ let mut supertrait_def_ids =
+ traits::supertrait_def_ids(tcx,
+ data.principal().unwrap().def_id());
+ if supertrait_def_ids.any(|d| d == trait_def_id) {
+ span_err!(tcx.sess,
+ tcx.span_of_impl(impl_def_id).unwrap(),
+ E0371,
+ "the object type `{}` automatically \
+ implements the trait `{}`",
+ trait_ref.self_ty(),
+ tcx.item_path_str(trait_def_id));
+ }
+ }
+ }
+}
}
}
- // In addition to the above rules, we restrict impls of defaulted traits
+ // In addition to the above rules, we restrict impls of auto traits
// so that they can only be implemented on nominal types, such as structs,
// enums or foreign types. To see why this restriction exists, consider the
- // following example (#22978). Imagine that crate A defines a defaulted trait
+ // following example (#22978). Imagine that crate A defines an auto trait
// `Foo` and a fn that operates on pairs of types:
//
// ```
// // Crate A
- // trait Foo { }
- // impl Foo for .. { }
+ // auto trait Foo { }
// fn two_foos<A:Foo,B:Foo>(..) {
// one_foo::<(A,B)>(..)
// }
}
}
}
- hir::ItemAutoImpl(_, ref item_trait_ref) => {
- // "Trait" impl
- debug!("coherence2::orphan check: default trait impl {}",
- self.tcx.hir.node_to_string(item.id));
- let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
- if !trait_ref.def_id.is_local() {
- struct_span_err!(self.tcx.sess,
- item_trait_ref.path.span,
- E0318,
- "cannot create default implementations for traits outside \
- the crate they're defined in; define a new trait instead")
- .span_label(item_trait_ref.path.span,
- format!("`{}` trait not defined in this crate",
- self.tcx.hir.node_to_pretty_string(item_trait_ref.ref_id)))
- .emit();
- return;
- }
- }
_ => {
// Not an impl
}
+++ /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.
-
-//! Overlap: No two impls for the same trait are implemented for the
-//! same type. Likewise, no two inherent impls for a given type
-//! constructor provide a method with the same name.
-
-use rustc::traits;
-use rustc::ty::{self, TyCtxt, TypeFoldable};
-use syntax::ast;
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-
-pub fn check_auto_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let mut overlap = OverlapChecker { tcx };
-
- // this secondary walk specifically checks for some other cases,
- // like defaulted traits, for which additional overlap rules exist
- tcx.hir.krate().visit_all_item_likes(&mut overlap);
-}
-
-pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
- let impl_def_id = tcx.hir.local_def_id(node_id);
- let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
- let trait_def_id = trait_ref.def_id;
-
- if trait_ref.references_error() {
- debug!("coherence: skipping impl {:?} with error {:?}",
- impl_def_id, trait_ref);
- return
- }
-
- // Trigger building the specialization graph for the trait of this impl.
- // This will detect any overlap errors.
- tcx.specialization_graph_of(trait_def_id);
-
-
- // check for overlap with the automatic `impl Trait for Trait`
- if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
- // This is something like impl Trait1 for Trait2. Illegal
- // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
-
- if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
- // This is an error, but it will be reported by wfcheck. Ignore it here.
- // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
- } else {
- let mut supertrait_def_ids =
- traits::supertrait_def_ids(tcx,
- data.principal().unwrap().def_id());
- if supertrait_def_ids.any(|d| d == trait_def_id) {
- span_err!(tcx.sess,
- tcx.span_of_impl(impl_def_id).unwrap(),
- E0371,
- "the object type `{}` automatically \
- implements the trait `{}`",
- trait_ref.self_ty(),
- tcx.item_path_str(trait_def_id));
- }
- }
- }
-}
-
-struct OverlapChecker<'cx, 'tcx: 'cx> {
- tcx: TyCtxt<'cx, 'tcx, 'tcx>,
-}
-
-impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
- fn visit_item(&mut self, item: &'v hir::Item) {
- match item.node {
- hir::ItemAutoImpl(..) => {
- // look for another auto impl; note that due to the
- // general orphan/coherence rules, it must always be
- // in this crate.
- let impl_def_id = self.tcx.hir.local_def_id(item.id);
- let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
-
- let prev_id = self.tcx.hir.trait_auto_impl(trait_ref.def_id).unwrap();
- if prev_id != item.id {
- let mut err = struct_span_err!(self.tcx.sess,
- self.tcx.span_of_impl(impl_def_id).unwrap(),
- E0521,
- "redundant auto implementations of trait \
- `{}`:",
- trait_ref);
- err.span_note(self.tcx
- .span_of_impl(self.tcx.hir.local_def_id(prev_id))
- .unwrap(),
- "redundant implementation is here:");
- err.emit();
- }
- }
- hir::ItemImpl(.., Some(_), _, _) => {
- }
- _ => {}
- }
- }
-
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
- }
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
- }
-}
let trait_def = self.tcx.trait_def(trait_ref.def_id);
let unsafe_attr = impl_generics.and_then(|g| g.carries_unsafe_attr());
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
- (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
- span_err!(self.tcx.sess,
- item.span,
- E0198,
- "negative implementations are not unsafe");
- }
-
- (Unsafety::Normal, None, Unsafety::Unsafe, _) => {
+ (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
span_err!(self.tcx.sess,
item.span,
E0199,
g.attr_name());
}
+ (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
+ // Reported in AST validation
+ self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
+ }
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative) |
(Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) |
(Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) |
impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v hir::Item) {
match item.node {
- hir::ItemAutoImpl(unsafety, _) => {
- self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
- }
hir::ItemImpl(unsafety, polarity, _, ref generics, ..) => {
self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
}
impl_trait_ref,
impl_polarity,
is_foreign_item,
- is_auto_impl,
..*providers
};
}
tcx.predicates_of(def_id);
convert_enum_variant_types(tcx, def_id, &enum_definition.variants);
},
- hir::ItemAutoImpl(..) => {
- tcx.impl_trait_ref(def_id);
- }
hir::ItemImpl(..) => {
tcx.generics_of(def_id);
tcx.type_of(def_id);
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
let item = tcx.hir.expect_item(node_id);
- let unsafety = match item.node {
- hir::ItemTrait(_, unsafety, ..) => unsafety,
- hir::ItemTraitAlias(..) => hir::Unsafety::Normal,
+ let (is_auto, unsafety) = match item.node {
+ hir::ItemTrait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety),
+ hir::ItemTraitAlias(..) => (false, hir::Unsafety::Normal),
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
};
}
let def_path_hash = tcx.def_path_hash(def_id);
- let is_auto = match item.node {
- hir::ItemTrait(hir::IsAuto::Yes, ..) => true,
- _ => tcx.hir.trait_is_auto(def_id),
- };
let def = ty::TraitDef::new(def_id,
unsafety,
paren_sugar,
let substs = Substs::identity_for_item(tcx, def_id);
tcx.mk_adt(def, substs)
}
- ItemAutoImpl(..) |
ItemTrait(..) | ItemTraitAlias(..) |
ItemMod(..) |
ItemForeignMod(..) |
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
match tcx.hir.expect_item(node_id).node {
- hir::ItemAutoImpl(_, ref ast_trait_ref) => {
- Some(AstConv::instantiate_mono_trait_ref(&icx,
- ast_trait_ref,
- tcx.mk_self_type()))
- }
hir::ItemImpl(.., ref opt_trait_ref, _, _) => {
opt_trait_ref.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id);
_ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id)
}
}
-
-fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def_id: DefId)
- -> bool {
- match tcx.hir.get_if_local(def_id) {
- Some(hir_map::NodeItem(&hir::Item { node: hir::ItemAutoImpl(..), .. }))
- => true,
- Some(_) => false,
- _ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id)
- }
-}
"##,
E0192: r##"
-Negative impls are only allowed for traits with default impls. For more
+Negative impls are only allowed for auto traits. 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
```
"##,
-E0197: r##"
-Inherent implementations (one that do not implement a trait but provide
-methods associated with a type) are always safe because they are not
-implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
-implementation will resolve this error.
-
-```compile_fail,E0197
-struct Foo;
-
-// this will cause this error
-unsafe impl Foo { }
-// converting it to this will fix it
-impl Foo { }
-```
-"##,
-
-E0198: r##"
-A negative implementation is one that excludes a type from implementing a
-particular trait. Not being able to use a trait is always a safe operation,
-so negative implementations are always safe and never need to be marked as
-unsafe.
-
-```compile_fail
-#![feature(optin_builtin_traits)]
-
-struct Foo;
-
-// unsafe is unnecessary
-unsafe impl !Clone for Foo { }
-```
-
-This will compile:
-
-```ignore (ignore auto_trait future compatibility warning)
-#![feature(optin_builtin_traits)]
-
-struct Foo;
-
-trait Enterprise {}
-
-impl Enterprise for .. { }
-
-impl !Enterprise for Foo { }
-```
-
-Please note that negative impls are only allowed for traits with default impls.
-"##,
-
E0199: r##"
Safe traits should not have unsafe implementations, therefore marking an
implementation for a safe trait unsafe will cause a compiler error. Removing
```
"##,
-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][RFC 19].
-
-[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
-"##,
-
E0321: r##"
A cross-crate opt-out trait was implemented on something which wasn't a struct
or enum type. Erroneous code example:
struct.
"##,
-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][RFC 19].
-
-[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
-"##,
-
E0390: r##"
You tried to implement methods for a primitive type. Erroneous code example:
// E0372, // coherence not object safe
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with the same definition
- E0521, // redundant auto implementations of trait
E0533, // `{}` does not name a unit variant, unit struct or a constant
// E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
E0564, // only named lifetimes are allowed in `impl Trait`,
// but `{}` was found in the type `{}`
- E0567, // auto traits can not have type parameters
- E0568, // auto-traits can not have predicates,
E0587, // struct has conflicting packed and align representation hints
E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
E0592, // duplicate definitions with name `{}`
fn build_struct(cx: &DocContext, did: DefId) -> clean::Struct {
let predicates = cx.tcx.predicates_of(did);
- let variant = cx.tcx.adt_def(did).struct_variant();
+ let variant = cx.tcx.adt_def(did).non_enum_variant();
clean::Struct {
struct_type: match variant.ctor_kind {
fn build_union(cx: &DocContext, did: DefId) -> clean::Union {
let predicates = cx.tcx.predicates_of(did);
- let variant = cx.tcx.adt_def(did).struct_variant();
+ let variant = cx.tcx.adt_def(did).non_enum_variant();
clean::Union {
struct_type: doctree::Plain,
}
}
- // If this is an auto impl, then bail out early here
- if tcx.is_auto_impl(did) {
- return ret.push(clean::Item {
- inner: clean::AutoImplItem(clean::AutoImpl {
- // FIXME: this should be decoded
- unsafety: hir::Unsafety::Normal,
- trait_: match associated_trait.as_ref().unwrap().clean(cx) {
- clean::TraitBound(polyt, _) => polyt.trait_,
- clean::RegionBound(..) => unreachable!(),
- },
- }),
- source: tcx.def_span(did).clean(cx),
- name: None,
- attrs,
- visibility: Some(clean::Inherited),
- stability: tcx.lookup_stability(did).clean(cx),
- deprecation: tcx.lookup_deprecation(did).clean(cx),
- def_id: did,
- });
- }
-
let for_ = tcx.type_of(did).clean(cx);
// Only inline impl if the implementing type is
PrimitiveItem(PrimitiveType),
AssociatedConstItem(Type, Option<String>),
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
- AutoImplItem(AutoImpl),
/// An item that has been stripped by a rustdoc pass
StrippedItem(Box<ItemEnum>),
}
items.extend(self.traits.iter().map(|x| x.clean(cx)));
items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
items.extend(self.macros.iter().map(|x| x.clean(cx)));
- items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct AutoImpl {
- pub unsafety: hir::Unsafety,
- pub trait_: Type,
-}
-
-impl Clean<Item> for doctree::AutoImpl {
- fn clean(&self, cx: &DocContext) -> Item {
- Item {
- name: None,
- attrs: self.attrs.clean(cx),
- source: self.whence.clean(cx),
- def_id: cx.tcx.hir.local_def_id(self.id),
- visibility: Some(Public),
- stability: None,
- deprecation: None,
- inner: AutoImplItem(AutoImpl {
- unsafety: self.unsafety,
- trait_: self.trait_.clean(cx),
- }),
- }
- }
-}
-
impl Clean<Item> for doctree::ExternCrate {
fn clean(&self, cx: &DocContext) -> Item {
Item {
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub impls: Vec<Impl>,
- pub def_traits: Vec<AutoImpl>,
pub foreigns: Vec<hir::ForeignMod>,
pub macros: Vec<Macro>,
pub is_crate: bool,
constants : Vec::new(),
traits : Vec::new(),
impls : Vec::new(),
- def_traits : Vec::new(),
foreigns : Vec::new(),
macros : Vec::new(),
is_crate : false,
pub id: ast::NodeId,
}
-pub struct AutoImpl {
- pub unsafety: hir::Unsafety,
- pub trait_: hir::TraitRef,
- pub id: ast::NodeId,
- pub attrs: hir::HirVec<ast::Attribute>,
- pub whence: Span,
-}
-
// For Macro we store the DefId instead of the NodeId, since we also create
// these imported macro_rules (which only have a DUMMY_NODE_ID).
pub struct Macro {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::fs::File;
-use std::io::prelude::*;
+use std::fs;
use std::path::Path;
use std::str;
use html::markdown::{Markdown, RenderType};
pub fn load_string<P: AsRef<Path>>(file_path: P) -> Result<String, LoadStringError> {
let file_path = file_path.as_ref();
- let mut contents = vec![];
- let result = File::open(file_path)
- .and_then(|mut f| f.read_to_end(&mut contents));
- if let Err(e) = result {
- eprintln!("error reading `{}`: {}", file_path.display(), e);
- return Err(LoadStringError::ReadFail);
- }
+ let contents = match fs::read(file_path) {
+ Ok(bytes) => bytes,
+ Err(e) => {
+ eprintln!("error reading `{}`: {}", file_path.display(), e);
+ return Err(LoadStringError::ReadFail);
+ }
+ };
match str::from_utf8(&contents) {
Ok(s) => Ok(s.to_string()),
Err(_) => {
clean::PrimitiveItem(..) => ItemType::Primitive,
clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
- clean::AutoImplItem(..) => ItemType::Impl,
clean::ForeignTypeItem => ItemType::ForeignType,
clean::StrippedItem(..) => unreachable!(),
}
.map(|l| map_line(l).for_code())
.collect::<Vec<&str>>().join("\n");
let krate = krate.as_ref().map(|s| &**s);
- let test = test::make_test(&test, krate, false,
+ let (test, _) = test::make_test(&test, krate, false,
&Default::default());
let channel = if test.contains("#![feature(") {
"&version=nightly"
.map(|l| map_line(l).for_code())
.collect::<Vec<&str>>().join("\n");
let krate = krate.as_ref().map(|s| &**s);
- let test = test::make_test(&test, krate, false,
+ let (test, _) = test::make_test(&test, krate, false,
&Default::default());
let channel = if test.contains("#![feature(") {
"&version=nightly"
write(cx.dst.join("main.css"),
include_bytes!("static/styles/main.css"))?;
if let Some(ref css) = cx.shared.css_file_extension {
- let mut content = String::new();
- let css = css.as_path();
- let mut f = try_err!(File::open(css), css);
-
- try_err!(f.read_to_string(&mut content), css);
- let css = cx.dst.join("theme.css");
- let css = css.as_path();
- let mut f = try_err!(File::create(css), css);
- try_err!(write!(f, "{}", &content), css);
+ let out = cx.dst.join("theme.css");
+ try_err!(fs::copy(css, out), css);
}
write(cx.dst.join("normalize.css"),
include_bytes!("static/normalize.css"))?;
/// Writes the entire contents of a string to a destination, not attempting to
/// catch any errors.
fn write(dst: PathBuf, contents: &[u8]) -> Result<(), Error> {
- Ok(try_err!(try_err!(File::create(&dst), &dst).write_all(contents), &dst))
+ Ok(try_err!(fs::write(&dst, contents), &dst))
}
/// Takes a path to a source file and cleans the path to it. This canonicalizes
return Ok(());
}
- let mut contents = Vec::new();
- File::open(&p).and_then(|mut f| f.read_to_end(&mut contents))?;
-
- let contents = str::from_utf8(&contents).unwrap();
+ let contents = fs::read_string(&p)?;
// Remove the utf-8 BOM if any
let contents = if contents.starts_with("\u{feff}") {
&contents[3..]
} else {
- contents
+ &contents[..]
};
// Create the intermediate directories
item: &clean::Item, items: &[clean::Item]) -> fmt::Result {
document(w, cx, item)?;
- let mut indices = (0..items.len()).filter(|i| {
- if let clean::AutoImplItem(..) = items[*i].inner {
- return false;
- }
- !items[*i].is_stripped()
- }).collect::<Vec<usize>>();
+ let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped())
+ .collect::<Vec<usize>>();
// the order of item types in the listing
fn reorder(ty: ItemType) -> u8 {
ItemType::Function, ItemType::Typedef, ItemType::Union, ItemType::Impl,
ItemType::TyMethod, ItemType::Method, ItemType::StructField, ItemType::Variant,
ItemType::AssociatedType, ItemType::AssociatedConst, ItemType::ForeignType] {
- if items.iter().any(|it| {
- if let clean::AutoImplItem(..) = it.inner {
- false
- } else {
- !it.is_stripped() && it.type_() == myty
- }
- }) {
+ if items.iter().any(|it| !it.is_stripped() && it.type_() == myty) {
let (short, name) = match myty {
ItemType::ExternCrate |
ItemType::Import => ("reexports", "Reexports"),
#![feature(rustc_private)]
#![feature(box_patterns)]
#![feature(box_syntax)]
+#![feature(fs_read_write)]
#![feature(libc)]
#![feature(set_stdio)]
#![feature(slice_patterns)]
// handled in the `strip-priv-imports` pass
clean::ExternCrateItem(..) | clean::ImportItem(..) => {}
- clean::AutoImplItem(..) | clean::ImplItem(..) => {}
+ clean::ImplItem(..) => {}
// tymethods/macros have no control over privacy
clean::MacroItem(..) | clean::TyMethodItem(..) => {}
opts
}
-fn run_test(test: &str, cratename: &str, filename: &FileName, cfgs: Vec<String>, libs: SearchPaths,
+fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
+ cfgs: Vec<String>, libs: SearchPaths,
externs: Externs,
should_panic: bool, no_run: bool, as_test_harness: bool,
compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
linker: Option<PathBuf>) {
// the test harness wants its own `main` & top level functions, so
// never wrap the test in `fn main() { ... }`
- let test = make_test(test, Some(cratename), as_test_harness, opts);
+ let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts);
// FIXME(#44940): if doctests ever support path remapping, then this filename
// needs to be the result of CodeMap::span_to_unmapped_path
let input = config::Input::Str {
}
}
let data = Arc::new(Mutex::new(Vec::new()));
- let codemap = Rc::new(CodeMap::new(sessopts.file_path_mapping()));
+ let codemap = Rc::new(CodeMap::new_doctest(
+ sessopts.file_path_mapping(), filename.clone(), line as isize - line_offset as isize
+ ));
let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
Some(codemap.clone()),
false);
}
}
+/// Makes the test file. Also returns the number of lines before the code begins
pub fn make_test(s: &str,
cratename: Option<&str>,
dont_insert_main: bool,
opts: &TestOptions)
- -> String {
+ -> (String, usize) {
let (crate_attrs, everything_else) = partition_source(s);
-
+ let mut line_offset = 0;
let mut prog = String::new();
if opts.attrs.is_empty() {
// commonly used to make tests fail in case they trigger warnings, so having this there in
// that case may cause some tests to pass when they shouldn't have.
prog.push_str("#![allow(unused)]\n");
+ line_offset += 1;
}
// Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
for attr in &opts.attrs {
prog.push_str(&format!("#![{}]\n", attr));
+ line_offset += 1;
}
// Now push any outer attributes from the example, assuming they
if let Some(cratename) = cratename {
if s.contains(cratename) {
prog.push_str(&format!("extern crate {};\n", cratename));
+ line_offset += 1;
}
}
}
prog.push_str(&everything_else);
} else {
prog.push_str("fn main() {\n");
+ line_offset += 1;
prog.push_str(&everything_else);
prog = prog.trim().into();
prog.push_str("\n}");
info!("final test program: {}", prog);
- prog
+ (prog, line_offset)
}
// FIXME(aburka): use a real parser to deal with multiline attributes
run_test(&test,
&cratename,
&filename,
+ line,
cfgs,
libs,
externs,
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::middle::cstore::{LoadedMacro, CrateStore};
use rustc::middle::privacy::AccessLevel;
+use rustc::ty::Visibility;
use rustc::util::nodemap::FxHashSet;
use rustc::hir;
self.inside_public_path = orig_inside_public_path;
let def_id = self.cx.tcx.hir.local_def_id(id);
if let Some(exports) = self.cx.tcx.module_exports(def_id) {
- for export in exports.iter() {
+ for export in exports.iter().filter(|e| e.vis == Visibility::Public) {
if let Def::Macro(def_id, ..) = export.def {
if def_id.krate == LOCAL_CRATE || self.reexported_macros.contains(&def_id) {
continue // These are `krate.exported_macros`, handled in `self.visit()`.
om.impls.push(i);
}
},
- hir::ItemAutoImpl(unsafety, ref trait_ref) => {
- // See comment above about ItemImpl.
- if !self.inlining {
- let i = AutoImpl {
- unsafety,
- trait_: trait_ref.clone(),
- id: item.id,
- attrs: item.attrs.clone(),
- whence: item.span,
- };
- om.def_traits.push(i);
- }
- }
}
}
pub fn new(cursor: &'a mut io::Cursor<Vec<u8>>) -> Encoder<'a> {
Encoder { cursor: cursor }
}
+
+ pub fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult {
+ self.cursor.write_all(s)
+ }
}
pub fn advance(&mut self, bytes: usize) {
self.position += bytes;
}
+
+ pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
+ let start = self.position;
+ let end = start + s.len();
+
+ s.copy_from_slice(&self.data[start..end]);
+
+ self.position = end;
+
+ Ok(())
+ }
}
macro_rules! read_uleb128 {
self.search_mut(k).into_occupied_bucket().map(|bucket| pop_internal(bucket).1)
}
+ /// Removes a key from the map, returning the stored key and value if the
+ /// key was previously in the map.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// [`Eq`]: ../../std/cmp/trait.Eq.html
+ /// [`Hash`]: ../../std/hash/trait.Hash.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(hash_map_remove_entry)]
+ /// use std::collections::HashMap;
+ ///
+ /// # fn main() {
+ /// let mut map = HashMap::new();
+ /// map.insert(1, "a");
+ /// assert_eq!(map.remove_entry(&1), Some((1, "a")));
+ /// assert_eq!(map.remove(&1), None);
+ /// # }
+ /// ```
+ #[unstable(feature = "hash_map_remove_entry", issue = "46344")]
+ pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
+ where K: Borrow<Q>,
+ Q: Hash + Eq
+ {
+ if self.table.size() == 0 {
+ return None;
+ }
+
+ self.search_mut(k)
+ .into_occupied_bucket()
+ .map(|bucket| {
+ let (k, v, _) = pop_internal(bucket);
+ (k, v)
+ })
+ }
+
/// Retains only the elements specified by the predicate.
///
/// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`.
}
#[test]
- fn test_pop() {
+ fn test_remove() {
let mut m = HashMap::new();
m.insert(1, 2);
assert_eq!(m.remove(&1), Some(2));
assert_eq!(m.remove(&1), None);
}
+ #[test]
+ fn test_remove_entry() {
+ let mut m = HashMap::new();
+ m.insert(1, 2);
+ assert_eq!(m.remove_entry(&1), Some((1, 2)));
+ assert_eq!(m.remove(&1), None);
+ }
+
#[test]
fn test_iterate() {
let mut m = HashMap::with_capacity(4);
mod tests {
use super::*;
- use ffi::OsStr;
- use path::{Path, PathBuf};
+ use path::Path;
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[test]
#[cfg(windows)]
fn split_paths_windows() {
+ use path::PathBuf;
+
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
split_paths(unparsed).collect::<Vec<_>>() ==
parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
#[test]
#[cfg(unix)]
fn split_paths_unix() {
+ use path::PathBuf;
+
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
split_paths(unparsed).collect::<Vec<_>>() ==
parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
#[test]
#[cfg(unix)]
fn join_paths_unix() {
+ use ffi::OsStr;
+
fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() ==
OsStr::new(output)
#[test]
#[cfg(windows)]
fn join_paths_windows() {
+ use ffi::OsStr;
+
fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() ==
OsStr::new(output)
//! terminator, so the buffer length is really `len+1` characters.
//! Rust strings don't have a nul terminator; their length is always
//! stored and does not need to be calculated. While in Rust
-//! accessing a string's length is a O(1) operation (becasue the
+//! accessing a string's length is a O(1) operation (because the
//! length is stored); in C it is an O(length) operation because the
//! length needs to be computed by scanning the string for the nul
//! terminator.
/// and platform-native string values, and in particular allowing a Rust string
/// to be converted into an "OS" string with no cost if possible.
///
-/// `OsString` is to [`OsStr`] as [`String`] is to [`&str`]: the former
+/// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former
/// in each pair are owned strings; the latter are borrowed
/// references.
///
/// the traits which `OsString` implements for conversions from/to native representations.
///
/// [`OsStr`]: struct.OsStr.html
+/// [`&OsStr`]: struct.OsStr.html
/// [`From`]: ../convert/trait.From.html
/// [`String`]: ../string/struct.String.html
/// [`&str`]: ../primitive.str.html
/// This type represents a borrowed reference to a string in the operating system's preferred
/// representation.
///
-/// `OsStr` is to [`OsString`] as [`String`] is to [`&str`]: the former in each pair are borrowed
+/// `&OsStr` is to [`OsString`] as [`&str`] is to [`String`]: the former in each pair are borrowed
/// references; the latter are owned strings.
///
/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
/// the traits which `OsStr` implements for conversions from/to native representations.
///
/// [`OsString`]: struct.OsString.html
+/// [`&str`]: ../primitive.str.html
+/// [`String`]: ../string/struct.String.html
/// [conversions]: index.html#conversions
#[stable(feature = "rust1", since = "1.0.0")]
pub struct OsStr {
recursive: bool,
}
+/// How large a buffer to pre-allocate before reading the entire file at `path`.
+fn initial_buffer_size<P: AsRef<Path>>(path: P) -> usize {
+ // Allocate one extra byte so the buffer doesn't need to grow before the
+ // final `read` call at the end of the file. Don't worry about `usize`
+ // overflow because reading will fail regardless in that case.
+ metadata(path).map(|m| m.len() as usize + 1).unwrap_or(0)
+}
+
/// Read the entire contents of a file into a bytes vector.
///
/// This is a convenience function for using [`File::open`] and [`read_to_end`]
/// ```
#[unstable(feature = "fs_read_write", issue = "46588")]
pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
- let mut bytes = Vec::new();
+ let mut bytes = Vec::with_capacity(initial_buffer_size(&path));
File::open(path)?.read_to_end(&mut bytes)?;
Ok(bytes)
}
/// ```
#[unstable(feature = "fs_read_write", issue = "46588")]
pub fn read_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
- let mut string = String::new();
+ let mut string = String::with_capacity(initial_buffer_size(&path));
File::open(path)?.read_to_string(&mut string)?;
Ok(string)
}
}
}
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
use io::prelude::*;
pub fn into_inner(self) -> R { self.inner }
}
+impl<R: Seek> BufReader<R> {
+ /// Seeks relative to the current position. If the new position lies within the buffer,
+ /// the buffer will not be flushed, allowing for more efficient seeks.
+ /// This method does not return the location of the underlying reader, so the caller
+ /// must track this information themselves if it is required.
+ #[unstable(feature = "bufreader_seek_relative", issue = "31100")]
+ pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
+ let pos = self.pos as u64;
+ if offset < 0 {
+ if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
+ self.pos = new_pos as usize;
+ return Ok(())
+ }
+ } else {
+ if let Some(new_pos) = pos.checked_add(offset as u64) {
+ if new_pos <= self.cap as u64 {
+ self.pos = new_pos as usize;
+ return Ok(())
+ }
+ }
+ }
+ self.seek(SeekFrom::Current(offset)).map(|_|())
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read> Read for BufReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
/// `.into_inner()` immediately after a seek yields the underlying reader
/// at the same position.
///
+ /// To seek without discarding the internal buffer, use [`seek_relative`].
+ ///
/// See `std::io::Seek` for more details.
///
/// Note: In the edge case where you're seeking with `SeekFrom::Current(n)`
/// seeks will be performed instead of one. If the second seek returns
/// `Err`, the underlying reader will be left at the same position it would
/// have if you seeked to `SeekFrom::Current(0)`.
+ ///
+ /// [`seek_relative`]: #method.seek_relative
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
let result: u64;
if let SeekFrom::Current(n) = pos {
assert_eq!(reader.seek(SeekFrom::Current(-2)).ok(), Some(3));
}
+ #[test]
+ fn test_buffered_reader_seek_relative() {
+ let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+ let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner));
+
+ assert!(reader.seek_relative(3).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+ assert!(reader.seek_relative(0).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+ assert!(reader.seek_relative(1).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[1][..]));
+ assert!(reader.seek_relative(-1).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+ assert!(reader.seek_relative(2).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[2, 3][..]));
+ }
+
#[test]
fn test_buffered_reader_seek_underflow() {
// gimmick reader that yields its position modulo 256 for each byte
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
}
+// Non-resizing write implementation
+fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> {
+ let pos = cmp::min(*pos_mut, slice.len() as u64);
+ let amt = (&mut slice[(pos as usize)..]).write(buf)?;
+ *pos_mut += amt as u64;
+ Ok(amt)
+}
+
+// Resizing write implementation
+fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
+ let pos: usize = (*pos_mut).try_into().map_err(|_| {
+ Error::new(ErrorKind::InvalidInput,
+ "cursor position exceeds maximum possible vector length")
+ })?;
+ // Make sure the internal buffer is as least as big as where we
+ // currently are
+ let len = vec.len();
+ if len < pos {
+ // use `resize` so that the zero filling is as efficient as possible
+ vec.resize(pos, 0);
+ }
+ // Figure out what bytes will be used to overwrite what's currently
+ // there (left), and what will be appended on the end (right)
+ {
+ let space = vec.len() - pos;
+ let (left, right) = buf.split_at(cmp::min(space, buf.len()));
+ vec[pos..pos + left.len()].copy_from_slice(left);
+ vec.extend_from_slice(right);
+ }
+
+ // Bump us forward
+ *pos_mut = (pos + buf.len()) as u64;
+ Ok(buf.len())
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for Cursor<&'a mut [u8]> {
#[inline]
- fn write(&mut self, data: &[u8]) -> io::Result<usize> {
- let pos = cmp::min(self.pos, self.inner.len() as u64);
- let amt = (&mut self.inner[(pos as usize)..]).write(data)?;
- self.pos += amt as u64;
- Ok(amt)
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ slice_write(&mut self.pos, self.inner, buf)
+ }
+ fn flush(&mut self) -> io::Result<()> { Ok(()) }
+}
+
+#[unstable(feature = "cursor_mut_vec", issue = "30132")]
+impl<'a> Write for Cursor<&'a mut Vec<u8>> {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ vec_write(&mut self.pos, self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Cursor<Vec<u8>> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- let pos: usize = self.position().try_into().map_err(|_| {
- Error::new(ErrorKind::InvalidInput,
- "cursor position exceeds maximum possible vector length")
- })?;
- // Make sure the internal buffer is as least as big as where we
- // currently are
- let len = self.inner.len();
- if len < pos {
- // use `resize` so that the zero filling is as efficient as possible
- self.inner.resize(pos, 0);
- }
- // Figure out what bytes will be used to overwrite what's currently
- // there (left), and what will be appended on the end (right)
- {
- let space = self.inner.len() - pos;
- let (left, right) = buf.split_at(cmp::min(space, buf.len()));
- self.inner[pos..pos + left.len()].copy_from_slice(left);
- self.inner.extend_from_slice(right);
- }
-
- // Bump us forward
- self.set_position((pos + buf.len()) as u64);
- Ok(buf.len())
+ vec_write(&mut self.pos, &mut self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
impl Write for Cursor<Box<[u8]>> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- let pos = cmp::min(self.pos, self.inner.len() as u64);
- let amt = (&mut self.inner[(pos as usize)..]).write(buf)?;
- self.pos += amt as u64;
- Ok(amt)
+ slice_write(&mut self.pos, &mut self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
assert_eq!(&writer.get_ref()[..], b);
}
+ #[test]
+ fn test_mem_mut_writer() {
+ let mut vec = Vec::new();
+ let mut writer = Cursor::new(&mut vec);
+ assert_eq!(writer.write(&[0]).unwrap(), 1);
+ assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+ assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+ let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
+ assert_eq!(&writer.get_ref()[..], b);
+ }
+
#[test]
fn test_box_slice_writer() {
let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
/// [`Write`]: ../io/trait.Write.html
/// [`Seek`]: ../io/trait.Seek.html
/// [`ErrorKind`]: enum.ErrorKind.html
-#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Error {
repr: Repr,
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&self.repr, f)
+ }
+}
+
enum Repr {
Os(i32),
Simple(ErrorKind),
impl fmt::Debug for Repr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
- Repr::Os(ref code) =>
- fmt.debug_struct("Os").field("code", code)
- .field("message", &sys::os::error_string(*code)).finish(),
- Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
+ Repr::Os(code) =>
+ fmt.debug_struct("Os")
+ .field("code", &code)
+ .field("kind", &sys::decode_error_kind(code))
+ .field("message", &sys::os::error_string(code)).finish(),
+ Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
}
}
#[cfg(test)]
mod test {
- use super::{Error, ErrorKind};
+ use super::{Error, ErrorKind, Repr, Custom};
use error;
use fmt;
use sys::os::error_string;
+ use sys::decode_error_kind;
#[test]
fn test_debug_error() {
let code = 6;
let msg = error_string(code);
- let err = Error { repr: super::Repr::Os(code) };
- let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
+ let kind = decode_error_kind(code);
+ let err = Error {
+ repr: Repr::Custom(box Custom {
+ kind: ErrorKind::InvalidInput,
+ error: box Error {
+ repr: super::Repr::Os(code)
+ },
+ })
+ };
+ let expected = format!(
+ "Custom {{ \
+ kind: InvalidInput, \
+ error: Os {{ \
+ code: {:?}, \
+ kind: {:?}, \
+ message: {:?} \
+ }} \
+ }}",
+ code, kind, msg
+ );
assert_eq!(format!("{:?}", err), expected);
}
///
/// Calls to `write` are not guaranteed to block waiting for data to be
/// written, and a write which would otherwise block can be indicated through
- /// an `Err` variant.
+ /// an [`Err`] variant.
///
- /// If the return value is `Ok(n)` then it must be guaranteed that
+ /// If the return value is [`Ok(n)`] then it must be guaranteed that
/// `0 <= n <= buf.len()`. A return value of `0` typically means that the
/// underlying object is no longer able to accept bytes and will likely not
/// be able to in the future as well, or that the buffer provided is empty.
/// It is **not** considered an error if the entire buffer could not be
/// written to this writer.
///
- /// An error of the `ErrorKind::Interrupted` kind is non-fatal and the
+ /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the
/// write operation should be retried if there is nothing else to do.
///
+ /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+ /// [`Ok(n)`]: ../../std/result/enum.Result.html#variant.Ok
+ /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+ ///
/// # Examples
///
/// ```
/// Attempts to write an entire buffer into this write.
///
- /// This method will continuously call `write` until there is no more data
- /// to be written or an error of non-`ErrorKind::Interrupted` kind is
+ /// This method will continuously call [`write`] until there is no more data
+ /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
/// returned. This method will not return until the entire buffer has been
/// successfully written or such an error occurs. The first error that is
- /// not of `ErrorKind::Interrupted` kind generated from this method will be
+ /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
/// returned.
///
/// # Errors
///
/// This function will return the first error of
- /// non-`ErrorKind::Interrupted` kind that `write` returns.
+ /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns.
+ ///
+ /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+ /// [`write`]: #tymethod.write
///
/// # Examples
///
// Turn warnings into errors, but only after stage0, where it can be useful for
// code to emit warnings during language transitions
-#![deny(warnings)]
+#![cfg_attr(not(stage0), deny(warnings))]
// std may use features in a platform-specific way
#![allow(unused_features)]
#![feature(rand)]
#![feature(raw)]
#![feature(repr_align)]
-#![feature(repr_simd)]
#![feature(rustc_attrs)]
#![feature(shared)]
#![feature(sip_hash_13)]
/// Unconditionally causes compilation to fail with the given error message when encountered.
///
/// This macro should be used when a crate uses a conditional compilation strategy to provide
- /// better error messages for errornous conditions.
+ /// better error messages for erroneous conditions.
///
/// # Examples
///
}
}
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
use io::ErrorKind;
use io::prelude::*;
}
}
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
use io::ErrorKind;
use net::*;
#[stable(feature = "catch_unwind", since = "1.9.0")]
#[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
across an unwind boundary"]
-pub trait UnwindSafe {}
+pub auto trait UnwindSafe {}
/// A marker trait representing types where a shared reference is considered
/// unwind safe.
#[rustc_on_unimplemented = "the type {Self} may contain interior mutability \
and a reference may not be safely transferrable \
across a catch_unwind boundary"]
-pub trait RefUnwindSafe {}
+pub auto trait RefUnwindSafe {}
/// A simple wrapper around a type to assert that it is unwind safe.
///
// * Unique, an owning pointer, lifts an implementation
// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
// * Our custom AssertUnwindSafe wrapper is indeed unwind safe
-#[stable(feature = "catch_unwind", since = "1.9.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl UnwindSafe for .. {}
+
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<'a, T: ?Sized> !UnwindSafe for &'a mut T {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T> {}
// Pretty simple implementations for the `RefUnwindSafe` marker trait,
-// basically just saying that this is a marker trait and `UnsafeCell` is the
+// basically just saying that `UnsafeCell` is the
// only thing which doesn't implement it (which then transitively applies to
// everything else).
#[stable(feature = "catch_unwind", since = "1.9.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl RefUnwindSafe for .. {}
-#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T> RefUnwindSafe for AssertUnwindSafe<T> {}
/// # Examples
///
/// ```should_panic
- /// #![feature(panic_col)]
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///
/// panic!("Normal panic");
/// ```
- #[unstable(feature = "panic_col", reason = "recently added", issue = "42939")]
+ #[stable(feature = "panic_col", since = "1.25")]
pub fn column(&self) -> u32 {
self.col
}
}
}
+#[stable(feature = "path_component_asref", since = "1.24.0")]
+impl<'a> AsRef<Path> for Component<'a> {
+ fn as_ref(&self) -> &Path {
+ self.as_os_str().as_ref()
+ }
+}
+
/// An iterator over the [`Component`]s of a [`Path`].
///
/// This `struct` is created by the [`components`] method on [`Path`].
/// let path_buf = Path::new("foo.txt").to_path_buf();
/// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
/// ```
+ #[rustc_conversion_suggestion]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_path_buf(&self) -> PathBuf {
PathBuf::from(self.inner.to_os_string())
::sys::os::getpid()
}
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
use io::prelude::*;
/// required that `T` satisfies [`Send`] to be shared across threads and
/// [`Sync`] to allow concurrent access through readers. The RAII guards
/// returned from the locking methods implement [`Deref`][] (and [`DerefMut`]
-/// for the `write` methods) to allow access to the contained of the lock.
+/// for the `write` methods) to allow access to the content of the lock.
///
/// # Poisoning
///
--- /dev/null
+// Copyright (c) 2018 Nuxi (https://nuxi.nl/) and contributors.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+
+// Appease Rust's tidy.
+// ignore-license
+
+#[cfg(feature = "bitflags")]
+#[macro_use]
+extern crate bitflags;
+
+// Minimal implementation of bitflags! in case we can't depend on the bitflags
+// crate. Only implements `bits()` and a `from_bits_truncate()` that doesn't
+// actually truncate.
+#[cfg(not(feature = "bitflags"))]
+macro_rules! bitflags {
+ (
+ $(#[$attr:meta])*
+ pub struct $name:ident: $type:ty {
+ $($(#[$const_attr:meta])* const $const:ident = $val:expr;)*
+ }
+ ) => {
+ $(#[$attr])*
+ #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+ pub struct $name { bits: $type }
+ impl $name {
+ $($(#[$const_attr])* pub const $const: $name = $name{ bits: $val };)*
+ pub fn bits(&self) -> $type { self.bits }
+ pub fn from_bits_truncate(bits: $type) -> Self { $name{ bits } }
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2016-2017 Nuxi (https://nuxi.nl/) and contributors.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// This file is automatically generated. Do not edit.
+//
+// Source: https://github.com/NuxiNL/cloudabi
+
+// Appease Rust's tidy.
+// ignore-license
+// ignore-tidy-linelength
+
+//! **PLEASE NOTE: This entire crate including this
+//! documentation is automatically generated from
+//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt)**
+//!
+//! # Nuxi CloudABI
+//!
+//! CloudABI is what you get if you take POSIX, add capability-based
+//! security, and remove everything that's incompatible with that. The
+//! result is a minimal ABI consisting of only 49 syscalls.
+//!
+//! CloudABI doesn't have its own kernel, but instead is implemented in existing
+//! kernels: FreeBSD has CloudABI support for x86-64 and arm64, and [a patch-set
+//! for NetBSD](https://github.com/NuxiNL/netbsd) and [a patch-set for
+//! Linux](https://github.com/NuxiNL/linux) are available as well. This means that
+//! CloudABI binaries can be executed on different operating systems, without any
+//! modification.
+//!
+//! ## Capability-Based Security
+//!
+//! Capability-based security means that processes can only perform
+//! actions that have no global impact. Processes cannot open files by
+//! their absolute path, cannot open network connections, and cannot
+//! observe global system state such as the process table.
+//!
+//! The capabilities of a process are fully determined by its set of open
+//! file descriptors (fds). For example, files can only be opened if the
+//! process already has a file descriptor to a directory the file is in.
+//!
+//! Unlike in POSIX, where processes are normally started with file
+//! descriptors 0, 1, and 2 reserved for standard input, output, and
+//! error, CloudABI does not reserve any file descriptor numbers for
+//! specific purposes.
+//!
+//! In CloudABI, a process depends on its parent process to launch it with
+//! the right set of resources, since the process will not be able to open
+//! any new resources. For example, a simple static web server would need
+//! to be started with a file descriptor to a [TCP
+//! listener](https://github.com/NuxiNL/flower), and a file descriptor to
+//! the directory for which to serve files. The web server will then be
+//! unable to do anything other than reading files in that directory, and
+//! process incoming network connections.
+//!
+//! So, unknown CloudABI binaries can safely be executed without the need
+//! for containers, virtual machines, or other sandboxing technologies.
+//!
+//! Watch [Ed Schouten's Talk at
+//! 32C3](https://www.youtube.com/watch?v=3N29vrPoDv8) for more
+//! information about what capability-based security for UNIX means.
+//!
+//! ## Cloudlibc
+//!
+//! [Cloudlibc](https://github.com/NuxiNL/cloudlibc) is an implementation
+//! of the C standard library, without all CloudABI-incompatible
+//! functions. For example, Cloudlibc does not have `printf`, but does
+//! have `fprintf`. It does not have `open`, but does have `openat`.
+//!
+//! ## CloudABI-Ports
+//!
+//! [CloudABI-Ports](https://github.com/NuxiNL/cloudabi-ports) is a
+//! collection of ports of commonly used libraries and applications to
+//! CloudABI. It contains software such as `zlib`, `libpng`, `boost`,
+//! `memcached`, and much more. The software is patched to not depend on
+//! any global state, such as files in `/etc` or `/dev`, using `open()`,
+//! etc.
+//!
+//! ## Using CloudABI
+//!
+//! Instructions for using CloudABI (including kernel modules/patches,
+//! toolchain, and ports) are available for several operating systems:
+//!
+//! - [Arch Linux](https://nuxi.nl/cloudabi/archlinux/)
+//! - [Debian, Ubuntu, and other Debian derivatives](https://nuxi.nl/cloudabi/debian/)
+//! - [FreeBSD, PC-BSD and DragonFly BSD](https://nuxi.nl/cloudabi/freebsd/)
+//! - [Mac OS X](https://nuxi.nl/cloudabi/mac/)
+//! - [NetBSD](https://nuxi.nl/cloudabi/netbsd/)
+//!
+//! ## Specification of the ABI
+//!
+//! The entire ABI is specified in a a file called
+//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt),
+//! from which all
+//! [headers](https://github.com/NuxiNL/cloudabi/tree/master/headers)
+//! and documentation (including the one you're reading now) is generated.
+
+#![no_std]
+#![allow(non_camel_case_types)]
+
+include!("bitflags.rs");
+
+/// File or memory access pattern advisory information.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum advice {
+ /// The application expects that it will not access the
+ /// specified data in the near future.
+ DONTNEED = 1,
+ /// The application expects to access the specified data
+ /// once and then not reuse it thereafter.
+ NOREUSE = 2,
+ /// The application has no advice to give on its behavior
+ /// with respect to the specified data.
+ NORMAL = 3,
+ /// The application expects to access the specified data
+ /// in a random order.
+ RANDOM = 4,
+ /// The application expects to access the specified data
+ /// sequentially from lower offsets to higher offsets.
+ SEQUENTIAL = 5,
+ /// The application expects to access the specified data
+ /// in the near future.
+ WILLNEED = 6,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Enumeration describing the kind of value stored in [`auxv`](struct.auxv.html).
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum auxtype {
+ /// Base address of the binary argument data provided to
+ /// [`proc_exec()`](fn.proc_exec.html).
+ ARGDATA = 256,
+ /// Length of the binary argument data provided to
+ /// [`proc_exec()`](fn.proc_exec.html).
+ ARGDATALEN = 257,
+ /// Base address at which the executable is placed in
+ /// memory.
+ BASE = 7,
+ /// Base address of a buffer of random data that may be
+ /// used for non-cryptographic purposes, for example as a
+ /// canary for stack smashing protection.
+ CANARY = 258,
+ /// Length of a buffer of random data that may be used
+ /// for non-cryptographic purposes, for example as a
+ /// canary for stack smashing protection.
+ CANARYLEN = 259,
+ /// Number of CPUs that the system this process is running
+ /// on has.
+ NCPUS = 260,
+ /// Terminator of the auxiliary vector.
+ NULL = 0,
+ /// Smallest memory object size for which individual
+ /// memory protection controls can be configured.
+ PAGESZ = 6,
+ /// Address of the first ELF program header of the
+ /// executable.
+ PHDR = 3,
+ /// Number of ELF program headers of the executable.
+ PHNUM = 4,
+ /// Identifier of the process.
+ ///
+ /// This environment does not provide any simple numerical
+ /// process identifiers, for the reason that these are not
+ /// useful in distributed contexts. Instead, processes are
+ /// identified by a UUID.
+ ///
+ /// This record should point to sixteen bytes of binary
+ /// data, containing a version 4 UUID (fully random).
+ PID = 263,
+ /// Address of the ELF header of the vDSO.
+ ///
+ /// The vDSO is a shared library that is mapped in the
+ /// address space of the process. It provides entry points
+ /// for every system call supported by the environment,
+ /// all having a corresponding symbol that is prefixed
+ /// with `cloudabi_sys_`. System calls should be invoked
+ /// through these entry points.
+ ///
+ /// The first advantage of letting processes call into a
+ /// vDSO to perform system calls instead of raising
+ /// hardware traps is that it allows for easy emulation of
+ /// executables on top of existing operating systems. The
+ /// second advantage is that in cases where an operating
+ /// system provides native support for CloudABI executables,
+ /// it may still implement partial userspace
+ /// implementations of these system calls to improve
+ /// performance (e.g., [`clock_time_get()`](fn.clock_time_get.html)). It also provides
+ /// a more dynamic way of adding, removing or replacing
+ /// system calls.
+ SYSINFO_EHDR = 262,
+ /// Thread ID of the initial thread of the process.
+ TID = 261,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
+}
+
+/// Identifiers for clocks.
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum clockid {
+ /// The system-wide monotonic clock, which is defined as a
+ /// clock measuring real time, whose value cannot be
+ /// adjusted and which cannot have negative clock jumps.
+ ///
+ /// The epoch of this clock is undefined. The absolute
+ /// time value of this clock therefore has no meaning.
+ MONOTONIC = 1,
+ /// The CPU-time clock associated with the current
+ /// process.
+ PROCESS_CPUTIME_ID = 2,
+ /// The system-wide clock measuring real time. Time value
+ /// zero corresponds with 1970-01-01T00:00:00Z.
+ REALTIME = 3,
+ /// The CPU-time clock associated with the current thread.
+ THREAD_CPUTIME_ID = 4,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
+}
+
+/// A userspace condition variable.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct condvar(pub u32);
+/// The condition variable is in its initial state. There
+/// are no threads waiting to be woken up. If the
+/// condition variable has any other value, the kernel
+/// must be called to wake up any sleeping threads.
+pub const CONDVAR_HAS_NO_WAITERS: condvar = condvar(0);
+
+/// Identifier for a device containing a file system. Can be used
+/// in combination with [`inode`](struct.inode.html) to uniquely identify a file on the
+/// local system.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct device(pub u64);
+
+/// A reference to the offset of a directory entry.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct dircookie(pub u64);
+/// Permanent reference to the first directory entry
+/// within a directory.
+pub const DIRCOOKIE_START: dircookie = dircookie(0);
+
+/// Error codes returned by system calls.
+///
+/// Not all of these error codes are returned by the system calls
+/// provided by this environment, but are either used in userspace
+/// exclusively or merely provided for alignment with POSIX.
+#[repr(u16)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum errno {
+ /// No error occurred. System call completed successfully.
+ SUCCESS = 0,
+ /// Argument list too long.
+ TOOBIG = 1,
+ /// Permission denied.
+ ACCES = 2,
+ /// Address in use.
+ ADDRINUSE = 3,
+ /// Address not available.
+ ADDRNOTAVAIL = 4,
+ /// Address family not supported.
+ AFNOSUPPORT = 5,
+ /// Resource unavailable, or operation would block.
+ AGAIN = 6,
+ /// Connection already in progress.
+ ALREADY = 7,
+ /// Bad file descriptor.
+ BADF = 8,
+ /// Bad message.
+ BADMSG = 9,
+ /// Device or resource busy.
+ BUSY = 10,
+ /// Operation canceled.
+ CANCELED = 11,
+ /// No child processes.
+ CHILD = 12,
+ /// Connection aborted.
+ CONNABORTED = 13,
+ /// Connection refused.
+ CONNREFUSED = 14,
+ /// Connection reset.
+ CONNRESET = 15,
+ /// Resource deadlock would occur.
+ DEADLK = 16,
+ /// Destination address required.
+ DESTADDRREQ = 17,
+ /// Mathematics argument out of domain of function.
+ DOM = 18,
+ /// Reserved.
+ DQUOT = 19,
+ /// File exists.
+ EXIST = 20,
+ /// Bad address.
+ FAULT = 21,
+ /// File too large.
+ FBIG = 22,
+ /// Host is unreachable.
+ HOSTUNREACH = 23,
+ /// Identifier removed.
+ IDRM = 24,
+ /// Illegal byte sequence.
+ ILSEQ = 25,
+ /// Operation in progress.
+ INPROGRESS = 26,
+ /// Interrupted function.
+ INTR = 27,
+ /// Invalid argument.
+ INVAL = 28,
+ /// I/O error.
+ IO = 29,
+ /// Socket is connected.
+ ISCONN = 30,
+ /// Is a directory.
+ ISDIR = 31,
+ /// Too many levels of symbolic links.
+ LOOP = 32,
+ /// File descriptor value too large.
+ MFILE = 33,
+ /// Too many links.
+ MLINK = 34,
+ /// Message too large.
+ MSGSIZE = 35,
+ /// Reserved.
+ MULTIHOP = 36,
+ /// Filename too long.
+ NAMETOOLONG = 37,
+ /// Network is down.
+ NETDOWN = 38,
+ /// Connection aborted by network.
+ NETRESET = 39,
+ /// Network unreachable.
+ NETUNREACH = 40,
+ /// Too many files open in system.
+ NFILE = 41,
+ /// No buffer space available.
+ NOBUFS = 42,
+ /// No such device.
+ NODEV = 43,
+ /// No such file or directory.
+ NOENT = 44,
+ /// Executable file format error.
+ NOEXEC = 45,
+ /// No locks available.
+ NOLCK = 46,
+ /// Reserved.
+ NOLINK = 47,
+ /// Not enough space.
+ NOMEM = 48,
+ /// No message of the desired type.
+ NOMSG = 49,
+ /// Protocol not available.
+ NOPROTOOPT = 50,
+ /// No space left on device.
+ NOSPC = 51,
+ /// Function not supported.
+ NOSYS = 52,
+ /// The socket is not connected.
+ NOTCONN = 53,
+ /// Not a directory or a symbolic link to a directory.
+ NOTDIR = 54,
+ /// Directory not empty.
+ NOTEMPTY = 55,
+ /// State not recoverable.
+ NOTRECOVERABLE = 56,
+ /// Not a socket.
+ NOTSOCK = 57,
+ /// Not supported, or operation not supported on socket.
+ NOTSUP = 58,
+ /// Inappropriate I/O control operation.
+ NOTTY = 59,
+ /// No such device or address.
+ NXIO = 60,
+ /// Value too large to be stored in data type.
+ OVERFLOW = 61,
+ /// Previous owner died.
+ OWNERDEAD = 62,
+ /// Operation not permitted.
+ PERM = 63,
+ /// Broken pipe.
+ PIPE = 64,
+ /// Protocol error.
+ PROTO = 65,
+ /// Protocol not supported.
+ PROTONOSUPPORT = 66,
+ /// Protocol wrong type for socket.
+ PROTOTYPE = 67,
+ /// Result too large.
+ RANGE = 68,
+ /// Read-only file system.
+ ROFS = 69,
+ /// Invalid seek.
+ SPIPE = 70,
+ /// No such process.
+ SRCH = 71,
+ /// Reserved.
+ STALE = 72,
+ /// Connection timed out.
+ TIMEDOUT = 73,
+ /// Text file busy.
+ TXTBSY = 74,
+ /// Cross-device link.
+ XDEV = 75,
+ /// Extension: Capabilities insufficient.
+ NOTCAPABLE = 76,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u16,
+}
+
+bitflags! {
+ /// The state of the file descriptor subscribed to with
+ /// [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+ #[repr(C)]
+ pub struct eventrwflags: u16 {
+ /// The peer of this socket has closed or disconnected.
+ const HANGUP = 0x0001;
+ }
+}
+
+/// Type of a subscription to an event or its occurrence.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum eventtype {
+ /// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id)
+ /// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout).
+ CLOCK = 1,
+ /// Condition variable [`subscription.union.condvar.condvar`](struct.subscription_condvar.html#structfield.condvar) has
+ /// been woken up and [`subscription.union.condvar.lock`](struct.subscription_condvar.html#structfield.lock) has been
+ /// acquired for writing.
+ CONDVAR = 2,
+ /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
+ /// data available for reading. This event always triggers
+ /// for regular files.
+ FD_READ = 3,
+ /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
+ /// capacity available for writing. This event always
+ /// triggers for regular files.
+ FD_WRITE = 4,
+ /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
+ /// reading.
+ LOCK_RDLOCK = 5,
+ /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
+ /// writing.
+ LOCK_WRLOCK = 6,
+ /// The process associated with process descriptor
+ /// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated.
+ PROC_TERMINATE = 7,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Exit code generated by a process when exiting.
+pub type exitcode = u32;
+
+/// A file descriptor number.
+///
+/// Unlike on POSIX-compliant systems, none of the file descriptor
+/// numbers are reserved for a purpose (e.g., stdin, stdout,
+/// stderr). Operating systems are not required to allocate new
+/// file descriptors in ascending order.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct fd(pub u32);
+/// Returned to the child process by [`proc_fork()`](fn.proc_fork.html).
+pub const PROCESS_CHILD: fd = fd(0xffffffff);
+/// Passed to [`mem_map()`](fn.mem_map.html) when creating a mapping to
+/// anonymous memory.
+pub const MAP_ANON_FD : fd = fd(0xffffffff);
+
+bitflags! {
+ /// File descriptor flags.
+ #[repr(C)]
+ pub struct fdflags: u16 {
+ /// Append mode: Data written to the file is always
+ /// appended to the file's end.
+ const APPEND = 0x0001;
+ /// Write according to synchronized I/O data integrity
+ /// completion. Only the data stored in the file is
+ /// synchronized.
+ const DSYNC = 0x0002;
+ /// Non-blocking mode.
+ const NONBLOCK = 0x0004;
+ /// Synchronized read I/O operations.
+ const RSYNC = 0x0008;
+ /// Write according to synchronized I/O file integrity
+ /// completion. In addition to synchronizing the data
+ /// stored in the file, the system may also synchronously
+ /// update the file's metadata.
+ const SYNC = 0x0010;
+ }
+}
+
+bitflags! {
+ /// Which file descriptor attributes to adjust.
+ #[repr(C)]
+ pub struct fdsflags: u16 {
+ /// Adjust the file descriptor flags stored in
+ /// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags).
+ const FLAGS = 0x0001;
+ /// Restrict the rights of the file descriptor to the
+ /// rights stored in [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
+ /// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting).
+ const RIGHTS = 0x0002;
+ }
+}
+
+/// Relative offset within a file.
+pub type filedelta = i64;
+
+/// Non-negative file size or length of a region within a file.
+pub type filesize = u64;
+
+/// The type of a file descriptor or file.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum filetype {
+ /// The type of the file descriptor or file is unknown or
+ /// is different from any of the other types specified.
+ UNKNOWN = 0,
+ /// The file descriptor or file refers to a block device
+ /// inode.
+ BLOCK_DEVICE = 16,
+ /// The file descriptor or file refers to a character
+ /// device inode.
+ CHARACTER_DEVICE = 17,
+ /// The file descriptor or file refers to a directory
+ /// inode.
+ DIRECTORY = 32,
+ /// The file descriptor refers to a process handle.
+ PROCESS = 80,
+ /// The file descriptor or file refers to a regular file
+ /// inode.
+ REGULAR_FILE = 96,
+ /// The file descriptor refers to a shared memory object.
+ SHARED_MEMORY = 112,
+ /// The file descriptor or file refers to a datagram
+ /// socket.
+ SOCKET_DGRAM = 128,
+ /// The file descriptor or file refers to a byte-stream
+ /// socket.
+ SOCKET_STREAM = 130,
+ /// The file refers to a symbolic link inode.
+ SYMBOLIC_LINK = 144,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+bitflags! {
+ /// Which file attributes to adjust.
+ #[repr(C)]
+ pub struct fsflags: u16 {
+ /// Adjust the last data access timestamp to the value
+ /// stored in [`filestat.st_atim`](struct.filestat.html#structfield.st_atim).
+ const ATIM = 0x0001;
+ /// Adjust the last data access timestamp to the time
+ /// of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
+ const ATIM_NOW = 0x0002;
+ /// Adjust the last data modification timestamp to the
+ /// value stored in [`filestat.st_mtim`](struct.filestat.html#structfield.st_mtim).
+ const MTIM = 0x0004;
+ /// Adjust the last data modification timestamp to the
+ /// time of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
+ const MTIM_NOW = 0x0008;
+ /// Truncate or extend the file to the size stored in
+ /// [`filestat.st_size`](struct.filestat.html#structfield.st_size).
+ const SIZE = 0x0010;
+ }
+}
+
+/// File serial number that is unique within its file system.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct inode(pub u64);
+
+/// Number of hard links to an inode.
+pub type linkcount = u32;
+
+/// A userspace read-recursive readers-writer lock, similar to a
+/// Linux futex or a FreeBSD umtx.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct lock(pub u32);
+/// Value indicating that the lock is in its initial
+/// unlocked state.
+pub const LOCK_UNLOCKED : lock = lock(0x00000000);
+/// Bitmask indicating that the lock is write-locked. If
+/// set, the lower 30 bits of the lock contain the
+/// identifier of the thread that owns the write lock.
+/// Otherwise, the lower 30 bits of the lock contain the
+/// number of acquired read locks.
+pub const LOCK_WRLOCKED : lock = lock(0x40000000);
+/// Bitmask indicating that the lock is either read locked
+/// or write locked, and that one or more threads have
+/// their execution suspended, waiting to acquire the
+/// lock. The last owner of the lock must call the
+/// kernel to unlock.
+///
+/// When the lock is acquired for reading and this bit is
+/// set, it means that one or more threads are attempting
+/// to acquire this lock for writing. In that case, other
+/// threads should only acquire additional read locks if
+/// suspending execution would cause a deadlock. It is
+/// preferred to suspend execution, as this prevents
+/// starvation of writers.
+pub const LOCK_KERNEL_MANAGED: lock = lock(0x80000000);
+/// Value indicating that the lock is in an incorrect
+/// state. A lock cannot be in its initial unlocked state,
+/// while also managed by the kernel.
+pub const LOCK_BOGUS : lock = lock(0x80000000);
+
+bitflags! {
+ /// Flags determining the method of how paths are resolved.
+ #[repr(C)]
+ pub struct lookupflags: u32 {
+ /// As long as the resolved path corresponds to a symbolic
+ /// link, it is expanded.
+ const SYMLINK_FOLLOW = 0x00000001;
+ }
+}
+
+bitflags! {
+ /// Memory mapping flags.
+ #[repr(C)]
+ pub struct mflags: u8 {
+ /// Instead of mapping the contents of the file provided,
+ /// create a mapping to anonymous memory. The file
+ /// descriptor argument must be set to [`MAP_ANON_FD`](constant.MAP_ANON_FD.html),
+ /// and the offset must be set to zero.
+ const ANON = 0x01;
+ /// Require that the mapping is performed at the base
+ /// address provided.
+ const FIXED = 0x02;
+ /// Changes are private.
+ const PRIVATE = 0x04;
+ /// Changes are shared.
+ const SHARED = 0x08;
+ }
+}
+
+bitflags! {
+ /// Memory page protection options.
+ ///
+ /// This implementation enforces the `W^X` property: Pages cannot be
+ /// mapped for execution while also mapped for writing.
+ #[repr(C)]
+ pub struct mprot: u8 {
+ /// Page can be executed.
+ const EXEC = 0x01;
+ /// Page can be written.
+ const WRITE = 0x02;
+ /// Page can be read.
+ const READ = 0x04;
+ }
+}
+
+bitflags! {
+ /// Methods of synchronizing memory with physical storage.
+ #[repr(C)]
+ pub struct msflags: u8 {
+ /// Perform asynchronous writes.
+ const ASYNC = 0x01;
+ /// Invalidate cached data.
+ const INVALIDATE = 0x02;
+ /// Perform synchronous writes.
+ const SYNC = 0x04;
+ }
+}
+
+/// Specifies the number of threads sleeping on a condition
+/// variable that should be woken up.
+pub type nthreads = u32;
+
+bitflags! {
+ /// Open flags used by [`file_open()`](fn.file_open.html).
+ #[repr(C)]
+ pub struct oflags: u16 {
+ /// Create file if it does not exist.
+ const CREAT = 0x0001;
+ /// Fail if not a directory.
+ const DIRECTORY = 0x0002;
+ /// Fail if file already exists.
+ const EXCL = 0x0004;
+ /// Truncate file to size 0.
+ const TRUNC = 0x0008;
+ }
+}
+
+bitflags! {
+ /// Flags provided to [`sock_recv()`](fn.sock_recv.html).
+ #[repr(C)]
+ pub struct riflags: u16 {
+ /// Returns the message without removing it from the
+ /// socket's receive queue.
+ const PEEK = 0x0004;
+ /// On byte-stream sockets, block until the full amount
+ /// of data can be returned.
+ const WAITALL = 0x0010;
+ }
+}
+
+bitflags! {
+ /// File descriptor rights, determining which actions may be
+ /// performed.
+ #[repr(C)]
+ pub struct rights: u64 {
+ /// The right to invoke [`fd_datasync()`](fn.fd_datasync.html).
+ ///
+ /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
+ /// invoke [`file_open()`](fn.file_open.html) with [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
+ const FD_DATASYNC = 0x0000000000000001;
+ /// The right to invoke [`fd_read()`](fn.fd_read.html) and [`sock_recv()`](fn.sock_recv.html).
+ ///
+ /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
+ /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
+ /// [`READ`](struct.mprot.html#associatedconstant.READ).
+ ///
+ /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to invoke
+ /// [`fd_pread()`](fn.fd_pread.html).
+ const FD_READ = 0x0000000000000002;
+ /// The right to invoke [`fd_seek()`](fn.fd_seek.html). This flag implies
+ /// [`FD_TELL`](struct.rights.html#associatedconstant.FD_TELL).
+ const FD_SEEK = 0x0000000000000004;
+ /// The right to invoke [`fd_stat_put()`](fn.fd_stat_put.html) with
+ /// [`FLAGS`](struct.fdsflags.html#associatedconstant.FLAGS).
+ const FD_STAT_PUT_FLAGS = 0x0000000000000008;
+ /// The right to invoke [`fd_sync()`](fn.fd_sync.html).
+ ///
+ /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
+ /// invoke [`file_open()`](fn.file_open.html) with [`RSYNC`](struct.fdflags.html#associatedconstant.RSYNC) and
+ /// [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
+ const FD_SYNC = 0x0000000000000010;
+ /// The right to invoke [`fd_seek()`](fn.fd_seek.html) in such a way that the
+ /// file offset remains unaltered (i.e., [`CUR`](enum.whence.html#variant.CUR) with
+ /// offset zero).
+ const FD_TELL = 0x0000000000000020;
+ /// The right to invoke [`fd_write()`](fn.fd_write.html) and [`sock_send()`](fn.sock_send.html).
+ ///
+ /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
+ /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
+ /// [`WRITE`](struct.mprot.html#associatedconstant.WRITE).
+ ///
+ /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to
+ /// invoke [`fd_pwrite()`](fn.fd_pwrite.html).
+ const FD_WRITE = 0x0000000000000040;
+ /// The right to invoke [`file_advise()`](fn.file_advise.html).
+ const FILE_ADVISE = 0x0000000000000080;
+ /// The right to invoke [`file_allocate()`](fn.file_allocate.html).
+ const FILE_ALLOCATE = 0x0000000000000100;
+ /// The right to invoke [`file_create()`](fn.file_create.html) with
+ /// [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY).
+ const FILE_CREATE_DIRECTORY = 0x0000000000000200;
+ /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, the right to invoke
+ /// [`file_open()`](fn.file_open.html) with [`CREAT`](struct.oflags.html#associatedconstant.CREAT).
+ const FILE_CREATE_FILE = 0x0000000000000400;
+ /// The right to invoke [`file_link()`](fn.file_link.html) with the file
+ /// descriptor as the source directory.
+ const FILE_LINK_SOURCE = 0x0000000000001000;
+ /// The right to invoke [`file_link()`](fn.file_link.html) with the file
+ /// descriptor as the target directory.
+ const FILE_LINK_TARGET = 0x0000000000002000;
+ /// The right to invoke [`file_open()`](fn.file_open.html).
+ const FILE_OPEN = 0x0000000000004000;
+ /// The right to invoke [`file_readdir()`](fn.file_readdir.html).
+ const FILE_READDIR = 0x0000000000008000;
+ /// The right to invoke [`file_readlink()`](fn.file_readlink.html).
+ const FILE_READLINK = 0x0000000000010000;
+ /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
+ /// descriptor as the source directory.
+ const FILE_RENAME_SOURCE = 0x0000000000020000;
+ /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
+ /// descriptor as the target directory.
+ const FILE_RENAME_TARGET = 0x0000000000040000;
+ /// The right to invoke [`file_stat_fget()`](fn.file_stat_fget.html).
+ const FILE_STAT_FGET = 0x0000000000080000;
+ /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
+ /// [`SIZE`](struct.fsflags.html#associatedconstant.SIZE).
+ ///
+ /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
+ /// invoke [`file_open()`](fn.file_open.html) with [`TRUNC`](struct.oflags.html#associatedconstant.TRUNC).
+ const FILE_STAT_FPUT_SIZE = 0x0000000000100000;
+ /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
+ /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
+ /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
+ const FILE_STAT_FPUT_TIMES = 0x0000000000200000;
+ /// The right to invoke [`file_stat_get()`](fn.file_stat_get.html).
+ const FILE_STAT_GET = 0x0000000000400000;
+ /// The right to invoke [`file_stat_put()`](fn.file_stat_put.html) with
+ /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
+ /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
+ const FILE_STAT_PUT_TIMES = 0x0000000000800000;
+ /// The right to invoke [`file_symlink()`](fn.file_symlink.html).
+ const FILE_SYMLINK = 0x0000000001000000;
+ /// The right to invoke [`file_unlink()`](fn.file_unlink.html).
+ const FILE_UNLINK = 0x0000000002000000;
+ /// The right to invoke [`mem_map()`](fn.mem_map.html) with [`mprot`](struct.mprot.html) set to
+ /// zero.
+ const MEM_MAP = 0x0000000004000000;
+ /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, the right to invoke
+ /// [`mem_map()`](fn.mem_map.html) with [`EXEC`](struct.mprot.html#associatedconstant.EXEC).
+ const MEM_MAP_EXEC = 0x0000000008000000;
+ /// If [`FD_READ`](struct.rights.html#associatedconstant.FD_READ) is set, includes the right to
+ /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_READ`](enum.eventtype.html#variant.FD_READ).
+ ///
+ /// If [`FD_WRITE`](struct.rights.html#associatedconstant.FD_WRITE) is set, includes the right to
+ /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+ const POLL_FD_READWRITE = 0x0000000010000000;
+ /// The right to invoke [`poll()`](fn.poll.html) to subscribe to
+ /// [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
+ const POLL_PROC_TERMINATE = 0x0000000040000000;
+ /// The right to invoke [`proc_exec()`](fn.proc_exec.html).
+ const PROC_EXEC = 0x0000000100000000;
+ /// The right to invoke [`sock_shutdown()`](fn.sock_shutdown.html).
+ const SOCK_SHUTDOWN = 0x0000008000000000;
+ }
+}
+
+bitflags! {
+ /// Flags returned by [`sock_recv()`](fn.sock_recv.html).
+ #[repr(C)]
+ pub struct roflags: u16 {
+ /// Returned by [`sock_recv()`](fn.sock_recv.html): List of file descriptors
+ /// has been truncated.
+ const FDS_TRUNCATED = 0x0001;
+ /// Returned by [`sock_recv()`](fn.sock_recv.html): Message data has been
+ /// truncated.
+ const DATA_TRUNCATED = 0x0008;
+ }
+}
+
+/// Indicates whether an object is stored in private or shared
+/// memory.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum scope {
+ /// The object is stored in private memory.
+ PRIVATE = 4,
+ /// The object is stored in shared memory.
+ SHARED = 8,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+bitflags! {
+ /// Which channels on a socket need to be shut down.
+ #[repr(C)]
+ pub struct sdflags: u8 {
+ /// Disables further receive operations.
+ const RD = 0x01;
+ /// Disables further send operations.
+ const WR = 0x02;
+ }
+}
+
+bitflags! {
+ /// Flags provided to [`sock_send()`](fn.sock_send.html). As there are currently no flags
+ /// defined, it must be set to zero.
+ #[repr(C)]
+ pub struct siflags: u16 {
+ const DEFAULT = 0;
+ }
+}
+
+/// Signal condition.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum signal {
+ /// Process abort signal.
+ ///
+ /// Action: Terminates the process.
+ ABRT = 1,
+ /// Alarm clock.
+ ///
+ /// Action: Terminates the process.
+ ALRM = 2,
+ /// Access to an undefined portion of a memory object.
+ ///
+ /// Action: Terminates the process.
+ BUS = 3,
+ /// Child process terminated, stopped, or continued.
+ ///
+ /// Action: Ignored.
+ CHLD = 4,
+ /// Continue executing, if stopped.
+ ///
+ /// Action: Continues executing, if stopped.
+ CONT = 5,
+ /// Erroneous arithmetic operation.
+ ///
+ /// Action: Terminates the process.
+ FPE = 6,
+ /// Hangup.
+ ///
+ /// Action: Terminates the process.
+ HUP = 7,
+ /// Illegal instruction.
+ ///
+ /// Action: Terminates the process.
+ ILL = 8,
+ /// Terminate interrupt signal.
+ ///
+ /// Action: Terminates the process.
+ INT = 9,
+ /// Kill.
+ ///
+ /// Action: Terminates the process.
+ KILL = 10,
+ /// Write on a pipe with no one to read it.
+ ///
+ /// Action: Ignored.
+ PIPE = 11,
+ /// Terminal quit signal.
+ ///
+ /// Action: Terminates the process.
+ QUIT = 12,
+ /// Invalid memory reference.
+ ///
+ /// Action: Terminates the process.
+ SEGV = 13,
+ /// Stop executing.
+ ///
+ /// Action: Stops executing.
+ STOP = 14,
+ /// Bad system call.
+ ///
+ /// Action: Terminates the process.
+ SYS = 15,
+ /// Termination signal.
+ ///
+ /// Action: Terminates the process.
+ TERM = 16,
+ /// Trace/breakpoint trap.
+ ///
+ /// Action: Terminates the process.
+ TRAP = 17,
+ /// Terminal stop signal.
+ ///
+ /// Action: Stops executing.
+ TSTP = 18,
+ /// Background process attempting read.
+ ///
+ /// Action: Stops executing.
+ TTIN = 19,
+ /// Background process attempting write.
+ ///
+ /// Action: Stops executing.
+ TTOU = 20,
+ /// High bandwidth data is available at a socket.
+ ///
+ /// Action: Ignored.
+ URG = 21,
+ /// User-defined signal 1.
+ ///
+ /// Action: Terminates the process.
+ USR1 = 22,
+ /// User-defined signal 2.
+ ///
+ /// Action: Terminates the process.
+ USR2 = 23,
+ /// Virtual timer expired.
+ ///
+ /// Action: Terminates the process.
+ VTALRM = 24,
+ /// CPU time limit exceeded.
+ ///
+ /// Action: Terminates the process.
+ XCPU = 25,
+ /// File size limit exceeded.
+ ///
+ /// Action: Terminates the process.
+ XFSZ = 26,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+bitflags! {
+ /// Flags determining how the timestamp provided in
+ /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) should be interpreted.
+ #[repr(C)]
+ pub struct subclockflags: u16 {
+ /// If set, treat the timestamp provided in
+ /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) as an absolute timestamp
+ /// of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
+ ///
+ /// If clear, treat the timestamp provided in
+ /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) relative to the current
+ /// time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
+ const ABSTIME = 0x0001;
+ }
+}
+
+bitflags! {
+ /// Flags influencing the method of polling for read or writing on
+ /// a file descriptor.
+ #[repr(C)]
+ pub struct subrwflags: u16 {
+ /// Deprecated. Must be set by callers and ignored by
+ /// implementations.
+ const POLL = 0x0001;
+ }
+}
+
+/// Unique system-local identifier of a thread. This identifier is
+/// only valid during the lifetime of the thread.
+///
+/// Threads must be aware of their thread identifier, as it is
+/// written it into locks when acquiring them for writing. It is
+/// not advised to use these identifiers for any other purpose.
+///
+/// As the thread identifier is also stored in [`lock`](struct.lock.html) when
+/// [`LOCK_WRLOCKED`](constant.LOCK_WRLOCKED.html) is set, the top two bits of the thread
+/// must always be set to zero.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct tid(pub u32);
+
+/// Timestamp in nanoseconds.
+pub type timestamp = u64;
+
+bitflags! {
+ /// Specifies whether files are unlinked or directories are
+ /// removed.
+ #[repr(C)]
+ pub struct ulflags: u8 {
+ /// If set, removes a directory. Otherwise, unlinks any
+ /// non-directory file.
+ const REMOVEDIR = 0x01;
+ }
+}
+
+/// User-provided value that can be attached to objects that is
+/// retained when extracted from the kernel.
+pub type userdata = u64;
+
+/// Relative to which position the offset of the file descriptor
+/// should be set.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum whence {
+ /// Seek relative to current position.
+ CUR = 1,
+ /// Seek relative to end-of-file.
+ END = 2,
+ /// Seek relative to start-of-file.
+ SET = 3,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Auxiliary vector entry.
+///
+/// The auxiliary vector is a list of key-value pairs that is
+/// provided to the process on startup. Unlike structures, it is
+/// extensible, as it is possible to add new records later on.
+/// The auxiliary vector is always terminated by an entry having
+/// type [`NULL`](enum.auxtype.html#variant.NULL).
+///
+/// The auxiliary vector is part of the x86-64 ABI, but is used by
+/// this environment on all architectures.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct auxv {
+ /// The type of the auxiliary vector entry.
+ pub a_type: auxtype,
+ pub union: auxv_union
+}
+/// A union inside `auxv`.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union auxv_union {
+ /// Used when `a_type` is [`ARGDATALEN`](enum.auxtype.html#variant.ARGDATALEN), [`CANARYLEN`](enum.auxtype.html#variant.CANARYLEN), [`NCPUS`](enum.auxtype.html#variant.NCPUS), [`PAGESZ`](enum.auxtype.html#variant.PAGESZ), [`PHNUM`](enum.auxtype.html#variant.PHNUM), or [`TID`](enum.auxtype.html#variant.TID).
+/// A numerical value.
+ pub a_val: usize,
+ /// Used when `a_type` is [`ARGDATA`](enum.auxtype.html#variant.ARGDATA), [`BASE`](enum.auxtype.html#variant.BASE), [`CANARY`](enum.auxtype.html#variant.CANARY), [`PHDR`](enum.auxtype.html#variant.PHDR), [`PID`](enum.auxtype.html#variant.PID), or [`SYSINFO_EHDR`](enum.auxtype.html#variant.SYSINFO_EHDR).
+/// A pointer value.
+ pub a_ptr: *mut (),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn auxv_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<auxv>(), 8);
+ assert_eq!(::core::mem::align_of::<auxv>(), 4);
+ unsafe {
+ let obj: auxv = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.a_type as *const _ as usize - base, 0);
+ assert_eq!(&obj.union.a_val as *const _ as usize - base, 4);
+ assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 4);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn auxv_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<auxv>(), 16);
+ assert_eq!(::core::mem::align_of::<auxv>(), 8);
+ unsafe {
+ let obj: auxv = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.a_type as *const _ as usize - base, 0);
+ assert_eq!(&obj.union.a_val as *const _ as usize - base, 8);
+ assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 8);
+ }
+}
+
+/// A region of memory for scatter/gather writes.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct ciovec {
+ /// The address and length of the buffer to be written.
+ pub buf: (*const (), usize),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn ciovec_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<ciovec>(), 8);
+ assert_eq!(::core::mem::align_of::<ciovec>(), 4);
+ unsafe {
+ let obj: ciovec = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn ciovec_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<ciovec>(), 16);
+ assert_eq!(::core::mem::align_of::<ciovec>(), 8);
+ unsafe {
+ let obj: ciovec = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
+ }
+}
+
+/// A directory entry.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct dirent {
+ /// The offset of the next directory entry stored in this
+ /// directory.
+ pub d_next: dircookie,
+ /// The serial number of the file referred to by this
+ /// directory entry.
+ pub d_ino: inode,
+ /// The length of the name of the directory entry.
+ pub d_namlen: u32,
+ /// The type of the file referred to by this directory
+ /// entry.
+ pub d_type: filetype,
+}
+#[test]
+fn dirent_layout_test() {
+ assert_eq!(::core::mem::size_of::<dirent>(), 24);
+ assert_eq!(::core::mem::align_of::<dirent>(), 8);
+ unsafe {
+ let obj: dirent = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.d_next as *const _ as usize - base, 0);
+ assert_eq!(&obj.d_ino as *const _ as usize - base, 8);
+ assert_eq!(&obj.d_namlen as *const _ as usize - base, 16);
+ assert_eq!(&obj.d_type as *const _ as usize - base, 20);
+ }
+}
+
+/// An event that occurred.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct event {
+ /// User-provided value that got attached to
+ /// [`subscription.userdata`](struct.subscription.html#structfield.userdata).
+ pub userdata: userdata,
+ /// If non-zero, an error that occurred while processing
+ /// the subscription request.
+ pub error: errno,
+ /// The type of the event that occurred.
+ pub type_: eventtype,
+ pub union: event_union
+}
+/// A union inside `event`.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union event_union {
+ /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+ pub fd_readwrite: event_fd_readwrite,
+ /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
+ pub proc_terminate: event_proc_terminate,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct event_fd_readwrite {
+ /// The number of bytes available
+ /// for reading or writing.
+ pub nbytes: filesize,
+ /// Obsolete.
+ pub unused: [u8; 4],
+ /// The state of the file
+ /// descriptor.
+ pub flags: eventrwflags,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct event_proc_terminate {
+ /// Obsolete.
+ pub unused: [u8; 4],
+ /// If zero, the process has
+ /// exited.
+ /// Otherwise, the signal
+ /// condition causing it to
+ /// terminated.
+ pub signal: signal,
+ /// If exited, the exit code of
+ /// the process.
+ pub exitcode: exitcode,
+}
+#[test]
+fn event_layout_test() {
+ assert_eq!(::core::mem::size_of::<event>(), 32);
+ assert_eq!(::core::mem::align_of::<event>(), 8);
+ unsafe {
+ let obj: event = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.userdata as *const _ as usize - base, 0);
+ assert_eq!(&obj.error as *const _ as usize - base, 8);
+ assert_eq!(&obj.type_ as *const _ as usize - base, 10);
+ assert_eq!(&obj.union.fd_readwrite.nbytes as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.fd_readwrite.unused as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 28);
+ assert_eq!(&obj.union.proc_terminate.unused as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.proc_terminate.signal as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.proc_terminate.exitcode as *const _ as usize - base, 24);
+ }
+}
+
+/// File descriptor attributes.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct fdstat {
+ /// File type.
+ pub fs_filetype: filetype,
+ /// File descriptor flags.
+ pub fs_flags: fdflags,
+ /// Rights that apply to this file descriptor.
+ pub fs_rights_base: rights,
+ /// Maximum set of rights that can be installed on new
+ /// file descriptors that are created through this file
+ /// descriptor, e.g., through [`file_open()`](fn.file_open.html).
+ pub fs_rights_inheriting: rights,
+}
+#[test]
+fn fdstat_layout_test() {
+ assert_eq!(::core::mem::size_of::<fdstat>(), 24);
+ assert_eq!(::core::mem::align_of::<fdstat>(), 8);
+ unsafe {
+ let obj: fdstat = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.fs_filetype as *const _ as usize - base, 0);
+ assert_eq!(&obj.fs_flags as *const _ as usize - base, 2);
+ assert_eq!(&obj.fs_rights_base as *const _ as usize - base, 8);
+ assert_eq!(&obj.fs_rights_inheriting as *const _ as usize - base, 16);
+ }
+}
+
+/// File attributes.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct filestat {
+ /// Device ID of device containing the file.
+ pub st_dev: device,
+ /// File serial number.
+ pub st_ino: inode,
+ /// File type.
+ pub st_filetype: filetype,
+ /// Number of hard links to the file.
+ pub st_nlink: linkcount,
+ /// For regular files, the file size in bytes. For
+ /// symbolic links, the length in bytes of the pathname
+ /// contained in the symbolic link.
+ pub st_size: filesize,
+ /// Last data access timestamp.
+ pub st_atim: timestamp,
+ /// Last data modification timestamp.
+ pub st_mtim: timestamp,
+ /// Last file status change timestamp.
+ pub st_ctim: timestamp,
+}
+#[test]
+fn filestat_layout_test() {
+ assert_eq!(::core::mem::size_of::<filestat>(), 56);
+ assert_eq!(::core::mem::align_of::<filestat>(), 8);
+ unsafe {
+ let obj: filestat = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.st_dev as *const _ as usize - base, 0);
+ assert_eq!(&obj.st_ino as *const _ as usize - base, 8);
+ assert_eq!(&obj.st_filetype as *const _ as usize - base, 16);
+ assert_eq!(&obj.st_nlink as *const _ as usize - base, 20);
+ assert_eq!(&obj.st_size as *const _ as usize - base, 24);
+ assert_eq!(&obj.st_atim as *const _ as usize - base, 32);
+ assert_eq!(&obj.st_mtim as *const _ as usize - base, 40);
+ assert_eq!(&obj.st_ctim as *const _ as usize - base, 48);
+ }
+}
+
+/// A region of memory for scatter/gather reads.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct iovec {
+ /// The address and length of the buffer to be filled.
+ pub buf: (*mut (), usize),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn iovec_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<iovec>(), 8);
+ assert_eq!(::core::mem::align_of::<iovec>(), 4);
+ unsafe {
+ let obj: iovec = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn iovec_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<iovec>(), 16);
+ assert_eq!(::core::mem::align_of::<iovec>(), 8);
+ unsafe {
+ let obj: iovec = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
+ }
+}
+
+/// Path lookup properties.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct lookup {
+ /// The working directory at which the resolution of the
+ /// path starts.
+ pub fd: fd,
+ /// Flags determining the method of how the path is
+ /// resolved.
+ pub flags: lookupflags,
+}
+#[test]
+fn lookup_layout_test() {
+ assert_eq!(::core::mem::size_of::<lookup>(), 8);
+ assert_eq!(::core::mem::align_of::<lookup>(), 4);
+ unsafe {
+ let obj: lookup = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.fd as *const _ as usize - base, 0);
+ assert_eq!(&obj.flags as *const _ as usize - base, 4);
+ }
+}
+
+/// Entry point for a process (`_start`).
+///
+/// **auxv**:
+/// The auxiliary vector. See [`auxv`](struct.auxv.html).
+pub type processentry = unsafe extern "C" fn(
+ auxv: *const auxv,
+) -> ();
+
+/// Arguments of [`sock_recv()`](fn.sock_recv.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct recv_in {
+ /// List of scatter/gather vectors where message data
+ /// should be stored.
+ pub ri_data: (*const iovec, usize),
+ /// Buffer where numbers of incoming file descriptors
+ /// should be stored.
+ pub ri_fds: (*mut fd, usize),
+ /// Message flags.
+ pub ri_flags: riflags,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn recv_in_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<recv_in>(), 20);
+ assert_eq!(::core::mem::align_of::<recv_in>(), 4);
+ unsafe {
+ let obj: recv_in = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 4);
+ assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 8);
+ assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 12);
+ assert_eq!(&obj.ri_flags as *const _ as usize - base, 16);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn recv_in_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<recv_in>(), 40);
+ assert_eq!(::core::mem::align_of::<recv_in>(), 8);
+ unsafe {
+ let obj: recv_in = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 8);
+ assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 16);
+ assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 24);
+ assert_eq!(&obj.ri_flags as *const _ as usize - base, 32);
+ }
+}
+
+/// Results of [`sock_recv()`](fn.sock_recv.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct recv_out {
+ /// Number of bytes stored in [`recv_in.ri_data`](struct.recv_in.html#structfield.ri_data).
+ pub ro_datalen: usize,
+ /// Number of file descriptors stored in [`recv_in.ri_fds`](struct.recv_in.html#structfield.ri_fds).
+ pub ro_fdslen: usize,
+ /// Fields that were used by previous implementations.
+ pub ro_unused: [u8; 40],
+ /// Message flags.
+ pub ro_flags: roflags,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn recv_out_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<recv_out>(), 52);
+ assert_eq!(::core::mem::align_of::<recv_out>(), 4);
+ unsafe {
+ let obj: recv_out = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
+ assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 4);
+ assert_eq!(&obj.ro_unused as *const _ as usize - base, 8);
+ assert_eq!(&obj.ro_flags as *const _ as usize - base, 48);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn recv_out_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<recv_out>(), 64);
+ assert_eq!(::core::mem::align_of::<recv_out>(), 8);
+ unsafe {
+ let obj: recv_out = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
+ assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 8);
+ assert_eq!(&obj.ro_unused as *const _ as usize - base, 16);
+ assert_eq!(&obj.ro_flags as *const _ as usize - base, 56);
+ }
+}
+
+/// Arguments of [`sock_send()`](fn.sock_send.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct send_in {
+ /// List of scatter/gather vectors where message data
+ /// should be retrieved.
+ pub si_data: (*const ciovec, usize),
+ /// File descriptors that need to be attached to the
+ /// message.
+ pub si_fds: (*const fd, usize),
+ /// Message flags.
+ pub si_flags: siflags,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn send_in_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<send_in>(), 20);
+ assert_eq!(::core::mem::align_of::<send_in>(), 4);
+ unsafe {
+ let obj: send_in = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.si_data.1 as *const _ as usize - base, 4);
+ assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 8);
+ assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 12);
+ assert_eq!(&obj.si_flags as *const _ as usize - base, 16);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn send_in_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<send_in>(), 40);
+ assert_eq!(::core::mem::align_of::<send_in>(), 8);
+ unsafe {
+ let obj: send_in = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.si_data.1 as *const _ as usize - base, 8);
+ assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 16);
+ assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 24);
+ assert_eq!(&obj.si_flags as *const _ as usize - base, 32);
+ }
+}
+
+/// Results of [`sock_send()`](fn.sock_send.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct send_out {
+ /// Number of bytes transmitted.
+ pub so_datalen: usize,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn send_out_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<send_out>(), 4);
+ assert_eq!(::core::mem::align_of::<send_out>(), 4);
+ unsafe {
+ let obj: send_out = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn send_out_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<send_out>(), 8);
+ assert_eq!(::core::mem::align_of::<send_out>(), 8);
+ unsafe {
+ let obj: send_out = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
+ }
+}
+
+/// Subscription to an event.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription {
+ /// User-provided value that is attached to the
+ /// subscription in the kernel and returned through
+ /// [`event.userdata`](struct.event.html#structfield.userdata).
+ pub userdata: userdata,
+ /// Used by previous implementations. Ignored.
+ pub unused: u16,
+ /// The type of the event to which to subscribe.
+ ///
+ /// Currently, [`CONDVAR`](enum.eventtype.html#variant.CONDVAR),
+ /// [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK), and [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK)
+ /// must be provided as the first subscription and may
+ /// only be followed by up to one other subscription,
+ /// having type [`CLOCK`](enum.eventtype.html#variant.CLOCK).
+ pub type_: eventtype,
+ pub union: subscription_union
+}
+/// A union inside `subscription`.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union subscription_union {
+ /// Used when `type_` is [`CLOCK`](enum.eventtype.html#variant.CLOCK).
+ pub clock: subscription_clock,
+ /// Used when `type_` is [`CONDVAR`](enum.eventtype.html#variant.CONDVAR).
+ pub condvar: subscription_condvar,
+ /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+ pub fd_readwrite: subscription_fd_readwrite,
+ /// Used when `type_` is [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK) or [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK).
+ pub lock: subscription_lock,
+ /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
+ pub proc_terminate: subscription_proc_terminate,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_clock {
+ /// The user-defined unique
+ /// identifier of the clock.
+ pub identifier: userdata,
+ /// The clock against which the
+ /// timestamp should be compared.
+ pub clock_id: clockid,
+ /// The absolute or relative
+ /// timestamp.
+ pub timeout: timestamp,
+ /// The amount of time that the
+ /// kernel may wait additionally
+ /// to coalesce with other events.
+ pub precision: timestamp,
+ /// Flags specifying whether the
+ /// timeout is absolute or
+ /// relative.
+ pub flags: subclockflags,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_condvar {
+ /// The condition variable on
+ /// which to wait to be woken up.
+ pub condvar: *mut condvar,
+ /// The lock that will be
+ /// released while waiting.
+ ///
+ /// The lock will be reacquired
+ /// for writing when the condition
+ /// variable triggers.
+ pub lock: *mut lock,
+ /// Whether the condition variable
+ /// is stored in private or shared
+ /// memory.
+ pub condvar_scope: scope,
+ /// Whether the lock is stored in
+ /// private or shared memory.
+ pub lock_scope: scope,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_fd_readwrite {
+ /// The file descriptor on which
+ /// to wait for it to become ready
+ /// for reading or writing.
+ pub fd: fd,
+ /// Under which conditions to
+ /// trigger.
+ pub flags: subrwflags,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_lock {
+ /// The lock that will be acquired
+ /// for reading or writing.
+ pub lock: *mut lock,
+ /// Whether the lock is stored in
+ /// private or shared memory.
+ pub lock_scope: scope,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_proc_terminate {
+ /// The process descriptor on
+ /// which to wait for process
+ /// termination.
+ pub fd: fd,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn subscription_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<subscription>(), 56);
+ assert_eq!(::core::mem::align_of::<subscription>(), 8);
+ unsafe {
+ let obj: subscription = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.userdata as *const _ as usize - base, 0);
+ assert_eq!(&obj.unused as *const _ as usize - base, 8);
+ assert_eq!(&obj.type_ as *const _ as usize - base, 10);
+ assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
+ assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
+ assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
+ assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 25);
+ assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn subscription_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<subscription>(), 56);
+ assert_eq!(::core::mem::align_of::<subscription>(), 8);
+ unsafe {
+ let obj: subscription = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.userdata as *const _ as usize - base, 0);
+ assert_eq!(&obj.unused as *const _ as usize - base, 8);
+ assert_eq!(&obj.type_ as *const _ as usize - base, 10);
+ assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
+ assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
+ assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
+ assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 32);
+ assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 33);
+ assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
+ }
+}
+
+/// The Thread Control Block (TCB).
+///
+/// After a thread begins execution (at program startup or when
+/// created through [`thread_create()`](fn.thread_create.html)), the CPU's registers
+/// controlling Thread-Local Storage (TLS) will already be
+/// initialized. They will point to an area only containing the
+/// TCB.
+///
+/// If the thread needs space for storing thread-specific
+/// variables, the thread may allocate a larger area and adjust
+/// the CPU's registers to point to that area instead. However, it
+/// does need to make sure that the TCB is copied over to the new
+/// TLS area.
+///
+/// The purpose of the TCB is that it allows light-weight
+/// emulators to store information related to individual threads.
+/// For example, it may be used to store a copy of the CPU
+/// registers prior emulation, so that TLS for the host system
+/// can be restored if needed.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct tcb {
+ /// Pointer that may be freely assigned by the system. Its
+ /// value cannot be interpreted by the application.
+ pub parent: *mut (),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn tcb_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<tcb>(), 4);
+ assert_eq!(::core::mem::align_of::<tcb>(), 4);
+ unsafe {
+ let obj: tcb = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.parent as *const _ as usize - base, 0);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn tcb_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<tcb>(), 8);
+ assert_eq!(::core::mem::align_of::<tcb>(), 8);
+ unsafe {
+ let obj: tcb = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.parent as *const _ as usize - base, 0);
+ }
+}
+
+/// Entry point for additionally created threads.
+///
+/// **tid**:
+/// Thread ID of the current thread.
+///
+/// **aux**:
+/// Copy of the value stored in
+/// [`threadattr.argument`](struct.threadattr.html#structfield.argument).
+pub type threadentry = unsafe extern "C" fn(
+ tid: tid,
+ aux: *mut (),
+) -> ();
+
+/// Attributes for thread creation.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct threadattr {
+ /// Initial program counter value.
+ pub entry_point: threadentry,
+ /// Region allocated to serve as stack space.
+ pub stack: (*mut (), usize),
+ /// Argument to be forwarded to the entry point function.
+ pub argument: *mut (),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn threadattr_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<threadattr>(), 16);
+ assert_eq!(::core::mem::align_of::<threadattr>(), 4);
+ unsafe {
+ let obj: threadattr = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
+ assert_eq!(&obj.stack.0 as *const _ as usize - base, 4);
+ assert_eq!(&obj.stack.1 as *const _ as usize - base, 8);
+ assert_eq!(&obj.argument as *const _ as usize - base, 12);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn threadattr_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<threadattr>(), 32);
+ assert_eq!(::core::mem::align_of::<threadattr>(), 8);
+ unsafe {
+ let obj: threadattr = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
+ assert_eq!(&obj.stack.0 as *const _ as usize - base, 8);
+ assert_eq!(&obj.stack.1 as *const _ as usize - base, 16);
+ assert_eq!(&obj.argument as *const _ as usize - base, 24);
+ }
+}
+
+/// The table with pointers to all syscall implementations.
+#[allow(improper_ctypes)]
+extern "C" {
+ fn cloudabi_sys_clock_res_get(_: clockid, _: *mut timestamp) -> errno;
+ fn cloudabi_sys_clock_time_get(_: clockid, _: timestamp, _: *mut timestamp) -> errno;
+ fn cloudabi_sys_condvar_signal(_: *mut condvar, _: scope, _: nthreads) -> errno;
+ fn cloudabi_sys_fd_close(_: fd) -> errno;
+ fn cloudabi_sys_fd_create1(_: filetype, _: *mut fd) -> errno;
+ fn cloudabi_sys_fd_create2(_: filetype, _: *mut fd, _: *mut fd) -> errno;
+ fn cloudabi_sys_fd_datasync(_: fd) -> errno;
+ fn cloudabi_sys_fd_dup(_: fd, _: *mut fd) -> errno;
+ fn cloudabi_sys_fd_pread(_: fd, _: *const iovec, _: usize, _: filesize, _: *mut usize) -> errno;
+ fn cloudabi_sys_fd_pwrite(_: fd, _: *const ciovec, _: usize, _: filesize, _: *mut usize) -> errno;
+ fn cloudabi_sys_fd_read(_: fd, _: *const iovec, _: usize, _: *mut usize) -> errno;
+ fn cloudabi_sys_fd_replace(_: fd, _: fd) -> errno;
+ fn cloudabi_sys_fd_seek(_: fd, _: filedelta, _: whence, _: *mut filesize) -> errno;
+ fn cloudabi_sys_fd_stat_get(_: fd, _: *mut fdstat) -> errno;
+ fn cloudabi_sys_fd_stat_put(_: fd, _: *const fdstat, _: fdsflags) -> errno;
+ fn cloudabi_sys_fd_sync(_: fd) -> errno;
+ fn cloudabi_sys_fd_write(_: fd, _: *const ciovec, _: usize, _: *mut usize) -> errno;
+ fn cloudabi_sys_file_advise(_: fd, _: filesize, _: filesize, _: advice) -> errno;
+ fn cloudabi_sys_file_allocate(_: fd, _: filesize, _: filesize) -> errno;
+ fn cloudabi_sys_file_create(_: fd, _: *const u8, _: usize, _: filetype) -> errno;
+ fn cloudabi_sys_file_link(_: lookup, _: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
+ fn cloudabi_sys_file_open(_: lookup, _: *const u8, _: usize, _: oflags, _: *const fdstat, _: *mut fd) -> errno;
+ fn cloudabi_sys_file_readdir(_: fd, _: *mut (), _: usize, _: dircookie, _: *mut usize) -> errno;
+ fn cloudabi_sys_file_readlink(_: fd, _: *const u8, _: usize, _: *mut u8, _: usize, _: *mut usize) -> errno;
+ fn cloudabi_sys_file_rename(_: fd, _: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
+ fn cloudabi_sys_file_stat_fget(_: fd, _: *mut filestat) -> errno;
+ fn cloudabi_sys_file_stat_fput(_: fd, _: *const filestat, _: fsflags) -> errno;
+ fn cloudabi_sys_file_stat_get(_: lookup, _: *const u8, _: usize, _: *mut filestat) -> errno;
+ fn cloudabi_sys_file_stat_put(_: lookup, _: *const u8, _: usize, _: *const filestat, _: fsflags) -> errno;
+ fn cloudabi_sys_file_symlink(_: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
+ fn cloudabi_sys_file_unlink(_: fd, _: *const u8, _: usize, _: ulflags) -> errno;
+ fn cloudabi_sys_lock_unlock(_: *mut lock, _: scope) -> errno;
+ fn cloudabi_sys_mem_advise(_: *mut (), _: usize, _: advice) -> errno;
+ fn cloudabi_sys_mem_map(_: *mut (), _: usize, _: mprot, _: mflags, _: fd, _: filesize, _: *mut *mut ()) -> errno;
+ fn cloudabi_sys_mem_protect(_: *mut (), _: usize, _: mprot) -> errno;
+ fn cloudabi_sys_mem_sync(_: *mut (), _: usize, _: msflags) -> errno;
+ fn cloudabi_sys_mem_unmap(_: *mut (), _: usize) -> errno;
+ fn cloudabi_sys_poll(_: *const subscription, _: *mut event, _: usize, _: *mut usize) -> errno;
+ fn cloudabi_sys_proc_exec(_: fd, _: *const (), _: usize, _: *const fd, _: usize) -> errno;
+ fn cloudabi_sys_proc_exit(_: exitcode) -> !;
+ fn cloudabi_sys_proc_fork(_: *mut fd, _: *mut tid) -> errno;
+ fn cloudabi_sys_proc_raise(_: signal) -> errno;
+ fn cloudabi_sys_random_get(_: *mut (), _: usize) -> errno;
+ fn cloudabi_sys_sock_recv(_: fd, _: *const recv_in, _: *mut recv_out) -> errno;
+ fn cloudabi_sys_sock_send(_: fd, _: *const send_in, _: *mut send_out) -> errno;
+ fn cloudabi_sys_sock_shutdown(_: fd, _: sdflags) -> errno;
+ fn cloudabi_sys_thread_create(_: *mut threadattr, _: *mut tid) -> errno;
+ fn cloudabi_sys_thread_exit(_: *mut lock, _: scope) -> !;
+ fn cloudabi_sys_thread_yield() -> errno;
+}
+
+/// Obtains the resolution of a clock.
+///
+/// ## Parameters
+///
+/// **clock_id**:
+/// The clock for which the resolution needs to be
+/// returned.
+///
+/// **resolution**:
+/// The resolution of the clock.
+#[inline]
+pub unsafe fn clock_res_get(clock_id_: clockid, resolution_: &mut timestamp) -> errno {
+ cloudabi_sys_clock_res_get(clock_id_, resolution_)
+}
+
+/// Obtains the time value of a clock.
+///
+/// ## Parameters
+///
+/// **clock_id**:
+/// The clock for which the time needs to be
+/// returned.
+///
+/// **precision**:
+/// The maximum lag (exclusive) that the returned
+/// time value may have, compared to its actual
+/// value.
+///
+/// **time**:
+/// The time value of the clock.
+#[inline]
+pub unsafe fn clock_time_get(clock_id_: clockid, precision_: timestamp, time_: &mut timestamp) -> errno {
+ cloudabi_sys_clock_time_get(clock_id_, precision_, time_)
+}
+
+/// Wakes up threads waiting on a userspace condition variable.
+///
+/// If an invocation of this system call causes all waiting
+/// threads to be woken up, the value of the condition variable
+/// is set to [`CONDVAR_HAS_NO_WAITERS`](constant.CONDVAR_HAS_NO_WAITERS.html). As long as the condition
+/// variable is set to this value, it is not needed to invoke this
+/// system call.
+///
+/// ## Parameters
+///
+/// **condvar**:
+/// The userspace condition variable that has
+/// waiting threads.
+///
+/// **scope**:
+/// Whether the condition variable is stored in
+/// private or shared memory.
+///
+/// **nwaiters**:
+/// The number of threads that need to be woken
+/// up. If it exceeds the number of waiting
+/// threads, all threads are woken up.
+#[inline]
+pub unsafe fn condvar_signal(condvar_: *mut condvar, scope_: scope, nwaiters_: nthreads) -> errno {
+ cloudabi_sys_condvar_signal(condvar_, scope_, nwaiters_)
+}
+
+/// Closes a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor that needs to be closed.
+#[inline]
+pub unsafe fn fd_close(fd_: fd) -> errno {
+ cloudabi_sys_fd_close(fd_)
+}
+
+/// Creates a file descriptor.
+///
+/// ## Parameters
+///
+/// **type**:
+/// Possible values:
+///
+/// - [`SHARED_MEMORY`](enum.filetype.html#variant.SHARED_MEMORY):
+/// Creates an anonymous shared memory
+/// object.
+///
+/// **fd**:
+/// The file descriptor that has been created.
+#[inline]
+pub unsafe fn fd_create1(type_: filetype, fd_: &mut fd) -> errno {
+ cloudabi_sys_fd_create1(type_, fd_)
+}
+
+/// Creates a pair of file descriptors.
+///
+/// ## Parameters
+///
+/// **type**:
+/// Possible values:
+///
+/// - [`SOCKET_DGRAM`](enum.filetype.html#variant.SOCKET_DGRAM):
+/// Creates a UNIX datagram socket pair.
+/// - [`SOCKET_STREAM`](enum.filetype.html#variant.SOCKET_STREAM):
+/// Creates a UNIX byte-stream socket
+/// pair.
+///
+/// **fd1**:
+/// The first file descriptor of the pair.
+///
+/// **fd2**:
+/// The second file descriptor of the pair.
+#[inline]
+pub unsafe fn fd_create2(type_: filetype, fd1_: &mut fd, fd2_: &mut fd) -> errno {
+ cloudabi_sys_fd_create2(type_, fd1_, fd2_)
+}
+
+/// Synchronizes the data of a file to disk.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor of the file whose data
+/// needs to be synchronized to disk.
+#[inline]
+pub unsafe fn fd_datasync(fd_: fd) -> errno {
+ cloudabi_sys_fd_datasync(fd_)
+}
+
+/// Duplicates a file descriptor.
+///
+/// ## Parameters
+///
+/// **from**:
+/// The file descriptor that needs to be
+/// duplicated.
+///
+/// **fd**:
+/// The new file descriptor.
+#[inline]
+pub unsafe fn fd_dup(from_: fd, fd_: &mut fd) -> errno {
+ cloudabi_sys_fd_dup(from_, fd_)
+}
+
+/// Reads from a file descriptor, without using and updating the
+/// file descriptor's offset.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor from which data should be
+/// read.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be stored.
+///
+/// **offset**:
+/// The offset within the file at which reading
+/// should start.
+///
+/// **nread**:
+/// The number of bytes read.
+#[inline]
+pub unsafe fn fd_pread(fd_: fd, iovs_: &[iovec], offset_: filesize, nread_: &mut usize) -> errno {
+ cloudabi_sys_fd_pread(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nread_)
+}
+
+/// Writes to a file descriptor, without using and updating the
+/// file descriptor's offset.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor to which data should be
+/// written.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be retrieved.
+///
+/// **offset**:
+/// The offset within the file at which writing
+/// should start.
+///
+/// **nwritten**:
+/// The number of bytes written.
+#[inline]
+pub unsafe fn fd_pwrite(fd_: fd, iovs_: &[ciovec], offset_: filesize, nwritten_: &mut usize) -> errno {
+ cloudabi_sys_fd_pwrite(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nwritten_)
+}
+
+/// Reads from a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor from which data should be
+/// read.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be stored.
+///
+/// **nread**:
+/// The number of bytes read.
+#[inline]
+pub unsafe fn fd_read(fd_: fd, iovs_: &[iovec], nread_: &mut usize) -> errno {
+ cloudabi_sys_fd_read(fd_, iovs_.as_ptr(), iovs_.len(), nread_)
+}
+
+/// Atomically replaces a file descriptor by a copy of another
+/// file descriptor.
+///
+/// Due to the strong focus on thread safety, this environment
+/// does not provide a mechanism to duplicate a file descriptor to
+/// an arbitrary number, like dup2(). This would be prone to race
+/// conditions, as an actual file descriptor with the same number
+/// could be allocated by a different thread at the same time.
+///
+/// This system call provides a way to atomically replace file
+/// descriptors, which would disappear if dup2() were to be
+/// removed entirely.
+///
+/// ## Parameters
+///
+/// **from**:
+/// The file descriptor that needs to be copied.
+///
+/// **to**:
+/// The file descriptor that needs to be
+/// overwritten.
+#[inline]
+pub unsafe fn fd_replace(from_: fd, to_: fd) -> errno {
+ cloudabi_sys_fd_replace(from_, to_)
+}
+
+/// Moves the offset of the file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose offset has to be
+/// moved.
+///
+/// **offset**:
+/// The number of bytes to move.
+///
+/// **whence**:
+/// Relative to which position the move should
+/// take place.
+///
+/// **newoffset**:
+/// The new offset of the file descriptor,
+/// relative to the start of the file.
+#[inline]
+pub unsafe fn fd_seek(fd_: fd, offset_: filedelta, whence_: whence, newoffset_: &mut filesize) -> errno {
+ cloudabi_sys_fd_seek(fd_, offset_, whence_, newoffset_)
+}
+
+/// Gets attributes of a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be obtained.
+///
+/// **buf**:
+/// The buffer where the file descriptor's
+/// attributes are stored.
+#[inline]
+pub unsafe fn fd_stat_get(fd_: fd, buf_: *mut fdstat) -> errno {
+ cloudabi_sys_fd_stat_get(fd_, buf_)
+}
+
+/// Adjusts attributes of a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be adjusted.
+///
+/// **buf**:
+/// The desired values of the file descriptor
+/// attributes that are adjusted.
+///
+/// **flags**:
+/// A bitmask indicating which attributes have to
+/// be adjusted.
+#[inline]
+pub unsafe fn fd_stat_put(fd_: fd, buf_: *const fdstat, flags_: fdsflags) -> errno {
+ cloudabi_sys_fd_stat_put(fd_, buf_, flags_)
+}
+
+/// Synchronizes the data and metadata of a file to disk.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor of the file whose data
+/// and metadata needs to be synchronized to disk.
+#[inline]
+pub unsafe fn fd_sync(fd_: fd) -> errno {
+ cloudabi_sys_fd_sync(fd_)
+}
+
+/// Writes to a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor to which data should be
+/// written.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be retrieved.
+///
+/// **nwritten**:
+/// The number of bytes written.
+#[inline]
+pub unsafe fn fd_write(fd_: fd, iovs_: &[ciovec], nwritten_: &mut usize) -> errno {
+ cloudabi_sys_fd_write(fd_, iovs_.as_ptr(), iovs_.len(), nwritten_)
+}
+
+/// Provides file advisory information on a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor for which to provide file
+/// advisory information.
+///
+/// **offset**:
+/// The offset within the file to which the
+/// advisory applies.
+///
+/// **len**:
+/// The length of the region to which the advisory
+/// applies.
+///
+/// **advice**:
+/// The advice.
+#[inline]
+pub unsafe fn file_advise(fd_: fd, offset_: filesize, len_: filesize, advice_: advice) -> errno {
+ cloudabi_sys_file_advise(fd_, offset_, len_, advice_)
+}
+
+/// Forces the allocation of space in a file.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file in which the space should be
+/// allocated.
+///
+/// **offset**:
+/// The offset at which the allocation should
+/// start.
+///
+/// **len**:
+/// The length of the area that is allocated.
+#[inline]
+pub unsafe fn file_allocate(fd_: fd, offset_: filesize, len_: filesize) -> errno {
+ cloudabi_sys_file_allocate(fd_, offset_, len_)
+}
+
+/// Creates a file of a specified type.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the file to be created starts.
+///
+/// **path**:
+/// The path at which the file should be created.
+///
+/// **type**:
+/// Possible values:
+///
+/// - [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY):
+/// Creates a directory.
+#[inline]
+pub unsafe fn file_create(fd_: fd, path_: &[u8], type_: filetype) -> errno {
+ cloudabi_sys_file_create(fd_, path_.as_ptr(), path_.len(), type_)
+}
+
+/// Creates a hard link.
+///
+/// ## Parameters
+///
+/// **fd1**:
+/// The working directory at which the resolution
+/// of the source path starts.
+///
+/// **path1**:
+/// The source path of the file that should be
+/// hard linked.
+///
+/// **fd2**:
+/// The working directory at which the resolution
+/// of the destination path starts.
+///
+/// **path2**:
+/// The destination path at which the hard link
+/// should be created.
+#[inline]
+pub unsafe fn file_link(fd1_: lookup, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
+ cloudabi_sys_file_link(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len())
+}
+
+/// Opens a file.
+///
+/// ## Parameters
+///
+/// **dirfd**:
+/// The working directory at which the resolution
+/// of the file to be opened starts.
+///
+/// **path**:
+/// The path of the file that should be opened.
+///
+/// **oflags**:
+/// The method at which the file should be opened.
+///
+/// **fds**:
+/// [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
+/// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting) specify the
+/// initial rights of the newly created file
+/// descriptor. The operating system is allowed to
+/// return a file descriptor with fewer rights
+/// than specified, if and only if those rights do
+/// not apply to the type of file being opened.
+///
+/// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags) specifies the initial flags
+/// of the file descriptor.
+///
+/// [`fdstat.fs_filetype`](struct.fdstat.html#structfield.fs_filetype) is ignored.
+///
+/// **fd**:
+/// The file descriptor of the file that has been
+/// opened.
+#[inline]
+pub unsafe fn file_open(dirfd_: lookup, path_: &[u8], oflags_: oflags, fds_: *const fdstat, fd_: &mut fd) -> errno {
+ cloudabi_sys_file_open(dirfd_, path_.as_ptr(), path_.len(), oflags_, fds_, fd_)
+}
+
+/// Reads directory entries from a directory.
+///
+/// When successful, the contents of the output buffer consist of
+/// a sequence of directory entries. Each directory entry consists
+/// of a [`dirent`](struct.dirent.html) object, followed by [`dirent.d_namlen`](struct.dirent.html#structfield.d_namlen) bytes
+/// holding the name of the directory entry.
+///
+/// This system call fills the output buffer as much as possible,
+/// potentially truncating the last directory entry. This allows
+/// the caller to grow its read buffer size in case it's too small
+/// to fit a single large directory entry, or skip the oversized
+/// directory entry.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The directory from which to read the directory
+/// entries.
+///
+/// **buf**:
+/// The buffer where directory entries are stored.
+///
+/// **cookie**:
+/// The location within the directory to start
+/// reading.
+///
+/// **bufused**:
+/// The number of bytes stored in the read buffer.
+/// If less than the size of the read buffer, the
+/// end of the directory has been reached.
+#[inline]
+pub unsafe fn file_readdir(fd_: fd, buf_: &mut [u8], cookie_: dircookie, bufused_: &mut usize) -> errno {
+ cloudabi_sys_file_readdir(fd_, buf_.as_mut_ptr() as *mut (), buf_.len(), cookie_, bufused_)
+}
+
+/// Reads the contents of a symbolic link.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path of the symbolic starts.
+///
+/// **path**:
+/// The path of the symbolic link whose contents
+/// should be read.
+///
+/// **buf**:
+/// The buffer where the contents of the symbolic
+/// link should be stored.
+///
+/// **bufused**:
+/// The number of bytes placed in the buffer.
+#[inline]
+pub unsafe fn file_readlink(fd_: fd, path_: &[u8], buf_: &mut [u8], bufused_: &mut usize) -> errno {
+ cloudabi_sys_file_readlink(fd_, path_.as_ptr(), path_.len(), buf_.as_mut_ptr(), buf_.len(), bufused_)
+}
+
+/// Renames a file.
+///
+/// ## Parameters
+///
+/// **fd1**:
+/// The working directory at which the resolution
+/// of the source path starts.
+///
+/// **path1**:
+/// The source path of the file that should be
+/// renamed.
+///
+/// **fd2**:
+/// The working directory at which the resolution
+/// of the destination path starts.
+///
+/// **path2**:
+/// The destination path to which the file should
+/// be renamed.
+#[inline]
+pub unsafe fn file_rename(fd1_: fd, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
+ cloudabi_sys_file_rename(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len())
+}
+
+/// Gets attributes of a file by file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be obtained.
+///
+/// **buf**:
+/// The buffer where the file's attributes are
+/// stored.
+#[inline]
+pub unsafe fn file_stat_fget(fd_: fd, buf_: *mut filestat) -> errno {
+ cloudabi_sys_file_stat_fget(fd_, buf_)
+}
+
+/// Adjusts attributes of a file by file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be adjusted.
+///
+/// **buf**:
+/// The desired values of the file attributes that
+/// are adjusted.
+///
+/// **flags**:
+/// A bitmask indicating which attributes have to
+/// be adjusted.
+#[inline]
+pub unsafe fn file_stat_fput(fd_: fd, buf_: *const filestat, flags_: fsflags) -> errno {
+ cloudabi_sys_file_stat_fput(fd_, buf_, flags_)
+}
+
+/// Gets attributes of a file by path.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path whose attributes have to be
+/// obtained starts.
+///
+/// **path**:
+/// The path of the file whose attributes have to
+/// be obtained.
+///
+/// **buf**:
+/// The buffer where the file's attributes are
+/// stored.
+#[inline]
+pub unsafe fn file_stat_get(fd_: lookup, path_: &[u8], buf_: *mut filestat) -> errno {
+ cloudabi_sys_file_stat_get(fd_, path_.as_ptr(), path_.len(), buf_)
+}
+
+/// Adjusts attributes of a file by path.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path whose attributes have to be
+/// adjusted starts.
+///
+/// **path**:
+/// The path of the file whose attributes have to
+/// be adjusted.
+///
+/// **buf**:
+/// The desired values of the file attributes that
+/// are adjusted.
+///
+/// **flags**:
+/// A bitmask indicating which attributes have to
+/// be adjusted.
+#[inline]
+pub unsafe fn file_stat_put(fd_: lookup, path_: &[u8], buf_: *const filestat, flags_: fsflags) -> errno {
+ cloudabi_sys_file_stat_put(fd_, path_.as_ptr(), path_.len(), buf_, flags_)
+}
+
+/// Creates a symbolic link.
+///
+/// ## Parameters
+///
+/// **path1**:
+/// The contents of the symbolic link.
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the destination path starts.
+///
+/// **path2**:
+/// The destination path at which the symbolic
+/// link should be created.
+#[inline]
+pub unsafe fn file_symlink(path1_: &[u8], fd_: fd, path2_: &[u8]) -> errno {
+ cloudabi_sys_file_symlink(path1_.as_ptr(), path1_.len(), fd_, path2_.as_ptr(), path2_.len())
+}
+
+/// Unlinks a file, or removes a directory.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path starts.
+///
+/// **path**:
+/// The path that needs to be unlinked or removed.
+///
+/// **flags**:
+/// Possible values:
+///
+/// - [`REMOVEDIR`](struct.ulflags.html#associatedconstant.REMOVEDIR):
+/// If set, attempt to remove a directory.
+/// Otherwise, unlink a file.
+#[inline]
+pub unsafe fn file_unlink(fd_: fd, path_: &[u8], flags_: ulflags) -> errno {
+ cloudabi_sys_file_unlink(fd_, path_.as_ptr(), path_.len(), flags_)
+}
+
+/// Unlocks a write-locked userspace lock.
+///
+/// If a userspace lock is unlocked while having its
+/// [`LOCK_KERNEL_MANAGED`](constant.LOCK_KERNEL_MANAGED.html) flag set, the lock cannot be unlocked in
+/// userspace directly. This system call needs to be performed
+/// instead, so that any waiting threads can be woken up.
+///
+/// To prevent spurious invocations of this system call, the lock
+/// must be locked for writing. This prevents other threads from
+/// acquiring additional read locks while the system call is in
+/// progress. If the lock is acquired for reading, it must first
+/// be upgraded to a write lock.
+///
+/// ## Parameters
+///
+/// **lock**:
+/// The userspace lock that is locked for writing
+/// by the calling thread.
+///
+/// **scope**:
+/// Whether the lock is stored in private or
+/// shared memory.
+#[inline]
+pub unsafe fn lock_unlock(lock_: *mut lock, scope_: scope) -> errno {
+ cloudabi_sys_lock_unlock(lock_, scope_)
+}
+
+/// Provides memory advisory information on a region of memory.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages for which to provide memory advisory
+/// information.
+///
+/// **advice**:
+/// The advice.
+#[inline]
+pub unsafe fn mem_advise(mapping_: &mut [u8], advice_: advice) -> errno {
+ cloudabi_sys_mem_advise(mapping_.as_mut_ptr() as *mut (), mapping_.len(), advice_)
+}
+
+/// Creates a memory mapping, making the contents of a file
+/// accessible through memory.
+///
+/// ## Parameters
+///
+/// **addr**:
+/// If [`FIXED`](struct.mflags.html#associatedconstant.FIXED) is set, specifies to which
+/// address the file region is mapped. Otherwise,
+/// the mapping is performed at an unused
+/// location.
+///
+/// **len**:
+/// The length of the memory mapping to be
+/// created.
+///
+/// **prot**:
+/// Initial memory protection options for the
+/// memory mapping.
+///
+/// **flags**:
+/// Memory mapping flags.
+///
+/// **fd**:
+/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
+/// [`MAP_ANON_FD`](constant.MAP_ANON_FD.html). Otherwise, this argument
+/// specifies the file whose contents need to be
+/// mapped.
+///
+/// **off**:
+/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
+/// zero. Otherwise, this argument specifies the
+/// offset within the file at which the mapping
+/// starts.
+///
+/// **mem**:
+/// The starting address of the memory mapping.
+#[inline]
+pub unsafe fn mem_map(addr_: *mut (), len_: usize, prot_: mprot, flags_: mflags, fd_: fd, off_: filesize, mem_: &mut *mut ()) -> errno {
+ cloudabi_sys_mem_map(addr_, len_, prot_, flags_, fd_, off_, mem_)
+}
+
+/// Change the protection of a memory mapping.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages that need their protection changed.
+///
+/// **prot**:
+/// New protection options.
+#[inline]
+pub unsafe fn mem_protect(mapping_: &mut [u8], prot_: mprot) -> errno {
+ cloudabi_sys_mem_protect(mapping_.as_mut_ptr() as *mut (), mapping_.len(), prot_)
+}
+
+/// Synchronize a region of memory with its physical storage.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages that need to be synchronized.
+///
+/// **flags**:
+/// The method of synchronization.
+#[inline]
+pub unsafe fn mem_sync(mapping_: &mut [u8], flags_: msflags) -> errno {
+ cloudabi_sys_mem_sync(mapping_.as_mut_ptr() as *mut (), mapping_.len(), flags_)
+}
+
+/// Unmaps a region of memory.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages that needs to be unmapped.
+#[inline]
+pub unsafe fn mem_unmap(mapping_: &mut [u8]) -> errno {
+ cloudabi_sys_mem_unmap(mapping_.as_mut_ptr() as *mut (), mapping_.len())
+}
+
+/// Concurrently polls for the occurrence of a set of events.
+///
+/// ## Parameters
+///
+/// **in**:
+/// The events to which to subscribe.
+///
+/// **out**:
+/// The events that have occurred.
+///
+/// **nsubscriptions**:
+/// Both the number of subscriptions and events.
+///
+/// **nevents**:
+/// The number of events stored.
+#[inline]
+pub unsafe fn poll(in_: *const subscription, out_: *mut event, nsubscriptions_: usize, nevents_: &mut usize) -> errno {
+ cloudabi_sys_poll(in_, out_, nsubscriptions_, nevents_)
+}
+
+/// Replaces the process by a new executable.
+///
+/// Process execution in CloudABI differs from POSIX in two ways:
+/// handling of arguments and inheritance of file descriptors.
+///
+/// CloudABI does not use string command line arguments. Instead,
+/// a buffer with binary data is copied into the address space of
+/// the new executable. The kernel does not enforce any specific
+/// structure to this data, although CloudABI's C library uses it
+/// to store a tree structure that is semantically identical to
+/// YAML.
+///
+/// Due to the strong focus on thread safety, file descriptors
+/// aren't inherited through close-on-exec flags. An explicit
+/// list of file descriptors that need to be retained needs to be
+/// provided. After execution, file descriptors are placed in the
+/// order in which they are stored in the array. This not only
+/// makes the execution process deterministic. It also prevents
+/// potential information disclosures about the layout of the
+/// original process.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// A file descriptor of the new executable.
+///
+/// **data**:
+/// Binary argument data that is passed on to the
+/// new executable.
+///
+/// **fds**:
+/// The layout of the file descriptor table after
+/// execution.
+#[inline]
+pub unsafe fn proc_exec(fd_: fd, data_: &[u8], fds_: &[fd]) -> errno {
+ cloudabi_sys_proc_exec(fd_, data_.as_ptr() as *const (), data_.len(), fds_.as_ptr(), fds_.len())
+}
+
+/// Terminates the process normally.
+///
+/// ## Parameters
+///
+/// **rval**:
+/// The exit code returned by the process. The
+/// exit code can be obtained by other processes
+/// through [`event.union.proc_terminate.exitcode`](struct.event_proc_terminate.html#structfield.exitcode).
+#[inline]
+pub unsafe fn proc_exit(rval_: exitcode) -> ! {
+ cloudabi_sys_proc_exit(rval_)
+}
+
+/// Forks the process of the calling thread.
+///
+/// After forking, a new process shall be created, having only a
+/// copy of the calling thread. The parent process will obtain a
+/// process descriptor. When closed, the child process is
+/// automatically signaled with [`KILL`](enum.signal.html#variant.KILL).
+///
+/// ## Parameters
+///
+/// **fd**:
+/// In the parent process: the file descriptor
+/// number of the process descriptor.
+///
+/// In the child process: [`PROCESS_CHILD`](constant.PROCESS_CHILD.html).
+///
+/// **tid**:
+/// In the parent process: undefined.
+///
+/// In the child process: the thread ID of the
+/// initial thread of the child process.
+#[inline]
+pub unsafe fn proc_fork(fd_: &mut fd, tid_: &mut tid) -> errno {
+ cloudabi_sys_proc_fork(fd_, tid_)
+}
+
+/// Sends a signal to the process of the calling thread.
+///
+/// ## Parameters
+///
+/// **sig**:
+/// The signal condition that should be triggered.
+/// If the signal causes the process to terminate,
+/// its condition can be obtained by other
+/// processes through
+/// [`event.union.proc_terminate.signal`](struct.event_proc_terminate.html#structfield.signal).
+#[inline]
+pub unsafe fn proc_raise(sig_: signal) -> errno {
+ cloudabi_sys_proc_raise(sig_)
+}
+
+/// Obtains random data from the kernel random number generator.
+///
+/// As this interface is not guaranteed to be fast, it is advised
+/// that the random data obtained through this system call is used
+/// as the seed for a userspace pseudo-random number generator.
+///
+/// ## Parameters
+///
+/// **buf**:
+/// The buffer that needs to be filled with random
+/// data.
+#[inline]
+pub unsafe fn random_get(buf_: &mut [u8]) -> errno {
+ cloudabi_sys_random_get(buf_.as_mut_ptr() as *mut (), buf_.len())
+}
+
+/// Receives a message on a socket.
+///
+/// ## Parameters
+///
+/// **sock**:
+/// The socket on which a message should be
+/// received.
+///
+/// **in**:
+/// Input parameters.
+///
+/// **out**:
+/// Output parameters.
+#[inline]
+pub unsafe fn sock_recv(sock_: fd, in_: *const recv_in, out_: *mut recv_out) -> errno {
+ cloudabi_sys_sock_recv(sock_, in_, out_)
+}
+
+/// Sends a message on a socket.
+///
+/// ## Parameters
+///
+/// **sock**:
+/// The socket on which a message should be sent.
+///
+/// **in**:
+/// Input parameters.
+///
+/// **out**:
+/// Output parameters.
+#[inline]
+pub unsafe fn sock_send(sock_: fd, in_: *const send_in, out_: *mut send_out) -> errno {
+ cloudabi_sys_sock_send(sock_, in_, out_)
+}
+
+/// Shuts down socket send and receive channels.
+///
+/// ## Parameters
+///
+/// **sock**:
+/// The socket that needs its channels shut down.
+///
+/// **how**:
+/// Which channels on the socket need to be shut
+/// down.
+#[inline]
+pub unsafe fn sock_shutdown(sock_: fd, how_: sdflags) -> errno {
+ cloudabi_sys_sock_shutdown(sock_, how_)
+}
+
+/// Creates a new thread within the current process.
+///
+/// ## Parameters
+///
+/// **attr**:
+/// The desired attributes of the new thread.
+///
+/// **tid**:
+/// The thread ID of the new thread.
+#[inline]
+pub unsafe fn thread_create(attr_: *mut threadattr, tid_: &mut tid) -> errno {
+ cloudabi_sys_thread_create(attr_, tid_)
+}
+
+/// Terminates the calling thread.
+///
+/// This system call can also unlock a single userspace lock
+/// after termination, which can be used to implement thread
+/// joining.
+///
+/// ## Parameters
+///
+/// **lock**:
+/// Userspace lock that is locked for writing by
+/// the calling thread.
+///
+/// **scope**:
+/// Whether the lock is stored in private or
+/// shared memory.
+#[inline]
+pub unsafe fn thread_exit(lock_: *mut lock, scope_: scope) -> ! {
+ cloudabi_sys_thread_exit(lock_, scope_)
+}
+
+/// Temporarily yields execution of the calling thread.
+#[inline]
+pub unsafe fn thread_yield() -> errno {
+ cloudabi_sys_thread_yield()
+}
--- /dev/null
+// Copyright 2018 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.
+
+#[allow(warnings)]
+mod cloudabi;
+pub use self::cloudabi::*;
--- /dev/null
+// Copyright 2018 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 use sys::cloudabi::shims::args::*;
+
+#[allow(dead_code)]
+pub fn init(_: isize, _: *const *const u8) {}
+
+#[allow(dead_code)]
+pub fn cleanup() {}
--- /dev/null
+// Copyright 2014-2018 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 error::Error;
+use ffi::CStr;
+use intrinsics;
+use io;
+use libc;
+use sys_common::backtrace::Frame;
+use unwind as uw;
+
+pub struct BacktraceContext;
+
+struct Context<'a> {
+ idx: usize,
+ frames: &'a mut [Frame],
+}
+
+#[derive(Debug)]
+struct UnwindError(uw::_Unwind_Reason_Code);
+
+impl Error for UnwindError {
+ fn description(&self) -> &'static str {
+ "unexpected return value while unwinding"
+ }
+}
+
+impl ::fmt::Display for UnwindError {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ write!(f, "{}: {:?}", self.description(), self.0)
+ }
+}
+
+#[inline(never)] // if we know this is a function call, we can skip it when
+ // tracing
+pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
+ let mut cx = Context { idx: 0, frames };
+ let result_unwind =
+ unsafe { uw::_Unwind_Backtrace(trace_fn, &mut cx as *mut Context as *mut libc::c_void) };
+ // See libunwind:src/unwind/Backtrace.c for the return values.
+ // No, there is no doc.
+ match result_unwind {
+ // These return codes seem to be benign and need to be ignored for backtraces
+ // to show up properly on all tested platforms.
+ uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
+ Ok((cx.idx, BacktraceContext))
+ }
+ _ => Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnwindError(result_unwind),
+ )),
+ }
+}
+
+extern "C" fn trace_fn(
+ ctx: *mut uw::_Unwind_Context,
+ arg: *mut libc::c_void,
+) -> uw::_Unwind_Reason_Code {
+ let cx = unsafe { &mut *(arg as *mut Context) };
+ let mut ip_before_insn = 0;
+ let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void };
+ if !ip.is_null() && ip_before_insn == 0 {
+ // this is a non-signaling frame, so `ip` refers to the address
+ // after the calling instruction. account for that.
+ ip = (ip as usize - 1) as *mut _;
+ }
+
+ let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) };
+ if cx.idx < cx.frames.len() {
+ cx.frames[cx.idx] = Frame {
+ symbol_addr: symaddr as *mut u8,
+ exact_position: ip as *mut u8,
+ };
+ cx.idx += 1;
+ }
+
+ uw::_URC_NO_REASON
+}
+
+pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool>
+where
+ F: FnMut(&[u8], u32) -> io::Result<()>,
+{
+ // No way to obtain this information on CloudABI.
+ Ok(false)
+}
+
+pub fn resolve_symname<F>(frame: Frame, callback: F, _: &BacktraceContext) -> io::Result<()>
+where
+ F: FnOnce(Option<&str>) -> io::Result<()>,
+{
+ unsafe {
+ let mut info: Dl_info = intrinsics::init();
+ let symname =
+ if dladdr(frame.exact_position as *mut _, &mut info) == 0 || info.dli_sname.is_null() {
+ None
+ } else {
+ CStr::from_ptr(info.dli_sname).to_str().ok()
+ };
+ callback(symname)
+ }
+}
+
+#[repr(C)]
+struct Dl_info {
+ dli_fname: *const libc::c_char,
+ dli_fbase: *mut libc::c_void,
+ dli_sname: *const libc::c_char,
+ dli_saddr: *mut libc::c_void,
+}
+
+extern "C" {
+ fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int;
+}
--- /dev/null
+// Copyright 2018 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 cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+use sys::mutex::{self, Mutex};
+use sys::time::dur2intervals;
+use time::Duration;
+
+extern "C" {
+ #[thread_local]
+ static __pthread_thread_id: abi::tid;
+}
+
+pub struct Condvar {
+ condvar: UnsafeCell<AtomicU32>,
+}
+
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
+impl Condvar {
+ pub const fn new() -> Condvar {
+ Condvar {
+ condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
+ }
+ }
+
+ pub unsafe fn init(&mut self) {}
+
+ pub unsafe fn notify_one(&self) {
+ let condvar = self.condvar.get();
+ if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+ let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
+ assert_eq!(
+ ret,
+ abi::errno::SUCCESS,
+ "Failed to signal on condition variable"
+ );
+ }
+ }
+
+ pub unsafe fn notify_all(&self) {
+ let condvar = self.condvar.get();
+ if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+ let ret = abi::condvar_signal(
+ condvar as *mut abi::condvar,
+ abi::scope::PRIVATE,
+ abi::nthreads::max_value(),
+ );
+ assert_eq!(
+ ret,
+ abi::errno::SUCCESS,
+ "Failed to broadcast on condition variable"
+ );
+ }
+ }
+
+ pub unsafe fn wait(&self, mutex: &Mutex) {
+ let mutex = mutex::raw(mutex);
+ assert_eq!(
+ (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "This lock is not write-locked by this thread"
+ );
+
+ // Call into the kernel to wait on the condition variable.
+ let condvar = self.condvar.get();
+ let subscription = abi::subscription {
+ type_: abi::eventtype::CONDVAR,
+ union: abi::subscription_union {
+ condvar: abi::subscription_condvar {
+ condvar: condvar as *mut abi::condvar,
+ condvar_scope: abi::scope::PRIVATE,
+ lock: mutex as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(
+ ret,
+ abi::errno::SUCCESS,
+ "Failed to wait on condition variable"
+ );
+ assert_eq!(
+ event.error,
+ abi::errno::SUCCESS,
+ "Failed to wait on condition variable"
+ );
+ }
+
+ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+ let mutex = mutex::raw(mutex);
+ assert_eq!(
+ (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "This lock is not write-locked by this thread"
+ );
+
+ // Call into the kernel to wait on the condition variable.
+ let condvar = self.condvar.get();
+ let subscriptions = [
+ abi::subscription {
+ type_: abi::eventtype::CONDVAR,
+ union: abi::subscription_union {
+ condvar: abi::subscription_condvar {
+ condvar: condvar as *mut abi::condvar,
+ condvar_scope: abi::scope::PRIVATE,
+ lock: mutex as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ },
+ abi::subscription {
+ type_: abi::eventtype::CLOCK,
+ union: abi::subscription_union {
+ clock: abi::subscription_clock {
+ clock_id: abi::clockid::MONOTONIC,
+ timeout: dur2intervals(&dur),
+ ..mem::zeroed()
+ },
+ },
+ ..mem::zeroed()
+ },
+ ];
+ let mut events: [abi::event; 2] = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents);
+ assert_eq!(
+ ret,
+ abi::errno::SUCCESS,
+ "Failed to wait on condition variable"
+ );
+ for i in 0..nevents {
+ assert_eq!(
+ events[i].error,
+ abi::errno::SUCCESS,
+ "Failed to wait on condition variable"
+ );
+ if events[i].type_ == abi::eventtype::CONDVAR {
+ return true;
+ }
+ }
+ false
+ }
+
+ pub unsafe fn destroy(&self) {
+ let condvar = self.condvar.get();
+ assert_eq!(
+ (*condvar).load(Ordering::Relaxed),
+ abi::CONDVAR_HAS_NO_WAITERS.0,
+ "Attempted to destroy a condition variable with blocked threads"
+ );
+ }
+}
--- /dev/null
+// Copyright 2018 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 io;
+use libc;
+use mem;
+
+pub mod args;
+#[cfg(feature = "backtrace")]
+pub mod backtrace;
+#[path = "../unix/cmath.rs"]
+pub mod cmath;
+pub mod condvar;
+#[path = "../unix/memchr.rs"]
+pub mod memchr;
+pub mod mutex;
+pub mod os;
+#[path = "../unix/os_str.rs"]
+pub mod os_str;
+pub mod rwlock;
+pub mod stack_overflow;
+pub mod stdio;
+pub mod thread;
+#[path = "../unix/thread_local.rs"]
+pub mod thread_local;
+pub mod time;
+
+mod abi;
+
+mod shims;
+pub use self::shims::*;
+
+#[allow(dead_code)]
+pub fn init() {}
+
+pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
+ match errno {
+ x if x == abi::errno::ACCES as i32 => io::ErrorKind::PermissionDenied,
+ x if x == abi::errno::ADDRINUSE as i32 => io::ErrorKind::AddrInUse,
+ x if x == abi::errno::ADDRNOTAVAIL as i32 => io::ErrorKind::AddrNotAvailable,
+ x if x == abi::errno::AGAIN as i32 => io::ErrorKind::WouldBlock,
+ x if x == abi::errno::CONNABORTED as i32 => io::ErrorKind::ConnectionAborted,
+ x if x == abi::errno::CONNREFUSED as i32 => io::ErrorKind::ConnectionRefused,
+ x if x == abi::errno::CONNRESET as i32 => io::ErrorKind::ConnectionReset,
+ x if x == abi::errno::EXIST as i32 => io::ErrorKind::AlreadyExists,
+ x if x == abi::errno::INTR as i32 => io::ErrorKind::Interrupted,
+ x if x == abi::errno::INVAL as i32 => io::ErrorKind::InvalidInput,
+ x if x == abi::errno::NOENT as i32 => io::ErrorKind::NotFound,
+ x if x == abi::errno::NOTCONN as i32 => io::ErrorKind::NotConnected,
+ x if x == abi::errno::PERM as i32 => io::ErrorKind::PermissionDenied,
+ x if x == abi::errno::PIPE as i32 => io::ErrorKind::BrokenPipe,
+ x if x == abi::errno::TIMEDOUT as i32 => io::ErrorKind::TimedOut,
+ _ => io::ErrorKind::Other,
+ }
+}
+
+pub unsafe fn abort_internal() -> ! {
+ ::core::intrinsics::abort();
+}
+
+pub use libc::strlen;
+
+pub fn hashmap_random_keys() -> (u64, u64) {
+ unsafe {
+ let mut v = mem::uninitialized();
+ libc::arc4random_buf(&mut v as *mut _ as *mut libc::c_void, mem::size_of_val(&v));
+ v
+ }
+}
--- /dev/null
+// Copyright 2018 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 cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+use sys::rwlock::{self, RWLock};
+
+extern "C" {
+ #[thread_local]
+ static __pthread_thread_id: abi::tid;
+}
+
+// Implement Mutex using an RWLock. This doesn't introduce any
+// performance overhead in this environment, as the operations would be
+// implemented identically.
+pub struct Mutex(RWLock);
+
+pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 {
+ rwlock::raw(&m.0)
+}
+
+impl Mutex {
+ pub const fn new() -> Mutex {
+ Mutex(RWLock::new())
+ }
+
+ pub unsafe fn init(&mut self) {
+ // This function should normally reinitialize the mutex after
+ // moving it to a different memory address. This implementation
+ // does not require adjustments after moving.
+ }
+
+ pub unsafe fn try_lock(&self) -> bool {
+ self.0.try_write()
+ }
+
+ pub unsafe fn lock(&self) {
+ self.0.write()
+ }
+
+ pub unsafe fn unlock(&self) {
+ self.0.write_unlock()
+ }
+
+ pub unsafe fn destroy(&self) {
+ self.0.destroy()
+ }
+}
+
+pub struct ReentrantMutex {
+ lock: UnsafeCell<AtomicU32>,
+ recursion: UnsafeCell<u32>,
+}
+
+impl ReentrantMutex {
+ pub unsafe fn uninitialized() -> ReentrantMutex {
+ mem::uninitialized()
+ }
+
+ pub unsafe fn init(&mut self) {
+ self.lock = UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0));
+ self.recursion = UnsafeCell::new(0);
+ }
+
+ pub unsafe fn try_lock(&self) -> bool {
+ // Attempt to acquire the lock.
+ let lock = self.lock.get();
+ let recursion = self.recursion.get();
+ if let Err(old) = (*lock).compare_exchange(
+ abi::LOCK_UNLOCKED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ Ordering::Acquire,
+ Ordering::Relaxed,
+ ) {
+ // If we fail to acquire the lock, it may be the case
+ // that we've already acquired it and may need to recurse.
+ if old & !abi::LOCK_KERNEL_MANAGED.0 == __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 {
+ *recursion += 1;
+ true
+ } else {
+ false
+ }
+ } else {
+ // Success.
+ assert_eq!(*recursion, 0, "Mutex has invalid recursion count");
+ true
+ }
+ }
+
+ pub unsafe fn lock(&self) {
+ if !self.try_lock() {
+ // Call into the kernel to acquire a write lock.
+ let lock = self.lock.get();
+ let subscription = abi::subscription {
+ type_: abi::eventtype::LOCK_WRLOCK,
+ union: abi::subscription_union {
+ lock: abi::subscription_lock {
+ lock: lock as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex");
+ assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex");
+ }
+ }
+
+ pub unsafe fn unlock(&self) {
+ let lock = self.lock.get();
+ let recursion = self.recursion.get();
+ assert_eq!(
+ (*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "This mutex is locked by a different thread"
+ );
+
+ if *recursion > 0 {
+ *recursion -= 1;
+ } else if !(*lock)
+ .compare_exchange(
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ abi::LOCK_UNLOCKED.0,
+ Ordering::Release,
+ Ordering::Relaxed,
+ )
+ .is_ok()
+ {
+ // Lock is managed by kernelspace. Call into the kernel
+ // to unblock waiting threads.
+ let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
+ }
+ }
+
+ pub unsafe fn destroy(&self) {
+ let lock = self.lock.get();
+ let recursion = self.recursion.get();
+ assert_eq!(
+ (*lock).load(Ordering::Relaxed),
+ abi::LOCK_UNLOCKED.0,
+ "Attempted to destroy locked mutex"
+ );
+ assert_eq!(*recursion, 0, "Recursion counter invalid");
+ }
+}
--- /dev/null
+// Copyright 2018 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 ffi::CStr;
+use libc::{self, c_int};
+use str;
+
+pub use sys::cloudabi::shims::os::*;
+
+pub fn errno() -> i32 {
+ extern "C" {
+ #[thread_local]
+ static errno: c_int;
+ }
+
+ unsafe { errno as i32 }
+}
+
+/// Gets a detailed string description for the given error number.
+pub fn error_string(errno: i32) -> String {
+ // cloudlibc's strerror() is guaranteed to be thread-safe. There is
+ // thus no need to use strerror_r().
+ str::from_utf8(unsafe { CStr::from_ptr(libc::strerror(errno)) }.to_bytes())
+ .unwrap()
+ .to_owned()
+}
+
+pub fn exit(code: i32) -> ! {
+ unsafe { libc::exit(code as c_int) }
+}
--- /dev/null
+// Copyright 2018 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 cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+
+extern "C" {
+ #[thread_local]
+ static __pthread_thread_id: abi::tid;
+}
+
+#[thread_local]
+static mut RDLOCKS_ACQUIRED: u32 = 0;
+
+pub struct RWLock {
+ lock: UnsafeCell<AtomicU32>,
+}
+
+pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
+ r.lock.get()
+}
+
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
+impl RWLock {
+ pub const fn new() -> RWLock {
+ RWLock {
+ lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)),
+ }
+ }
+
+ pub unsafe fn try_read(&self) -> bool {
+ let lock = self.lock.get();
+ let mut old = abi::LOCK_UNLOCKED.0;
+ while let Err(cur) =
+ (*lock).compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
+ {
+ if (cur & abi::LOCK_WRLOCKED.0) != 0 {
+ // Another thread already has a write lock.
+ assert_ne!(
+ old & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "Attempted to acquire a read lock while holding a write lock"
+ );
+ return false;
+ } else if (old & abi::LOCK_KERNEL_MANAGED.0) != 0 && RDLOCKS_ACQUIRED == 0 {
+ // Lock has threads waiting for the lock. Only acquire
+ // the lock if we have already acquired read locks. In
+ // that case, it is justified to acquire this lock to
+ // prevent a deadlock.
+ return false;
+ }
+ old = cur;
+ }
+
+ RDLOCKS_ACQUIRED += 1;
+ true
+ }
+
+ pub unsafe fn read(&self) {
+ if !self.try_read() {
+ // Call into the kernel to acquire a read lock.
+ let lock = self.lock.get();
+ let subscription = abi::subscription {
+ type_: abi::eventtype::LOCK_RDLOCK,
+ union: abi::subscription_union {
+ lock: abi::subscription_lock {
+ lock: lock as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire read lock");
+ assert_eq!(
+ event.error,
+ abi::errno::SUCCESS,
+ "Failed to acquire read lock"
+ );
+
+ RDLOCKS_ACQUIRED += 1;
+ }
+ }
+
+ pub unsafe fn read_unlock(&self) {
+ // Perform a read unlock. We can do this in userspace, except when
+ // other threads are blocked and we are performing the last unlock.
+ // In that case, call into the kernel.
+ //
+ // Other threads may attempt to increment the read lock count,
+ // meaning that the call into the kernel could be spurious. To
+ // prevent this from happening, upgrade to a write lock first. This
+ // allows us to call into the kernel, having the guarantee that the
+ // lock value will not change in the meantime.
+ assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
+ let mut old = 1;
+ loop {
+ let lock = self.lock.get();
+ if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
+ // Last read lock while threads are waiting. Attempt to upgrade
+ // to a write lock before calling into the kernel to unlock.
+ if let Err(cur) = (*lock).compare_exchange_weak(
+ old,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
+ Ordering::Acquire,
+ Ordering::Relaxed,
+ ) {
+ old = cur;
+ } else {
+ // Call into the kernel to unlock.
+ let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
+ break;
+ }
+ } else {
+ // No threads waiting or not the last read lock. Just decrement
+ // the read lock count.
+ assert_ne!(
+ old & !abi::LOCK_KERNEL_MANAGED.0,
+ 0,
+ "This rwlock is not locked"
+ );
+ assert_eq!(
+ old & abi::LOCK_WRLOCKED.0,
+ 0,
+ "Attempted to read-unlock a write-locked rwlock"
+ );
+ if let Err(cur) = (*lock).compare_exchange_weak(
+ old,
+ old - 1,
+ Ordering::Acquire,
+ Ordering::Relaxed,
+ ) {
+ old = cur;
+ } else {
+ break;
+ }
+ }
+ }
+
+ RDLOCKS_ACQUIRED -= 1;
+ }
+
+ pub unsafe fn try_write(&self) -> bool {
+ // Attempt to acquire the lock.
+ let lock = self.lock.get();
+ if let Err(old) = (*lock).compare_exchange(
+ abi::LOCK_UNLOCKED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ Ordering::Acquire,
+ Ordering::Relaxed,
+ ) {
+ // Failure. Crash upon recursive acquisition.
+ assert_ne!(
+ old & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "Attempted to recursive write-lock a rwlock",
+ );
+ false
+ } else {
+ // Success.
+ true
+ }
+ }
+
+ pub unsafe fn write(&self) {
+ if !self.try_write() {
+ // Call into the kernel to acquire a write lock.
+ let lock = self.lock.get();
+ let subscription = abi::subscription {
+ type_: abi::eventtype::LOCK_WRLOCK,
+ union: abi::subscription_union {
+ lock: abi::subscription_lock {
+ lock: lock as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire write lock");
+ assert_eq!(
+ event.error,
+ abi::errno::SUCCESS,
+ "Failed to acquire write lock"
+ );
+ }
+ }
+
+ pub unsafe fn write_unlock(&self) {
+ let lock = self.lock.get();
+ assert_eq!(
+ (*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "This rwlock is not write-locked by this thread"
+ );
+
+ if !(*lock)
+ .compare_exchange(
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ abi::LOCK_UNLOCKED.0,
+ Ordering::Release,
+ Ordering::Relaxed,
+ )
+ .is_ok()
+ {
+ // Lock is managed by kernelspace. Call into the kernel
+ // to unblock waiting threads.
+ let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
+ }
+ }
+
+ pub unsafe fn destroy(&self) {
+ let lock = self.lock.get();
+ assert_eq!(
+ (*lock).load(Ordering::Relaxed),
+ abi::LOCK_UNLOCKED.0,
+ "Attempted to destroy locked rwlock"
+ );
+ }
+}
--- /dev/null
+// Copyright 2018 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 ffi::OsString;
+
+pub struct Args(());
+
+impl Args {
+ pub fn inner_debug(&self) -> &[OsString] {
+ &[]
+ }
+}
+
+impl Iterator for Args {
+ type Item = OsString;
+ fn next(&mut self) -> Option<OsString> {
+ None
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, Some(0))
+ }
+}
+
+impl ExactSizeIterator for Args {
+ fn len(&self) -> usize {
+ 0
+ }
+}
+
+impl DoubleEndedIterator for Args {
+ fn next_back(&mut self) -> Option<OsString> {
+ None
+ }
+}
+
+pub fn args() -> Args {
+ Args(())
+}
--- /dev/null
+// Copyright 2018 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 mod os {
+ pub const FAMILY: &'static str = "cloudabi";
+ pub const OS: &'static str = "cloudabi";
+ pub const DLL_PREFIX: &'static str = "lib";
+ pub const DLL_SUFFIX: &'static str = ".so";
+ pub const DLL_EXTENSION: &'static str = "so";
+ pub const EXE_SUFFIX: &'static str = "";
+ pub const EXE_EXTENSION: &'static str = "";
+}
--- /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 ffi::OsString;
+use fmt;
+use hash::{Hash, Hasher};
+use io::{self, SeekFrom};
+use path::{Path, PathBuf};
+use sys::time::SystemTime;
+use sys::{unsupported, Void};
+
+pub struct File(Void);
+
+pub struct FileAttr(Void);
+
+pub struct ReadDir(Void);
+
+pub struct DirEntry(Void);
+
+#[derive(Clone, Debug)]
+pub struct OpenOptions {}
+
+pub struct FilePermissions(Void);
+
+pub struct FileType(Void);
+
+#[derive(Debug)]
+pub struct DirBuilder {}
+
+impl FileAttr {
+ pub fn size(&self) -> u64 {
+ match self.0 {}
+ }
+
+ pub fn perm(&self) -> FilePermissions {
+ match self.0 {}
+ }
+
+ pub fn file_type(&self) -> FileType {
+ match self.0 {}
+ }
+
+ pub fn modified(&self) -> io::Result<SystemTime> {
+ match self.0 {}
+ }
+
+ pub fn accessed(&self) -> io::Result<SystemTime> {
+ match self.0 {}
+ }
+
+ pub fn created(&self) -> io::Result<SystemTime> {
+ match self.0 {}
+ }
+}
+
+impl Clone for FileAttr {
+ fn clone(&self) -> FileAttr {
+ match self.0 {}
+ }
+}
+
+impl FilePermissions {
+ pub fn readonly(&self) -> bool {
+ match self.0 {}
+ }
+
+ pub fn set_readonly(&mut self, _readonly: bool) {
+ match self.0 {}
+ }
+}
+
+impl Clone for FilePermissions {
+ fn clone(&self) -> FilePermissions {
+ match self.0 {}
+ }
+}
+
+impl PartialEq for FilePermissions {
+ fn eq(&self, _other: &FilePermissions) -> bool {
+ match self.0 {}
+ }
+}
+
+impl Eq for FilePermissions {}
+
+impl fmt::Debug for FilePermissions {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+impl FileType {
+ pub fn is_dir(&self) -> bool {
+ match self.0 {}
+ }
+
+ pub fn is_file(&self) -> bool {
+ match self.0 {}
+ }
+
+ pub fn is_symlink(&self) -> bool {
+ match self.0 {}
+ }
+}
+
+impl Clone for FileType {
+ fn clone(&self) -> FileType {
+ match self.0 {}
+ }
+}
+
+impl Copy for FileType {}
+
+impl PartialEq for FileType {
+ fn eq(&self, _other: &FileType) -> bool {
+ match self.0 {}
+ }
+}
+
+impl Eq for FileType {}
+
+impl Hash for FileType {
+ fn hash<H: Hasher>(&self, _h: &mut H) {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for FileType {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for ReadDir {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+impl Iterator for ReadDir {
+ type Item = io::Result<DirEntry>;
+
+ fn next(&mut self) -> Option<io::Result<DirEntry>> {
+ match self.0 {}
+ }
+}
+
+impl DirEntry {
+ pub fn path(&self) -> PathBuf {
+ match self.0 {}
+ }
+
+ pub fn file_name(&self) -> OsString {
+ match self.0 {}
+ }
+
+ pub fn metadata(&self) -> io::Result<FileAttr> {
+ match self.0 {}
+ }
+
+ pub fn file_type(&self) -> io::Result<FileType> {
+ match self.0 {}
+ }
+}
+
+impl OpenOptions {
+ pub fn new() -> OpenOptions {
+ OpenOptions {}
+ }
+
+ pub fn read(&mut self, _read: bool) {}
+ pub fn write(&mut self, _write: bool) {}
+ pub fn append(&mut self, _append: bool) {}
+ pub fn truncate(&mut self, _truncate: bool) {}
+ pub fn create(&mut self, _create: bool) {}
+ pub fn create_new(&mut self, _create_new: bool) {}
+}
+
+impl File {
+ pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
+ unsupported()
+ }
+
+ pub fn file_attr(&self) -> io::Result<FileAttr> {
+ match self.0 {}
+ }
+
+ pub fn fsync(&self) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn datasync(&self) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn truncate(&self, _size: u64) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn flush(&self) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
+ match self.0 {}
+ }
+
+ pub fn duplicate(&self) -> io::Result<File> {
+ match self.0 {}
+ }
+
+ pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn diverge(&self) -> ! {
+ match self.0 {}
+ }
+}
+
+impl DirBuilder {
+ pub fn new() -> DirBuilder {
+ DirBuilder {}
+ }
+
+ pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
+ unsupported()
+ }
+}
+
+impl fmt::Debug for File {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
+ unsupported()
+}
+
+pub fn unlink(_p: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
+ match perm.0 {}
+}
+
+pub fn rmdir(_p: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
+ unsupported()
+}
+
+pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn stat(_p: &Path) -> io::Result<FileAttr> {
+ unsupported()
+}
+
+pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
+ unsupported()
+}
+
+pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
+ unsupported()
+}
+
+pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
+ unsupported()
+}
--- /dev/null
+// Copyright 2018 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 io;
+
+pub mod args;
+pub mod env;
+pub mod fs;
+pub mod net;
+#[path = "../../unix/path.rs"]
+pub mod path;
+pub mod pipe;
+pub mod process;
+pub mod os;
+
+// This enum is used as the storage for a bunch of types which can't actually exist.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub enum Void {}
+
+pub fn unsupported<T>() -> io::Result<T> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ "This function is not available on CloudABI.",
+ ))
+}
--- /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 fmt;
+use io;
+use net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use time::Duration;
+use sys::{unsupported, Void};
+
+pub extern crate libc as netc;
+
+pub struct TcpStream(Void);
+
+impl TcpStream {
+ pub fn connect(_: &SocketAddr) -> io::Result<TcpStream> {
+ unsupported()
+ }
+
+ pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
+ unsupported()
+ }
+
+ pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+ match self.0 {}
+ }
+
+ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+ match self.0 {}
+ }
+
+ pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+ match self.0 {}
+ }
+
+ pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+ match self.0 {}
+ }
+
+ pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn duplicate(&self) -> io::Result<TcpStream> {
+ match self.0 {}
+ }
+
+ pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn nodelay(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn ttl(&self) -> io::Result<u32> {
+ match self.0 {}
+ }
+
+ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+ match self.0 {}
+ }
+
+ pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for TcpStream {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub struct TcpListener(Void);
+
+impl TcpListener {
+ pub fn bind(_: &SocketAddr) -> io::Result<TcpListener> {
+ unsupported()
+ }
+
+ pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+ match self.0 {}
+ }
+
+ pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
+ match self.0 {}
+ }
+
+ pub fn duplicate(&self) -> io::Result<TcpListener> {
+ match self.0 {}
+ }
+
+ pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn ttl(&self) -> io::Result<u32> {
+ match self.0 {}
+ }
+
+ pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn only_v6(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+ match self.0 {}
+ }
+
+ pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for TcpListener {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub struct UdpSocket(Void);
+
+impl UdpSocket {
+ pub fn bind(_: &SocketAddr) -> io::Result<UdpSocket> {
+ unsupported()
+ }
+
+ pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+ match self.0 {}
+ }
+
+ pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ match self.0 {}
+ }
+
+ pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ match self.0 {}
+ }
+
+ pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn duplicate(&self) -> io::Result<UdpSocket> {
+ match self.0 {}
+ }
+
+ pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+ match self.0 {}
+ }
+
+ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+ match self.0 {}
+ }
+
+ pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn broadcast(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn multicast_loop_v4(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
+ match self.0 {}
+ }
+
+ pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn multicast_loop_v6(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn ttl(&self) -> io::Result<u32> {
+ match self.0 {}
+ }
+
+ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+ match self.0 {}
+ }
+
+ pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn send(&self, _: &[u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn connect(&self, _: &SocketAddr) -> io::Result<()> {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for UdpSocket {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub struct LookupHost(Void);
+
+impl Iterator for LookupHost {
+ type Item = SocketAddr;
+ fn next(&mut self) -> Option<SocketAddr> {
+ match self.0 {}
+ }
+}
+
+pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
+ unsupported()
+}
--- /dev/null
+// Copyright 2018 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 error::Error as StdError;
+use ffi::{OsStr, OsString};
+use fmt;
+use io;
+use iter;
+use path::{self, PathBuf};
+use sys::{unsupported, Void};
+
+pub fn getcwd() -> io::Result<PathBuf> {
+ unsupported()
+}
+
+pub fn chdir(_: &path::Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub type Env = iter::Empty<(OsString, OsString)>;
+
+pub fn env() -> Env {
+ iter::empty()
+}
+
+pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
+ Ok(None)
+}
+
+pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn unsetenv(_: &OsStr) -> io::Result<()> {
+ unsupported()
+}
+
+pub struct SplitPaths<'a>(&'a Void);
+
+pub fn split_paths(_unparsed: &OsStr) -> SplitPaths {
+ panic!("unsupported")
+}
+
+impl<'a> Iterator for SplitPaths<'a> {
+ type Item = PathBuf;
+ fn next(&mut self) -> Option<PathBuf> {
+ match *self.0 {}
+ }
+}
+
+#[derive(Debug)]
+pub struct JoinPathsError;
+
+pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
+where
+ I: Iterator<Item = T>,
+ T: AsRef<OsStr>,
+{
+ Err(JoinPathsError)
+}
+
+impl fmt::Display for JoinPathsError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ "not supported on CloudABI yet".fmt(f)
+ }
+}
+
+impl StdError for JoinPathsError {
+ fn description(&self) -> &str {
+ "not supported on CloudABI yet"
+ }
+}
+
+pub fn home_dir() -> Option<PathBuf> {
+ None
+}
+
+pub fn temp_dir() -> PathBuf {
+ PathBuf::from("/tmp")
+}
+
+pub fn current_exe() -> io::Result<PathBuf> {
+ unsupported()
+}
+
+pub fn getpid() -> u32 {
+ 1
+}
--- /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 io;
+use sys::Void;
+
+pub struct AnonPipe(Void);
+
+impl AnonPipe {
+ pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn diverge(&self) -> ! {
+ match self.0 {}
+ }
+}
+
+pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
+ match p1.0 {}
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ffi::OsStr;
+use fmt;
+use io;
+use sys::fs::File;
+use sys::pipe::AnonPipe;
+use sys::{unsupported, Void};
+use sys_common::process::{CommandEnv, DefaultEnvKey};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Command {
+ env: CommandEnv<DefaultEnvKey>,
+}
+
+// passed back to std::process with the pipes connected to the child, if any
+// were requested
+pub struct StdioPipes {
+ pub stdin: Option<AnonPipe>,
+ pub stdout: Option<AnonPipe>,
+ pub stderr: Option<AnonPipe>,
+}
+
+pub enum Stdio {
+ Inherit,
+ Null,
+ MakePipe,
+}
+
+impl Command {
+ pub fn new(_program: &OsStr) -> Command {
+ Command {
+ env: Default::default(),
+ }
+ }
+
+ pub fn arg(&mut self, _arg: &OsStr) {}
+
+ pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+ &mut self.env
+ }
+
+ pub fn cwd(&mut self, _dir: &OsStr) {}
+
+ pub fn stdin(&mut self, _stdin: Stdio) {}
+
+ pub fn stdout(&mut self, _stdout: Stdio) {}
+
+ pub fn stderr(&mut self, _stderr: Stdio) {}
+
+ pub fn spawn(
+ &mut self,
+ _default: Stdio,
+ _needs_stdin: bool,
+ ) -> io::Result<(Process, StdioPipes)> {
+ unsupported()
+ }
+}
+
+impl From<AnonPipe> for Stdio {
+ fn from(pipe: AnonPipe) -> Stdio {
+ pipe.diverge()
+ }
+}
+
+impl From<File> for Stdio {
+ fn from(file: File) -> Stdio {
+ file.diverge()
+ }
+}
+
+impl fmt::Debug for Command {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ Ok(())
+ }
+}
+
+pub struct ExitStatus(Void);
+
+impl ExitStatus {
+ pub fn success(&self) -> bool {
+ match self.0 {}
+ }
+
+ pub fn code(&self) -> Option<i32> {
+ match self.0 {}
+ }
+}
+
+impl Clone for ExitStatus {
+ fn clone(&self) -> ExitStatus {
+ match self.0 {}
+ }
+}
+
+impl Copy for ExitStatus {}
+
+impl PartialEq for ExitStatus {
+ fn eq(&self, _other: &ExitStatus) -> bool {
+ match self.0 {}
+ }
+}
+
+impl Eq for ExitStatus {}
+
+impl fmt::Debug for ExitStatus {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+impl fmt::Display for ExitStatus {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub struct Process(Void);
+
+impl Process {
+ pub fn id(&self) -> u32 {
+ match self.0 {}
+ }
+
+ pub fn kill(&mut self) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn wait(&mut self) -> io::Result<ExitStatus> {
+ match self.0 {}
+ }
+
+ pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+ match self.0 {}
+ }
+}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(test, allow(dead_code))]
+
+pub struct Handler;
+
+impl Handler {
+ pub unsafe fn new() -> Handler {
+ Handler
+ }
+}
+
+pub unsafe fn init() {}
+
+pub unsafe fn cleanup() {}
--- /dev/null
+// Copyright 2018 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 io;
+use sys::cloudabi::abi;
+
+pub struct Stdin(());
+pub struct Stdout(());
+pub struct Stderr(());
+
+impl Stdin {
+ pub fn new() -> io::Result<Stdin> {
+ Ok(Stdin(()))
+ }
+
+ pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
+ Ok(0)
+ }
+}
+
+impl Stdout {
+ pub fn new() -> io::Result<Stdout> {
+ Ok(Stdout(()))
+ }
+
+ pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+ Err(io::Error::new(
+ io::ErrorKind::BrokenPipe,
+ "Stdout is not connected to any output in this environment",
+ ))
+ }
+
+ pub fn flush(&self) -> io::Result<()> {
+ Ok(())
+ }
+}
+
+impl Stderr {
+ pub fn new() -> io::Result<Stderr> {
+ Ok(Stderr(()))
+ }
+
+ pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+ Err(io::Error::new(
+ io::ErrorKind::BrokenPipe,
+ "Stderr is not connected to any output in this environment",
+ ))
+ }
+
+ pub fn flush(&self) -> io::Result<()> {
+ Ok(())
+ }
+}
+
+// FIXME: right now this raw stderr handle is used in a few places because
+// std::io::stderr_raw isn't exposed, but once that's exposed this impl
+// should go away
+impl io::Write for Stderr {
+ fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+ Stderr::write(self, data)
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ Stderr::flush(self)
+ }
+}
+
+pub fn is_ebadf(err: &io::Error) -> bool {
+ err.raw_os_error() == Some(abi::errno::BADF as i32)
+}
+
+pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
--- /dev/null
+// Copyright 2014-2018 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 alloc::boxed::FnBox;
+use cmp;
+use ffi::CStr;
+use io;
+use libc;
+use mem;
+use ptr;
+use sys::cloudabi::abi;
+use sys::time::dur2intervals;
+use sys_common::thread::*;
+use time::Duration;
+
+pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
+
+pub struct Thread {
+ id: libc::pthread_t,
+}
+
+// CloudABI has pthread_t as a pointer in which case we still want
+// a thread to be Send/Sync
+unsafe impl Send for Thread {}
+unsafe impl Sync for Thread {}
+
+impl Thread {
+ pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>) -> io::Result<Thread> {
+ let p = box p;
+ let mut native: libc::pthread_t = mem::zeroed();
+ let mut attr: libc::pthread_attr_t = mem::zeroed();
+ assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+
+ let stack_size = cmp::max(stack, min_stack_size(&attr));
+ assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
+
+ let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
+ assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+
+ return if ret != 0 {
+ Err(io::Error::from_raw_os_error(ret))
+ } else {
+ mem::forget(p); // ownership passed to pthread_create
+ Ok(Thread { id: native })
+ };
+
+ extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
+ unsafe {
+ start_thread(main as *mut u8);
+ }
+ ptr::null_mut()
+ }
+ }
+
+ pub fn yield_now() {
+ let ret = unsafe { abi::thread_yield() };
+ debug_assert_eq!(ret, abi::errno::SUCCESS);
+ }
+
+ pub fn set_name(_name: &CStr) {
+ // CloudABI has no way to set a thread name.
+ }
+
+ pub fn sleep(dur: Duration) {
+ unsafe {
+ let subscription = abi::subscription {
+ type_: abi::eventtype::CLOCK,
+ union: abi::subscription_union {
+ clock: abi::subscription_clock {
+ clock_id: abi::clockid::MONOTONIC,
+ timeout: dur2intervals(&dur),
+ ..mem::zeroed()
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(ret, abi::errno::SUCCESS);
+ assert_eq!(event.error, abi::errno::SUCCESS);
+ }
+ }
+
+ pub fn join(self) {
+ unsafe {
+ let ret = libc::pthread_join(self.id, ptr::null_mut());
+ mem::forget(self);
+ assert!(
+ ret == 0,
+ "failed to join thread: {}",
+ io::Error::from_raw_os_error(ret)
+ );
+ }
+ }
+}
+
+impl Drop for Thread {
+ fn drop(&mut self) {
+ let ret = unsafe { libc::pthread_detach(self.id) };
+ debug_assert_eq!(ret, 0);
+ }
+}
+
+#[cfg_attr(test, allow(dead_code))]
+pub mod guard {
+ pub unsafe fn current() -> Option<usize> {
+ None
+ }
+ pub unsafe fn init() -> Option<usize> {
+ None
+ }
+}
+
+fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
+ libc::PTHREAD_STACK_MIN
+}
--- /dev/null
+// Copyright 2018 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 mem;
+use sys::cloudabi::abi;
+use time::Duration;
+
+const NSEC_PER_SEC: abi::timestamp = 1_000_000_000;
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct Instant {
+ t: abi::timestamp,
+}
+
+pub fn dur2intervals(dur: &Duration) -> abi::timestamp {
+ dur.as_secs()
+ .checked_mul(NSEC_PER_SEC)
+ .and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp))
+ .expect("overflow converting duration to nanoseconds")
+}
+
+impl Instant {
+ pub fn now() -> Instant {
+ unsafe {
+ let mut t = mem::uninitialized();
+ let ret = abi::clock_time_get(abi::clockid::MONOTONIC, 0, &mut t);
+ assert_eq!(ret, abi::errno::SUCCESS);
+ Instant { t: t }
+ }
+ }
+
+ pub fn sub_instant(&self, other: &Instant) -> Duration {
+ let diff = self.t
+ .checked_sub(other.t)
+ .expect("second instant is later than self");
+ Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
+ }
+
+ pub fn add_duration(&self, other: &Duration) -> Instant {
+ Instant {
+ t: self.t
+ .checked_add(dur2intervals(other))
+ .expect("overflow when adding duration to instant"),
+ }
+ }
+
+ pub fn sub_duration(&self, other: &Duration) -> Instant {
+ Instant {
+ t: self.t
+ .checked_sub(dur2intervals(other))
+ .expect("overflow when subtracting duration from instant"),
+ }
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct SystemTime {
+ t: abi::timestamp,
+}
+
+impl SystemTime {
+ pub fn now() -> SystemTime {
+ unsafe {
+ let mut t = mem::uninitialized();
+ let ret = abi::clock_time_get(abi::clockid::REALTIME, 0, &mut t);
+ assert_eq!(ret, abi::errno::SUCCESS);
+ SystemTime { t: t }
+ }
+ }
+
+ pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+ if self.t >= other.t {
+ let diff = self.t - other.t;
+ Ok(Duration::new(
+ diff / NSEC_PER_SEC,
+ (diff % NSEC_PER_SEC) as u32,
+ ))
+ } else {
+ let diff = other.t - self.t;
+ Err(Duration::new(
+ diff / NSEC_PER_SEC,
+ (diff % NSEC_PER_SEC) as u32,
+ ))
+ }
+ }
+
+ pub fn add_duration(&self, other: &Duration) -> SystemTime {
+ SystemTime {
+ t: self.t
+ .checked_add(dur2intervals(other))
+ .expect("overflow when adding duration to instant"),
+ }
+ }
+
+ pub fn sub_duration(&self, other: &Duration) -> SystemTime {
+ SystemTime {
+ t: self.t
+ .checked_sub(dur2intervals(other))
+ .expect("overflow when subtracting duration from instant"),
+ }
+ }
+}
+
+pub const UNIX_EPOCH: SystemTime = SystemTime { t: 0 };
} else if #[cfg(windows)] {
mod windows;
pub use self::windows::*;
+ } else if #[cfg(target_os = "cloudabi")] {
+ mod cloudabi;
+ pub use self::cloudabi::*;
} else if #[cfg(target_os = "redox")] {
mod redox;
pub use self::redox::*;
if #[cfg(any(unix, target_os = "redox"))] {
// On unix we'll document what's already available
pub use self::ext as unix_ext;
- } else if #[cfg(target_arch = "wasm32")] {
- // On wasm right now the module below doesn't compile (missing things
- // in `libc` which is empty) so just omit everything with an empty module
+ } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
+ // On CloudABI and wasm right now the module below doesn't compile
+ // (missing things in `libc` which is empty) so just omit everything
+ // with an empty module
#[unstable(issue = "0", feature = "std_internals")]
pub mod unix_ext {}
} else {
if #[cfg(windows)] {
// On windows we'll just be documenting what's already available
pub use self::ext as windows_ext;
- } else if #[cfg(target_arch = "wasm32")] {
- // On wasm right now the shim below doesn't compile, so just omit it
+ } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
+ // On CloudABI and wasm right now the shim below doesn't compile, so
+ // just omit it
#[unstable(issue = "0", feature = "std_internals")]
pub mod windows_ext {}
} else {
const DEBUG: bool = false;
pub mod args;
+#[cfg(feature = "backtrace")]
pub mod backtrace;
pub mod cmath;
pub mod condvar;
use libc::{wchar_t, size_t, c_void};
use ptr;
-#[repr(simd)]
-#[repr(C)]
-#[cfg(target_arch = "x86_64")]
-struct u64x2(u64, u64);
-
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
pub use self::EXCEPTION_DISPOSITION::*;
}
#[cfg(target_arch = "x86_64")]
-#[repr(C)]
+#[repr(C, align(16))]
pub struct CONTEXT {
- _align_hack: [u64x2; 0], // FIXME align on 16-byte
pub P1Home: DWORDLONG,
pub P2Home: DWORDLONG,
pub P3Home: DWORDLONG,
}
#[cfg(target_arch = "x86_64")]
-#[repr(C)]
+#[repr(C, align(16))]
pub struct M128A {
- _align_hack: [u64x2; 0], // FIXME align on 16-byte
pub Low: c_ulonglong,
pub High: c_longlong
}
#[cfg(target_arch = "x86_64")]
-#[repr(C)]
+#[repr(C, align(16))]
pub struct FLOATING_SAVE_AREA {
- _align_hack: [u64x2; 0], // FIXME align on 16-byte
_Dummy: [u8; 512] // FIXME: Fill this out
}
pub mod process;
cfg_if! {
- if #[cfg(any(target_os = "redox", target_os = "l4re"))] {
+ if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] {
pub use sys::net;
} else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
pub use sys::net;
///
/// let duration = Duration::from_millis(5432);
/// assert_eq!(duration.as_secs(), 5);
- /// assert_eq!(duration.subsec_nanos(), 432_000_000);
+ /// assert_eq!(duration.subsec_millis(), 432);
/// ```
#[unstable(feature = "duration_extras", issue = "46507")]
#[inline]
///
/// let duration = Duration::from_micros(1_234_567);
/// assert_eq!(duration.as_secs(), 1);
- /// assert_eq!(duration.subsec_nanos(), 234_567_000);
+ /// assert_eq!(duration.subsec_micros(), 234_567);
/// ```
#[unstable(feature = "duration_extras", issue = "46507")]
#[inline]
///
/// E.g. `trait Foo = Bar + Quux;`
TraitAlias(Generics, TyParamBounds),
- /// Auto trait implementation.
- ///
- /// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
- AutoImpl(Unsafety, TraitRef),
/// An implementation.
///
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
ItemKind::TraitAlias(..) => "trait alias",
ItemKind::Mac(..) |
ItemKind::MacroDef(..) |
- ItemKind::Impl(..) |
- ItemKind::AutoImpl(..) => "item"
+ ItemKind::Impl(..) => "item"
}
}
}
if let Some(mi) = item.word() {
let word = &*mi.name().as_str();
let hint = match word {
- // Can't use "extern" because it's not a lexical identifier.
- "C" => Some(ReprExtern),
+ "C" => Some(ReprC),
"packed" => Some(ReprPacked),
"simd" => Some(ReprSimd),
_ => match int_type_of_word(word) {
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
pub enum ReprAttr {
ReprInt(IntType),
- ReprExtern,
+ ReprC,
ReprPacked,
ReprSimd,
ReprAlign(u32),
// -Zremap-path-prefix to all FileMaps allocated within this CodeMap.
path_mapping: FilePathMapping,
stable_id_to_filemap: RefCell<FxHashMap<StableFilemapId, Rc<FileMap>>>,
+ /// In case we are in a doctest, replace all file names with the PathBuf,
+ /// and add the given offsets to the line info
+ doctest_offset: Option<(FileName, isize)>,
}
impl CodeMap {
file_loader: Box::new(RealFileLoader),
path_mapping,
stable_id_to_filemap: RefCell::new(FxHashMap()),
+ doctest_offset: None,
}
}
+ pub fn new_doctest(path_mapping: FilePathMapping,
+ file: FileName, line: isize) -> CodeMap {
+ CodeMap {
+ doctest_offset: Some((file, line)),
+ ..CodeMap::new(path_mapping)
+ }
+
+ }
+
pub fn with_file_loader(file_loader: Box<FileLoader>,
path_mapping: FilePathMapping)
-> CodeMap {
file_loader,
path_mapping,
stable_id_to_filemap: RefCell::new(FxHashMap()),
+ doctest_offset: None,
}
}
pub fn load_file(&self, path: &Path) -> io::Result<Rc<FileMap>> {
let src = self.file_loader.read_file(path)?;
- Ok(self.new_filemap(path.to_owned().into(), src))
+ let filename = if let Some((ref name, _)) = self.doctest_offset {
+ name.clone()
+ } else {
+ path.to_owned().into()
+ };
+ Ok(self.new_filemap(filename, src))
}
pub fn files(&self) -> Ref<Vec<Rc<FileMap>>> {
pos.col.to_usize() + 1)).to_string()
}
+ // If there is a doctest_offset, apply it to the line
+ pub fn doctest_offset_line(&self, mut orig: usize) -> usize {
+ if let Some((_, line)) = self.doctest_offset {
+ if line >= 0 {
+ orig = orig + line as usize;
+ } else {
+ orig = orig - (-line) as usize;
+ }
+ }
+ orig
+ }
+
/// Lookup source information about a BytePos
pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
let chpos = self.bytepos_to_file_charpos(pos);
}
)
}
+ fn doctest_offset_line(&self, line: usize) -> usize {
+ self.doctest_offset_line(line)
+ }
}
#[derive(Clone)]
(active, link_llvm_intrinsics, "1.0.0", Some(29602)),
(active, linkage, "1.0.0", Some(29603)),
(active, quote, "1.0.0", Some(29601)),
- (active, simd, "1.0.0", Some(27731)),
// rustc internal
(removed, unmarked_api, "1.0.0", None),
(removed, pushpop_unsafe, "1.2.0", None),
(removed, allocator, "1.0.0", None),
+ // Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]`
+ (removed, simd, "1.0.0", Some(27731)),
);
declare_features! (
("start", Normal, Ungated),
("test", Normal, Ungated),
("bench", Normal, Ungated),
- ("simd", Normal, Ungated),
("repr", Normal, Ungated),
("path", Normal, Ungated),
("abi", Normal, Ungated),
never be stable",
cfg_fn!(rustc_attrs))),
+ // whitelists "identity-like" conversion methods to suggest on type mismatch
+ ("rustc_conversion_suggestion", Whitelisted, Gated(Stability::Unstable,
+ "rustc_attrs",
+ "this is an internal attribute that will \
+ never be stable",
+ cfg_fn!(rustc_attrs))),
+
("wasm_import_memory", Whitelisted, Gated(Stability::Unstable,
"wasm_import_memory",
"wasm_import_memory attribute is currently unstable",
}
ast::ItemKind::Struct(..) => {
- if let Some(attr) = attr::find_by_name(&i.attrs[..], "simd") {
- gate_feature_post!(&self, simd, attr.span,
- "SIMD types are experimental and possibly buggy");
- self.context.parse_sess.span_diagnostic.span_warn(attr.span,
- "the `#[simd]` attribute \
- is deprecated, use \
- `#[repr(simd)]` instead");
- }
if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
if item.check_name("simd") {
"trait aliases are not yet fully implemented");
}
- ast::ItemKind::AutoImpl(..) => {
- gate_feature_post!(&self, optin_builtin_traits,
- i.span,
- "auto trait implementations are experimental \
- and possibly buggy");
- }
-
ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
if polarity == ast::ImplPolarity::Negative {
gate_feature_post!(&self, optin_builtin_traits,
let generics = folder.fold_generics(generics);
ItemKind::Union(folder.fold_variant_data(struct_def), generics)
}
- ItemKind::AutoImpl(unsafety, ref trait_ref) => {
- ItemKind::AutoImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
- }
ItemKind::Impl(unsafety,
polarity,
defaultness,
break;
}
}
- if i > line.len() {
+ if i >= line.len() {
can_trim = false;
}
if !can_trim {
}
}
-type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
+type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>);
/// How to parse a path.
#[derive(Copy, Clone, PartialEq)]
};
}
-fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
- -> Vec<Attribute> {
- if let Some(ref attrs) = rhs {
- lhs.extend(attrs.iter().cloned())
+fn maybe_append(mut lhs: Vec<Attribute>, mut rhs: Option<Vec<Attribute>>) -> Vec<Attribute> {
+ if let Some(ref mut rhs) = rhs {
+ lhs.append(rhs);
}
lhs
}
Parser::token_to_string(&self.token)
}
+ pub fn token_descr(&self) -> Option<&'static str> {
+ Some(match &self.token {
+ t if t.is_special_ident() => "reserved identifier",
+ t if t.is_used_keyword() => "keyword",
+ t if t.is_unused_keyword() => "reserved keyword",
+ _ => return None,
+ })
+ }
+
pub fn this_token_descr(&self) -> String {
- let prefix = match &self.token {
- t if t.is_special_ident() => "reserved identifier ",
- t if t.is_used_keyword() => "keyword ",
- t if t.is_unused_keyword() => "reserved keyword ",
- _ => "",
- };
- format!("{}`{}`", prefix, self.this_token_to_string())
+ if let Some(prefix) = self.token_descr() {
+ format!("{} `{}`", prefix, self.this_token_to_string())
+ } else {
+ format!("`{}`", self.this_token_to_string())
+ }
}
pub fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> {
}
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
+ self.parse_ident_common(true)
+ }
+
+ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
match self.token {
token::Ident(i) => {
if self.token.is_reserved_ident() {
- self.span_err(self.span, &format!("expected identifier, found {}",
- self.this_token_descr()));
+ let mut err = self.struct_span_err(self.span,
+ &format!("expected identifier, found {}",
+ self.this_token_descr()));
+ if let Some(token_descr) = self.token_descr() {
+ err.span_label(self.span, format!("expected identifier, found {}",
+ token_descr));
+ } else {
+ err.span_label(self.span, "expected identifier");
+ }
+ if recover {
+ err.emit();
+ } else {
+ return Err(err);
+ }
}
self.bump();
Ok(i)
} else {
let mut err = self.fatal(&format!("expected identifier, found `{}`",
self.this_token_to_string()));
+ if let Some(token_descr) = self.token_descr() {
+ err.span_label(self.span, format!("expected identifier, found {}",
+ token_descr));
+ } else {
+ err.span_label(self.span, "expected identifier");
+ }
if self.token == token::Underscore {
err.note("`_` is a wildcard pattern, not an identifier");
}
Function Style
*/
- let unsafety = self.parse_unsafety()?;
+ let unsafety = self.parse_unsafety();
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi()?.unwrap_or(Abi::C)
} else {
})))
}
- pub fn parse_unsafety(&mut self) -> PResult<'a, Unsafety> {
+ /// Parse unsafety: `unsafe` or nothing.
+ fn parse_unsafety(&mut self) -> Unsafety {
if self.eat_keyword(keywords::Unsafe) {
- return Ok(Unsafety::Unsafe);
+ Unsafety::Unsafe
} else {
- return Ok(Unsafety::Normal);
+ Unsafety::Normal
}
}
self.bump();
Ok(Ident::with_empty_ctxt(name))
} else {
- self.parse_ident()
+ self.parse_ident_common(false)
}
}
hi = self.prev_span;
(fieldname, self.parse_expr()?, false)
} else {
- let fieldname = self.parse_ident()?;
+ let fieldname = self.parse_ident_common(false)?;
hi = self.prev_span;
// Mimic `x: x` for the `x` field shorthand.
fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>> {
+ let struct_sp = lo.to(self.prev_span);
self.bump();
let mut fields = Vec::new();
let mut base = None;
match self.parse_field() {
Ok(f) => fields.push(f),
Err(mut e) => {
+ e.span_label(struct_sp, "while parsing this struct");
e.emit();
self.recover_stmt();
break;
self.token.is_keyword(keywords::Extern) && self.look_ahead(1, |t| t != &token::ModSep)
}
- fn eat_auto_trait(&mut self) -> bool {
- if self.token.is_keyword(keywords::Auto)
- && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
- {
- self.eat_keyword(keywords::Auto) && self.eat_keyword(keywords::Trait)
- } else {
- false
- }
- }
-
- fn is_defaultness(&self) -> bool {
- // `pub` is included for better error messages
- self.token.is_keyword(keywords::Default) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
- t.is_keyword(keywords::Const) ||
- t.is_keyword(keywords::Fn) ||
- t.is_keyword(keywords::Unsafe) ||
- t.is_keyword(keywords::Extern) ||
- t.is_keyword(keywords::Type) ||
- t.is_keyword(keywords::Pub))
- }
-
- fn eat_defaultness(&mut self) -> bool {
- let is_defaultness = self.is_defaultness();
- if is_defaultness {
- self.bump()
- } else {
- self.expected_tokens.push(TokenType::Keyword(keywords::Default));
- }
- is_defaultness
+ fn is_auto_trait_item(&mut self) -> bool {
+ // auto trait
+ (self.token.is_keyword(keywords::Auto)
+ && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
+ || // unsafe auto trait
+ (self.token.is_keyword(keywords::Unsafe) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) &&
+ self.look_ahead(2, |t| t.is_keyword(keywords::Trait)))
}
fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
node: StmtKind::Item(macro_def),
span: lo.to(self.prev_span),
}
- // Starts like a simple path, but not a union item or item with `crate` visibility.
+ // Starts like a simple path, being careful to avoid contextual keywords
+ // such as a union items, item with `crate` visibility or auto trait items.
// Our goal here is to parse an arbitrary path `a::b::c` but not something that starts
// like a path (1 token), but it fact not a path.
// `union::b::c` - path, `union U { ... }` - not a path.
!self.token.is_qpath_start() &&
!self.is_union_item() &&
!self.is_crate_vis() &&
- !self.is_extern_non_path() {
+ !self.is_extern_non_path() &&
+ !self.is_auto_trait_item() {
let pth = self.parse_path(PathStyle::Expr)?;
if !self.eat(&token::Not) {
}
let lo = self.prev_span;
- // This is a temporary future proofing.
- //
// We are considering adding generics to the `where` keyword as an alternative higher-rank
// parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
- // change, for now we refuse to parse `where < (ident | lifetime) (> | , | :)`.
- if token::Lt == self.token {
- let ident_or_lifetime = self.look_ahead(1, |t| t.is_ident() || t.is_lifetime());
- if ident_or_lifetime {
- let gt_comma_or_colon = self.look_ahead(2, |t| {
- *t == token::Gt || *t == token::Comma || *t == token::Colon
- });
- if gt_comma_or_colon {
- self.span_err(self.span, "syntax `where<T>` is reserved for future use");
- }
- }
+ // change we parse those generics now, but report an error.
+ if self.choose_generics_over_qpath() {
+ let generics = self.parse_generics()?;
+ self.span_err(generics.span,
+ "generic parameters on `where` clauses are reserved for future use");
}
loop {
fn parse_item_fn(&mut self,
unsafety: Unsafety,
constness: Spanned<Constness>,
- abi: abi::Abi)
+ abi: Abi)
-> PResult<'a, ItemInfo> {
let (ident, mut generics) = self.parse_fn_header()?;
let decl = self.parse_fn_decl(false)?;
/// - `const unsafe fn`
/// - `extern fn`
/// - etc
- pub fn parse_fn_front_matter(&mut self)
- -> PResult<'a, (Spanned<ast::Constness>,
- ast::Unsafety,
- abi::Abi)> {
+ pub fn parse_fn_front_matter(&mut self) -> PResult<'a, (Spanned<Constness>, Unsafety, Abi)> {
let is_const_fn = self.eat_keyword(keywords::Const);
let const_span = self.prev_span;
- let unsafety = self.parse_unsafety()?;
+ let unsafety = self.parse_unsafety();
let (constness, unsafety, abi) = if is_const_fn {
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
} else {
mut attrs: Vec<Attribute>) -> PResult<'a, ImplItem> {
let lo = self.span;
let vis = self.parse_visibility(false)?;
- let defaultness = self.parse_defaultness()?;
+ let defaultness = self.parse_defaultness();
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
// This parses the grammar:
// ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
/// Parse a method or a macro invocation in a trait impl.
fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
- -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::Generics,
+ -> PResult<'a, (Ident, Vec<Attribute>, ast::Generics,
ast::ImplItemKind)> {
// code copied from parse_macro_use_or_failure... abstraction!
if self.token.is_path_start() && !self.is_extern_non_path() {
}
}
- /// Parses items implementations variants
- /// impl<T> Foo { ... }
- /// impl<T> ToString for &'static T { ... }
- /// impl Send for .. {}
- fn parse_item_impl(&mut self,
- unsafety: ast::Unsafety,
- defaultness: Defaultness) -> PResult<'a, ItemInfo> {
- let impl_span = self.span;
+ fn choose_generics_over_qpath(&self) -> bool {
+ // There's an ambiguity between generic parameters and qualified paths in impls.
+ // If we see `<` it may start both, so we have to inspect some following tokens.
+ // The following combinations can only start generics,
+ // but not qualified paths (with one exception):
+ // `<` `>` - empty generic parameters
+ // `<` `#` - generic parameters with attributes
+ // `<` (LIFETIME|IDENT) `>` - single generic parameter
+ // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
+ // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
+ // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
+ // The only truly ambiguous case is
+ // `<` IDENT `>` `::` IDENT ...
+ // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
+ // because this is what almost always expected in practice, qualified paths in impls
+ // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
+ self.token == token::Lt &&
+ (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) ||
+ self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
+ self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
+ t == &token::Colon || t == &token::Eq))
+ }
+
+ fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
+ self.expect(&token::OpenDelim(token::Brace))?;
+ let attrs = self.parse_inner_attributes()?;
- // First, parse type parameters if necessary.
- let mut generics = self.parse_generics()?;
+ let mut impl_items = Vec::new();
+ while !self.eat(&token::CloseDelim(token::Brace)) {
+ let mut at_end = false;
+ match self.parse_impl_item(&mut at_end) {
+ Ok(impl_item) => impl_items.push(impl_item),
+ Err(mut err) => {
+ err.emit();
+ if !at_end {
+ self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
+ }
+ }
+ }
+ }
+ Ok((impl_items, attrs))
+ }
- // Special case: if the next identifier that follows is '(', don't
- // allow this to be parsed as a trait.
- let could_be_trait = self.token != token::OpenDelim(token::Paren);
+ /// Parses an implementation item, `impl` keyword is already parsed.
+ /// impl<'a, T> TYPE { /* impl items */ }
+ /// impl<'a, T> TRAIT for TYPE { /* impl items */ }
+ /// impl<'a, T> !TRAIT for TYPE { /* impl items */ }
+ /// We actually parse slightly more relaxed grammar for better error reporting and recovery.
+ /// `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
+ /// `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
+ fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
+ -> PResult<'a, ItemInfo> {
+ // First, parse generic parameters if necessary.
+ let mut generics = if self.choose_generics_over_qpath() {
+ self.parse_generics()?
+ } else {
+ ast::Generics::default()
+ };
- let neg_span = self.span;
- let polarity = if self.eat(&token::Not) {
+ // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
+ let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
+ self.bump(); // `!`
ast::ImplPolarity::Negative
} else {
ast::ImplPolarity::Positive
};
- // Parse the trait.
- let mut ty = self.parse_ty()?;
-
- // Parse traits, if necessary.
- let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
- // New-style trait. Reinterpret the type as a trait.
- match ty.node {
- TyKind::Path(None, ref path) => {
- Some(TraitRef {
- path: (*path).clone(),
- ref_id: ty.id,
- })
- }
- _ => {
- self.span_err(ty.span, "not a trait");
- None
- }
- }
+ // Parse both types and traits as a type, then reinterpret if necessary.
+ let ty_first = self.parse_ty()?;
+
+ // If `for` is missing we try to recover.
+ let has_for = self.eat_keyword(keywords::For);
+ let missing_for_span = self.prev_span.between(self.span);
+
+ let ty_second = if self.token == token::DotDot {
+ // We need to report this error after `cfg` expansion for compatibility reasons
+ self.bump(); // `..`, do not add it to expected tokens
+ Some(P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID }))
+ } else if has_for || self.token.can_begin_type() {
+ Some(self.parse_ty()?)
} else {
- if polarity == ast::ImplPolarity::Negative {
- // This is a negated type implementation
- // `impl !MyType {}`, which is not allowed.
- self.span_err(neg_span, "inherent implementation can't be negated");
- }
None
};
- if opt_trait.is_some() && self.eat(&token::DotDot) {
- if generics.is_parameterized() {
- self.span_err(impl_span, "auto trait implementations are not \
- allowed to have generics");
- }
+ generics.where_clause = self.parse_where_clause()?;
- if let ast::Defaultness::Default = defaultness {
- self.span_err(impl_span, "`default impl` is not allowed for \
- auto trait implementations");
- }
+ let (impl_items, attrs) = self.parse_impl_body()?;
- self.expect(&token::OpenDelim(token::Brace))?;
- self.expect(&token::CloseDelim(token::Brace))?;
- Ok((keywords::Invalid.ident(),
- ItemKind::AutoImpl(unsafety, opt_trait.unwrap()), None))
- } else {
- if opt_trait.is_some() {
- ty = self.parse_ty()?;
- }
- generics.where_clause = self.parse_where_clause()?;
-
- self.expect(&token::OpenDelim(token::Brace))?;
- let attrs = self.parse_inner_attributes()?;
+ let item_kind = match ty_second {
+ Some(ty_second) => {
+ // impl Trait for Type
+ if !has_for {
+ self.span_err(missing_for_span, "missing `for` in a trait impl");
+ }
- let mut impl_items = vec![];
- while !self.eat(&token::CloseDelim(token::Brace)) {
- let mut at_end = false;
- match self.parse_impl_item(&mut at_end) {
- Ok(item) => impl_items.push(item),
- Err(mut e) => {
- e.emit();
- if !at_end {
- self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
- }
+ let ty_first = ty_first.into_inner();
+ let path = match ty_first.node {
+ // This notably includes paths passed through `ty` macro fragments (#46438).
+ TyKind::Path(None, path) => path,
+ _ => {
+ self.span_err(ty_first.span, "expected a trait, found type");
+ ast::Path::from_ident(ty_first.span, keywords::Invalid.ident())
}
- }
+ };
+ let trait_ref = TraitRef { path, ref_id: ty_first.id };
+
+ ItemKind::Impl(unsafety, polarity, defaultness,
+ generics, Some(trait_ref), ty_second, impl_items)
}
+ None => {
+ // impl Type
+ ItemKind::Impl(unsafety, polarity, defaultness,
+ generics, None, ty_first, impl_items)
+ }
+ };
- Ok((keywords::Invalid.ident(),
- ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items),
- Some(attrs)))
- }
+ Ok((keywords::Invalid.ident(), item_kind, Some(attrs)))
}
fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
Ok(Visibility::Public)
}
- /// Parse defaultness: DEFAULT or nothing
- fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> {
- if self.eat_defaultness() {
- Ok(Defaultness::Default)
+ /// Parse defaultness: `default` or nothing.
+ fn parse_defaultness(&mut self) -> Defaultness {
+ // `pub` is included for better error messages
+ if self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
+ t.is_keyword(keywords::Const) ||
+ t.is_keyword(keywords::Fn) ||
+ t.is_keyword(keywords::Unsafe) ||
+ t.is_keyword(keywords::Extern) ||
+ t.is_keyword(keywords::Type) ||
+ t.is_keyword(keywords::Pub)) {
+ self.bump(); // `default`
+ Defaultness::Default
} else {
- Ok(Defaultness::Final)
+ Defaultness::Final
}
}
let (module, mut attrs) =
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
if warn {
- let attr = ast::Attribute {
+ let attr = Attribute {
id: attr::mk_attr_id(),
style: ast::AttrStyle::Outer,
path: ast::Path::from_ident(syntax_pos::DUMMY_SP,
}
}
- pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> {
+ pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str()))
}
fn submod_path(&mut self,
id: ast::Ident,
- outer_attrs: &[ast::Attribute],
+ outer_attrs: &[Attribute],
id_sp: Span)
-> PResult<'a, ModulePathSuccess> {
if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
return Ok(ModulePathSuccess {
directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
- Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
- Some(_) => {
- DirectoryOwnership::Owned { relative: Some(id) }
- }
+ // All `#[path]` files are treated as though they are a `mod.rs` file.
+ // This means that `mod foo;` declarations inside `#[path]`-included
+ // files are siblings,
+ //
+ // Note that this will produce weirdness when a file named `foo.rs` is
+ // `#[path]` included and contains a `mod foo;` declaration.
+ // If you encounter this, it's your own darn fault :P
+ Some(_) => DirectoryOwnership::Owned { relative: None },
_ => DirectoryOwnership::UnownedViaMod(true),
},
path,
directory_ownership: DirectoryOwnership,
name: String,
id_sp: Span)
- -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
+ -> PResult<'a, (ast::ItemKind, Vec<Attribute> )> {
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
let mut err = String::from("circular modules: ");
/// extern {}
fn parse_item_foreign_mod(&mut self,
lo: Span,
- opt_abi: Option<abi::Abi>,
+ opt_abi: Option<Abi>,
visibility: Visibility,
mut attrs: Vec<Attribute>)
-> PResult<'a, P<Item>> {
/// Parses a string as an ABI spec on an extern type or module. Consumes
/// the `extern` keyword, if one is found.
- fn parse_opt_abi(&mut self) -> PResult<'a, Option<abi::Abi>> {
+ fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
match self.token {
token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
let sp = self.span;
|| (self.check_keyword(keywords::Unsafe)
&& self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
// CONST FUNCTION ITEM
- let unsafety = if self.eat_keyword(keywords::Unsafe) {
- Unsafety::Unsafe
- } else {
- Unsafety::Normal
- };
+ let unsafety = self.parse_unsafety();
self.bump();
let (ident, item_, extra_attrs) =
self.parse_item_fn(unsafety,
self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
{
// UNSAFE TRAIT ITEM
- self.expect_keyword(keywords::Unsafe)?;
+ self.bump(); // `unsafe`
let is_auto = if self.eat_keyword(keywords::Trait) {
IsAuto::No
} else {
- self.eat_auto_trait();
+ self.expect_keyword(keywords::Auto)?;
+ self.expect_keyword(keywords::Trait)?;
IsAuto::Yes
};
let (ident, item_, extra_attrs) =
- self.parse_item_trait(is_auto, ast::Unsafety::Unsafe)?;
+ self.parse_item_trait(is_auto, Unsafety::Unsafe)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
- if (self.check_keyword(keywords::Unsafe) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
- (self.check_keyword(keywords::Default) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
- self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
- {
+ if self.check_keyword(keywords::Impl) ||
+ self.check_keyword(keywords::Unsafe) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
+ self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
+ self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) {
// IMPL ITEM
- let defaultness = self.parse_defaultness()?;
- self.expect_keyword(keywords::Unsafe)?;
+ let defaultness = self.parse_defaultness();
+ let unsafety = self.parse_unsafety();
self.expect_keyword(keywords::Impl)?;
- let (ident,
- item_,
- extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe, defaultness)?;
- let prev_span = self.prev_span;
- let item = self.mk_item(lo.to(prev_span),
- ident,
- item_,
- visibility,
- maybe_append(attrs, extra_attrs));
- return Ok(Some(item));
+ let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
+ let span = lo.to(self.prev_span);
+ return Ok(Some(self.mk_item(span, ident, item, visibility,
+ maybe_append(attrs, extra_attrs))));
}
if self.check_keyword(keywords::Fn) {
// FUNCTION ITEM
if self.check_keyword(keywords::Unsafe)
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
// UNSAFE FUNCTION ITEM
- self.bump();
+ self.bump(); // `unsafe`
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi()?.unwrap_or(Abi::C)
} else {
let is_auto = if self.eat_keyword(keywords::Trait) {
IsAuto::No
} else {
- self.eat_auto_trait();
+ self.expect_keyword(keywords::Auto)?;
+ self.expect_keyword(keywords::Trait)?;
IsAuto::Yes
};
// TRAIT ITEM
let (ident, item_, extra_attrs) =
- self.parse_item_trait(is_auto, ast::Unsafety::Normal)?;
- let prev_span = self.prev_span;
- let item = self.mk_item(lo.to(prev_span),
- ident,
- item_,
- visibility,
- maybe_append(attrs, extra_attrs));
- return Ok(Some(item));
- }
- if (self.check_keyword(keywords::Impl)) ||
- (self.check_keyword(keywords::Default) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl)))
- {
- // IMPL ITEM
- let defaultness = self.parse_defaultness()?;
- self.expect_keyword(keywords::Impl)?;
- let (ident,
- item_,
- extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal, defaultness)?;
+ self.parse_item_trait(is_auto, Unsafety::Normal)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,
self.head(&visibility_qualified(&item.vis, "union"))?;
self.print_struct(struct_def, generics, item.ident, item.span, true)?;
}
- ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.print_unsafety(unsafety)?;
- self.word_nbsp("impl")?;
- self.print_trait_ref(trait_ref)?;
- self.s.space()?;
- self.word_space("for")?;
- self.word_space("..")?;
- self.bopen()?;
- self.bclose(item.span)?;
- }
ast::ItemKind::Impl(unsafety,
polarity,
defaultness,
TokenStream::concat(result)
}
- fn first_tree(&self) -> Option<TokenTree> {
+ fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> {
match self.kind {
TokenStreamKind::Empty => None,
- TokenStreamKind::Tree(ref tree) |
- TokenStreamKind::JointTree(ref tree) => Some(tree.clone()),
- TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree(),
+ TokenStreamKind::Tree(ref tree) => Some((tree.clone(), false)),
+ TokenStreamKind::JointTree(ref tree) => Some((tree.clone(), true)),
+ TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(),
}
}
let stream = stream.into();
let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint);
if let Some(TokenTree::Token(last_span, last_tok)) = last_tree_if_joint {
- if let Some(TokenTree::Token(span, tok)) = stream.first_tree() {
+ if let Some((TokenTree::Token(span, tok), is_joint)) = stream.first_tree_and_joint() {
if let Some(glued_tok) = last_tok.glue(tok) {
let last_stream = self.0.pop().unwrap();
self.push_all_but_last_tree(&last_stream);
let glued_span = last_span.to(span);
- self.0.push(TokenTree::Token(glued_span, glued_tok).into());
+ let glued_tt = TokenTree::Token(glued_span, glued_tok);
+ let glued_tokenstream = if is_joint {
+ glued_tt.joint()
+ } else {
+ glued_tt.into()
+ };
+ self.0.push(glued_tokenstream);
self.push_all_but_first_tree(&stream);
return
}
assert_eq!(test1.is_empty(), false);
assert_eq!(test2.is_empty(), false);
}
+
+ #[test]
+ fn test_dotdotdot() {
+ let mut builder = TokenStreamBuilder::new();
+ builder.push(TokenTree::Token(sp(0, 1), Token::Dot).joint());
+ builder.push(TokenTree::Token(sp(1, 2), Token::Dot).joint());
+ builder.push(TokenTree::Token(sp(2, 3), Token::Dot));
+ let stream = builder.build();
+ assert!(stream.eq_unspanned(&string_to_ts("...")));
+ assert_eq!(stream.trees().count(), 1);
+ }
+
}
visitor.visit_generics(type_parameters);
visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
}
- ItemKind::AutoImpl(_, ref trait_ref) => {
- visitor.visit_trait_ref(trait_ref)
- }
ItemKind::Impl(_, _, _,
ref type_parameters,
ref opt_trait_reference,
for r in &attr::find_repr_attrs(diagnostic, a) {
repr_type_name = match *r {
attr::ReprPacked | attr::ReprSimd | attr::ReprAlign(_) => continue,
- attr::ReprExtern => "i32",
+ attr::ReprC => "i32",
attr::ReprInt(attr::SignedInt(ast::IntTy::Isize)) => "isize",
attr::ReprInt(attr::SignedInt(ast::IntTy::I8)) => "i8",
/// Extend a syntax context with a given mark
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
+ if mark.kind() == MarkKind::Modern {
+ return self.apply_mark_internal(mark);
+ }
+
+ let call_site_ctxt =
+ mark.expn_info().map_or(SyntaxContext::empty(), |info| info.call_site.ctxt()).modern();
+ if call_site_ctxt == SyntaxContext::empty() {
+ return self.apply_mark_internal(mark);
+ }
+
+ // Otherwise, `mark` is a macros 1.0 definition and the call site is in a
+ // macros 2.0 expansion, i.e. a macros 1.0 invocation is in a macros 2.0 definition.
+ //
+ // In this case, the tokens from the macros 1.0 definition inherit the hygiene
+ // at their invocation. That is, we pretend that the macros 1.0 definition
+ // was defined at its invocation (i.e. inside the macros 2.0 definition)
+ // so that the macros 2.0 definition remains hygienic.
+ //
+ // See the example at `test/run-pass/hygiene/legacy_interaction.rs`.
+ let mut ctxt = call_site_ctxt;
+ for mark in self.marks() {
+ ctxt = ctxt.apply_mark_internal(mark);
+ }
+ ctxt.apply_mark_internal(mark)
+ }
+
+ fn apply_mark_internal(self, mark: Mark) -> SyntaxContext {
HygieneData::with(|data| {
let syntax_contexts = &mut data.syntax_contexts;
let mut modern = syntax_contexts[self.0 as usize].modern;
})
}
+ pub fn marks(mut self) -> Vec<Mark> {
+ HygieneData::with(|data| {
+ let mut marks = Vec::new();
+ while self != SyntaxContext::empty() {
+ marks.push(data.syntax_contexts[self.0 as usize].outer_mark);
+ self = data.syntax_contexts[self.0 as usize].prev_ctxt;
+ }
+ marks.reverse();
+ marks
+ })
+ }
+
/// Adjust this context for resolution in a scope created by the given expansion.
/// For example, consider the following three resolutions of `f`:
///
#![feature(asm)]
#![feature(fnbox)]
-#![cfg_attr(unix, feature(libc))]
+#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
#![feature(set_stdio)]
#![feature(panic_unwind)]
#![feature(staged_api)]
extern crate getopts;
extern crate term;
-#[cfg(unix)]
+#[cfg(any(unix, target_os = "cloudabi"))]
extern crate libc;
extern crate panic_unwind;
1
}
- #[cfg(any(target_os = "linux",
- target_os = "macos",
- target_os = "ios",
- target_os = "android",
- target_os = "solaris",
+ #[cfg(any(target_os = "android",
+ target_os = "cloudabi",
target_os = "emscripten",
- target_os = "fuchsia"))]
+ target_os = "fuchsia",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "solaris"))]
fn num_cpus() -> usize {
unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize }
}
#[lang = "sized"]
trait Sized {}
#[lang = "sync"]
-trait Sync {}
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl Sync for .. {}
+auto trait Sync {}
#[lang = "copy"]
trait Copy {}
#[lang = "freeze"]
-trait Freeze {}
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
#[lang = "drop_in_place"]
#[inline]
#[lang = "copy"]
trait Copy {}
#[lang = "freeze"]
-trait Freeze {}
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
#[lang = "drop_in_place"]
#[inline]
return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
}
-extern "C" void LLVMRustSetDebug(int Enabled) {
-#ifndef NDEBUG
- DebugFlag = Enabled;
-#endif
-}
-
enum class LLVMRustAsmDialect {
Other,
Att,
return true;
}
-extern "C" bool LLVMRustLinkInParsedExternalBitcode(
- LLVMModuleRef DstRef, LLVMModuleRef SrcRef) {
-#if LLVM_VERSION_GE(4, 0)
- Module *Dst = unwrap(DstRef);
- std::unique_ptr<Module> Src(unwrap(SrcRef));
-
- if (Linker::linkModules(*Dst, std::move(Src))) {
- LLVMRustSetLastError("failed to link modules");
- return false;
- }
- return true;
-#else
- LLVMRustSetLastError("can't link parsed modules on this LLVM");
- return false;
-#endif
-}
-
// Note that the two following functions look quite similar to the
// LLVMGetSectionName function. Sadly, it appears that this function only
// returns a char* pointer, which isn't guaranteed to be null-terminated. The
}
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
RawRustStringOstream OS(Str);
report_fatal_error("Unhandled TypeID.");
}
-extern "C" void LLVMRustWriteDebugLocToString(LLVMContextRef C,
- LLVMDebugLocRef DL,
- RustStringRef Str) {
- RawRustStringOstream OS(Str);
- unwrap(DL)->print(OS);
-}
-
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
typedef struct OpaqueRustString *RustStringRef;
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
-typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef;
-typedef struct LLVMOpaqueRustJITMemoryManager *LLVMRustJITMemoryManagerRef;
extern "C" void LLVMRustStringWriteImpl(RustStringRef Str, const char *Ptr,
size_t Size);
struct Foo;
-unsafe impl !Clone for Foo { } //~ ERROR negative implementations are not unsafe [E0198]
+unsafe impl !Send for Foo { } //~ ERROR E0198
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(optin_builtin_traits)]
-
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
#![feature(optin_builtin_traits)]
auto trait Generic<T> {}
-//~^ ERROR auto traits cannot have generics
-//~^^ traits with auto impls (`e.g. impl Trait for ..`) can not have type parameters
+//~^ auto traits cannot have generic parameters [E0567]
auto trait Bound : Copy {}
-//~^ ERROR auto traits cannot have super traits
-//~^^ traits with auto impls (`e.g. impl Trait for ..`) cannot have predicates
+//~^ auto traits cannot have super traits [E0568]
auto trait MyTrait { fn foo() {} }
-//~^ ERROR auto traits cannot contain items
-//~^^ traits with default impls (`e.g. impl Trait for ..`) must have no methods or associated items
+//~^ auto traits cannot have methods or associated items [E0380]
fn main() {}
#![feature(optin_builtin_traits, core)]
#![crate_type = "rlib"]
-pub trait DefaultedTrait { }
-#[allow(auto_impl)]
-impl DefaultedTrait for .. { }
+pub auto trait DefaultedTrait { }
pub struct Something<T> { t: T }
fn foo(x: &()) {
bar(|| {
- //~^ ERROR does not fulfill
+ //~^ ERROR explicit lifetime required in the type of `x` [E0621]
let _ = x;
})
}
#![feature(optin_builtin_traits)]
-trait MyTrait { fn foo() {} }
+auto trait MySafeTrait {}
-#[allow(auto_impl)]
-impl MyTrait for .. {}
-//~^ ERROR redundant auto implementations of trait `MyTrait`
+struct Foo;
-#[allow(auto_impl)]
-impl MyTrait for .. {}
-
-trait MySafeTrait {}
-
-#[allow(auto_impl)]
-unsafe impl MySafeTrait for .. {}
+unsafe impl MySafeTrait for Foo {}
//~^ ERROR implementing the trait `MySafeTrait` is not unsafe
-unsafe trait MyUnsafeTrait {}
+unsafe auto trait MyUnsafeTrait {}
-#[allow(auto_impl)]
-impl MyUnsafeTrait for .. {}
+impl MyUnsafeTrait for Foo {}
//~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
fn main() {}
struct TestType;
unsafe impl !Send for TestType {}
-//~^ ERROR negative implementations are not unsafe
+//~^ ERROR negative impls cannot be unsafe
fn main() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern: mod statements in non-mod.rs files are unstable
-
-#[path="mod_file_not_owning_aux3.rs"]
-mod foo;
-
-fn main() {}
use std::fmt::Debug;
fn elided(x: &i32) -> impl Copy { x }
-//~^ ERROR cannot infer an appropriate lifetime
+//~^ ERROR explicit lifetime required in the type of `x` [E0621]
fn explicit<'a>(x: &'a i32) -> impl Copy { x }
//~^ ERROR cannot infer an appropriate lifetime
fn foo<T: Any>(value: &T) -> Box<Any> {
Box::new(value) as Box<Any>
- //~^ ERROR: cannot infer an appropriate lifetime
+ //~^ ERROR explicit lifetime required in the type of `value` [E0621]
}
fn main() {
#![feature(optin_builtin_traits)]
-unsafe trait Trait {
+unsafe auto trait Trait {
//~^ ERROR E0380
type Output;
}
-#[allow(auto_impl)]
-unsafe impl Trait for .. {}
-
fn call_method<T: Trait>(x: T) {}
fn main() {
// ICE
call_method(());
+ //~^ ERROR
}
#![feature(optin_builtin_traits)]
-unsafe trait Trait {
+unsafe auto trait Trait {
//~^ ERROR E0380
fn method(&self) {
println!("Hello");
}
}
-#[allow(auto_impl)]
-unsafe impl Trait for .. {}
-
fn call_method<T: Trait>(x: T) {
x.method();
}
enum bird {
pub duck,
//~^ ERROR: expected identifier, found keyword `pub`
- //~^^ ERROR: expected
+ //~| ERROR: expected
goose
}
--- /dev/null
+// Copyright 2018 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(fn_traits)]
+
+fn main() {
+ <fn() as Fn()>::call;
+ //~^ ERROR associated type bindings are not allowed here [E0229]
+}
--- /dev/null
+// Copyright 2018 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 xyz() -> u8 { 42 }
+
+const NUM: u8 = xyz();
+//~^ ERROR calls in constants are limited to constant functions, struct and enum constructors
+
+fn main() {
+ match 1 {
+ NUM => unimplemented!(),
+ _ => unimplemented!(),
+ }
+}
}
fn test_args(b: Box<i32>) { //[ast]~ NOTE first assignment
- //[mir]~^ NOTE first assignment
+ //[mir]~^ NOTE argument not declared as `mut`
b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
- //[mir]~^ ERROR cannot assign twice to immutable variable `b`
+ //[mir]~^ ERROR cannot assign to immutable argument `b`
//[ast]~| NOTE cannot assign twice to immutable
- //[mir]~| NOTE cannot assign twice to immutable
+ //[mir]~| NOTE cannot assign to immutable argument
}
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.
+
+macro_rules! m {
+ ($my_type: ty) => {
+ impl $my_type for u8 {}
+ }
+}
+
+trait Trait {}
+
+m!(Tr);
+
+m!(&'static u8); //~ ERROR expected a trait, found type
+
+fn main() {}
// `Box<SomeTrait>` defaults to a `'static` bound, so this return
// is illegal.
- ss.r //~ ERROR cannot infer an appropriate lifetime
+ ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
}
fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
// except according to those terms.
// Ensure that OIBIT checks `T` when it encounters a `PhantomData<T>` field, instead of checking
-// the `PhantomData<T>` type itself (which almost always implements a "default" trait
-// (`impl Trait for ..`))
+// the `PhantomData<T>` type itself (which almost always implements an auto trait)
#![feature(optin_builtin_traits)]
use std::marker::{PhantomData};
-unsafe trait Zen {}
-
-#[allow(auto_impl)]
-unsafe impl Zen for .. {}
+unsafe auto trait Zen {}
unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
#![feature(optin_builtin_traits)]
-trait MarkerTr {}
pub trait Tr {
fn f();
const C: u8;
}
struct Ts(pub u8);
-#[allow(auto_impl)]
-pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
pub impl Tr for S { //~ ERROR unnecessary visibility qualifier
pub fn f() {} //~ ERROR unnecessary visibility qualifier
pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
}
const MAIN: u8 = {
- trait MarkerTr {}
pub trait Tr {
fn f();
const C: u8;
}
struct Ts(pub u8);
- #[allow(auto_impl)]
- pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
pub impl Tr for S { //~ ERROR unnecessary visibility qualifier
pub fn f() {} //~ ERROR unnecessary visibility qualifier
pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
};
fn main() {
- trait MarkerTr {}
pub trait Tr {
fn f();
const C: u8;
}
struct Ts(pub u8);
- #[allow(auto_impl)]
- pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
pub impl Tr for S { //~ ERROR unnecessary visibility qualifier
pub fn f() {} //~ ERROR unnecessary visibility qualifier
pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
type AssocAlias = m::Pub3;
}
- impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
+ impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
pub fn f(arg: Priv) {} // private type `aliases_pub::Priv` in public interface
}
}
type AssocAlias = Priv3;
}
- impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
+ impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
pub fn f(arg: Priv) {} // OK
}
}
fn a(v: &[u8]) -> Box<Foo + 'static> {
let x: Box<Foo + 'static> = Box::new(v);
- //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+ //~^ ERROR explicit lifetime required in the type of `v` [E0621]
x
}
fn b(v: &[u8]) -> Box<Foo + 'static> {
Box::new(v)
- //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+ //~^ ERROR explicit lifetime required in the type of `v` [E0621]
}
fn c(v: &[u8]) -> Box<Foo> {
// same as previous case due to RFC 599
Box::new(v)
- //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+ //~^ ERROR explicit lifetime required in the type of `v` [E0621]
}
fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
// This is illegal, because the region bound on `proc` is 'static.
- Box::new(move|| { *x }) //~ ERROR cannot infer an appropriate lifetime
+ Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
}
fn main() { }
}
fn error(u: &(), v: &()) {
- static_id(&u); //[ll]~ ERROR cannot infer an appropriate lifetime
+ static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
//[nll]~^ WARNING not reporting region error due to -Znll
- //[nll]~| ERROR free region `` does not outlive free region `'static`
- static_id_indirect(&v); //[ll]~ ERROR cannot infer an appropriate lifetime
+ //[nll]~| ERROR explicit lifetime required in the type of `u` [E0621]
+ static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
//[nll]~^ WARNING not reporting region error due to -Znll
- //[nll]~| ERROR free region `` does not outlive free region `'static`
+ //[nll]~| ERROR explicit lifetime required in the type of `v` [E0621]
}
fn main() {}
+++ /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.
-
-#![feature(specialization)]
-#![feature(optin_builtin_traits)]
-
-trait Foo {}
-
-#[allow(auto_impl)]
-default impl Foo for .. {}
-//~^ ERROR `default impl` is not allowed for auto trait implementations
-
-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(optin_builtin_traits)]
+#![feature(specialization)]
+
+struct S;
+struct Z;
+
+default impl S {} //~ ERROR inherent impls cannot be default
+
+default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
+default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
+
+trait Tr {}
+default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
#![feature(optin_builtin_traits)]
#![feature(specialization)]
-trait Foo {}
-
-#[allow(auto_impl)]
-impl Foo for .. {}
+auto trait Foo {}
impl<T> Foo for T {}
impl !Foo for u8 {} //~ ERROR E0119
-trait Bar {}
-
-#[allow(auto_impl)]
-impl Bar for .. {}
+auto trait Bar {}
impl<T> !Bar for T {}
impl Bar for u8 {} //~ ERROR E0119
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(const_fn)]
+
struct WithDtor;
impl Drop for WithDtor {
const EARLY_DROP_C: i32 = (WithDtor, 0).1;
//~^ ERROR destructors cannot be evaluated at compile-time
+const fn const_drop<T>(_: T) {}
+//~^ ERROR destructors cannot be evaluated at compile-time
+
+const fn const_drop2<T>(x: T) {
+ (x, ()).1
+ //~^ ERROR destructors cannot be evaluated at compile-time
+}
+
fn main () {}
trait TestTrait {}
-unsafe impl !Send for TestType {}
+impl !Send for TestType {}
//~^ ERROR negative trait bounds
fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent impls cannot be negative
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative impls cannot be unsafe
+impl !TestTrait for TestType {}
+//~^ ERROR negative impls are only allowed for auto traits
+
+struct TestType2<T>(T);
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent impls cannot be negative
+
+unsafe impl<T> !Send for TestType2<T> {}
+//~^ ERROR negative impls cannot be unsafe
+impl<T> !TestTrait for TestType2<T> {}
+//~^ ERROR negative impls are only allowed for auto traits
+
+fn main() {}
+++ /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.
-
-#![feature(optin_builtin_traits)]
-
-trait MyAutoImpl {}
-
-#[allow(auto_impl)]
-impl<T> MyAutoImpl for .. {}
-//~^ ERROR auto trait implementations are not allowed to have generics
-
-fn main() {}
struct SomeStruct;
-unsafe impl SomeStruct { //~ ERROR inherent impls cannot be declared as unsafe
+unsafe impl SomeStruct { //~ ERROR inherent impls cannot be unsafe
fn foo(self) { }
}
#![feature(optin_builtin_traits)]
-trait Magic: Copy {} //~ ERROR E0568
-#[allow(auto_impl)]
-impl Magic for .. {}
+auto trait Magic: Copy {} //~ ERROR E0568
fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
struct NoClone;
fn main() {
- let (a, b) = copy(NoClone);
+ let (a, b) = copy(NoClone); //~ ERROR
println!("{:?} {:?}", a, b);
}
#![feature(optin_builtin_traits)]
-trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
-#[allow(auto_impl)]
-impl Magic for .. {}
+auto trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
impl<T:Magic> Magic for T {}
fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
#![feature(optin_builtin_traits)]
-trait Magic: Copy {} //~ ERROR E0568
-#[allow(auto_impl)]
-impl Magic for .. {}
+auto trait Magic: Copy {} //~ ERROR E0568
impl<T:Magic> Magic for T {}
fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(optin_builtin_traits)]
-
-trait Magic<T> {} //~ ERROR E0567
-#[allow(auto_impl)]
-impl Magic<isize> for .. {}
#![feature(optin_builtin_traits)]
-trait MyTrait {}
-
-#[allow(auto_impl)]
-impl MyTrait for .. {}
+auto trait MyTrait {}
struct MyS;
#![feature(optin_builtin_traits)]
-trait MyTrait {}
+auto trait MyTrait {}
-#[allow(auto_impl)]
-impl MyTrait for .. {}
impl<T> !MyTrait for *mut T {}
struct MyS;
#![feature(optin_builtin_traits)]
-trait MyTrait {}
+auto trait MyTrait {}
-#[allow(auto_impl)]
-impl MyTrait for .. {}
-
-unsafe trait MyUnsafeTrait {}
-
-#[allow(auto_impl)]
-unsafe impl MyUnsafeTrait for .. {}
+unsafe auto trait MyUnsafeTrait {}
struct ThisImplsTrait;
// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies
// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In
-// other words, the `..` impl only applies if there are no existing
+// other words, the auto impl only applies if there are no existing
// impls whose types unify.
#![feature(optin_builtin_traits)]
-trait Defaulted { }
-#[allow(auto_impl)]
-impl Defaulted for .. { }
+auto trait Defaulted { }
impl<'a,T:Signed> Defaulted for &'a T { }
impl<'a,T:Signed> Defaulted for &'a mut T { }
fn is_defaulted<T:Defaulted>() { }
}
impl !TestTrait for TestType {}
-//~^ ERROR negative impls are only allowed for traits with default impls (e.g., `Send` and `Sync`)
+//~^ ERROR negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
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.
+
+// compile-flags: -Z parse-only
+
+impl <*const u8>::AssocTy {} // OK
+impl <Type as Trait>::AssocTy {} // OK
+impl <'a + Trait>::AssocTy {} // OK
+impl <<Type>::AssocTy>::AssocTy {} // OK
+
+FAIL //~ ERROR
let mut _b = 0;
let mut _ = 0; //~ ERROR expected identifier, found `_`
//~^ NOTE `_` is a wildcard pattern, not an identifier
+ //~| NOTE expected identifier
}
+++ /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.
-
-// compile-flags: -Z parse-only -Z continue-parse-after-error
-
-#![feature(optin_builtin_traits)]
-
-use std::marker::Send;
-
-struct TestType;
-
-impl !TestType {}
-//~^ ERROR inherent implementation can't be negated
-
-trait TestTrait {}
-
-unsafe impl !Send for TestType {}
-impl !TestTrait for TestType {}
-
-struct TestType2<T>;
-
-impl<T> !TestType2<T> {}
-//~^ ERROR inherent implementation can't be negated
-
-unsafe impl<T> !Send for TestType2<T> {}
-impl<T> !TestTrait for TestType2<T> {}
-
-fn main() {}
struct Bar;
-impl Foo + Owned for Bar {
-//~^ ERROR not a trait
-//~^^ ERROR expected one of `where` or `{`, found `Bar`
+impl Foo + Owned for Bar { //~ ERROR expected a trait, found type
}
fn main() { }
// compile-flags: -Z parse-only
fn foo<T>() where <T>::Item: ToString, T: Iterator { }
- //~^ syntax `where<T>` is reserved for future use
+//~^ ERROR generic parameters on `where` clauses are reserved for future use
fn main() {}
# Make sure we don't ICE if the linker prints a non-UTF-8 error message.
-ifdef IS_WINDOWS
-# ignore windows
+# Ignore Windows and Apple
# This does not work in its current form on windows, possibly due to
# gcc bugs or something about valid Windows paths. See issue #29151
# for more information.
-all:
+ifndef IS_WINDOWS
-else
+# This also does not work on Apple APFS due to the filesystem requiring
+# valid UTF-8 paths.
+ifneq ($(shell uname),Darwin)
# The zzz it to allow humans to tab complete or glob this thing.
bad_dir := $(TMPDIR)/zzz$$'\xff'
mkdir $(bad_dir)
mv $(TMPDIR)/liblibrary.a $(bad_dir)
LIBRARY_PATH=$(bad_dir) $(RUSTC) exec.rs 2>&1 | $(CGREP) this_symbol_not_defined
+else
+all:
+
+endif
+
+else
+all:
endif
--- /dev/null
+-include ../tools.mk
+
+# Test that hir-tree output doens't crash and includes
+# the string constant we would expect to see.
+
+all:
+ $(RUSTDOC) --test input.rs > $(TMPDIR)/output || true
+ $(CGREP) 'input.rs:17:15' < $(TMPDIR)/output
--- /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.
+
+// Test for #45868
+
+// random #![feature] to ensure that crate attrs
+// do not offset things
+/// ```rust
+/// #![feature(nll)]
+/// let x: char = 1;
+/// ```
+pub fn foo() {
+
+}
}
#[lang = "freeze"]
-trait Freeze {}
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
trait Sized { }
#[lang = "freeze"]
-trait Freeze {}
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
#[lang="start"]
fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { 0 }
#![feature(optin_builtin_traits)]
auto trait Auto {}
-// Redundant but accepted until we remove it.
-#[allow(auto_impl)]
-impl Auto for .. {}
-
unsafe auto trait AutoUnsafe {}
impl !Auto for bool {}
fn take_auto_unsafe<T: AutoUnsafe>(_: T) {}
fn main() {
+ // Parse inside functions.
+ auto trait AutoInner {}
+ unsafe auto trait AutoUnsafeInner {}
+
take_auto(0);
take_auto(AutoBool(true));
take_auto_unsafe(0);
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#[macro_export]
+macro_rules! m {
+ () => {
+ fn f() {} // (2)
+ g(); // (1)
+ }
+}
--- /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 f() {}
--- /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.
+
+#![crate_type = "lib"]
+
+extern crate my_crate;
+
+pub fn g() {} // (a)
+
+#[macro_export]
+macro_rules! unhygienic_macro {
+ () => {
+ // (1) unhygienic: depends on `my_crate` in the crate root at the invocation site.
+ ::my_crate::f();
+
+ // (2) unhygienic: defines `f` at the invocation site (in addition to the above point).
+ use my_crate::f;
+ f();
+
+ g(); // (3) unhygienic: `g` needs to be in scope at use site.
+
+ $crate::g(); // (4) hygienic: this always resolves to (a)
+ }
+}
+
+#[allow(unused)]
+fn test_unhygienic() {
+ unhygienic_macro!();
+ f(); // `f` was defined at the use site
+}
--- /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.
+
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:legacy_interaction.rs
+
+#![feature(decl_macro)]
+#[allow(unused)]
+
+extern crate legacy_interaction;
+// ^ defines
+// ```rust
+// macro_rules! m {
+// () => {
+// fn f() // (1)
+// g() // (2)
+// }
+// }
+// ```rust
+
+mod def_site {
+ // Unless this macro opts out of hygiene, it should resolve the same wherever it is invoked.
+ pub macro m2() {
+ ::legacy_interaction::m!();
+ f(); // This should resolve to (1)
+ fn g() {} // We want (2) resolve to this, not to (4)
+ }
+}
+
+mod use_site {
+ fn test() {
+ fn f() -> bool { true } // (3)
+ fn g() -> bool { true } // (4)
+
+ ::def_site::m2!();
+
+ let _: bool = f(); // This should resolve to (3)
+ let _: bool = g(); // This should resolve to (4)
+ }
+}
+
+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.
+
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:my_crate.rs
+// aux-build:unhygienic_example.rs
+
+#![feature(decl_macro)]
+
+extern crate unhygienic_example;
+extern crate my_crate; // (b)
+
+// Hygienic version of `unhygienic_macro`.
+pub macro hygienic_macro() {
+ fn g() {} // (c)
+ ::unhygienic_example::unhygienic_macro!();
+ // ^ Even though we invoke an unhygienic macro, `hygienic_macro` remains hygienic.
+ // In the above expansion:
+ // (1) `my_crate` always resolves to (b) regardless of invocation site.
+ // (2) The defined function `f` is only usable inside this macro definition.
+ // (3) `g` always resolves to (c) regardless of invocation site.
+ // (4) `$crate::g` remains hygienic and continues to resolve to (a).
+
+ f();
+}
+
+#[allow(unused)]
+fn test_hygienic_macro() {
+ hygienic_macro!();
+
+ fn f() {} // (d) no conflict
+ f(); // resolves to (d)
+}
+
+fn main() {}
universal_impl_trait,
fn_traits,
step_trait,
- unboxed_closures
+ unboxed_closures,
+ copy_closures,
+ clone_closures
)]
//! Derived from: <https://raw.githubusercontent.com/quickfur/dcal/master/dcal.d>.
}
}
-/// Wrapper for zero-sized closures.
-// HACK(eddyb) Only needed because closures can't implement Copy.
-struct Fn0<F>(std::marker::PhantomData<F>);
-
-impl<F> Copy for Fn0<F> {}
-impl<F> Clone for Fn0<F> {
- fn clone(&self) -> Self { *self }
-}
-
-impl<F: FnOnce<A>, A> FnOnce<A> for Fn0<F> {
- type Output = F::Output;
-
- extern "rust-call" fn call_once(self, args: A) -> Self::Output {
- let f = unsafe { std::mem::uninitialized::<F>() };
- f.call_once(args)
- }
-}
-
-impl<F: FnMut<A>, A> FnMut<A> for Fn0<F> {
- extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output {
- let mut f = unsafe { std::mem::uninitialized::<F>() };
- f.call_mut(args)
- }
-}
-
-trait AsFn0<A>: Sized {
- fn copyable(self) -> Fn0<Self>;
-}
-
-impl<F: FnMut<A>, A> AsFn0<A> for F {
- fn copyable(self) -> Fn0<Self> {
- assert_eq!(std::mem::size_of::<F>(), 0);
- Fn0(std::marker::PhantomData)
- }
-}
-
/// GroupBy implementation.
struct GroupBy<It: Iterator, F> {
it: std::iter::Peekable<It>,
}
impl<It, F> Clone for GroupBy<It, F>
-where It: Iterator + Clone, It::Item: Clone, F: Clone {
- fn clone(&self) -> GroupBy<It, F> {
+where
+ It: Iterator + Clone,
+ It::Item: Clone,
+ F: Clone,
+{
+ fn clone(&self) -> Self {
GroupBy {
it: self.it.clone(),
- f: self.f.clone()
+ f: self.f.clone(),
}
}
}
}
trait IteratorExt: Iterator + Sized {
- fn group_by<G, F>(self, f: F) -> GroupBy<Self, Fn0<F>>
- where F: FnMut(&Self::Item) -> G,
+ fn group_by<G, F>(self, f: F) -> GroupBy<Self, F>
+ where F: Clone + FnMut(&Self::Item) -> G,
G: Eq
{
- GroupBy {
- it: self.peekable(),
- f: f.copyable(),
- }
+ GroupBy { it: self.peekable(), f }
}
fn join(mut self, sep: &str) -> String
fn dates_in_year(year: i32) -> impl Iterator<Item=NaiveDate>+Clone {
InGroup {
it: NaiveDate::from_ymd(year, 1, 1)..,
- f: (|d: &NaiveDate| d.year()).copyable(),
+ f: |d: &NaiveDate| d.year(),
g: year
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait Paramters { type SelfRef; }
+pub trait Parameters { type SelfRef; }
struct RP<'a> { _marker: std::marker::PhantomData<&'a ()> }
struct BP;
-impl<'a> Paramters for RP<'a> { type SelfRef = &'a X<RP<'a>>; }
-impl Paramters for BP { type SelfRef = Box<X<BP>>; }
+impl<'a> Parameters for RP<'a> { type SelfRef = &'a X<RP<'a>>; }
+impl Parameters for BP { type SelfRef = Box<X<BP>>; }
pub struct Y;
-pub enum X<P: Paramters> {
+pub enum X<P: Parameters> {
Nothing,
SameAgain(P::SelfRef, Y)
}
#![feature(optin_builtin_traits)]
-trait NotSame {}
-#[allow(auto_impl)]
-impl NotSame for .. {}
+auto trait NotSame {}
+
impl<A> !NotSame for (A, A) {}
trait OneOfEach {}
--- /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.
+
+// Issue 33903:
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Only built-in indexing can be used in constant expresssions
+
+const FOO: i32 = [12, 34][0 + 1];
+
+fn main() {}
+
--- /dev/null
+// Copyright 2018 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(conservative_impl_trait)]
+fn foo() -> impl Copy {
+ foo
+}
+fn main() {
+ foo();
+}
--- /dev/null
+// Copyright 2018 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(specialization)]
+
+trait Iterate<'a> {
+ type Ty: Valid;
+ fn iterate(self);
+}
+impl<'a, T> Iterate<'a> for T where T: Check {
+ default type Ty = ();
+ default fn iterate(self) {}
+}
+
+trait Check {}
+impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
+
+trait Valid {}
+
+fn main() {
+ Iterate::iterate(0);
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Zst;
+
+fn main() {
+ unsafe { ::std::ptr::write_volatile(1 as *mut Zst, Zst) }
+}
--- /dev/null
+// Copyright 2018 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)]
+
+impl A for i32 {
+ type Foo = u32;
+}
+impl B for u32 {
+ const BAR: i32 = 0;
+}
+
+trait A {
+ type Foo: B;
+}
+
+trait B {
+ const BAR: i32;
+}
+
+fn generic<T: A>() {
+ // This panics if the universal function call syntax is used as well
+ println!("{}", T::Foo::BAR);
+}
+
+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.
+
+struct A;
+
+impl A {
+ fn take_mutably(&mut self) {}
+}
+
+fn identity<T>(t: T) -> T {
+ t
+}
+
+// Issue 46095
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Overloaded indexing would cause wrapped to be borrowed mutably
+
+fn main() {
+ let mut a1 = A;
+ let mut a2 = A;
+
+ let wrapped = [&mut a1, &mut a2];
+
+ {
+ wrapped[0 + 1 - 1].take_mutably();
+ }
+
+ {
+ wrapped[identity(0)].take_mutably();
+ }
+}
+++ /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 foo() {}
+++ /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 mod innest;
--- /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 foo() {}
--- /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 mod innest;
pub mod bar {
use std::marker;
- pub trait Bar {}
-
- #[allow(auto_impl)]
- impl Bar for .. {}
+ pub auto trait Bar {}
pub trait Foo {
fn foo(&self) {}
#![feature(optin_builtin_traits)]
-pub trait AnOibit {}
-
-#[allow(auto_impl)]
-impl AnOibit for .. {}
+pub auto trait AnOibit {}
#![feature(optin_builtin_traits)]
-pub trait AnOibit {}
-
-#[allow(auto_impl)]
-impl AnOibit for .. {}
+pub auto trait AnOibit {}
pub struct Foo<T> { field: T }
--- /dev/null
+// Copyright 2018 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(decl_macro)]
+
+#![crate_name = "foo"]
+
+use std::vec;
+
+// @has 'foo/index.html'
+// @!has - '//*[@id="macros"]' 'Macros'
+// @!has - '//a/@href' 'macro.vec.html'
+// @!has 'foo/macro.vec.html'
--- /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.
+
+// @has issue_47197_blank_line_in_doc_block/fn.whose_woods_these_are_i_think_i_know.html
+
+/**
+* snow
+
+* ice
+*/
+pub fn whose_woods_these_are_i_think_i_know() {}
--- /dev/null
+// Copyright 2018 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: -Z emit-end-regions -Z borrowck=compare
+
+fn foo(_x: u32) {
+ _x = 4;
+ //~^ ERROR cannot assign to immutable argument `_x` (Mir)
+ //~^^ ERROR cannot assign twice to immutable variable `_x` (Ast)
+}
+
+fn main() {}
+
--- /dev/null
+error[E0384]: cannot assign twice to immutable variable `_x` (Ast)
+ --> $DIR/immutable-arg.rs:14:5
+ |
+13 | fn foo(_x: u32) {
+ | -- first assignment to `_x`
+14 | _x = 4;
+ | ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign to immutable argument `_x` (Mir)
+ --> $DIR/immutable-arg.rs:14:5
+ |
+13 | fn foo(_x: u32) {
+ | -- argument not declared as `mut`
+14 | _x = 4;
+ | ^^^^^^ cannot assign to immutable argument
+
+error: aborting due to 2 previous errors
+
--> $DIR/deref-suggestion.rs:18:9
|
18 | foo(s); //~ ERROR mismatched types
- | ^ expected struct `std::string::String`, found reference
+ | ^
+ | |
+ | expected struct `std::string::String`, found reference
+ | help: try using a conversion method: `s.to_string()`
|
= note: expected type `std::string::String`
found type `&std::string::String`
- = help: here are some functions which might fulfill your needs:
- - .escape_debug()
- - .escape_default()
- - .escape_unicode()
- - .to_ascii_lowercase()
- - .to_ascii_uppercase()
error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:23:10
62 | let x: &Bottom = &t; //~ ERROR mismatched types
| ^^ deref recursion limit reached
|
- = help: consider adding a `#[recursion_limit="20"]` attribute to your crate
+ = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
error[E0055]: reached the recursion limit while auto-dereferencing I
|
- = help: consider adding a `#[recursion_limit="20"]` attribute to your crate
+ = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
error[E0308]: mismatched types
--> $DIR/recursion_limit_deref.rs:62:22
auto trait AutoDummyTrait {}
//~^ ERROR auto traits are experimental and possibly buggy
-#[allow(auto_impl)]
-impl DummyTrait for .. {}
-//~^ ERROR auto trait implementations are experimental and possibly buggy
-
impl !DummyTrait for DummyStruct {}
//~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
|
= help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
-error: auto trait implementations are experimental and possibly buggy (see issue #13231)
- --> $DIR/feature-gate-optin-builtin-traits.rs:24:1
- |
-24 | impl DummyTrait for .. {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
-
error: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231)
- --> $DIR/feature-gate-optin-builtin-traits.rs:27:1
+ --> $DIR/feature-gate-optin-builtin-traits.rs:23:1
|
-27 | impl !DummyTrait for DummyStruct {}
+23 | impl !DummyTrait for DummyStruct {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
#![start = "x4300"] //~ WARN unused attribute
// see issue-43106-gating-of-test.rs for crate-level; but non crate-level is below at "4200"
// see issue-43106-gating-of-bench.rs for crate-level; but non crate-level is below at "4100"
-#![simd = "4000"] //~ WARN unused attribute
#![repr = "3900"] //~ WARN unused attribute
#![path = "3800"] //~ WARN unused attribute
#![abi = "3700"] //~ WARN unused attribute
impl S { }
}
-#[simd = "4000"]
-//~^ WARN unused attribute
-mod simd {
- mod inner { #![simd="4000"] }
- //~^ WARN unused attribute
-
- #[simd = "4000"] fn f() { }
- //~^ WARN unused attribute
-
- struct S; // for `struct S` case, see feature-gate-repr-simd.rs
-
- #[simd = "4000"] type T = S;
- //~^ WARN unused attribute
-
- #[simd = "4000"] impl S { }
- //~^ WARN unused attribute
-}
-
#[repr = "3900"]
//~^ WARN unused attribute
mod repr {
warning: macro_escape is a deprecated synonym for macro_use
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:513:1
|
-532 | #[macro_escape]
+513 | #[macro_escape]
| ^^^^^^^^^^^^^^^
warning: macro_escape is a deprecated synonym for macro_use
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:17
|
-535 | mod inner { #![macro_escape] }
+516 | mod inner { #![macro_escape] }
| ^^^^^^^^^^^^^^^^
|
= help: consider an outer attribute, #[macro_use] mod ...
warning: `#[must_use]` on functions is experimental (see issue #43302)
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
|
-682 | #[must_use = "1400"] fn f() { }
+663 | #[must_use = "1400"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(fn_must_use)] to the crate attributes to enable
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:8
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:8
|
-114 | #[warn(x5400)]
+113 | #[warn(x5400)]
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:25
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:25
|
-117 | mod inner { #![warn(x5400)] }
+116 | mod inner { #![warn(x5400)] }
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:119:12
|
-120 | #[warn(x5400)] fn f() { }
+119 | #[warn(x5400)] fn f() { }
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:122:12
|
-123 | #[warn(x5400)] struct S;
+122 | #[warn(x5400)] struct S;
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:12
|
-126 | #[warn(x5400)] type T = S;
+125 | #[warn(x5400)] type T = S;
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:128:12
|
-129 | #[warn(x5400)] impl S { }
+128 | #[warn(x5400)] impl S { }
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:9
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:9
|
-133 | #[allow(x5300)]
+132 | #[allow(x5300)]
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:26
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:26
|
-136 | mod inner { #![allow(x5300)] }
+135 | mod inner { #![allow(x5300)] }
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:138:13
|
-139 | #[allow(x5300)] fn f() { }
+138 | #[allow(x5300)] fn f() { }
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:13
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:141:13
|
-142 | #[allow(x5300)] struct S;
+141 | #[allow(x5300)] struct S;
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:13
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:13
|
-145 | #[allow(x5300)] type T = S;
+144 | #[allow(x5300)] type T = S;
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:13
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:147:13
|
-148 | #[allow(x5300)] impl S { }
+147 | #[allow(x5300)] impl S { }
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:10
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:10
|
-152 | #[forbid(x5200)]
+151 | #[forbid(x5200)]
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:27
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:27
|
-155 | mod inner { #![forbid(x5200)] }
+154 | mod inner { #![forbid(x5200)] }
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:157:14
|
-158 | #[forbid(x5200)] fn f() { }
+157 | #[forbid(x5200)] fn f() { }
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:14
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:160:14
|
-161 | #[forbid(x5200)] struct S;
+160 | #[forbid(x5200)] struct S;
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:14
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:14
|
-164 | #[forbid(x5200)] type T = S;
+163 | #[forbid(x5200)] type T = S;
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:14
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:166:14
|
-167 | #[forbid(x5200)] impl S { }
+166 | #[forbid(x5200)] impl S { }
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:8
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:8
|
-171 | #[deny(x5100)]
+170 | #[deny(x5100)]
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:25
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:25
|
-174 | mod inner { #![deny(x5100)] }
+173 | mod inner { #![deny(x5100)] }
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:12
|
-177 | #[deny(x5100)] fn f() { }
+176 | #[deny(x5100)] fn f() { }
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:180:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:179:12
|
-180 | #[deny(x5100)] struct S;
+179 | #[deny(x5100)] struct S;
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:183:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:182:12
|
-183 | #[deny(x5100)] type T = S;
+182 | #[deny(x5100)] type T = S;
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:186:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:12
|
-186 | #[deny(x5100)] impl S { }
+185 | #[deny(x5100)] impl S { }
| ^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:17
|
-193 | mod inner { #![macro_reexport="5000"] }
+192 | mod inner { #![macro_reexport="5000"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:196:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:195:5
|
-196 | #[macro_reexport = "5000"] fn f() { }
+195 | #[macro_reexport = "5000"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:199:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5
|
-199 | #[macro_reexport = "5000"] struct S;
+198 | #[macro_reexport = "5000"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:202:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5
|
-202 | #[macro_reexport = "5000"] type T = S;
+201 | #[macro_reexport = "5000"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:205:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5
|
-205 | #[macro_reexport = "5000"] impl S { }
+204 | #[macro_reexport = "5000"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:189:1
|
-190 | #[macro_reexport = "5000"]
+189 | #[macro_reexport = "5000"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:212:5
|
-213 | #[macro_use] fn f() { }
+212 | #[macro_use] fn f() { }
| ^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:215:5
|
-216 | #[macro_use] struct S;
+215 | #[macro_use] struct S;
| ^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:218:5
|
-219 | #[macro_use] type T = S;
+218 | #[macro_use] type T = S;
| ^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:222:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:5
|
-222 | #[macro_use] impl S { }
+221 | #[macro_use] impl S { }
| ^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:229:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17
|
-229 | mod inner { #![macro_export="4800"] }
+228 | mod inner { #![macro_export="4800"] }
| ^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:232:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:231:5
|
-232 | #[macro_export = "4800"] fn f() { }
+231 | #[macro_export = "4800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:234:5
|
-235 | #[macro_export = "4800"] struct S;
+234 | #[macro_export = "4800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:238:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:237:5
|
-238 | #[macro_export = "4800"] type T = S;
+237 | #[macro_export = "4800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:241:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:240:5
|
-241 | #[macro_export = "4800"] impl S { }
+240 | #[macro_export = "4800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:226:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:225:1
|
-226 | #[macro_export = "4800"]
+225 | #[macro_export = "4800"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:248:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:247:17
|
-248 | mod inner { #![plugin_registrar="4700"] }
+247 | mod inner { #![plugin_registrar="4700"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:5
|
-253 | #[plugin_registrar = "4700"] struct S;
+252 | #[plugin_registrar = "4700"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:5
|
-256 | #[plugin_registrar = "4700"] type T = S;
+255 | #[plugin_registrar = "4700"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:5
|
-259 | #[plugin_registrar = "4700"] impl S { }
+258 | #[plugin_registrar = "4700"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:244:1
|
-245 | #[plugin_registrar = "4700"]
+244 | #[plugin_registrar = "4700"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:17
|
-266 | mod inner { #![main="4300"] }
+265 | mod inner { #![main="4300"] }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:270:5
|
-271 | #[main = "4400"] struct S;
+270 | #[main = "4400"] struct S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:273:5
|
-274 | #[main = "4400"] type T = S;
+273 | #[main = "4400"] type T = S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:277:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:276:5
|
-277 | #[main = "4400"] impl S { }
+276 | #[main = "4400"] impl S { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:262:1
|
-263 | #[main = "4400"]
+262 | #[main = "4400"]
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:283:17
|
-284 | mod inner { #![start="4300"] }
+283 | mod inner { #![start="4300"] }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:289:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:288:5
|
-289 | #[start = "4300"] struct S;
+288 | #[start = "4300"] struct S;
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:292:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:291:5
|
-292 | #[start = "4300"] type T = S;
+291 | #[start = "4300"] type T = S;
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:294:5
|
-295 | #[start = "4300"] impl S { }
+294 | #[start = "4300"] impl S { }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:1
|
-281 | #[start = "4300"]
+280 | #[start = "4300"]
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:334:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:17
|
-334 | mod inner { #![simd="4000"] }
+333 | mod inner { #![repr="3900"] }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:337:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:5
|
-337 | #[simd = "4000"] fn f() { }
+336 | #[repr = "3900"] fn f() { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5
|
-342 | #[simd = "4000"] type T = S;
+341 | #[repr = "3900"] type T = S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5
|
-345 | #[simd = "4000"] impl S { }
+344 | #[repr = "3900"] impl S { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:331:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:330:1
|
-331 | #[simd = "4000"]
+330 | #[repr = "3900"]
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:5
|
-352 | mod inner { #![repr="3900"] }
- | ^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5
- |
-355 | #[repr = "3900"] fn f() { }
+352 | #[path = "3800"] fn f() { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:360:5
- |
-360 | #[repr = "3900"] type T = S;
- | ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:5
- |
-363 | #[repr = "3900"] impl S { }
- | ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:349:1
- |
-349 | #[repr = "3900"]
- | ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
- |
-371 | #[path = "3800"] fn f() { }
- | ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5
|
-374 | #[path = "3800"] struct S;
+355 | #[path = "3800"] struct S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:5
|
-377 | #[path = "3800"] type T = S;
+358 | #[path = "3800"] type T = S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5
|
-380 | #[path = "3800"] impl S { }
+361 | #[path = "3800"] impl S { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:17
|
-387 | mod inner { #![abi="3700"] }
+368 | mod inner { #![abi="3700"] }
| ^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
|
-390 | #[abi = "3700"] fn f() { }
+371 | #[abi = "3700"] fn f() { }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5
|
-393 | #[abi = "3700"] struct S;
+374 | #[abi = "3700"] struct S;
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5
|
-396 | #[abi = "3700"] type T = S;
+377 | #[abi = "3700"] type T = S;
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
|
-399 | #[abi = "3700"] impl S { }
+380 | #[abi = "3700"] impl S { }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:1
|
-384 | #[abi = "3700"]
+365 | #[abi = "3700"]
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:17
|
-406 | mod inner { #![automatically_derived="3600"] }
+387 | mod inner { #![automatically_derived="3600"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
|
-409 | #[automatically_derived = "3600"] fn f() { }
+390 | #[automatically_derived = "3600"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5
|
-412 | #[automatically_derived = "3600"] struct S;
+393 | #[automatically_derived = "3600"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:415:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:5
|
-415 | #[automatically_derived = "3600"] type T = S;
+396 | #[automatically_derived = "3600"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:5
|
-418 | #[automatically_derived = "3600"] impl S { }
+399 | #[automatically_derived = "3600"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:1
|
-403 | #[automatically_derived = "3600"]
+384 | #[automatically_derived = "3600"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: function is marked #[no_mangle], but not exported
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:27
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:27
|
-426 | #[no_mangle = "3500"] fn f() { }
+407 | #[no_mangle = "3500"] fn f() { }
| -^^^^^^^^^
| |
| help: try making it public: `pub`
= note: #[warn(private_no_mangle_fns)] on by default
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:17
|
-439 | mod inner { #![no_link="3400"] }
+420 | mod inner { #![no_link="3400"] }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5
|
-442 | #[no_link = "3400"] fn f() { }
+423 | #[no_link = "3400"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5
|
-445 | #[no_link = "3400"] struct S;
+426 | #[no_link = "3400"] struct S;
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5
|
-448 | #[no_link = "3400"]type T = S;
+429 | #[no_link = "3400"]type T = S;
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5
|
-451 | #[no_link = "3400"] impl S { }
+432 | #[no_link = "3400"] impl S { }
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:1
|
-436 | #[no_link = "3400"]
+417 | #[no_link = "3400"]
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:17
|
-458 | mod inner { #![should_panic="3200"] }
+439 | mod inner { #![should_panic="3200"] }
| ^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
|
-461 | #[should_panic = "3200"] fn f() { }
+442 | #[should_panic = "3200"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5
|
-464 | #[should_panic = "3200"] struct S;
+445 | #[should_panic = "3200"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5
|
-467 | #[should_panic = "3200"] type T = S;
+448 | #[should_panic = "3200"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5
|
-470 | #[should_panic = "3200"] impl S { }
+451 | #[should_panic = "3200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:1
|
-455 | #[should_panic = "3200"]
+436 | #[should_panic = "3200"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17
|
-477 | mod inner { #![ignore="3100"] }
+458 | mod inner { #![ignore="3100"] }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5
|
-480 | #[ignore = "3100"] fn f() { }
+461 | #[ignore = "3100"] fn f() { }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5
|
-483 | #[ignore = "3100"] struct S;
+464 | #[ignore = "3100"] struct S;
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
|
-486 | #[ignore = "3100"] type T = S;
+467 | #[ignore = "3100"] type T = S;
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5
|
-489 | #[ignore = "3100"] impl S { }
+470 | #[ignore = "3100"] impl S { }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:1
|
-474 | #[ignore = "3100"]
+455 | #[ignore = "3100"]
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:17
|
-496 | mod inner { #![no_implicit_prelude="3000"] }
+477 | mod inner { #![no_implicit_prelude="3000"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:5
|
-499 | #[no_implicit_prelude = "3000"] fn f() { }
+480 | #[no_implicit_prelude = "3000"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5
|
-502 | #[no_implicit_prelude = "3000"] struct S;
+483 | #[no_implicit_prelude = "3000"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
|
-505 | #[no_implicit_prelude = "3000"] type T = S;
+486 | #[no_implicit_prelude = "3000"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
|
-508 | #[no_implicit_prelude = "3000"] impl S { }
+489 | #[no_implicit_prelude = "3000"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:1
|
-493 | #[no_implicit_prelude = "3000"]
+474 | #[no_implicit_prelude = "3000"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17
|
-515 | mod inner { #![reexport_test_harness_main="2900"] }
+496 | mod inner { #![reexport_test_harness_main="2900"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
|
-518 | #[reexport_test_harness_main = "2900"] fn f() { }
+499 | #[reexport_test_harness_main = "2900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
|
-521 | #[reexport_test_harness_main = "2900"] struct S;
+502 | #[reexport_test_harness_main = "2900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
|
-524 | #[reexport_test_harness_main = "2900"] type T = S;
+505 | #[reexport_test_harness_main = "2900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5
|
-527 | #[reexport_test_harness_main = "2900"] impl S { }
+508 | #[reexport_test_harness_main = "2900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1
|
-512 | #[reexport_test_harness_main = "2900"]
+493 | #[reexport_test_harness_main = "2900"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:5
|
-538 | #[macro_escape] fn f() { }
+519 | #[macro_escape] fn f() { }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5
|
-541 | #[macro_escape] struct S;
+522 | #[macro_escape] struct S;
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:525:5
|
-544 | #[macro_escape] type T = S;
+525 | #[macro_escape] type T = S;
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
|
-547 | #[macro_escape] impl S { }
+528 | #[macro_escape] impl S { }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17
|
-555 | mod inner { #![no_std="2600"] }
+536 | mod inner { #![no_std="2600"] }
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17
|
-555 | mod inner { #![no_std="2600"] }
+536 | mod inner { #![no_std="2600"] }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
|
-559 | #[no_std = "2600"] fn f() { }
+540 | #[no_std = "2600"] fn f() { }
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
|
-559 | #[no_std = "2600"] fn f() { }
+540 | #[no_std = "2600"] fn f() { }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
|
-563 | #[no_std = "2600"] struct S;
+544 | #[no_std = "2600"] struct S;
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
|
-563 | #[no_std = "2600"] struct S;
+544 | #[no_std = "2600"] struct S;
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5
|
-567 | #[no_std = "2600"] type T = S;
+548 | #[no_std = "2600"] type T = S;
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5
|
-567 | #[no_std = "2600"] type T = S;
+548 | #[no_std = "2600"] type T = S;
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5
|
-571 | #[no_std = "2600"] impl S { }
+552 | #[no_std = "2600"] impl S { }
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5
|
-571 | #[no_std = "2600"] impl S { }
+552 | #[no_std = "2600"] impl S { }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
|
-551 | #[no_std = "2600"]
+532 | #[no_std = "2600"]
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
|
-551 | #[no_std = "2600"]
+532 | #[no_std = "2600"]
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17
|
-711 | mod inner { #![crate_name="0900"] }
+692 | mod inner { #![crate_name="0900"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17
|
-711 | mod inner { #![crate_name="0900"] }
+692 | mod inner { #![crate_name="0900"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
|
-715 | #[crate_name = "0900"] fn f() { }
+696 | #[crate_name = "0900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
|
-715 | #[crate_name = "0900"] fn f() { }
+696 | #[crate_name = "0900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
|
-719 | #[crate_name = "0900"] struct S;
+700 | #[crate_name = "0900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
|
-719 | #[crate_name = "0900"] struct S;
+700 | #[crate_name = "0900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
|
-723 | #[crate_name = "0900"] type T = S;
+704 | #[crate_name = "0900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
|
-723 | #[crate_name = "0900"] type T = S;
+704 | #[crate_name = "0900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
|
-727 | #[crate_name = "0900"] impl S { }
+708 | #[crate_name = "0900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
|
-727 | #[crate_name = "0900"] impl S { }
+708 | #[crate_name = "0900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1
|
-707 | #[crate_name = "0900"]
+688 | #[crate_name = "0900"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1
|
-707 | #[crate_name = "0900"]
+688 | #[crate_name = "0900"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17
|
-736 | mod inner { #![crate_type="0800"] }
+717 | mod inner { #![crate_type="0800"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17
|
-736 | mod inner { #![crate_type="0800"] }
+717 | mod inner { #![crate_type="0800"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
|
-740 | #[crate_type = "0800"] fn f() { }
+721 | #[crate_type = "0800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
|
-740 | #[crate_type = "0800"] fn f() { }
+721 | #[crate_type = "0800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
|
-744 | #[crate_type = "0800"] struct S;
+725 | #[crate_type = "0800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
|
-744 | #[crate_type = "0800"] struct S;
+725 | #[crate_type = "0800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
|
-748 | #[crate_type = "0800"] type T = S;
+729 | #[crate_type = "0800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
|
-748 | #[crate_type = "0800"] type T = S;
+729 | #[crate_type = "0800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
|
-752 | #[crate_type = "0800"] impl S { }
+733 | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
|
-752 | #[crate_type = "0800"] impl S { }
+733 | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1
|
-732 | #[crate_type = "0800"]
+713 | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1
|
-732 | #[crate_type = "0800"]
+713 | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17
|
-761 | mod inner { #![feature(x0600)] }
+742 | mod inner { #![feature(x0600)] }
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17
|
-761 | mod inner { #![feature(x0600)] }
+742 | mod inner { #![feature(x0600)] }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
|
-765 | #[feature(x0600)] fn f() { }
+746 | #[feature(x0600)] fn f() { }
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
|
-765 | #[feature(x0600)] fn f() { }
+746 | #[feature(x0600)] fn f() { }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
|
-769 | #[feature(x0600)] struct S;
+750 | #[feature(x0600)] struct S;
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
|
-769 | #[feature(x0600)] struct S;
+750 | #[feature(x0600)] struct S;
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5
|
-773 | #[feature(x0600)] type T = S;
+754 | #[feature(x0600)] type T = S;
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5
|
-773 | #[feature(x0600)] type T = S;
+754 | #[feature(x0600)] type T = S;
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
|
-777 | #[feature(x0600)] impl S { }
+758 | #[feature(x0600)] impl S { }
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
|
-777 | #[feature(x0600)] impl S { }
+758 | #[feature(x0600)] impl S { }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1
|
-757 | #[feature(x0600)]
+738 | #[feature(x0600)]
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1
|
-757 | #[feature(x0600)]
+738 | #[feature(x0600)]
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17
|
-787 | mod inner { #![no_main="0400"] }
+768 | mod inner { #![no_main="0400"] }
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17
|
-787 | mod inner { #![no_main="0400"] }
+768 | mod inner { #![no_main="0400"] }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5
|
-791 | #[no_main = "0400"] fn f() { }
+772 | #[no_main = "0400"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5
|
-791 | #[no_main = "0400"] fn f() { }
+772 | #[no_main = "0400"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
|
-795 | #[no_main = "0400"] struct S;
+776 | #[no_main = "0400"] struct S;
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
|
-795 | #[no_main = "0400"] struct S;
+776 | #[no_main = "0400"] struct S;
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5
|
-799 | #[no_main = "0400"] type T = S;
+780 | #[no_main = "0400"] type T = S;
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5
|
-799 | #[no_main = "0400"] type T = S;
+780 | #[no_main = "0400"] type T = S;
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5
|
-803 | #[no_main = "0400"] impl S { }
+784 | #[no_main = "0400"] impl S { }
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5
|
-803 | #[no_main = "0400"] impl S { }
+784 | #[no_main = "0400"] impl S { }
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1
|
-783 | #[no_main = "0400"]
+764 | #[no_main = "0400"]
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1
|
-783 | #[no_main = "0400"]
+764 | #[no_main = "0400"]
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17
|
-825 | mod inner { #![recursion_limit="0200"] }
+806 | mod inner { #![recursion_limit="0200"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17
|
-825 | mod inner { #![recursion_limit="0200"] }
+806 | mod inner { #![recursion_limit="0200"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
|
-829 | #[recursion_limit="0200"] fn f() { }
+810 | #[recursion_limit="0200"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
|
-829 | #[recursion_limit="0200"] fn f() { }
+810 | #[recursion_limit="0200"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
|
-833 | #[recursion_limit="0200"] struct S;
+814 | #[recursion_limit="0200"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
|
-833 | #[recursion_limit="0200"] struct S;
+814 | #[recursion_limit="0200"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
|
-837 | #[recursion_limit="0200"] type T = S;
+818 | #[recursion_limit="0200"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
|
-837 | #[recursion_limit="0200"] type T = S;
+818 | #[recursion_limit="0200"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
|
-841 | #[recursion_limit="0200"] impl S { }
+822 | #[recursion_limit="0200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
|
-841 | #[recursion_limit="0200"] impl S { }
+822 | #[recursion_limit="0200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1
|
-821 | #[recursion_limit="0200"]
+802 | #[recursion_limit="0200"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1
|
-821 | #[recursion_limit="0200"]
+802 | #[recursion_limit="0200"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17
|
-850 | mod inner { #![type_length_limit="0100"] }
+831 | mod inner { #![type_length_limit="0100"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17
|
-850 | mod inner { #![type_length_limit="0100"] }
+831 | mod inner { #![type_length_limit="0100"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
|
-854 | #[type_length_limit="0100"] fn f() { }
+835 | #[type_length_limit="0100"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
|
-854 | #[type_length_limit="0100"] fn f() { }
+835 | #[type_length_limit="0100"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5
|
-858 | #[type_length_limit="0100"] struct S;
+839 | #[type_length_limit="0100"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5
|
-858 | #[type_length_limit="0100"] struct S;
+839 | #[type_length_limit="0100"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
|
-862 | #[type_length_limit="0100"] type T = S;
+843 | #[type_length_limit="0100"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
|
-862 | #[type_length_limit="0100"] type T = S;
+843 | #[type_length_limit="0100"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
|
-866 | #[type_length_limit="0100"] impl S { }
+847 | #[type_length_limit="0100"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
|
-866 | #[type_length_limit="0100"] impl S { }
+847 | #[type_length_limit="0100"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1
|
-846 | #[type_length_limit="0100"]
+827 | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1
|
-846 | #[type_length_limit="0100"]
+827 | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1
|
-63 | #![simd = "4000"] //~ WARN unused attribute
+63 | #![repr = "3900"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
|
-64 | #![repr = "3900"] //~ WARN unused attribute
+64 | #![path = "3800"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
|
-65 | #![path = "3800"] //~ WARN unused attribute
+65 | #![abi = "3700"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
|
-66 | #![abi = "3700"] //~ WARN unused attribute
+66 | #![automatically_derived = "3600"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1
|
-67 | #![automatically_derived = "3600"] //~ WARN unused attribute
+68 | #![no_link = "3400"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1
|
-69 | #![no_link = "3400"] //~ WARN unused attribute
+70 | #![should_panic = "3200"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:71:1
|
-71 | #![should_panic = "3200"] //~ WARN unused attribute
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
- |
-72 | #![ignore = "3100"] //~ WARN unused attribute
+71 | #![ignore = "3100"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:78:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:77:1
|
-78 | #![proc_macro_derive = "2500"] //~ WARN unused attribute
+77 | #![proc_macro_derive = "2500"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: compilation successful
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:877:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:1
|
-877 | / fn main() { //~ ERROR compilation successful
-878 | | println!("Hello World");
-879 | | }
+858 | / fn main() { //~ ERROR compilation successful
+859 | | println!("Hello World");
+860 | | }
| |_^
+error[E0601]: main function not found
+
error[E0518]: attribute should be applied to function
--> $DIR/issue-43106-gating-of-inline.rs:21:1
|
35 | #[inline = "2100"] impl S { }
| ^^^^^^^^^^^^^^^^^^ ---------- not a function
-error[E0601]: main function not found
-
error: aborting due to 6 previous errors
--> $DIR/issue-44406.rs:18:10
|
18 | foo!(true); //~ ERROR expected type, found keyword
- | ^^^^
+ | ^^^^ expected identifier, found keyword
error: expected type, found keyword `true`
--> $DIR/issue-44406.rs:18:10
--- /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(nll)]
+
+fn foo(x: &u32) -> &'static u32 {
+ &*x
+ //~^ ERROR explicit lifetime required in the type of `x` [E0621]
+}
+
+fn main() {}
--- /dev/null
+error[E0621]: explicit lifetime required in the type of `x`
+ --> $DIR/issue-46983.rs:14:5
+ |
+13 | fn foo(x: &u32) -> &'static u32 {
+ | - consider changing the type of `x` to `&'static u32`
+14 | &*x
+ | ^^^ lifetime `'static` required
+
+error: aborting due to previous error
+
fn foo(x: &u32) -> &'static u32 {
&*x
//~^ WARN not reporting region error due to -Znll
- //~| ERROR does not outlive free region
+ //~| ERROR explicit lifetime required in the type of `x`
}
fn main() { }
19 | &*x
| ^^^
-error: free region `ReFree(DefId(0/0:3 ~ region_lbr_anon_does_not_outlive_static[317d]::foo[0]), BrAnon(0))` does not outlive free region `ReStatic`
+error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
|
+18 | fn foo(x: &u32) -> &'static u32 {
+ | - consider changing the type of `x` to `&ReStatic u32`
19 | &*x
- | ^^^
+ | ^^^ lifetime `ReStatic` required
error: aborting due to previous error
fn bar(s: &Box<(i32,)>) -> &'static i32 {
// FIXME(#46983): error message should be better
- &s.0 //~ ERROR free region `` does not outlive free region `'static`
+ &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621]
}
fn main() {
19 | *s = (2,); //~ ERROR cannot assign to `*s`
| ^^^^^^^^^ assignment to borrowed `*s` occurs here
-error: free region `` does not outlive free region `'static`
+error[E0621]: explicit lifetime required in the type of `s`
--> $DIR/guarantor-issue-46974.rs:25:5
|
-25 | &s.0 //~ ERROR free region `` does not outlive free region `'static`
- | ^^^^
+23 | fn bar(s: &Box<(i32,)>) -> &'static i32 {
+ | - consider changing the type of `s` to `&'static std::boxed::Box<(i32,)>`
+24 | // FIXME(#46983): error message should be better
+25 | &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621]
+ | ^^^^ lifetime `'static` required
error: aborting due to 2 previous errors
--- /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.
+
+// must-compile-successfully
+
+#![allow(warnings)]
+#![feature(nll)]
+
+struct LoadedObject {
+ bodies: Vec<Body>,
+ color: Color,
+}
+
+struct Body;
+
+#[derive(Clone)]
+struct Color;
+
+struct Graphic {
+ color: Color,
+}
+
+fn convert(objects: Vec<LoadedObject>) -> (Vec<Body>, Vec<Graphic>) {
+ objects
+ .into_iter()
+ .flat_map(|LoadedObject { bodies, color, .. }| {
+ bodies.into_iter().map(move |body| {
+ (
+ body,
+ Graphic {
+ color: color.clone(),
+ },
+ )
+ })
+ })
+ .unzip()
+}
+
+fn main() {}
+
= help: add #![feature(non_modrs_mods)] to the crate attributes to enable
= help: on stable builds, rename this file to inner_foors_mod/mod.rs
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
- --> $DIR/some_crazy_attr_mod_dir/arbitrary_name.rs:11:9
- |
-11 | pub mod inner_modrs_mod;
- | ^^^^^^^^^^^^^^^
- |
- = help: add #![feature(non_modrs_mods)] to the crate attributes to enable
- = help: on stable builds, rename this file to attr_mod/mod.rs
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
+++ /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 foo() {}
+++ /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 mod innest;
--- /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 foo() {}
--- /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 mod innest;
--- /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 Trait1 {}
+trait Trait2 {}
+
+#[cfg(not_enabled)]
+impl Trait1 for .. {}
+
+impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax
+
+fn main() {}
--- /dev/null
+error: `impl Trait for .. {}` is an obsolete syntax
+ --> $DIR/obsolete-syntax-impl-for-dotdot.rs:17:1
+ |
+17 | impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use `auto trait Trait {}` instead
+
+error: aborting due to previous error
+
--> $DIR/pub-restricted-error.rs:16:16
|
16 | pub(crate) () foo: usize, //~ ERROR expected identifier
- | ^
+ | ^ expected identifier
error: aborting due to previous error
--> $DIR/pub-restricted-non-path.rs:13:6
|
13 | pub (.) fn afn() {} //~ ERROR expected identifier
- | ^
+ | ^ expected identifier
error: aborting due to previous error
|
= note: expected type `usize`
found type `std::string::String`
- = help: here are some functions which might fulfill your needs:
- - .capacity()
- - .len()
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:19:19
--> $DIR/coerce-suggestions.rs:27:9
|
27 | f = box f;
- | ^^^^^ cyclic type of infinite size
+ | ^^^^^
+ | |
+ | cyclic type of infinite size
+ | help: try using a conversion method: `box f.to_string()`
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:31:9
--- /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.
+
+// compile-flags: -Z parse-only -Z continue-parse-after-error
+
+impl ! {} // OK
+impl ! where u8: Copy {} // OK
+
+impl Trait Type {} //~ ERROR missing `for` in a trait impl
+impl Trait .. {} //~ ERROR missing `for` in a trait impl
+impl ?Sized for Type {} //~ ERROR expected a trait, found type
+impl ?Sized for .. {} //~ ERROR expected a trait, found type
+
+default unsafe FAIL //~ ERROR expected `impl`, found `FAIL`
--- /dev/null
+error: missing `for` in a trait impl
+ --> $DIR/impl-parsing.rs:16:11
+ |
+16 | impl Trait Type {} //~ ERROR missing `for` in a trait impl
+ | ^
+
+error: missing `for` in a trait impl
+ --> $DIR/impl-parsing.rs:17:11
+ |
+17 | impl Trait .. {} //~ ERROR missing `for` in a trait impl
+ | ^
+
+error: expected a trait, found type
+ --> $DIR/impl-parsing.rs:18:6
+ |
+18 | impl ?Sized for Type {} //~ ERROR expected a trait, found type
+ | ^^^^^^
+
+error: expected a trait, found type
+ --> $DIR/impl-parsing.rs:19:6
+ |
+19 | impl ?Sized for .. {} //~ ERROR expected a trait, found type
+ | ^^^^^^
+
+error: expected `impl`, found `FAIL`
+ --> $DIR/impl-parsing.rs:21:16
+ |
+21 | default unsafe FAIL //~ ERROR expected `impl`, found `FAIL`
+ | ^^^^ expected `impl` here
+
+error: aborting due to 5 previous errors
+
|
= note: expected type `usize`
found type `&'static str`
- = help: here are some functions which might fulfill your needs:
- - .len()
error[E0061]: this function takes 2 parameters but 3 parameters were supplied
--> $DIR/issue-34264.rs:20: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.
+
+use std::path::{Path, PathBuf};
+
+
+fn main() {
+ let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types
+ let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+ //~^ ERROR mismatched types
+
+ let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+ //~^ ERROR mismatched types
+
+ let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3]; //~ ERROR mismatched types
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/conversion-methods.rs:15:41
+ |
+15 | let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types
+ | ^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | expected struct `std::string::String`, found reference
+ | help: try using a conversion method: `"'Tis a fond Ambush—".to_string()`
+ |
+ = note: expected type `std::string::String`
+ found type `&'static str`
+
+error[E0308]: mismatched types
+ --> $DIR/conversion-methods.rs:16:40
+ |
+16 | let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | expected struct `std::path::PathBuf`, found reference
+ | help: try using a conversion method: `Path::new("/ern/her/own/surprise").to_path_buf()`
+ |
+ = note: expected type `std::path::PathBuf`
+ found type `&std::path::Path`
+
+error[E0308]: mismatched types
+ --> $DIR/conversion-methods.rs:19:40
+ |
+19 | let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+ | ^
+ | |
+ | expected struct `std::string::String`, found integral variable
+ | help: try using a conversion method: `2.to_string()`
+ |
+ = note: expected type `std::string::String`
+ found type `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/conversion-methods.rs:22:47
+ |
+22 | let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3]; //~ ERROR mismatched types
+ | ^^^^^^^^^^
+ | |
+ | expected struct `std::vec::Vec`, found reference
+ | help: try using a conversion method: `&[1, 2, 3].to_vec()`
+ |
+ = note: expected type `std::vec::Vec<usize>`
+ found type `&[{integer}; 3]`
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+// Copyright 2018 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.
+
+#[no_mangle] pub const RAH: usize = 5;
+//~^ ERROR const items should never be #[no_mangle]
+
+fn main() {}
--- /dev/null
+error: const items should never be #[no_mangle]
+ --> $DIR/issue-45562.rs:11:14
+ |
+11 | #[no_mangle] pub const RAH: usize = 5;
+ | ---------^^^^^^^^^^^^^^^^
+ | |
+ | help: try a static value: `pub static`
+ |
+ = note: #[deny(no_mangle_const_items)] on by default
+
+error: aborting due to previous error
+
--- /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.
+
+// ignore-arm
+// ignore-aarch64
+// ignore-wasm
+// ignore-emscripten
+
+#![feature(target_feature)]
+
+#[target_feature = "+sse2"]
+//~^ WARN: deprecated
+#[target_feature(enable = "foo")]
+//~^ ERROR: not valid for this target
+#[target_feature(bar)]
+//~^ ERROR: only accepts sub-keys
+#[target_feature(disable = "baz")]
+//~^ ERROR: only accepts sub-keys
+unsafe fn foo() {}
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR: can only be applied to `unsafe` function
+fn bar() {}
+
+fn main() {
+ unsafe {
+ foo();
+ bar();
+ }
+}
--- /dev/null
+warning: #[target_feature = ".."] is deprecated and will eventually be removed, use #[target_feature(enable = "..")] instead
+ --> $DIR/target-feature-wrong.rs:18:1
+ |
+18 | #[target_feature = "+sse2"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the feature named `foo` is not valid for this target
+ --> $DIR/target-feature-wrong.rs:20:18
+ |
+20 | #[target_feature(enable = "foo")]
+ | ^^^^^^^^^^^^^^
+
+error: #[target_feature(..)] only accepts sub-keys of `enable` currently
+ --> $DIR/target-feature-wrong.rs:22:18
+ |
+22 | #[target_feature(bar)]
+ | ^^^
+
+error: #[target_feature(..)] only accepts sub-keys of `enable` currently
+ --> $DIR/target-feature-wrong.rs:24:18
+ |
+24 | #[target_feature(disable = "baz")]
+ | ^^^^^^^^^^^^^^^
+
+error: #[target_feature(..)] can only be applied to `unsafe` function
+ --> $DIR/target-feature-wrong.rs:28:1
+ |
+28 | #[target_feature(enable = "sse2")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+// Copyright 2018 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::io;
+
+fn main(){
+ let x: io::IoResult<()> = Ok(());
+ //~^ ERROR cannot find type `IoResult` in module `io`
+ //~| NOTE did you mean `Result`?
+ match x {
+ Err(ref e) if e.kind == io::EndOfFile {
+ //~^ NOTE while parsing this struct
+ return
+ //~^ ERROR expected identifier, found keyword `return`
+ //~| NOTE expected identifier, found keyword
+ }
+ //~^ NOTE expected one of `.`, `=>`, `?`, or an operator here
+ _ => {}
+ //~^ ERROR expected one of `.`, `=>`, `?`, or an operator, found `_`
+ //~| NOTE unexpected token
+ }
+}
--- /dev/null
+error: expected identifier, found keyword `return`
+ --> $DIR/issue-15980.rs:20:13
+ |
+18 | Err(ref e) if e.kind == io::EndOfFile {
+ | ------------- while parsing this struct
+19 | //~^ NOTE while parsing this struct
+20 | return
+ | ^^^^^^ expected identifier, found keyword
+
+error: expected one of `.`, `=>`, `?`, or an operator, found `_`
+ --> $DIR/issue-15980.rs:25:9
+ |
+23 | }
+ | - expected one of `.`, `=>`, `?`, or an operator here
+24 | //~^ NOTE expected one of `.`, `=>`, `?`, or an operator here
+25 | _ => {}
+ | ^ unexpected token
+
+error[E0412]: cannot find type `IoResult` in module `io`
+ --> $DIR/issue-15980.rs:14:16
+ |
+14 | let x: io::IoResult<()> = Ok(());
+ | ^^^^^^^^ did you mean `Result`?
+
+error: aborting due to 3 previous errors
+
+++ /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.
-
-#![feature(optin_builtin_traits)]
-
-#[allow(auto_impl)]
-impl Copy for .. {} //~ ERROR E0318
-fn main() {}
+++ /dev/null
-error[E0318]: cannot create default implementations for traits outside the crate they're defined in; define a new trait instead
- --> $DIR/typeck-default-trait-impl-outside-crate.rs:14:6
- |
-14 | impl Copy for .. {} //~ ERROR E0318
- | ^^^^ `Copy` trait not defined in this crate
-
-error: aborting due to previous error
-
"i386-apple-ios",
"i586-pc-windows-msvc",
"i586-unknown-linux-gnu",
+ "i586-unknown-linux-musl",
"i686-apple-darwin",
"i686-linux-android",
"i686-pc-windows-gnu",
use util::logv;
use regex::Regex;
+use std::collections::VecDeque;
use std::collections::HashMap;
use std::collections::HashSet;
use std::env;
}
}
+#[derive(Debug, PartialEq)]
+pub enum DiffLine {
+ Context(String),
+ Expected(String),
+ Resulting(String),
+}
+
+#[derive(Debug, PartialEq)]
+pub struct Mismatch {
+ pub line_number: u32,
+ pub lines: Vec<DiffLine>,
+}
+
+impl Mismatch {
+ fn new(line_number: u32) -> Mismatch {
+ Mismatch {
+ line_number: line_number,
+ lines: Vec::new(),
+ }
+ }
+}
+
+// Produces a diff between the expected output and actual output.
+pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
+ let mut line_number = 1;
+ let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size);
+ let mut lines_since_mismatch = context_size + 1;
+ let mut results = Vec::new();
+ let mut mismatch = Mismatch::new(0);
+
+ for result in diff::lines(actual, expected) {
+ match result {
+ diff::Result::Left(str) => {
+ if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
+ results.push(mismatch);
+ mismatch = Mismatch::new(line_number - context_queue.len() as u32);
+ }
+
+ while let Some(line) = context_queue.pop_front() {
+ mismatch.lines.push(DiffLine::Context(line.to_owned()));
+ }
+
+ mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
+ lines_since_mismatch = 0;
+ }
+ diff::Result::Right(str) => {
+ if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
+ results.push(mismatch);
+ mismatch = Mismatch::new(line_number - context_queue.len() as u32);
+ }
+
+ while let Some(line) = context_queue.pop_front() {
+ mismatch.lines.push(DiffLine::Context(line.to_owned()));
+ }
+
+ mismatch.lines.push(DiffLine::Expected(str.to_owned()));
+ line_number += 1;
+ lines_since_mismatch = 0;
+ }
+ diff::Result::Both(str, _) => {
+ if context_queue.len() >= context_size {
+ let _ = context_queue.pop_front();
+ }
+
+ if lines_since_mismatch < context_size {
+ mismatch.lines.push(DiffLine::Context(str.to_owned()));
+ } else if context_size > 0 {
+ context_queue.push_back(str);
+ }
+
+ line_number += 1;
+ lines_since_mismatch += 1;
+ }
+ }
+ }
+
+ results.push(mismatch);
+ results.remove(0);
+
+ results
+}
+
pub fn run(config: Config, testpaths: &TestPaths) {
match &*config.target {
"arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
rustc.args(&["-Z", "incremental-queries"]);
}
+ if self.config.mode == CodegenUnits {
+ rustc.args(&["-Z", "human_readable_cgu_names"]);
+ }
+
match self.config.mode {
CompileFail | ParseFail | Incremental => {
// If we are extracting and matching errors in the new
return 0;
}
- println!("normalized {}:\n{}\n", kind, actual);
- println!("expected {}:\n{}\n", kind, expected);
- println!("diff of {}:\n", kind);
-
- for diff in diff::lines(expected, actual) {
- match diff {
- diff::Result::Left(l) => println!("-{}", l),
- diff::Result::Both(l, _) => println!(" {}", l),
- diff::Result::Right(r) => println!("+{}", r),
+ if expected.is_empty() {
+ println!("normalized {}:\n{}\n", kind, actual);
+ } else {
+ println!("diff of {}:\n", kind);
+ let diff_results = make_diff(expected, actual, 3);
+ for result in diff_results {
+ let mut line_number = result.line_number;
+ for line in result.lines {
+ match line {
+ DiffLine::Expected(e) => {
+ println!("-\t{}", e);
+ line_number += 1;
+ },
+ DiffLine::Context(c) => {
+ println!("{}\t{}", line_number, c);
+ line_number += 1;
+ },
+ DiffLine::Resulting(r) => {
+ println!("+\t{}", r);
+ },
+ }
+ }
+ println!("");
}
}
*skipped += data.len();
if data.len() <= TAIL_LEN {
tail[..data.len()].copy_from_slice(data);
- tail.rotate(data.len());
+ tail.rotate_left(data.len());
} else {
tail.copy_from_slice(&data[(data.len() - TAIL_LEN)..]);
}
}
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>> {
- write!(output, "</body>\n</html>")?;
+ write!(output, r##"<script>
+function onEach(arr, func) {{
+ if (arr && arr.length > 0 && func) {{
+ for (var i = 0; i < arr.length; i++) {{
+ func(arr[i]);
+ }}
+ }}
+}}
+
+function hasClass(elem, className) {{
+ if (elem && className && elem.className) {{
+ var elemClass = elem.className;
+ var start = elemClass.indexOf(className);
+ if (start === -1) {{
+ return false;
+ }} else if (elemClass.length === className.length) {{
+ return true;
+ }} else {{
+ if (start > 0 && elemClass[start - 1] !== ' ') {{
+ return false;
+ }}
+ var end = start + className.length;
+ if (end < elemClass.length && elemClass[end] !== ' ') {{
+ return false;
+ }}
+ return true;
+ }}
+ if (start > 0 && elemClass[start - 1] !== ' ') {{
+ return false;
+ }}
+ var end = start + className.length;
+ if (end < elemClass.length && elemClass[end] !== ' ') {{
+ return false;
+ }}
+ return true;
+ }}
+ return false;
+}}
+
+onEach(document.getElementsByClassName('rust-example-rendered'), function(e) {{
+ if (hasClass(e, 'compile_fail')) {{
+ e.addEventListener("mouseover", function(event) {{
+ e.previousElementSibling.childNodes[0].style.color = '#f00';
+ }});
+ e.addEventListener("mouseout", function(event) {{
+ e.previousElementSibling.childNodes[0].style.color = '';
+ }});
+ }} else if (hasClass(e, 'ignore')) {{
+ e.addEventListener("mouseover", function(event) {{
+ e.previousElementSibling.childNodes[0].style.color = '#ff9200';
+ }});
+ e.addEventListener("mouseout", function(event) {{
+ e.previousElementSibling.childNodes[0].style.color = '';
+ }});
+ }}
+}});
+</script>
+</body>
+</html>"##)?;
Ok(())
}
}
file.ends_with("sync/struct.RwLock.html") {
return None;
}
- // FIXME(#47038)
- if file.ends_with("deriving/generic/index.html") ||
- file.ends_with("deriving/generic/macro.vec.html") ||
- file.ends_with("deriving/custom/macro.panic.html") ||
- file.ends_with("proc_macro_impl/macro.panic.html") {
- return None;
- }
let res = load_file(cache, root, file, SkipRedirect);
let (pretty_file, contents) = match res {
let prev_newline_idx = contents[..prev_newline_idx].rfind('\n');
if let Some(nl) = prev_newline_idx {
let prev_line = &contents[nl + 1 .. mod_tests_idx];
- let emcc_cfg = "cfg(all(test, not(target_os";
- if prev_line.contains(emcc_cfg) {
+ if prev_line.contains("cfg(all(test, not(target_os")
+ || prev_line.contains("cfg(all(test, not(any(target_os") {
nl
} else {
mod_tests_idx