"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cargo"
version = "0.21.0"
-source = "git+https://github.com/rust-lang/cargo#50b1c24d146fa072db71f12005deed319ac5ba9a"
+source = "git+https://github.com/rust-lang/cargo#abf01e1eddb3145c83f71b469ea7bee37141e5e1"
replace = "cargo 0.21.0"
[[package]]
"cargotest 0.1.0",
"crates-io 0.10.0",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
"psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 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)",
]
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 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)",
]
name = "crates-io"
version = "0.10.0"
dependencies = [
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "curl"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "curl-sys"
-version = "0.3.12"
+version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "docopt"
-version = "0.8.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "num_cpus"
-version = "1.5.1"
+version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "racer"
-version = "2.0.8"
+version = "2.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rls-vfs"
-version = "0.4.2"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustfmt-nightly"
-version = "0.1.3"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "socket2"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.1 (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.24 (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)",
+]
+
[[package]]
name = "stable_deref_trait"
version = "1.0.0"
"log 0.3.8 (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)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.3 (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)",
"syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "term"
-version = "0.4.5"
+version = "0.4.6"
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)",
[[package]]
name = "toml"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "url"
-version = "1.5.0"
+version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f"
"checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
-"checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b"
-"checksum curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f00c8ba847fb0730c293069b4d1203dc01bf3c2e1f90b4e55f426ed8f4a1eeac"
+"checksum curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6689276ab61f97c660669a5ecc117c36875dfc1ba301c986b16c653415bdf9d7"
+"checksum curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cbd8b8d593de3bbf49252b92f398ef47f0c6c1ebdfd0f9282b9b9348aad8d71c"
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
"checksum derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41be6ca3b99e0c0483fb2389685448f650459c3ecbe4e18d7705d8010ec4ab8e"
"checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472"
-"checksum docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e408eee8a772c5c61f62353992e3ebf51ef5c832dd04d986b3dc7d48c5b440"
+"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
"checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d"
"checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6"
-"checksum num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e416ba127a4bb3ff398cb19546a8d0414f73352efe2857f4060d36f5fe5983a"
+"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
"checksum openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "11ba043cb65fc9af71a431b8a36ffe8686cd4751cdf70a473ec1d01066ac7e41"
"checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
"checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469"
"checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edf2dfc188373ef96168bec3646a0415c5c21111c6144c0c36104fc720587ecd"
+"checksum racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9079a128fdb6f0c8850010e1478b215d4c00134654bf995bfda41824951ce9bd"
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
"checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e"
"checksum rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e502ac679bc35e023e982506c32d0278ef89e29af1e4ad21cb70c44b525b87a9"
"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
-"checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854"
+"checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7"
"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-"checksum rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "277deb9c0ee9c4788ee94faef5988fa334179cd7363bf281a2cae027edbbc8bf"
+"checksum rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "31ac6fe40a9844ee2de3d51d0be2bbcdb361bad6f3667a02db8c4e2330afbbb5"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
"checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"
"checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1"
"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
"checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
+"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde"
"checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b"
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
-"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
+"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
"checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca"
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
"checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
"checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f"
-"checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a"
+"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7"
"checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667"
"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a"
"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
-"checksum url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a69a2e36a5e5ed3f3063c8c64a3b028c4d50d689fa6c862abd7cfe65f882595c"
+"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27"
"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
{
let k = Layout::new::<T>();
if k.size() > 0 {
- unsafe { self.alloc(k).map(|p|Unique::new(*p as *mut T)) }
+ unsafe { self.alloc(k).map(|p| Unique::new(p as *mut T)) }
} else {
Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one"))
}
use core::hash::{Hash, Hasher};
use core::iter::{FromIterator, Peekable, FusedIterator};
use core::marker::PhantomData;
-use core::ops::Index;
+use core::ops::{Index, RangeArgument};
+use core::ops::Bound::{Excluded, Included, Unbounded};
use core::{fmt, intrinsics, mem, ptr};
use borrow::Borrow;
-use Bound::{Excluded, Included, Unbounded};
-use range::RangeArgument;
use super::node::{self, Handle, NodeRef, marker};
use super::search;
use core::fmt::Debug;
use core::fmt;
use core::iter::{Peekable, FromIterator, FusedIterator};
-use core::ops::{BitOr, BitAnd, BitXor, Sub};
+use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeArgument};
use borrow::Borrow;
use btree_map::{BTreeMap, Keys};
use super::Recover;
-use range::RangeArgument;
// FIXME(conventions): implement bounded iterators
use string;
-/// The format function takes a precompiled format string and a list of
-/// arguments, to return the resulting formatted string.
+/// The `format` function takes an `Arguments` struct and returns the resulting
+/// formatted string.
///
-/// # Arguments
-///
-/// * args - a structure of arguments generated via the `format_args!` macro.
+/// The `Arguments` instance can be created with the `format_args!` macro.
///
/// # Examples
///
pub use core::ops; // RangeFull
}
-/// An endpoint of a range of keys.
-///
-/// # Examples
-///
-/// `Bound`s are range endpoints:
-///
-/// ```
-/// #![feature(collections_range)]
-///
-/// use std::collections::range::RangeArgument;
-/// use std::collections::Bound::*;
-///
-/// assert_eq!((..100).start(), Unbounded);
-/// assert_eq!((1..12).start(), Included(&1));
-/// assert_eq!((1..12).end(), Excluded(&12));
-/// ```
-///
-/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`].
-/// Note that in most cases, it's better to use range syntax (`1..5`) instead.
-///
-/// ```
-/// use std::collections::BTreeMap;
-/// use std::collections::Bound::{Excluded, Included, Unbounded};
-///
-/// let mut map = BTreeMap::new();
-/// map.insert(3, "a");
-/// map.insert(5, "b");
-/// map.insert(8, "c");
-///
-/// for (key, value) in map.range((Excluded(3), Included(8))) {
-/// println!("{}: {}", key, value);
-/// }
-///
-/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next());
-/// ```
-///
-/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range
-#[stable(feature = "collections_bound", since = "1.17.0")]
-#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
-pub enum Bound<T> {
- /// An inclusive bound.
- #[stable(feature = "collections_bound", since = "1.17.0")]
- Included(T),
- /// An exclusive bound.
- #[stable(feature = "collections_bound", since = "1.17.0")]
- Excluded(T),
- /// An infinite endpoint. Indicates that there is no bound in this direction.
- #[stable(feature = "collections_bound", since = "1.17.0")]
- Unbounded,
-}
+pub use core::ops::Bound;
/// An intermediate trait for specialization of `Extend`.
#[doc(hidden)]
#![unstable(feature = "collections_range",
reason = "waiting for dust to settle on inclusive ranges",
issue = "30877")]
+#![rustc_deprecated(reason = "moved to core::ops", since = "1.19.0")]
//! Range syntax.
-use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive};
-use Bound::{self, Excluded, Included, Unbounded};
-
-/// `RangeArgument` is implemented by Rust's built-in range types, produced
-/// by range syntax like `..`, `a..`, `..b` or `c..d`.
-pub trait RangeArgument<T: ?Sized> {
- /// Start index bound.
- ///
- /// Returns the start value as a `Bound`.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(alloc)]
- /// #![feature(collections_range)]
- ///
- /// extern crate alloc;
- ///
- /// # fn main() {
- /// use alloc::range::RangeArgument;
- /// use alloc::Bound::*;
- ///
- /// assert_eq!((..10).start(), Unbounded);
- /// assert_eq!((3..10).start(), Included(&3));
- /// # }
- /// ```
- fn start(&self) -> Bound<&T>;
-
- /// End index bound.
- ///
- /// Returns the end value as a `Bound`.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(alloc)]
- /// #![feature(collections_range)]
- ///
- /// extern crate alloc;
- ///
- /// # fn main() {
- /// use alloc::range::RangeArgument;
- /// use alloc::Bound::*;
- ///
- /// assert_eq!((3..).end(), Unbounded);
- /// assert_eq!((3..10).end(), Excluded(&10));
- /// # }
- /// ```
- fn end(&self) -> Bound<&T>;
-}
-
-// FIXME add inclusive ranges to RangeArgument
-
-impl<T: ?Sized> RangeArgument<T> for RangeFull {
- fn start(&self) -> Bound<&T> {
- Unbounded
- }
- fn end(&self) -> Bound<&T> {
- Unbounded
- }
-}
-
-impl<T> RangeArgument<T> for RangeFrom<T> {
- fn start(&self) -> Bound<&T> {
- Included(&self.start)
- }
- fn end(&self) -> Bound<&T> {
- Unbounded
- }
-}
-
-impl<T> RangeArgument<T> for RangeTo<T> {
- fn start(&self) -> Bound<&T> {
- Unbounded
- }
- fn end(&self) -> Bound<&T> {
- Excluded(&self.end)
- }
-}
-
-impl<T> RangeArgument<T> for Range<T> {
- fn start(&self) -> Bound<&T> {
- Included(&self.start)
- }
- fn end(&self) -> Bound<&T> {
- Excluded(&self.end)
- }
-}
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-impl<T> RangeArgument<T> for RangeInclusive<T> {
- fn start(&self) -> Bound<&T> {
- Included(&self.start)
- }
- fn end(&self) -> Bound<&T> {
- Included(&self.end)
- }
-}
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-impl<T> RangeArgument<T> for RangeToInclusive<T> {
- fn start(&self) -> Bound<&T> {
- Unbounded
- }
- fn end(&self) -> Bound<&T> {
- Included(&self.end)
- }
-}
-
-impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) {
- fn start(&self) -> Bound<&T> {
- match *self {
- (Included(ref start), _) => Included(start),
- (Excluded(ref start), _) => Excluded(start),
- (Unbounded, _) => Unbounded,
- }
- }
-
- fn end(&self) -> Bound<&T> {
- match *self {
- (_, Included(ref end)) => Included(end),
- (_, Excluded(ref end)) => Excluded(end),
- (_, Unbounded) => Unbounded,
- }
- }
-}
-
-impl<'a, T: ?Sized + 'a> RangeArgument<T> for (Bound<&'a T>, Bound<&'a T>) {
- fn start(&self) -> Bound<&T> {
- self.0
- }
-
- fn end(&self) -> Bound<&T> {
- self.1
- }
-}
+pub use core::ops::RangeArgument;
use core::fmt;
use core::hash;
use core::iter::{FromIterator, FusedIterator};
-use core::ops::{self, Add, AddAssign, Index, IndexMut};
+use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeArgument};
+use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ptr;
use core::str::pattern::Pattern;
use std_unicode::lossy;
use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER};
use borrow::{Cow, ToOwned};
-use range::RangeArgument;
-use Bound::{Excluded, Included, Unbounded};
use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars};
use vec::Vec;
use boxed::Box;
use core::mem;
#[cfg(not(test))]
use core::num::Float;
-use core::ops::{InPlace, Index, IndexMut, Place, Placer};
+use core::ops::{InPlace, Index, IndexMut, Place, Placer, RangeArgument};
+use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ops;
use core::ptr;
use core::ptr::Shared;
use borrow::Cow;
use boxed::Box;
use raw_vec::RawVec;
-use super::range::RangeArgument;
-use Bound::{Excluded, Included, Unbounded};
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
///
use core::fmt;
use core::iter::{repeat, FromIterator, FusedIterator};
use core::mem;
-use core::ops::{Index, IndexMut, Place, Placer, InPlace};
+use core::ops::{Index, IndexMut, Place, Placer, InPlace, RangeArgument};
+use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ptr;
use core::ptr::Shared;
use core::slice;
use raw_vec::RawVec;
-use super::range::RangeArgument;
-use Bound::{Excluded, Included, Unbounded};
use super::vec::Vec;
const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
pub use alloc::borrow;
pub use alloc::fmt;
pub use alloc::linked_list;
+#[allow(deprecated)]
pub use alloc::range;
pub use alloc::slice;
pub use alloc::str;
/// Example usage:
///
/// ```
-/// #![feature(reverse_cmp_key)]
/// use std::cmp::Reverse;
///
/// let mut v = vec![1, 2, 3, 4, 5, 6];
/// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
/// ```
#[derive(PartialEq, Eq, Debug)]
-#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
pub struct Reverse<T>(pub T);
-#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
impl<T: PartialOrd> PartialOrd for Reverse<T> {
#[inline]
fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
fn gt(&self, other: &Self) -> bool { other.0 > self.0 }
}
-#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
impl<T: Ord> Ord for Reverse<T> {
#[inline]
fn cmp(&self, other: &Reverse<T>) -> Ordering {
fn fmt(&self, f: &mut Formatter) -> Result;
}
-/// The `write` function takes an output stream, a precompiled format string,
-/// and a list of arguments. The arguments will be formatted according to the
-/// specified format string into the output stream provided.
+/// The `write` function takes an output stream, and an `Arguments` struct
+/// that can be precompiled with the `format_args!` macro.
///
-/// # Arguments
-///
-/// * output - the buffer to write output to
-/// * args - the precompiled arguments generated by `format_args!`
+/// The arguments will be formatted according to the specified format string
+/// into the output stream provided.
///
/// # Examples
///
#[stable(feature = "rust1", since = "1.0.0")]
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
- // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
- // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel
- // Haswell E processors. LLVM is more able to optimize if we give a struct a
- // #[repr(simd)], even if we don't actually use this struct directly.
- //
- // FIXME repr(simd) broken on emscripten and redox
- #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))]
- struct Block(u64, u64, u64, u64);
- struct UnalignedBlock(u64, u64, u64, u64);
-
- let block_size = size_of::<Block>();
-
- // Get raw pointers to the bytes of x & y for easier manipulation
- let x = x as *mut T as *mut u8;
- let y = y as *mut T as *mut u8;
-
- // Loop through x & y, copying them `Block` at a time
- // The optimizer should unroll the loop fully for most types
- // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
- let len = size_of::<T>();
- let mut i = 0;
- while i + block_size <= len {
- // Create some uninitialized memory as scratch space
- // Declaring `t` here avoids aligning the stack when this loop is unused
- let mut t: Block = uninitialized();
- let t = &mut t as *mut _ as *mut u8;
- let x = x.offset(i as isize);
- let y = y.offset(i as isize);
-
- // Swap a block of bytes of x & y, using t as a temporary buffer
- // This should be optimized into efficient SIMD operations where available
- ptr::copy_nonoverlapping(x, t, block_size);
- ptr::copy_nonoverlapping(y, x, block_size);
- ptr::copy_nonoverlapping(t, y, block_size);
- i += block_size;
- }
-
-
- if i < len {
- // Swap any remaining bytes, using aligned types to copy
- // where appropriate (this information is lost by conversion
- // to *mut u8, so restore it manually here)
- let mut t: UnalignedBlock = uninitialized();
- let rem = len - i;
-
- let t = &mut t as *mut _ as *mut u8;
- let x = x.offset(i as isize);
- let y = y.offset(i as isize);
-
- ptr::copy_nonoverlapping(x, t, rem);
- ptr::copy_nonoverlapping(y, x, rem);
- ptr::copy_nonoverlapping(t, y, rem);
- }
+ ptr::swap_nonoverlapping(x, y, 1);
}
}
}
}
- /// Returns `true` if `self` is positive, including `+0.0` and
- /// `Float::infinity()`.
+ /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+ /// positive sign bit and positive infinity.
#[inline]
fn is_sign_positive(self) -> bool {
- self > 0.0 || (1.0 / self) == INFINITY
+ !self.is_sign_negative()
}
- /// Returns `true` if `self` is negative, including `-0.0` and
- /// `Float::neg_infinity()`.
+ /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+ /// negative sign bit and negative infinity.
#[inline]
fn is_sign_negative(self) -> bool {
- self < 0.0 || (1.0 / self) == NEG_INFINITY
+ // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
+ // applies to zeros and NaNs as well.
+ #[repr(C)]
+ union F32Bytes {
+ f: f32,
+ b: u32
+ }
+ unsafe { F32Bytes { f: self }.b & 0x8000_0000 != 0 }
}
/// Returns the reciprocal (multiplicative inverse) of the number.
}
}
- /// Returns `true` if `self` is positive, including `+0.0` and
- /// `Float::infinity()`.
+ /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+ /// positive sign bit and positive infinity.
#[inline]
fn is_sign_positive(self) -> bool {
- self > 0.0 || (1.0 / self) == INFINITY
+ !self.is_sign_negative()
}
- /// Returns `true` if `self` is negative, including `-0.0` and
- /// `Float::neg_infinity()`.
+ /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+ /// negative sign bit and negative infinity.
#[inline]
fn is_sign_negative(self) -> bool {
- self < 0.0 || (1.0 / self) == NEG_INFINITY
+ #[repr(C)]
+ union F64Bytes {
+ f: f64,
+ b: u64
+ }
+ unsafe { F64Bytes { f: self }.b & 0x8000_0000_0000_0000 != 0 }
}
/// Returns the reciprocal (multiplicative inverse) of the number.
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
+#[stable(feature = "range_argument", since = "1.19.0")]
+pub use self::range::{RangeArgument, Bound};
+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
pub use self::range::{RangeInclusive, RangeToInclusive};
// except according to those terms.
use fmt;
+use ops::Bound::{Included, Excluded, Unbounded};
/// An unbounded range. Use `..` (two dots) for its shorthand.
///
/// assert_eq!(arr[1..3], [ 1,2 ]); // Range
/// }
/// ```
-#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
+#[derive(Clone, PartialEq, Eq, Hash)]
+// not Copy -- see #27186
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Range<Idx> {
/// The lower bound of the range (inclusive).
/// assert_eq!(arr[1..3], [ 1,2 ]);
/// }
/// ```
-#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
+#[derive(Clone, PartialEq, Eq, Hash)]
+// not Copy -- see #27186
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeFrom<Idx> {
/// The lower bound of the range (inclusive).
/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive
/// }
/// ```
-#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
+#[derive(Clone, PartialEq, Eq, Hash)]
+// not Copy -- see #27186
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
pub struct RangeInclusive<Idx> {
/// The lower bound of the range (inclusive).
- #[unstable(feature = "inclusive_range",
- reason = "recently added, follows RFC",
+ #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC",
issue = "28237")]
pub start: Idx,
/// The upper bound of the range (inclusive).
- #[unstable(feature = "inclusive_range",
- reason = "recently added, follows RFC",
+ #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC",
issue = "28237")]
pub end: Idx,
}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
pub struct RangeToInclusive<Idx> {
/// The upper bound of the range (inclusive)
- #[unstable(feature = "inclusive_range",
- reason = "recently added, follows RFC",
+ #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC",
issue = "28237")]
pub end: Idx,
}
// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
// because underflow would be possible with (..0).into()
+
+/// `RangeArgument` is implemented by Rust's built-in range types, produced
+/// by range syntax like `..`, `a..`, `..b` or `c..d`.
+#[stable(feature = "range_argument", since = "1.19.0")]
+pub trait RangeArgument<T: ?Sized> {
+ /// Start index bound.
+ ///
+ /// Returns the start value as a `Bound`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ops::RangeArgument;
+ /// use std::ops::Bound::*;
+ ///
+ /// assert_eq!((..10).start(), Unbounded);
+ /// assert_eq!((3..10).start(), Included(&3));
+ /// ```
+ #[stable(feature = "range_argument", since = "1.19.0")]
+ fn start(&self) -> Bound<&T>;
+
+ /// End index bound.
+ ///
+ /// Returns the end value as a `Bound`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ops::RangeArgument;
+ /// use std::ops::Bound::*;
+ ///
+ /// assert_eq!((3..).end(), Unbounded);
+ /// assert_eq!((3..10).end(), Excluded(&10));
+ /// ```
+ #[stable(feature = "range_argument", since = "1.19.0")]
+ fn end(&self) -> Bound<&T>;
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T: ?Sized> RangeArgument<T> for RangeFull {
+ fn start(&self) -> Bound<&T> {
+ Unbounded
+ }
+ fn end(&self) -> Bound<&T> {
+ Unbounded
+ }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T> RangeArgument<T> for RangeFrom<T> {
+ fn start(&self) -> Bound<&T> {
+ Included(&self.start)
+ }
+ fn end(&self) -> Bound<&T> {
+ Unbounded
+ }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T> RangeArgument<T> for RangeTo<T> {
+ fn start(&self) -> Bound<&T> {
+ Unbounded
+ }
+ fn end(&self) -> Bound<&T> {
+ Excluded(&self.end)
+ }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T> RangeArgument<T> for Range<T> {
+ fn start(&self) -> Bound<&T> {
+ Included(&self.start)
+ }
+ fn end(&self) -> Bound<&T> {
+ Excluded(&self.end)
+ }
+}
+
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
+impl<T> RangeArgument<T> for RangeInclusive<T> {
+ fn start(&self) -> Bound<&T> {
+ Included(&self.start)
+ }
+ fn end(&self) -> Bound<&T> {
+ Included(&self.end)
+ }
+}
+
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
+impl<T> RangeArgument<T> for RangeToInclusive<T> {
+ fn start(&self) -> Bound<&T> {
+ Unbounded
+ }
+ fn end(&self) -> Bound<&T> {
+ Included(&self.end)
+ }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) {
+ fn start(&self) -> Bound<&T> {
+ match *self {
+ (Included(ref start), _) => Included(start),
+ (Excluded(ref start), _) => Excluded(start),
+ (Unbounded, _) => Unbounded,
+ }
+ }
+
+ fn end(&self) -> Bound<&T> {
+ match *self {
+ (_, Included(ref end)) => Included(end),
+ (_, Excluded(ref end)) => Excluded(end),
+ (_, Unbounded) => Unbounded,
+ }
+ }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<'a, T: ?Sized + 'a> RangeArgument<T> for (Bound<&'a T>, Bound<&'a T>) {
+ fn start(&self) -> Bound<&T> {
+ self.0
+ }
+
+ fn end(&self) -> Bound<&T> {
+ self.1
+ }
+}
+
+/// An endpoint of a range of keys.
+///
+/// # Examples
+///
+/// `Bound`s are range endpoints:
+///
+/// ```
+/// use std::ops::RangeArgument;
+/// use std::ops::Bound::*;
+///
+/// assert_eq!((..100).start(), Unbounded);
+/// assert_eq!((1..12).start(), Included(&1));
+/// assert_eq!((1..12).end(), Excluded(&12));
+/// ```
+#[stable(feature = "collections_bound", since = "1.17.0")]
+#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
+pub enum Bound<T> {
+ /// An inclusive bound.
+ #[stable(feature = "collections_bound", since = "1.17.0")]
+ Included(T),
+ /// An exclusive bound.
+ #[stable(feature = "collections_bound", since = "1.17.0")]
+ Excluded(T),
+ /// An infinite endpoint. Indicates that there is no bound in this direction.
+ #[stable(feature = "collections_bound", since = "1.17.0")]
+ Unbounded,
+}
mem::forget(tmp);
}
+/// Swaps a sequence of values at two mutable locations of the same type.
+///
+/// # Safety
+///
+/// The two arguments must each point to the beginning of `count` locations
+/// of valid memory, and the two memory ranges must not overlap.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// #![feature(swap_nonoverlapping)]
+///
+/// use std::ptr;
+///
+/// let mut x = [1, 2, 3, 4];
+/// let mut y = [7, 8, 9];
+///
+/// unsafe {
+/// ptr::swap_nonoverlapping(x.as_mut_ptr(), y.as_mut_ptr(), 2);
+/// }
+///
+/// assert_eq!(x, [7, 8, 3, 4]);
+/// assert_eq!(y, [1, 2, 9]);
+/// ```
+#[inline]
+#[unstable(feature = "swap_nonoverlapping", issue = "42818")]
+pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+ let x = x as *mut u8;
+ let y = y as *mut u8;
+ let len = mem::size_of::<T>() * count;
+ swap_nonoverlapping_bytes(x, y, len)
+}
+
+#[inline]
+unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
+ // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
+ // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel
+ // Haswell E processors. LLVM is more able to optimize if we give a struct a
+ // #[repr(simd)], even if we don't actually use this struct directly.
+ //
+ // FIXME repr(simd) broken on emscripten and redox
+ #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))]
+ struct Block(u64, u64, u64, u64);
+ struct UnalignedBlock(u64, u64, u64, u64);
+
+ let block_size = mem::size_of::<Block>();
+
+ // Loop through x & y, copying them `Block` at a time
+ // The optimizer should unroll the loop fully for most types
+ // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
+ let mut i = 0;
+ while i + block_size <= len {
+ // Create some uninitialized memory as scratch space
+ // Declaring `t` here avoids aligning the stack when this loop is unused
+ let mut t: Block = mem::uninitialized();
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ // Swap a block of bytes of x & y, using t as a temporary buffer
+ // This should be optimized into efficient SIMD operations where available
+ copy_nonoverlapping(x, t, block_size);
+ copy_nonoverlapping(y, x, block_size);
+ copy_nonoverlapping(t, y, block_size);
+ i += block_size;
+ }
+
+ if i < len {
+ // Swap any remaining bytes
+ let mut t: UnalignedBlock = mem::uninitialized();
+ let rem = len - i;
+
+ let t = &mut t as *mut _ as *mut u8;
+ let x = x.offset(i as isize);
+ let y = y.offset(i as isize);
+
+ copy_nonoverlapping(x, t, rem);
+ copy_nonoverlapping(y, x, rem);
+ copy_nonoverlapping(t, y, rem);
+ }
+}
+
/// Replaces the value at `dest` with `src`, returning the old
/// value, without dropping either.
///
break;
}
- ptr_swap_n(
+ ptr::swap_nonoverlapping(
mid.offset(-(left as isize)),
mid.offset((right-delta) as isize),
delta);
ptr::copy_nonoverlapping(buf, mid.offset(-(left as isize)), right);
}
}
-
-unsafe fn ptr_swap_n<T>(a: *mut T, b: *mut T, n: usize) {
- for i in 0..n {
- // These are nonoverlapping, so use mem::swap instead of ptr::swap
- mem::swap(&mut *a.offset(i as isize), &mut *b.offset(i as isize));
- }
-}
// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
// mut iter => {
// [opt_ident]: loop {
- // let mut _next;
+ // let mut __next;
// match ::std::iter::Iterator::next(&mut iter) {
- // ::std::option::Option::Some(val) => _next = val,
+ // ::std::option::Option::Some(val) => __next = val,
// ::std::option::Option::None => break
// };
- // let <pat> = _next;
+ // let <pat> = __next;
// StmtExpr(<body>);
// }
// }
let iter = self.str_to_ident("iter");
- let next_ident = self.str_to_ident("_next");
+ let next_ident = self.str_to_ident("__next");
let next_pat = self.pat_ident_binding_mode(e.span,
next_ident,
hir::BindByValue(hir::MutMutable));
let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id));
- // `let mut _next`
+ // `let mut __next`
let next_let = self.stmt_let_pat(e.span,
None,
next_pat,
hir::LocalSource::ForLoopDesugar);
- // `let <pat> = _next`
+ // `let <pat> = __next`
let pat = self.lower_pat(pat);
let pat_let = self.stmt_let_pat(e.span,
Some(next_expr),
/// last good node id we found. Note that reaching the crate root (id == 0),
/// is not an error, since items in the crate module have the crate root as
/// parent.
- fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, NodeId>
- where F: Fn(&Node<'hir>) -> bool
+ fn walk_parent_nodes<F, F2>(&self,
+ start_id: NodeId,
+ found: F,
+ bail_early: F2)
+ -> Result<NodeId, NodeId>
+ where F: Fn(&Node<'hir>) -> bool, F2: Fn(&Node<'hir>) -> bool
{
let mut id = start_id;
loop {
Some(ref node) => {
if found(node) {
return Ok(parent_node);
+ } else if bail_early(node) {
+ return Err(parent_node);
}
}
None => {
}
}
+ /// Retrieve the NodeId for `id`'s enclosing method, unless there's a
+ /// `while` or `loop` before reacing it, as block tail returns are not
+ /// available in them.
+ ///
+ /// ```
+ /// fn foo(x: usize) -> bool {
+ /// if x == 1 {
+ /// true // `get_return_block` gets passed the `id` corresponding
+ /// } else { // to this, it will return `foo`'s `NodeId`.
+ /// false
+ /// }
+ /// }
+ /// ```
+ ///
+ /// ```
+ /// fn foo(x: usize) -> bool {
+ /// loop {
+ /// true // `get_return_block` gets passed the `id` corresponding
+ /// } // to this, it will return `None`.
+ /// false
+ /// }
+ /// ```
+ pub fn get_return_block(&self, id: NodeId) -> Option<NodeId> {
+ let match_fn = |node: &Node| {
+ match *node {
+ NodeItem(_) |
+ NodeForeignItem(_) |
+ NodeTraitItem(_) |
+ NodeImplItem(_) => true,
+ _ => false,
+ }
+ };
+ let match_non_returning_block = |node: &Node| {
+ match *node {
+ NodeExpr(ref expr) => {
+ match expr.node {
+ ExprWhile(..) | ExprLoop(..) => true,
+ _ => false,
+ }
+ }
+ _ => false,
+ }
+ };
+
+ match self.walk_parent_nodes(id, match_fn, match_non_returning_block) {
+ Ok(id) => Some(id),
+ Err(_) => None,
+ }
+ }
+
/// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
/// parent item is in this map. The "parent item" is the closest parent node
/// in the AST which is recorded by the map and is an item, either an item
NodeTraitItem(_) |
NodeImplItem(_) => true,
_ => false,
- }) {
+ }, |_| false) {
Ok(id) => id,
Err(id) => id,
}
let id = match self.walk_parent_nodes(id, |node| match *node {
NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true,
_ => false,
- }) {
+ }, |_| false) {
Ok(id) => id,
Err(id) => id,
};
NodeImplItem(_) |
NodeBlock(_) => true,
_ => false,
- }) {
+ }, |_| false) {
Ok(id) => Some(id),
Err(_) => None,
}
region.hash_stable(hcx, hasher);
pointee_ty.hash_stable(hcx, hasher);
}
- TyFnDef(def_id, substs, ref sig) => {
+ TyFnDef(def_id, substs) => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
- sig.hash_stable(hcx, hasher);
}
TyFnPtr(ref sig) => {
sig.hash_stable(hcx, hasher);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use hir::{self, map, Local, Pat, Body};
+use hir::{self, Local, Pat, Body};
use hir::intravisit::{self, Visitor, NestedVisitorMap};
use infer::InferCtxt;
use infer::type_variable::TypeVariableOrigin;
}
}
- pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
+ pub fn need_type_info(&self, body_id: Option<hir::BodyId>, span: Span, ty: Ty<'tcx>) {
let ty = self.resolve_type_vars_if_possible(&ty);
let name = self.extract_type_name(&ty);
found_arg_pattern: None,
};
- // #40294: cause.body_id can also be a fn declaration.
- // Currently, if it's anything other than NodeExpr, we just ignore it
- match self.tcx.hir.find(body_id.node_id) {
- Some(map::NodeExpr(expr)) => local_visitor.visit_expr(expr),
- _ => ()
+ if let Some(body_id) = body_id {
+ let expr = self.tcx.hir.expect_expr(body_id.node_id);
+ local_visitor.visit_expr(expr);
}
if let Some(pattern) = local_visitor.found_arg_pattern {
Some(self.tcx.closure_kind(def_id))
}
- pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
+ /// Obtain the signature of a function or closure.
+ /// For closures, unlike `tcx.fn_sig(def_id)`, this method will
+ /// work during the type-checking of the enclosing function and
+ /// return the closure signature in its partially inferred state.
+ pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
if let Some(tables) = self.in_progress_tables {
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
if let Some(&ty) = tables.borrow().closure_tys.get(&id) {
}
}
- self.tcx.closure_type(def_id)
+ self.tcx.fn_sig(def_id)
}
}
self.by_name.insert(name.into(), Removed(reason.into()));
}
- #[allow(unused_variables)]
- fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
- -> Result<LintId, FindLintError>
- {
+ fn find_lint(&self, lint_name: &str) -> Result<LintId, FindLintError> {
match self.by_name.get(lint_name) {
Some(&Id(lint_id)) => Ok(lint_id),
Some(&Renamed(_, lint_id)) => {
Ok(lint_id)
},
- Some(&Removed(ref reason)) => {
+ Some(&Removed(_)) => {
Err(FindLintError::Removed)
},
None => Err(FindLintError::NotFound)
&lint_name[..], level);
let lint_flag_val = Symbol::intern(&lint_name);
- match self.find_lint(&lint_name[..], sess, None) {
+ match self.find_lint(&lint_name[..]) {
Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))),
Err(FindLintError::Removed) => { }
Err(_) => {
let mut pushed = 0;
for result in gather_attrs(attrs) {
- let v = match result {
+ let (is_group, lint_level_spans) = match result {
Err(span) => {
span_err!(self.sess(), span, E0452,
"malformed lint attribute");
continue;
}
Ok((lint_name, level, span)) => {
- match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) {
- Ok(lint_id) => vec![(lint_id, level, span)],
+ match self.lints().find_lint(&lint_name.as_str()) {
+ Ok(lint_id) => (false, vec![(lint_id, level, span)]),
Err(FindLintError::NotFound) => {
match self.lints().lint_groups.get(&*lint_name.as_str()) {
- Some(&(ref v, _)) => v.iter()
+ Some(&(ref v, _)) => (true,
+ v.iter()
.map(|lint_id: &LintId|
(*lint_id, level, span))
- .collect(),
+ .collect()),
None => {
// The lint or lint group doesn't exist.
// This is an error, but it was handled
let lint_attr_name = result.expect("lint attribute should be well-formed").0;
- for (lint_id, level, span) in v {
+ for (lint_id, level, span) in lint_level_spans {
let (now, now_source) = self.lint_sess().get_source(lint_id);
if now == Forbid && level != Forbid {
- let lint_name = lint_id.to_string();
+ let forbidden_lint_name = match now_source {
+ LintSource::Default => lint_id.to_string(),
+ LintSource::Node(name, _) => name.to_string(),
+ LintSource::CommandLine(name) => name.to_string(),
+ };
let mut diag_builder = struct_span_err!(self.sess(), span, E0453,
"{}({}) overruled by outer forbid({})",
- level.as_str(), lint_name,
- lint_name);
+ level.as_str(), lint_attr_name,
+ forbidden_lint_name);
diag_builder.span_label(span, "overruled by previous forbid");
match now_source {
LintSource::Default => &mut diag_builder,
LintSource::CommandLine(_) => {
diag_builder.note("`forbid` lint level was set on command line")
}
- }.emit()
+ }.emit();
+ if is_group { // don't set a separate error for every lint in the group
+ break;
+ }
} else if now != level {
let cx = self.lint_sess_mut();
cx.stack.push((lint_id, (now, now_source)));
fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
let s = d.read_str()?;
ty::tls::with(|tcx| {
- match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) {
+ match tcx.sess.lint_store.borrow().find_lint(&s) {
Ok(id) => Ok(id),
Err(_) => panic!("invalid lint-id `{}`", s),
}
//! `unsafe`.
use self::RootUnsafeContext::*;
-use ty::{self, Ty, TyCtxt};
+use ty::{self, TyCtxt};
use lint;
use syntax::ast;
UnsafeBlock(ast::NodeId),
}
-fn type_is_unsafe_function(ty: Ty) -> bool {
- match ty.sty {
- ty::TyFnDef(.., f) |
- ty::TyFnPtr(f) => f.unsafety() == hir::Unsafety::Unsafe,
- _ => false,
- }
-}
-
struct EffectCheckVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
match expr.node {
hir::ExprMethodCall(..) => {
let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
- let base_type = self.tcx.type_of(def_id);
- debug!("effect: method call case, base type is {:?}",
- base_type);
- if type_is_unsafe_function(base_type) {
+ let sig = self.tcx.fn_sig(def_id);
+ debug!("effect: method call case, signature is {:?}",
+ sig);
+
+ if sig.0.unsafety == hir::Unsafety::Unsafe {
self.require_unsafe(expr.span,
"invocation of unsafe method")
}
let base_type = self.tables.expr_ty_adjusted(base);
debug!("effect: call case, base type is {:?}",
base_type);
- if type_is_unsafe_function(base_type) {
- self.require_unsafe(expr.span, "call to unsafe function")
+ match base_type.sty {
+ ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+ if base_type.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
+ self.require_unsafe(expr.span, "call to unsafe function")
+ }
+ }
+ _ => {}
}
}
hir::ExprUnary(hir::UnDeref, ref base) => {
impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
fn def_id_is_transmute(&self, def_id: DefId) -> bool {
- let intrinsic = match self.tcx.type_of(def_id).sty {
- ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic,
- _ => return false
- };
- intrinsic && self.tcx.item_name(def_id) == "transmute"
+ self.tcx.fn_sig(def_id).abi() == RustIntrinsic &&
+ self.tcx.item_name(def_id) == "transmute"
}
fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
} else {
Def::Err
};
- match def {
- Def::Fn(did) if self.def_id_is_transmute(did) => {
+ if let Def::Fn(did) = def {
+ if self.def_id_is_transmute(did) {
let typ = self.tables.node_id_to_type(expr.id);
- let typ = self.tcx.lift_to_global(&typ).unwrap();
- match typ.sty {
- ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => {
- let from = sig.inputs().skip_binder()[0];
- let to = *sig.output().skip_binder();
- self.check_transmute(expr.span, from, to);
- }
- _ => {
- span_bug!(expr.span, "transmute wasn't a bare fn?!");
- }
- }
+ let sig = typ.fn_sig(self.tcx);
+ let from = sig.inputs().skip_binder()[0];
+ let to = *sig.output().skip_binder();
+ self.check_transmute(expr.span, from, to);
}
- _ => {}
}
intravisit::walk_expr(self, expr);
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn report_fulfillment_errors(&self,
- errors: &Vec<FulfillmentError<'tcx>>) {
+ errors: &Vec<FulfillmentError<'tcx>>,
+ body_id: Option<hir::BodyId>) {
#[derive(Debug)]
struct ErrorDescriptor<'tcx> {
predicate: ty::Predicate<'tcx>,
for (error, suppressed) in errors.iter().zip(is_suppressed) {
if !suppressed {
- self.report_fulfillment_error(error);
+ self.report_fulfillment_error(error, body_id);
}
}
}
false
}
- fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
+ fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>,
+ body_id: Option<hir::BodyId>) {
debug!("report_fulfillment_errors({:?})", error);
match error.code {
FulfillmentErrorCode::CodeSelectionError(ref e) => {
self.report_projection_error(&error.obligation, e);
}
FulfillmentErrorCode::CodeAmbiguity => {
- self.maybe_report_ambiguity(&error.obligation);
+ self.maybe_report_ambiguity(&error.obligation, body_id);
}
FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
self.report_mismatched_types(&error.obligation.cause,
}
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
- fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
+ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>,
+ body_id: Option<hir::BodyId>) {
// Unable to successfully determine, probably means
// insufficient type information, but could mean
// ambiguous impls. The latter *ought* to be a
// coherence violation, so we don't report it here.
let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
- let body_id = hir::BodyId { node_id: obligation.cause.body_id };
let span = obligation.cause.span;
debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
// both must be type variables, or the other would've been instantiated
assert!(a.is_ty_var() && b.is_ty_var());
- self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id },
+ self.need_type_info(body_id,
obligation.cause.span,
a);
}
ObligationCauseCode::VariableType(_) => {
err.note("all local variables must have a statically known size");
}
- ObligationCauseCode::ReturnType => {
+ ObligationCauseCode::SizedReturnType => {
err.note("the return type of a function must have a \
statically known size");
}
but not on the corresponding trait method",
predicate));
}
+ ObligationCauseCode::ReturnType(_) |
+ ObligationCauseCode::BlockTailExpression(_) => (),
}
}
/// Obligation incurred due to an object cast.
ObjectCastObligation(/* Object type */ Ty<'tcx>),
- /// Various cases where expressions must be sized/copy/etc:
- AssignmentLhsSized, // L = X implies that L is Sized
- StructInitializerSized, // S { ... } must be Sized
- VariableType(ast::NodeId), // Type of each variable must be Sized
- ReturnType, // Return type must be Sized
- RepeatVec, // [T,..n] --> T must be Copy
-
- // Types of fields (other than the last) in a struct must be sized.
+ // Various cases where expressions must be sized/copy/etc:
+ /// L = X implies that L is Sized
+ AssignmentLhsSized,
+ /// S { ... } must be Sized
+ StructInitializerSized,
+ /// Type of each variable must be Sized
+ VariableType(ast::NodeId),
+ /// Return type must be Sized
+ SizedReturnType,
+ /// [T,..n] --> T must be Copy
+ RepeatVec,
+
+ /// Types of fields (other than the last) in a struct must be sized.
FieldSized,
- // Constant expressions must be sized.
+ /// Constant expressions must be sized.
ConstSized,
- // static items must have `Sync` type
+ /// static items must have `Sync` type
SharedStatic,
BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
ImplDerivedObligation(DerivedObligationCause<'tcx>),
- // error derived when matching traits/impls; see ObligationCause for more details
+ /// error derived when matching traits/impls; see ObligationCause for more details
CompareImplMethodObligation {
item_name: ast::Name,
impl_item_def_id: DefId,
lint_id: Option<ast::NodeId>,
},
- // Checking that this expression can be assigned where it needs to be
+ /// Checking that this expression can be assigned where it needs to be
// FIXME(eddyb) #11161 is the original Expr required?
ExprAssignable,
- // Computing common supertype in the arms of a match expression
+ /// Computing common supertype in the arms of a match expression
MatchExpressionArm { arm_span: Span,
source: hir::MatchSource },
- // Computing common supertype in an if expression
+ /// Computing common supertype in an if expression
IfExpression,
- // Computing common supertype of an if expression with no else counter-part
+ /// Computing common supertype of an if expression with no else counter-part
IfExpressionWithNoElse,
- // `where a == b`
+ /// `where a == b`
EquatePredicate,
- // `main` has wrong type
+ /// `main` has wrong type
MainFunctionType,
- // `start` has wrong type
+ /// `start` has wrong type
StartFunctionType,
- // intrinsic has wrong type
+ /// intrinsic has wrong type
IntrinsicType,
- // method receiver
+ /// method receiver
MethodReceiver,
- // `return` with no expression
+ /// `return` with no expression
ReturnNoExpression,
+
+ /// `return` with an expression
+ ReturnType(ast::NodeId),
+
+ /// Block implicit return
+ BlockTailExpression(ast::NodeId),
}
#[derive(Clone, Debug, PartialEq, Eq)]
) {
Ok(predicates) => predicates,
Err(errors) => {
- infcx.report_fulfillment_errors(&errors);
+ infcx.report_fulfillment_errors(&errors, None);
// An unnormalized env is better than nothing.
return elaborated_env;
}
debug!("normalize_and_test_predicates(predicates={:?})",
predicates);
- tcx.infer_ctxt().enter(|infcx| {
+ let result = tcx.infer_ctxt().enter(|infcx| {
let param_env = ty::ParamEnv::empty(Reveal::All);
let mut selcx = SelectionContext::new(&infcx);
let mut fulfill_cx = FulfillmentContext::new();
}
fulfill_cx.select_all_or_error(&infcx).is_ok()
- })
+ });
+ debug!("normalize_and_test_predicates(predicates={:?}) = {:?}",
+ predicates, result);
+ result
}
/// Given a trait `trait_ref`, iterates the vtable entries
// The `Self` type is erased, so it should not appear in list of
// arguments or return type apart from the receiver.
- let ref sig = self.type_of(method.def_id).fn_sig();
+ let ref sig = self.fn_sig(method.def_id);
for input_ty in &sig.skip_binder().inputs()[1..] {
if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
return Some(MethodViolationCode::ReferencesSelf);
-> Progress<'tcx>
{
let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
- let sig = fn_type.fn_sig();
+ let sig = fn_type.fn_sig(selcx.tcx());
+ let Normalized {
+ value: sig,
+ obligations
+ } = normalize_with_depth(selcx,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth+1,
+ &sig);
+
confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
.with_addl_obligations(fn_pointer_vtable.nested)
+ .with_addl_obligations(obligations)
}
fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
-> Progress<'tcx>
{
let closure_typer = selcx.closure_typer();
- let closure_type = closure_typer.closure_type(vtable.closure_def_id)
+ let closure_type = closure_typer.fn_sig(vtable.closure_def_id)
.subst(selcx.tcx(), vtable.substs.substs);
let Normalized {
value: closure_type,
}
// provide an impl, but only for suitable `fn` pointers
- ty::TyFnDef(.., ty::Binder(ty::FnSig {
- unsafety: hir::Unsafety::Normal,
- abi: Abi::Rust,
- variadic: false,
- ..
- })) |
- ty::TyFnPtr(ty::Binder(ty::FnSig {
- unsafety: hir::Unsafety::Normal,
- abi: Abi::Rust,
- variadic: false,
- ..
- })) => {
- candidates.vec.push(FnPointerCandidate);
+ ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+ if let ty::Binder(ty::FnSig {
+ unsafety: hir::Unsafety::Normal,
+ abi: Abi::Rust,
+ variadic: false,
+ ..
+ }) = self_ty.fn_sig(self.tcx()) {
+ candidates.vec.push(FnPointerCandidate);
+ }
}
_ => { }
// ok to skip binder; it is reintroduced below
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
- let sig = self_ty.fn_sig();
+ let sig = self_ty.fn_sig(self.tcx());
let trait_ref =
self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
self_ty,
util::TupleArgumentsFlag::Yes)
.map_bound(|(trait_ref, _)| trait_ref);
+ let Normalized { value: trait_ref, obligations } =
+ project::normalize_with_depth(self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &trait_ref);
+
self.confirm_poly_trait_refs(obligation.cause.clone(),
obligation.param_env,
obligation.predicate.to_poly_trait_ref(),
trait_ref)?;
- Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] })
+ Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations })
}
fn confirm_closure_candidate(&mut self,
substs: ty::ClosureSubsts<'tcx>)
-> ty::PolyTraitRef<'tcx>
{
- let closure_type = self.infcx.closure_type(closure_def_id)
+ let closure_type = self.infcx.fn_sig(closure_def_id)
.subst(self.tcx(), substs.substs);
let ty::Binder((trait_ref, _)) =
self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
super::StructInitializerSized => Some(super::StructInitializerSized),
super::VariableType(id) => Some(super::VariableType(id)),
- super::ReturnType => Some(super::ReturnType),
+ super::ReturnType(id) => Some(super::ReturnType(id)),
+ super::SizedReturnType => Some(super::SizedReturnType),
super::RepeatVec => Some(super::RepeatVec),
super::FieldSized => Some(super::FieldSized),
super::ConstSized => Some(super::ConstSized),
lint_id: lint_id,
})
}
- super::ExprAssignable => {
- Some(super::ExprAssignable)
- }
+ super::ExprAssignable => Some(super::ExprAssignable),
super::MatchExpressionArm { arm_span, source } => {
Some(super::MatchExpressionArm { arm_span: arm_span,
source: source })
}
- super::IfExpression => {
- Some(super::IfExpression)
- }
- super::IfExpressionWithNoElse => {
- Some(super::IfExpressionWithNoElse)
- }
- super::EquatePredicate => {
- Some(super::EquatePredicate)
- }
- super::MainFunctionType => {
- Some(super::MainFunctionType)
- }
- super::StartFunctionType => {
- Some(super::StartFunctionType)
- }
- super::IntrinsicType => {
- Some(super::IntrinsicType)
- }
- super::MethodReceiver => {
- Some(super::MethodReceiver)
- }
+ super::IfExpression => Some(super::IfExpression),
+ super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
+ super::EquatePredicate => Some(super::EquatePredicate),
+ super::MainFunctionType => Some(super::MainFunctionType),
+ super::StartFunctionType => Some(super::StartFunctionType),
+ super::IntrinsicType => Some(super::IntrinsicType),
+ super::MethodReceiver => Some(super::MethodReceiver),
+ super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
}
}
}
super::AssignmentLhsSized |
super::StructInitializerSized |
super::VariableType(_) |
- super::ReturnType |
+ super::ReturnType(_) |
+ super::SizedReturnType |
super::ReturnNoExpression |
super::RepeatVec |
super::FieldSized |
super::ConstSized |
super::SharedStatic |
+ super::BlockTailExpression(_) |
super::CompareImplMethodObligation { .. } => self.clone(),
super::ProjectionWf(proj) => super::ProjectionWf(proj.fold_with(folder)),
super::AssignmentLhsSized |
super::StructInitializerSized |
super::VariableType(_) |
- super::ReturnType |
+ super::ReturnType(_) |
+ super::SizedReturnType |
super::ReturnNoExpression |
super::RepeatVec |
super::FieldSized |
super::ConstSized |
super::SharedStatic |
+ super::BlockTailExpression(_) |
super::CompareImplMethodObligation { .. } => false,
super::ProjectionWf(proj) => proj.visit_with(visitor),
}
pub fn mk_fn_def(self, def_id: DefId,
- substs: &'tcx Substs<'tcx>,
- fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
- self.mk_ty(TyFnDef(def_id, substs, fty))
+ substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+ self.mk_ty(TyFnDef(def_id, substs))
}
pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
// view of possibly unifying
simplify_type(tcx, mt.ty, can_simplify_params)
}
+ ty::TyFnDef(def_id, _) |
ty::TyClosure(def_id, _) => {
Some(ClosureSimplifiedType(def_id))
}
ty::TyTuple(ref tys, _) => {
Some(TupleSimplifiedType(tys.len()))
}
- ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => {
+ ty::TyFnPtr(ref f) => {
Some(FunctionSimplifiedType(f.skip_binder().inputs().len()))
}
ty::TyProjection(_) | ty::TyParam(_) => {
self.add_tys(&ts[..]);
}
- &ty::TyFnDef(_, substs, f) => {
+ &ty::TyFnDef(_, substs) => {
self.add_substs(substs);
- self.add_fn_sig(f);
}
&ty::TyFnPtr(f) => {
.filter_map(|ty| characteristic_def_id_of_type(ty))
.next(),
- ty::TyFnDef(def_id, ..) |
+ ty::TyFnDef(def_id, _) |
ty::TyClosure(def_id, _) => Some(def_id),
ty::TyBool |
/// for trans. This is also the only query that can fetch non-local MIR, at present.
[] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>,
- /// Records the type of each closure. The def ID is the ID of the
+ /// Type of each closure. The def ID is the ID of the
/// expression defining the closure.
[] closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
- /// Records the type of each closure. The def ID is the ID of the
- /// expression defining the closure.
- [] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
+ /// The signature of functions and closures.
+ [] fn_sig: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
/// Caches CoerceUnsized kinds for impls on custom types.
[] coerce_unsized_info: ItemSignature(DefId)
// late-bound regions, and we don't want method signatures to show up
// `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
// regions just fine, showing `fn(&MyType)`.
- format!("{}", tcx.type_of(self.def_id).fn_sig().skip_binder())
+ format!("{}", tcx.fn_sig(self.def_id).skip_binder())
}
ty::AssociatedKind::Type => format!("type {};", self.name.to_string()),
ty::AssociatedKind::Const => {
_ => false,
}
}
+
+ pub fn is_suggestable(&self) -> bool {
+ match self.sty {
+ TypeVariants::TyAnon(..) |
+ TypeVariants::TyFnDef(..) |
+ TypeVariants::TyFnPtr(..) |
+ TypeVariants::TyDynamic(..) |
+ TypeVariants::TyClosure(..) |
+ TypeVariants::TyProjection(..) => false,
+ _ => true,
+ }
+ }
}
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::TyS<'tcx> {
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
} else {
- let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
+ let substs = relate_substs(relation, None, a.substs, b.substs)?;
Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
}
}
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
} else {
- let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
+ let substs = relate_substs(relation, None, a.substs, b.substs)?;
Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
}
}
}
}
- (&ty::TyFnDef(a_def_id, a_substs, a_fty),
- &ty::TyFnDef(b_def_id, b_substs, b_fty))
+ (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs))
if a_def_id == b_def_id =>
{
- let substs = relate_substs(relation, None, a_substs, b_substs)?;
- let fty = relation.relate(&a_fty, &b_fty)?;
- Ok(tcx.mk_fn_def(a_def_id, substs, fty))
+ let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
+ Ok(tcx.mk_fn_def(a_def_id, substs))
}
(&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) =>
ty::TyDynamic(ref trait_ty, ref region) =>
ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted),
- ty::TyFnDef(def_id, substs, f) => {
- ty::TyFnDef(def_id,
- substs.fold_with(folder),
- f.fold_with(folder))
+ ty::TyFnDef(def_id, substs) => {
+ ty::TyFnDef(def_id, substs.fold_with(folder))
}
ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)),
ty::TyRef(ref r, tm) => {
ty::TyDynamic(ref trait_ty, ref reg) =>
trait_ty.visit_with(visitor) || reg.visit_with(visitor),
ty::TyTuple(ts, _) => ts.visit_with(visitor),
- ty::TyFnDef(_, substs, ref f) => {
- substs.visit_with(visitor) || f.visit_with(visitor)
- }
+ ty::TyFnDef(_, substs) => substs.visit_with(visitor),
ty::TyFnPtr(ref f) => f.visit_with(visitor),
ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
use hir::map::DefPathHash;
use middle::region;
-use ty::subst::Substs;
+use ty::subst::{Substs, Subst};
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
use ty::{Slice, TyS};
use ty::subst::Kind;
/// The anonymous type of a function declaration/definition. Each
/// function has a unique type.
- TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>),
+ TyFnDef(DefId, &'tcx Substs<'tcx>),
/// A pointer to a function. Written as `fn() -> i32`.
TyFnPtr(PolyFnSig<'tcx>),
}
}
- pub fn fn_sig(&self) -> PolyFnSig<'tcx> {
+ pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> {
match self.sty {
- TyFnDef(.., f) | TyFnPtr(f) => f,
+ TyFnDef(def_id, substs) => {
+ tcx.fn_sig(def_id).subst(tcx, substs)
+ }
+ TyFnPtr(f) => f,
_ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
}
}
TyRef(_, m) => self.hash(m.mutbl),
TyClosure(def_id, _) |
TyAnon(def_id, _) |
- TyFnDef(def_id, ..) => self.def_id(def_id),
+ TyFnDef(def_id, _) => self.def_id(def_id),
TyAdt(d, _) => self.def_id(d.did),
TyFnPtr(f) => {
self.hash(f.unsafety());
ty::TyTuple(ts, _) => {
stack.extend(ts.iter().cloned().rev());
}
- ty::TyFnDef(_, substs, ft) => {
+ ty::TyFnDef(_, substs) => {
stack.extend(substs.types().rev());
- push_sig_subtypes(stack, ft);
}
ty::TyFnPtr(ft) => {
push_sig_subtypes(stack, ft);
}
write!(f, ")")
}
- TyFnDef(def_id, substs, ref bare_fn) => {
- write!(f, "{} {{", bare_fn.0)?;
+ TyFnDef(def_id, substs) => {
+ ty::tls::with(|tcx| {
+ let mut sig = tcx.fn_sig(def_id);
+ if let Some(substs) = tcx.lift(&substs) {
+ sig = sig.subst(tcx, substs);
+ }
+ write!(f, "{} {{", sig.0)
+ })?;
parameterized(f, substs, def_id, &[])?;
write!(f, "}}")
}
terminator: &'a Option<mir::Terminator<'tcx>>)
-> Option<(&'a [mir::Operand<'tcx>], Span)> {
if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator {
- if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind
- {
- if let mir::Operand::Constant(ref func) = *oper
- {
- if let ty::TyFnDef(def_id, _, sig) = func.ty.sty
- {
- let abi = sig.abi();
+ if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind {
+ if let mir::Operand::Constant(ref func) = *oper {
+ if let ty::TyFnDef(def_id, _) = func.ty.sty {
+ let abi = tcx.fn_sig(def_id).abi();
let name = tcx.item_name(def_id);
- if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
- if name == "rustc_peek" {
- return Some((args, source_info.span));
- }
+ if abi == Abi::RustIntrinsic && name == "rustc_peek" {
+ return Some((args, source_info.span));
}
}
}
use rustc::middle::const_val::{ConstEvalErr, ConstVal};
use rustc::mir::{Field, BorrowKind, Mutability};
-use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region};
+use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
use rustc::ty::subst::{Substs, Kind};
use rustc::hir::{self, PatKind, RangeEnd};
use rustc::hir::def::{Def, CtorKind};
let adt_def = self.tcx.adt_def(enum_id);
if adt_def.variants.len() > 1 {
let substs = match ty.sty {
- TypeVariants::TyAdt(_, substs) => substs,
- TypeVariants::TyFnDef(_, substs, _) => substs,
+ ty::TyAdt(_, substs) |
+ ty::TyFnDef(_, substs) => substs,
_ => bug!("inappropriate type for def: {:?}", ty.sty),
};
PatternKind::Variant {
//!
//! The N above is determined by Array's implementor, by way of an associatated constant.
-use std::ops::{Deref, DerefMut};
+use std::ops::{Deref, DerefMut, RangeArgument};
use std::iter::{self, IntoIterator, FromIterator};
use std::slice;
use std::vec;
-use std::collections::range::RangeArgument;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use std::marker::Unsize;
use std::iter::Extend;
use std::ptr::{self, drop_in_place, Shared};
-use std::ops::{Deref, DerefMut, Range};
+use std::ops::{Deref, DerefMut, Range, RangeArgument};
+use std::ops::Bound::{Excluded, Included, Unbounded};
use std::hash::{Hash, Hasher};
use std::slice;
use std::fmt;
use std::mem;
-use std::collections::range::RangeArgument;
-use std::collections::Bound::{Excluded, Included, Unbounded};
use std::mem::ManuallyDrop;
pub unsafe trait Array {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::collections::range::RangeArgument;
use std::fmt::Debug;
use std::iter::{self, FromIterator};
use std::slice;
use std::marker::PhantomData;
-use std::ops::{Index, IndexMut, Range};
+use std::ops::{Index, IndexMut, Range, RangeArgument};
use std::fmt;
use std::vec;
use std::u32;
#![deny(warnings)]
#![feature(shared)]
-#![feature(collections_range)]
#![feature(nonzero)]
#![feature(unboxed_closures)]
#![feature(fn_traits)]
// don't display multiline suggestions as labels
sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
let substitution = &sugg.substitution_parts[0].substitutions[0];
- let msg = format!("help: {} `{}`", sugg.msg, substitution);
+ let msg = if substitution.len() == 0 {
+ // This substitution is only removal, don't show it
+ format!("help: {}", sugg.msg)
+ } else {
+ format!("help: {} `{}`", sugg.msg, substitution)
+ };
primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg);
} else {
// if there are multiple suggestions, print them all in full
// These may occur in patterns
// and can maybe contain float literals
ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f),
- // These may occur in patterns
- // and can't contain float literals
- ExprKind::Path(..) => (),
- // If something unhandled is encountered, we need to expand the
- // search or ignore more ExprKinds.
- _ => span_bug!(expr.span, "Unhandled expression {:?} in float lit pattern lint",
- expr.node),
+ // Other kinds of exprs can't occur in patterns so we don't have to check them
+ // (ast_validation will emit an error if they occur)
+ _ => (),
}
}
if !def_id_is_transmute(cx, did) {
return None;
}
- let typ = cx.tables.node_id_to_type(expr.id);
- match typ.sty {
- ty::TyFnDef(.., bare_fn) if bare_fn.abi() == RustIntrinsic => {
- let from = bare_fn.inputs().skip_binder()[0];
- let to = *bare_fn.output().skip_binder();
- return Some((&from.sty, &to.sty));
- }
- _ => (),
- }
+ let sig = cx.tables.node_id_to_type(expr.id).fn_sig(cx.tcx);
+ let from = sig.inputs().skip_binder()[0];
+ let to = *sig.output().skip_binder();
+ return Some((&from.sty, &to.sty));
}
None
}
fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool {
- match cx.tcx.type_of(def_id).sty {
- ty::TyFnDef(.., bfty) if bfty.abi() == RustIntrinsic => (),
- _ => return false,
- }
+ cx.tcx.fn_sig(def_id).abi() == RustIntrinsic &&
cx.tcx.item_name(def_id) == "transmute"
}
}
fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) {
let def_id = self.cx.tcx.hir.local_def_id(id);
- let sig = self.cx.tcx.type_of(def_id).fn_sig();
+ let sig = self.cx.tcx.fn_sig(def_id);
let sig = self.cx.tcx.erase_late_bound_regions(&sig);
for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) }
closure_kind => { cdata.closure_kind(def_id.index) }
- closure_type => { cdata.closure_ty(def_id.index, tcx) }
+ fn_sig => { cdata.fn_sig(def_id.index, tcx) }
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) }
}
}
- pub fn closure_ty(&self,
- closure_id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> ty::PolyFnSig<'tcx> {
- match self.entry(closure_id).kind {
- EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)),
+ pub fn fn_sig(&self,
+ id: DefIndex,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> ty::PolyFnSig<'tcx> {
+ let sig = match self.entry(id).kind {
+ EntryKind::Fn(data) |
+ EntryKind::ForeignFn(data) => data.decode(self).sig,
+ EntryKind::Method(data) => data.decode(self).fn_data.sig,
+ EntryKind::Variant(data) |
+ EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(),
+ EntryKind::Closure(data) => data.decode(self).sig,
_ => bug!(),
- }
+ };
+ sig.decode((self, tcx))
}
#[inline]
use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
EncodedMetadata, EncodedMetadataHashes,
EncodedMetadataHash};
+use rustc::hir::def::CtorKind;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind};
use rustc::ich::Fingerprint;
ctor_kind: variant.ctor_kind,
discr: variant.discr,
struct_ctor: None,
+ ctor_sig: if variant.ctor_kind == CtorKind::Fn {
+ Some(self.lazy(&tcx.fn_sig(def_id)))
+ } else {
+ None
+ }
};
let enum_id = tcx.hir.as_local_node_id(enum_did).unwrap();
ty: Some(self.encode_item_type(def_id)),
inherent_impls: LazySeq::empty(),
- variances: LazySeq::empty(),
+ variances: if variant.ctor_kind == CtorKind::Fn {
+ self.encode_variances_of(def_id)
+ } else {
+ LazySeq::empty()
+ },
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
ctor_kind: variant.ctor_kind,
discr: variant.discr,
struct_ctor: Some(def_id.index),
+ ctor_sig: if variant.ctor_kind == CtorKind::Fn {
+ Some(self.lazy(&tcx.fn_sig(def_id)))
+ } else {
+ None
+ }
};
let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap();
ty: Some(self.encode_item_type(def_id)),
inherent_impls: LazySeq::empty(),
- variances: LazySeq::empty(),
+ variances: if variant.ctor_kind == CtorKind::Fn {
+ self.encode_variances_of(def_id)
+ } else {
+ LazySeq::empty()
+ },
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
};
FnData {
constness: hir::Constness::NotConst,
- arg_names: arg_names
+ arg_names: arg_names,
+ sig: self.lazy(&tcx.fn_sig(def_id)),
}
} else {
bug!()
}
},
inherent_impls: LazySeq::empty(),
- variances: LazySeq::empty(),
+ variances: if trait_item.kind == ty::AssociatedKind::Method {
+ self.encode_variances_of(def_id)
+ } else {
+ LazySeq::empty()
+ },
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id);
+ let tcx = self.tcx;
+
let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
let ast_item = self.tcx.hir.expect_impl_item(node_id);
let impl_item = self.tcx.associated_item(def_id);
FnData {
constness: sig.constness,
arg_names: self.encode_fn_arg_names_for_body(body),
+ sig: self.lazy(&tcx.fn_sig(def_id)),
}
} else {
bug!()
ty: Some(self.encode_item_type(def_id)),
inherent_impls: LazySeq::empty(),
- variances: LazySeq::empty(),
+ variances: if impl_item.kind == ty::AssociatedKind::Method {
+ self.encode_variances_of(def_id)
+ } else {
+ LazySeq::empty()
+ },
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
let data = FnData {
constness: constness,
arg_names: self.encode_fn_arg_names_for_body(body),
+ sig: self.lazy(&tcx.fn_sig(def_id)),
};
EntryKind::Fn(self.lazy(&data))
ctor_kind: variant.ctor_kind,
discr: variant.discr,
struct_ctor: struct_ctor,
+ ctor_sig: None,
}), repr_options)
}
hir::ItemUnion(..) => {
ctor_kind: variant.ctor_kind,
discr: variant.discr,
struct_ctor: None,
+ ctor_sig: None,
}), repr_options)
}
hir::ItemDefaultImpl(..) => {
hir::ItemEnum(..) |
hir::ItemStruct(..) |
hir::ItemUnion(..) |
- hir::ItemTrait(..) => self.encode_variances_of(def_id),
+ hir::ItemFn(..) => self.encode_variances_of(def_id),
_ => LazySeq::empty(),
},
generics: match item.node {
let data = ClosureData {
kind: tcx.closure_kind(def_id),
- ty: self.lazy(&tcx.closure_type(def_id)),
+ sig: self.lazy(&tcx.fn_sig(def_id)),
};
Entry {
let data = FnData {
constness: hir::Constness::NotConst,
arg_names: self.encode_fn_arg_names(names),
+ sig: self.lazy(&tcx.fn_sig(def_id)),
};
EntryKind::ForeignFn(self.lazy(&data))
}
ty: Some(self.encode_item_type(def_id)),
inherent_impls: LazySeq::empty(),
- variances: LazySeq::empty(),
+ variances: match nitem.node {
+ hir::ForeignItemFn(..) => self.encode_variances_of(def_id),
+ _ => LazySeq::empty(),
+ },
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
Type,
Enum(ReprOptions),
Field,
- Variant(Lazy<VariantData>),
- Struct(Lazy<VariantData>, ReprOptions),
- Union(Lazy<VariantData>, ReprOptions),
- Fn(Lazy<FnData>),
- ForeignFn(Lazy<FnData>),
+ Variant(Lazy<VariantData<'tcx>>),
+ Struct(Lazy<VariantData<'tcx>>, ReprOptions),
+ Union(Lazy<VariantData<'tcx>>, ReprOptions),
+ Fn(Lazy<FnData<'tcx>>),
+ ForeignFn(Lazy<FnData<'tcx>>),
Mod(Lazy<ModData>),
MacroDef(Lazy<MacroDef>),
Closure(Lazy<ClosureData<'tcx>>),
Trait(Lazy<TraitData<'tcx>>),
Impl(Lazy<ImplData<'tcx>>),
DefaultImpl(Lazy<ImplData<'tcx>>),
- Method(Lazy<MethodData>),
+ Method(Lazy<MethodData<'tcx>>),
AssociatedType(AssociatedContainer),
AssociatedConst(AssociatedContainer, u8),
}
impl_stable_hash_for!(struct MacroDef { body, legacy });
#[derive(RustcEncodable, RustcDecodable)]
-pub struct FnData {
+pub struct FnData<'tcx> {
pub constness: hir::Constness,
pub arg_names: LazySeq<ast::Name>,
+ pub sig: Lazy<ty::PolyFnSig<'tcx>>,
}
-impl_stable_hash_for!(struct FnData { constness, arg_names });
+impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
#[derive(RustcEncodable, RustcDecodable)]
-pub struct VariantData {
+pub struct VariantData<'tcx> {
pub ctor_kind: CtorKind,
pub discr: ty::VariantDiscr,
/// If this is a struct's only variant, this
/// is the index of the "struct ctor" item.
pub struct_ctor: Option<DefIndex>,
+
+ /// If this is a tuple struct or variant
+ /// ctor, this is its "function" signature.
+ pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
}
-impl_stable_hash_for!(struct VariantData {
+impl_stable_hash_for!(struct VariantData<'tcx> {
ctor_kind,
discr,
- struct_ctor
+ struct_ctor,
+ ctor_sig
});
#[derive(RustcEncodable, RustcDecodable)]
}
#[derive(RustcEncodable, RustcDecodable)]
-pub struct MethodData {
- pub fn_data: FnData,
+pub struct MethodData<'tcx> {
+ pub fn_data: FnData<'tcx>,
pub container: AssociatedContainer,
pub has_self: bool,
}
-impl_stable_hash_for!(struct MethodData { fn_data, container, has_self });
+impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
#[derive(RustcEncodable, RustcDecodable)]
pub struct ClosureData<'tcx> {
pub kind: ty::ClosureKind,
- pub ty: Lazy<ty::PolyFnSig<'tcx>>,
+ pub sig: Lazy<ty::PolyFnSig<'tcx>>,
}
-impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });
+impl_stable_hash_for!(struct ClosureData<'tcx> { kind, sig });
// FIXME(canndrew): This is_never should probably be an is_uninhabited
let diverges = expr.ty.is_never();
let intrinsic = match ty.sty {
- ty::TyFnDef(def_id, _, ref f) if
- f.abi() == Abi::RustIntrinsic ||
- f.abi() == Abi::PlatformIntrinsic =>
- {
- Some(this.hir.tcx().item_name(def_id).as_str())
+ ty::TyFnDef(def_id, _) => {
+ let f = ty.fn_sig(this.hir.tcx());
+ if f.abi() == Abi::RustIntrinsic ||
+ f.abi() == Abi::PlatformIntrinsic {
+ Some(this.hir.tcx().item_name(def_id).as_str())
+ } else {
+ None
+ }
}
_ => None
};
use rustc::ty::{self, AdtKind, VariantDef, Ty};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
use rustc::ty::cast::CastKind as TyCastKind;
-use rustc::ty::subst::Subst;
use rustc::hir;
impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
});
Expr {
temp_lifetime: temp_lifetime,
- ty: cx.tcx.type_of(def_id).subst(cx.tcx, substs),
+ ty: cx.tcx().mk_fn_def(def_id, substs),
span: expr.span,
kind: ExprKind::Literal {
literal: Literal::Value {
// types in the MIR. They will be substituted again with
// the param-substs, but because they are concrete, this
// will not do any harm.
- let sig = tcx.erase_late_bound_regions(&ty.fn_sig());
+ let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx));
let arg_tys = sig.inputs();
build_call_shim(
} else {
Substs::identity_for_item(tcx, def_id)
};
- let fn_ty = tcx.type_of(def_id).subst(tcx, substs);
- let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
+ let sig = tcx.fn_sig(def_id).subst(tcx, substs);
+ let sig = tcx.erase_late_bound_regions(&sig);
let span = tcx.def_span(def_id);
let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE };
call_kind={:?}, untuple_args={:?})",
def_id, rcvr_adjustment, call_kind, untuple_args);
- let fn_ty = tcx.type_of(def_id);
- let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
+ let sig = tcx.fn_sig(def_id);
+ let sig = tcx.erase_late_bound_regions(&sig);
let span = tcx.def_span(def_id);
debug!("build_call_shim: sig={:?}", sig);
{
let tcx = infcx.tcx;
let def_id = tcx.hir.local_def_id(ctor_id);
- let sig = match tcx.type_of(def_id).sty {
- ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty)
- .expect("LBR in ADT constructor signature"),
- _ => bug!("unexpected type for ctor {:?}", def_id)
- };
+ let sig = tcx.no_late_bound_regions(&tcx.fn_sig(def_id))
+ .expect("LBR in ADT constructor signature");
let sig = tcx.erase_regions(&sig);
let (adt_def, substs) = match sig.output().sty {
}
fn visit_statement(&mut self,
- _block: BasicBlock,
+ block: BasicBlock,
statement: &mut Statement<'tcx>,
- _location: Location) {
+ location: Location) {
if let StatementKind::EndRegion(_) = statement.kind {
statement.kind = StatementKind::Nop;
}
+ self.super_statement(block, statement, location);
}
}
let terminator = bb_data.terminator();
if let TerminatorKind::Call {
func: Operand::Constant(ref f), .. } = terminator.kind {
- if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
+ if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
callsites.push_back(CallSite {
callee: callee_def_id,
substs: substs,
let terminator = bb_data.terminator();
if let TerminatorKind::Call {
func: Operand::Constant(ref f), .. } = terminator.kind {
- if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
+ if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
// Don't inline the same function multiple times.
if callsite.callee != callee_def_id {
callsites.push_back(CallSite {
}
TerminatorKind::Call {func: Operand::Constant(ref f), .. } => {
- if let ty::TyFnDef(.., f) = f.ty.sty {
+ if let ty::TyFnDef(def_id, _) = f.ty.sty {
// Don't give intrinsics the extra penalty for calls
+ let f = tcx.fn_sig(def_id);
if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
cost += INSTR_COST;
} else {
let fn_ty = func.ty(self.mir, self.tcx);
let (is_shuffle, is_const_fn) = match fn_ty.sty {
- ty::TyFnDef(def_id, _, f) => {
- (f.abi() == Abi::PlatformIntrinsic &&
+ ty::TyFnDef(def_id, _) => {
+ (self.tcx.fn_sig(def_id).abi() == Abi::PlatformIntrinsic &&
self.tcx.item_name(def_id).as_str().starts_with("simd_shuffle"),
self.tcx.is_const_fn(def_id))
}
tcx.require_lang_item(lang_items::SyncTraitLangItem),
cause);
if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
- infcx.report_fulfillment_errors(&err);
+ infcx.report_fulfillment_errors(&err, None);
}
});
}
let func_ty = func.ty(mir, tcx);
debug!("check_terminator: call, func_ty={:?}", func_ty);
let sig = match func_ty.sty {
- ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => sig,
+ ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx),
_ => {
span_mirbug!(self, term, "call to non-function {:?}", func_ty);
return;
}
}
}
+
+ /// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus)
+ fn check_expr_within_pat(&self, expr: &Expr) {
+ match expr.node {
+ ExprKind::Lit(..) | ExprKind::Path(..) => {}
+ ExprKind::Unary(UnOp::Neg, ref inner)
+ if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
+ _ => self.err_handler().span_err(expr.span, "arbitrary expressions aren't allowed \
+ in patterns")
+ }
+ }
}
impl<'a> Visitor<'a> for AstValidator<'a> {
}
visit::walk_generics(self, g)
}
+
+ fn visit_pat(&mut self, pat: &'a Pat) {
+ match pat.node {
+ PatKind::Lit(ref expr) => {
+ self.check_expr_within_pat(expr);
+ }
+ PatKind::Range(ref start, ref end, _) => {
+ self.check_expr_within_pat(start);
+ self.check_expr_within_pat(end);
+ }
+ _ => {}
+ }
+
+ visit::walk_pat(self, pat)
+ }
}
pub fn check_crate(session: &Session, krate: &Crate) {
}
fn ty(&mut self) -> &mut Self {
- self.ev.tcx.type_of(self.item_def_id).visit_with(self);
+ let ty = self.ev.tcx.type_of(self.item_def_id);
+ ty.visit_with(self);
+ if let ty::TyFnDef(def_id, _) = ty.sty {
+ if def_id == self.item_def_id {
+ self.ev.tcx.fn_sig(def_id).visit_with(self);
+ }
+ }
self
}
}
fn ty(&mut self) -> &mut Self {
- self.tcx.type_of(self.item_def_id).visit_with(self);
+ let ty = self.tcx.type_of(self.item_def_id);
+ ty.visit_with(self);
+ if let ty::TyFnDef(def_id, _) = ty.sty {
+ if def_id == self.item_def_id {
+ self.tcx.fn_sig(def_id).visit_with(self);
+ }
+ }
self
}
assert!(!item_type.has_erasable_regions());
hasher.visit_ty(item_type);
+ // If this is a function, we hash the signature as well.
+ // This is not *strictly* needed, but it may help in some
+ // situations, see the `run-make/a-b-a-linker-guard` test.
+ if let ty::TyFnDef(..) = item_type.sty {
+ item_type.fn_sig(tcx).visit_with(&mut hasher);
+ }
+
// also include any type parameters (for generic items)
if let Some(substs) = substs {
assert!(!substs.has_erasable_regions());
use rustc::hir::def_id::DefId;
use rustc::middle::lang_items::{ExchangeMallocFnLangItem};
use rustc::traits;
-use rustc::ty::subst::{Substs, Subst};
+use rustc::ty::subst::Substs;
use rustc::ty::{self, TypeFoldable, TyCtxt};
use rustc::ty::adjustment::CustomCoerceUnsized;
use rustc::mir::{self, Location};
scx.tcx().hir.krate().visit_all_item_likes(&mut visitor);
}
+ // We can only translate items that are instantiable - items all of
+ // whose predicates hold. Luckily, items that aren't instantiable
+ // can't actually be used, so we can just skip translating them.
+ roots.retain(|root| root.is_instantiable(scx.tcx()));
+
roots
}
is_direct_call: bool,
output: &mut Vec<TransItem<'tcx>>)
{
- if let ty::TyFnDef(def_id, substs, _) = ty.sty {
+ if let ty::TyFnDef(def_id, substs) = ty.sty {
let instance = monomorphize::resolve(scx, def_id, substs);
visit_instance_use(scx, instance, is_direct_call, output);
}
let instance =
monomorphize::resolve(scx, method.def_id, callee_substs);
- let predicates = tcx.predicates_of(instance.def_id()).predicates
- .subst(tcx, instance.substs);
- if !traits::normalize_and_test_predicates(tcx, predicates) {
- continue;
- }
-
- if should_trans_locally(tcx, &instance) {
- output.push(create_fn_trans_item(instance));
+ let trans_item = create_fn_trans_item(instance);
+ if trans_item.is_instantiable(tcx) && should_trans_locally(tcx, &instance) {
+ output.push(trans_item);
}
}
}
-> ty::PolyFnSig<'tcx>
{
match ty.sty {
- ty::TyFnDef(_, _, sig) => sig,
+ ty::TyFnDef(..) |
// Shims currently have type TyFnPtr. Not sure this should remain.
- ty::TyFnPtr(sig) => sig,
+ ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()),
ty::TyClosure(def_id, substs) => {
let tcx = ccx.tcx();
- let sig = tcx.closure_type(def_id).subst(tcx, substs.substs);
+ let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
let env_ty = match tcx.closure_kind(def_id) {
debug!("type_metadata: {:?}", t);
- let sty = &t.sty;
let ptr_metadata = |ty: Ty<'tcx>| {
match ty.sty {
ty::TySlice(typ) => {
}
};
- let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
+ let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty {
ty::TyNever |
ty::TyBool |
ty::TyChar |
Err(metadata) => return metadata,
}
}
- ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => {
+ ty::TyFnDef(..) | ty::TyFnPtr(_) => {
let fn_metadata = subroutine_type_metadata(cx,
unique_type_id,
- sig,
+ t.fn_sig(cx.tcx()),
usage_site_span).metadata;
match debug_context(cx).type_map
.borrow()
usage_site_span).finalize(cx)
}
_ => {
- bug!("debuginfo: unexpected type in type_metadata: {:?}", sty)
+ bug!("debuginfo: unexpected type in type_metadata: {:?}", t)
}
};
push_type_params(cx, principal.substs, output);
}
},
- ty::TyFnDef(.., sig) |
- ty::TyFnPtr(sig) => {
+ ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+ let sig = t.fn_sig(cx.tcx());
if sig.unsafety() == hir::Unsafety::Unsafe {
output.push_str("unsafe ");
}
let ccx = bcx.ccx;
let tcx = ccx.tcx();
- let (def_id, substs, sig) = match callee_ty.sty {
- ty::TyFnDef(def_id, substs, sig) => (def_id, substs, sig),
+ let (def_id, substs) = match callee_ty.sty {
+ ty::TyFnDef(def_id, substs) => (def_id, substs),
_ => bug!("expected fn item type, found {}", callee_ty)
};
+ let sig = callee_ty.fn_sig(tcx);
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
let arg_tys = sig.inputs();
let ret_ty = sig.output();
let tcx = bcx.tcx();
- let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig());
+ let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx));
let arg_tys = sig.inputs();
// every intrinsic takes a SIMD vector as its first argument
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(conservative_impl_trait)]
-#![feature(command_envs)]
use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::Symbol;
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
let callee = self.trans_operand(&bcx, func);
- let (instance, mut llfn, sig) = match callee.ty.sty {
- ty::TyFnDef(def_id, substs, sig) => {
+ let (instance, mut llfn) = match callee.ty.sty {
+ ty::TyFnDef(def_id, substs) => {
(Some(monomorphize::resolve(bcx.ccx.shared(), def_id, substs)),
- None,
- sig)
+ None)
}
- ty::TyFnPtr(sig) => {
- (None,
- Some(callee.immediate()),
- sig)
+ ty::TyFnPtr(_) => {
+ (None, Some(callee.immediate()))
}
_ => bug!("{} is not callable", callee.ty)
};
let def = instance.map(|i| i.def);
+ let sig = callee.ty.fn_sig(bcx.tcx());
let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
let abi = sig.abi;
let fn_ty = func.ty(self.mir, tcx);
let fn_ty = self.monomorphize(&fn_ty);
let (def_id, substs) = match fn_ty.sty {
- ty::TyFnDef(def_id, substs, _) => (def_id, substs),
+ ty::TyFnDef(def_id, substs) => (def_id, substs),
_ => span_bug!(span, "calling {:?} (of type {}) in constant",
func, fn_ty)
};
let val = match *kind {
mir::CastKind::ReifyFnPointer => {
match operand.ty.sty {
- ty::TyFnDef(def_id, substs, _) => {
+ ty::TyFnDef(def_id, substs) => {
callee::resolve_and_get_fn(self.ccx, def_id, substs)
}
_ => {
.find(|it| it.kind == ty::AssociatedKind::Method)
.unwrap().def_id;
// Now create its substs [Closure, Tuple]
- let input = tcx.closure_type(def_id)
+ let input = tcx.fn_sig(def_id)
.subst(tcx, substs.substs).input(0);
let input = tcx.erase_late_bound_regions_and_normalize(&input);
let substs = tcx.mk_substs([operand.ty, input]
let val = match *kind {
mir::CastKind::ReifyFnPointer => {
match operand.ty.sty {
- ty::TyFnDef(def_id, substs, _) => {
+ ty::TyFnDef(def_id, substs) => {
OperandValue::Immediate(
callee::resolve_and_get_fn(bcx.ccx, def_id, substs))
}
let self_ty = tcx.mk_closure_from_closure_substs(
closure_did, substs);
- let sig = tcx.closure_type(closure_did).subst(tcx, substs.substs);
+ let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
assert_eq!(sig.inputs().len(), 1);
let substs = tcx.mk_substs([
} else {
let item_type = def_ty(scx, def_id, substs);
let def = match item_type.sty {
- ty::TyFnDef(_, _, f) if
- f.abi() == Abi::RustIntrinsic ||
- f.abi() == Abi::PlatformIntrinsic =>
+ ty::TyFnDef(..) if {
+ let f = item_type.fn_sig(scx.tcx());
+ f.abi() == Abi::RustIntrinsic ||
+ f.abi() == Abi::PlatformIntrinsic
+ } =>
{
debug!(" => intrinsic");
ty::InstanceDef::Intrinsic(def_id)
use monomorphize::Instance;
use rustc::hir;
use rustc::hir::def_id::DefId;
+use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Subst, Substs};
use syntax::ast::{self, NodeId};
use syntax::attr;
use syntax_pos::Span;
}
}
+ /// Returns whether this instance is instantiable - whether it has no unsatisfied
+ /// predicates.
+ ///
+ /// In order to translate an item, all of its predicates must hold, because
+ /// otherwise the item does not make sense. Type-checking ensures that
+ /// the predicates of every item that is *used by* a valid item *do*
+ /// hold, so we can rely on that.
+ ///
+ /// However, we translate collector roots (reachable items) and functions
+ /// in vtables when they are seen, even if they are not used, and so they
+ /// might not be instantiable. For example, a programmer can define this
+ /// public function:
+ ///
+ /// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
+ /// <&mut () as Clone>::clone(&s);
+ /// }
+ ///
+ /// That function can't be translated, because the method `<&mut () as Clone>::clone`
+ /// does not exist. Luckily for us, that function can't ever be used,
+ /// because that would require for `&'a mut (): Clone` to hold, so we
+ /// can just not emit any code, or even a linker reference for it.
+ ///
+ /// Similarly, if a vtable method has such a signature, and therefore can't
+ /// be used, we can just not emit it and have a placeholder (a null pointer,
+ /// which will never be accessed) in its place.
+ pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
+ debug!("is_instantiable({:?})", self);
+ let (def_id, substs) = match *self {
+ TransItem::Fn(ref instance) => (instance.def_id(), instance.substs),
+ TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()),
+ // global asm never has predicates
+ TransItem::GlobalAsm(..) => return true
+ };
+
+ let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs);
+ traits::normalize_and_test_predicates(tcx, predicates)
+ }
+
pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
let hir_map = &tcx.hir;
output);
}
},
- ty::TyFnDef(.., sig) |
- ty::TyFnPtr(sig) => {
+ ty::TyFnDef(..) |
+ ty::TyFnPtr(_) => {
+ let sig = t.fn_sig(self.tcx);
if sig.unsafety() == hir::Unsafety::Unsafe {
output.push_str("unsafe ");
}
// Type check the path.
let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
// Replace constructor type with constructed type for tuple struct patterns.
- let pat_ty = pat_ty.fn_sig().output();
+ let pat_ty = pat_ty.fn_sig(tcx).output();
let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type");
self.demand_eqtype(pat.span, expected, pat_ty);
// haven't yet decided on whether the closure is fn vs
// fnmut vs fnonce. If so, we have to defer further processing.
if self.closure_kind(def_id).is_none() {
- let closure_ty = self.closure_type(def_id).subst(self.tcx, substs.substs);
+ let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs);
let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
infer::FnCall,
&closure_ty)
expected: Expectation<'tcx>)
-> Ty<'tcx> {
let (fn_sig, def_span) = match callee_ty.sty {
- ty::TyFnDef(def_id, .., sig) => {
- (sig, self.tcx.hir.span_if_local(def_id))
+ ty::TyFnDef(def_id, _) => {
+ (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id))
}
ty::TyFnPtr(sig) => (sig, None),
ref t => {
use super::{Diverges, FnCtxt};
-use lint;
+use errors::DiagnosticBuilder;
use hir::def_id::DefId;
+use lint;
use rustc::hir;
+use rustc::session::Session;
use rustc::traits;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::ty::cast::{CastKind, CastTy};
NonScalar,
}
+fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session,
+ span: Span,
+ expr_ty: Ty<'tcx>,
+ cast_ty: Ty<'tcx>,
+ fcx: &FnCtxt<'a, 'gcx, 'tcx>)
+ -> DiagnosticBuilder<'a> {
+ type_error_struct!(sess, span, expr_ty, E0606,
+ "casting `{}` as `{}` is invalid",
+ fcx.ty_to_string(expr_ty),
+ fcx.ty_to_string(cast_ty))
+}
+
impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr,
match e {
CastError::NeedDeref => {
let error_span = self.span;
+ let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
+ self.cast_ty, fcx);
let cast_ty = fcx.ty_to_string(self.cast_ty);
- let mut err = fcx.type_error_struct(error_span,
- |actual| {
- format!("casting `{}` as `{}` is invalid",
- actual,
- cast_ty)
- },
- self.expr_ty);
err.span_label(error_span,
format!("cannot cast `{}` as `{}`",
fcx.ty_to_string(self.expr_ty),
}
CastError::NeedViaThinPtr |
CastError::NeedViaPtr => {
- let mut err = fcx.type_error_struct(self.span,
- |actual| {
- format!("casting `{}` as `{}` is invalid",
- actual,
- fcx.ty_to_string(self.cast_ty))
- },
- self.expr_ty);
+ let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
+ self.cast_ty, fcx);
if self.cast_ty.is_uint() {
err.help(&format!("cast through {} first",
match e {
err.emit();
}
CastError::NeedViaInt => {
- fcx.type_error_struct(self.span,
- |actual| {
- format!("casting `{}` as `{}` is invalid",
- actual,
- fcx.ty_to_string(self.cast_ty))
- },
- self.expr_ty)
+ make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
.help(&format!("cast through {} first",
match e {
CastError::NeedViaInt => "an integer",
}))
.emit();
}
+ CastError::IllegalCast => {
+ make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
+ .emit();
+ }
+ CastError::DifferingKinds => {
+ make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
+ .note("vtable kinds may not match")
+ .emit();
+ }
CastError::CastToBool => {
struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
.span_label(self.span, "unsupported cast")
.emit();
}
CastError::CastToChar => {
- fcx.type_error_message(self.span,
- |actual| {
- format!("only `u8` can be cast as `char`, not `{}`",
- actual)
- },
- self.expr_ty);
+ type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604,
+ "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit();
}
CastError::NonScalar => {
- fcx.type_error_message(self.span,
- |actual| {
- format!("non-scalar cast: `{}` as `{}`",
- actual,
- fcx.ty_to_string(self.cast_ty))
- },
- self.expr_ty);
- }
- CastError::IllegalCast => {
- fcx.type_error_message(self.span,
- |actual| {
- format!("casting `{}` as `{}` is invalid",
- actual,
- fcx.ty_to_string(self.cast_ty))
- },
- self.expr_ty);
+ type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605,
+ "non-primitive cast: `{}` as `{}`",
+ self.expr_ty,
+ fcx.ty_to_string(self.cast_ty))
+ .note("an `as` expression can only be used to convert between \
+ primitive types. Consider using the `From` trait")
+ .emit();
}
CastError::SizedUnsizedCast => {
- fcx.type_error_message(self.span,
- |actual| {
- format!("cannot cast thin pointer `{}` to fat pointer \
- `{}`",
- actual,
- fcx.ty_to_string(self.cast_ty))
- },
- self.expr_ty)
- }
- CastError::DifferingKinds => {
- fcx.type_error_struct(self.span,
- |actual| {
- format!("casting `{}` as `{}` is invalid",
- actual,
- fcx.ty_to_string(self.cast_ty))
- },
- self.expr_ty)
- .note("vtable kinds may not match")
- .emit();
+ type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0607,
+ "cannot cast thin pointer `{}` to fat pointer `{}`",
+ self.expr_ty,
+ fcx.ty_to_string(self.cast_ty)).emit();
}
}
}
(Some(t_from), Some(t_cast)) => (t_from, t_cast),
// Function item types may need to be reified before casts.
(None, Some(t_cast)) => {
- if let ty::TyFnDef(.., f) = self.expr_ty.sty {
+ if let ty::TyFnDef(..) = self.expr_ty.sty {
// Attempt a coercion to a fn pointer type.
+ let f = self.expr_ty.fn_sig(fcx.tcx);
let res = fcx.try_coerce(self.expr,
self.expr_ty,
self.expr_diverges,
}
match a.sty {
- ty::TyFnDef(.., a_f) => {
+ ty::TyFnDef(..) => {
// Function items are coercible to any closure
// type; function pointers are not (that would
// require double indirection).
// Additionally, we permit coercion of function
// items to drop the unsafe qualifier.
- self.coerce_from_fn_item(a, a_f, b)
+ self.coerce_from_fn_item(a, b)
}
ty::TyFnPtr(a_f) => {
// We permit coercion of fn pointers to drop the
fn coerce_from_fn_item(&self,
a: Ty<'tcx>,
- fn_ty_a: ty::PolyFnSig<'tcx>,
b: Ty<'tcx>)
-> CoerceResult<'tcx> {
//! Attempts to coerce from the type of a Rust function item
match b.sty {
ty::TyFnPtr(_) => {
- let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
- self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b,
- simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))
+ let a_sig = a.fn_sig(self.tcx);
+ let InferOk { value: a_sig, mut obligations } =
+ self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);
+
+ let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig);
+ let InferOk { value, obligations: o2 } =
+ self.coerce_from_safe_fn(a_fn_pointer, a_sig, b,
+ simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))?;
+
+ obligations.extend(o2);
+ Ok(InferOk { value, obligations })
}
_ => self.unify_and(a, b, identity),
}
// `extern "rust-call" fn((arg0,arg1,...)) -> _`
// to
// `fn(arg0,arg1,...) -> _`
- let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs);
+ let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs);
let converted_sig = sig.map_bound(|s| {
let params_iter = match s.inputs()[0].sty {
ty::TyTuple(params, _) => {
// Special-case that coercion alone cannot handle:
// Two function item types of differing IDs or Substs.
- match (&prev_ty.sty, &new_ty.sty) {
- (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
- // The signature must always match.
- let fty = self.at(cause, self.param_env)
- .trace(prev_ty, new_ty)
- .lub(&a_fty, &b_fty)
- .map(|ok| self.register_infer_ok_obligations(ok))?;
-
- if a_def_id == b_def_id {
- // Same function, maybe the parameters match.
- let substs = self.commit_if_ok(|_| {
- self.at(cause, self.param_env)
- .trace(prev_ty, new_ty)
- .lub(&a_substs, &b_substs)
- .map(|ok| self.register_infer_ok_obligations(ok))
- });
-
- if let Ok(substs) = substs {
- // We have a LUB of prev_ty and new_ty, just return it.
- return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty));
- }
- }
+ if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) {
+ // Don't reify if the function types have a LUB, i.e. they
+ // are the same function and their parameters have a LUB.
+ let lub_ty = self.commit_if_ok(|_| {
+ self.at(cause, self.param_env)
+ .lub(prev_ty, new_ty)
+ .map(|ok| self.register_infer_ok_obligations(ok))
+ });
+
+ if lub_ty.is_ok() {
+ // We have a LUB of prev_ty and new_ty, just return it.
+ return lub_ty;
+ }
- // Reify both sides and return the reified fn pointer type.
- let fn_ptr = self.tcx.mk_fn_ptr(fty);
- for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) {
- // The only adjustment that can produce an fn item is
- // `NeverToAny`, so this should always be valid.
- self.apply_adjustments(expr, vec![Adjustment {
- kind: Adjust::ReifyFnPointer,
- target: fn_ptr
- }]);
- }
- return Ok(fn_ptr);
+ // The signature must match.
+ let a_sig = prev_ty.fn_sig(self.tcx);
+ let a_sig = self.normalize_associated_types_in(new.span, &a_sig);
+ let b_sig = new_ty.fn_sig(self.tcx);
+ let b_sig = self.normalize_associated_types_in(new.span, &b_sig);
+ let sig = self.at(cause, self.param_env)
+ .trace(prev_ty, new_ty)
+ .lub(&a_sig, &b_sig)
+ .map(|ok| self.register_infer_ok_obligations(ok))?;
+
+ // Reify both sides and return the reified fn pointer type.
+ let fn_ptr = self.tcx.mk_fn_ptr(sig);
+ for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) {
+ // The only adjustment that can produce an fn item is
+ // `NeverToAny`, so this should always be valid.
+ self.apply_adjustments(expr, vec![Adjustment {
+ kind: Adjust::ReifyFnPointer,
+ target: fn_ptr
+ }]);
}
- _ => {}
+ return Ok(fn_ptr);
}
let mut coerce = Coerce::new(self, cause.clone());
"`return;` in a function whose return type is not `()`");
db.span_label(cause.span, "return type is not ()");
}
+ ObligationCauseCode::BlockTailExpression(blk_id) => {
+ db = fcx.report_mismatched_types(cause, expected, found, err);
+
+ let expr = expression.unwrap_or_else(|| {
+ span_bug!(cause.span,
+ "supposed to be part of a block tail expression, but the \
+ expression is empty");
+ });
+ fcx.suggest_mismatched_types_on_tail(&mut db, expr,
+ expected, found,
+ cause.span, blk_id);
+ }
_ => {
db = fcx.report_mismatched_types(cause, expected, found, err);
}
// Compute skolemized form of impl and trait method tys.
let tcx = infcx.tcx;
- let m_sig = |method: &ty::AssociatedItem| {
- match tcx.type_of(method.def_id).sty {
- ty::TyFnDef(_, _, f) => f,
- _ => bug!()
- }
- };
-
let (impl_sig, _) =
infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
infer::HigherRankedType,
- &m_sig(impl_m));
+ &tcx.fn_sig(impl_m.def_id));
let impl_sig =
inh.normalize_associated_types_in(impl_m_span,
impl_m_node_id,
let trait_sig = inh.liberate_late_bound_regions(
impl_m.def_id,
- &m_sig(trait_m));
+ &tcx.fn_sig(trait_m.def_id));
let trait_sig =
trait_sig.subst(tcx, trait_to_skol_substs);
let trait_sig =
// Check that all obligations are satisfied by the implementation's
// version.
if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
- infcx.report_fulfillment_errors(errors);
+ infcx.report_fulfillment_errors(errors, None);
return Err(ErrorReported);
}
ty::ImplContainer(_) => impl_trait_ref.self_ty(),
ty::TraitContainer(_) => tcx.mk_self_type()
};
- let method_ty = tcx.type_of(method.def_id);
- let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder();
+ let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder();
match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) {
ExplicitSelf::ByValue => "self".to_string(),
ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(),
trait_m: &ty::AssociatedItem,
trait_item_span: Option<Span>)
-> Result<(), ErrorReported> {
- let m_fty = |method: &ty::AssociatedItem| {
- match tcx.type_of(method.def_id).sty {
- ty::TyFnDef(_, _, f) => f,
- _ => bug!()
- }
- };
- let impl_m_fty = m_fty(impl_m);
- let trait_m_fty = m_fty(trait_m);
+ let impl_m_fty = tcx.fn_sig(impl_m.def_id);
+ let trait_m_fty = tcx.fn_sig(trait_m.def_id);
let trait_number_args = trait_m_fty.inputs().skip_binder().len();
let impl_number_args = impl_m_fty.inputs().skip_binder().len();
if trait_number_args != impl_number_args {
// Check that all obligations are satisfied by the implementation's
// version.
if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
- infcx.report_fulfillment_errors(errors);
+ infcx.report_fulfillment_errors(errors, None);
return;
}
}
}
+ pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) {
+ if let Some(mut err) = self.demand_coerce_diag(expr, checked_ty, expected) {
+ err.emit();
+ }
+ }
+
// Checks that the type of `expr` can be coerced to `expected`.
//
// NB: This code relies on `self.diverges` to be accurate. In
// particular, assignments to `!` will be permitted if the
// diverges flag is currently "always".
- pub fn demand_coerce(&self,
- expr: &hir::Expr,
- checked_ty: Ty<'tcx>,
- expected: Ty<'tcx>) {
+ pub fn demand_coerce_diag(&self,
+ expr: &hir::Expr,
+ checked_ty: Ty<'tcx>,
+ expected: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
let expected = self.resolve_type_vars_with_obligations(expected);
if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
self.get_best_match(&suggestions).join("\n")));
}
}
- err.emit();
+ return Some(err);
}
+ None
}
fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
fn has_no_input_arg(&self, method: &AssociatedItem) -> bool {
match method.def() {
Def::Method(def_id) => {
- match self.tcx.type_of(def_id).sty {
- ty::TypeVariants::TyFnDef(_, _, sig) => {
- sig.inputs().skip_binder().len() == 1
- }
- _ => false,
- }
+ self.tcx.fn_sig(def_id).inputs().skip_binder().len() == 1
}
_ => false,
}
if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
// this could be reached when we get lazy normalization
- infcx.report_fulfillment_errors(errors);
+ infcx.report_fulfillment_errors(errors, None);
return Err(ErrorReported);
}
use intrinsics;
use rustc::traits::{ObligationCause, ObligationCauseCode};
-use rustc::ty::subst::Substs;
use rustc::ty::{self, TyCtxt, Ty};
use rustc::util::nodemap::FxHashMap;
use require_same_types;
output: Ty<'tcx>) {
let def_id = tcx.hir.local_def_id(it.id);
- let substs = Substs::for_item(tcx, def_id,
- |_, _| tcx.types.re_erased,
- |def, _| tcx.mk_param_from_def(def));
+ match it.node {
+ hir::ForeignItemFn(..) => {}
+ _ => {
+ struct_span_err!(tcx.sess, it.span, E0619,
+ "intrinsic must be a function")
+ .span_label(it.span, "expected a function")
+ .emit();
+ return;
+ }
+ }
- let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig(
- inputs.into_iter(),
- output,
- false,
- hir::Unsafety::Unsafe,
- abi
- )));
let i_n_tps = tcx.generics_of(def_id).types.len();
if i_n_tps != n_tps {
let span = match it.node {
hir::ForeignItemFn(_, _, ref generics) => generics.span,
- hir::ForeignItemStatic(..) => it.span
+ _ => bug!()
};
struct_span_err!(tcx.sess, span, E0094,
i_n_tps, n_tps)
.span_label(span, format!("expected {} type parameter", n_tps))
.emit();
- } else {
- require_same_types(tcx,
- &ObligationCause::new(it.span,
- it.id,
- ObligationCauseCode::IntrinsicType),
- tcx.type_of(def_id),
- fty);
+ return;
}
+
+ let fty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
+ inputs.into_iter(),
+ output,
+ false,
+ hir::Unsafety::Unsafe,
+ abi
+ )));
+ let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType);
+ require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty);
}
/// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
let mut structural_to_nomimal = FxHashMap();
- let sig = tcx.type_of(def_id).fn_sig();
+ let sig = tcx.fn_sig(def_id);
let sig = tcx.no_late_bound_regions(&sig).unwrap();
if intr.inputs.len() != sig.inputs().len() {
span_err!(tcx.sess, it.span, E0444,
debug!("method_predicates after subst = {:?}", method_predicates);
- let sig = self.tcx.type_of(def_id).fn_sig();
+ let sig = self.tcx.fn_sig(def_id);
// Instantiate late-bound regions and substitute the trait
// parameters into the method type to get the actual method type.
// NB: Instantiate late-bound regions first so that
// `instantiate_type_scheme` can normalize associated types that
// may reference those regions.
- let fn_sig = tcx.type_of(def_id).fn_sig();
+ let fn_sig = tcx.fn_sig(def_id);
let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
infer::FnCall,
&fn_sig).0;
expected: ty::Ty<'tcx>) -> bool {
match method.def() {
Def::Method(def_id) => {
- let fty = self.tcx.type_of(def_id).fn_sig();
+ let fty = self.tcx.fn_sig(def_id);
self.probe(|_| {
let substs = self.fresh_substs_for_item(self.span, method.def_id);
let output = fty.output().subst(self.tcx, substs);
impl_ty: Ty<'tcx>,
substs: &Substs<'tcx>)
-> Ty<'tcx> {
- let self_ty = self.tcx.type_of(method).fn_sig().input(0);
+ let self_ty = self.tcx.fn_sig(method).input(0);
debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
impl_ty,
self_ty,
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir::map::Node;
use rustc::hir::{self, PatKind};
use rustc::middle::lang_items;
use rustc_back::slice;
/// environment is for an item or something where the "callee" is
/// not clear.
implicit_region_bound: Option<ty::Region<'tcx>>,
+
+ body_id: Option<hir::BodyId>,
}
impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
deferred_cast_checks: RefCell::new(Vec::new()),
anon_types: RefCell::new(NodeMap()),
implicit_region_bound,
+ body_id,
}
}
typeck_item_bodies,
typeck_tables_of,
has_typeck_tables,
- closure_type,
closure_kind,
adt_destructor,
..*providers
};
}
-fn closure_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def_id: DefId)
- -> ty::PolyFnSig<'tcx> {
- let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
- tcx.typeck_tables_of(def_id).closure_tys[&node_id]
-}
-
fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> ty::ClosureKind {
Inherited::build(tcx, def_id).enter(|inh| {
let param_env = tcx.param_env(def_id);
let fcx = if let Some(decl) = fn_decl {
- let fn_sig = tcx.type_of(def_id).fn_sig();
+ let fn_sig = tcx.fn_sig(def_id);
check_abi(tcx, span, fn_sig.abi());
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
let ret_ty = fn_sig.output();
- fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
+ fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType);
let ret_ty = fcx.instantiate_anon_types(&ret_ty);
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
fn_sig = fcx.tcx.mk_fn_sig(
// Add formal parameters.
for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) {
- // The type of the argument must be well-formed.
- //
- // NB -- this is now checked in wfcheck, but that
- // currently only results in warnings, so we issue an
- // old-style WF obligation here so that we still get the
- // errors that we used to get.
- fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation);
-
// Check the pattern.
fcx.check_pat_arg(&arg.pat, arg_ty, true);
+
+ // Check that argument is Sized.
+ // The check for a non-trivial pattern is a hack to avoid duplicate warnings
+ // for simple cases like `fn foo(x: Trait)`,
+ // where we would error once on the parameter as a whole, and once on the binding `x`.
+ if arg.pat.simple_name().is_none() {
+ fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation);
+ }
+
fcx.write_ty(arg.id, arg_ty);
}
// Require that the predicate holds for the concrete type.
let cause = traits::ObligationCause::new(span, self.body_id,
- traits::ReturnType);
+ traits::SizedReturnType);
self.register_predicate(traits::Obligation::new(cause,
self.param_env,
predicate));
}
}
- /// Registers an obligation for checking later, during regionck, that the type `ty` must
- /// outlive the region `r`.
- pub fn register_region_obligation(&self,
- ty: Ty<'tcx>,
- region: ty::Region<'tcx>,
- cause: traits::ObligationCause<'tcx>)
- {
- let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
- fulfillment_cx.register_region_obligation(ty, region, cause);
- }
-
/// Registers an obligation for checking later, during regionck, that the type `ty` must
/// outlive the region `r`.
pub fn register_wf_obligation(&self,
ty::Predicate::WellFormed(ty)));
}
- pub fn register_old_wf_obligation(&self,
- ty: Ty<'tcx>,
- span: Span,
- code: traits::ObligationCauseCode<'tcx>)
- {
- // Registers an "old-style" WF obligation that uses the
- // implicator code. This is basically a buggy version of
- // `register_wf_obligation` that is being kept around
- // temporarily just to help with phasing in the newer rules.
- //
- // FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually
- let cause = traits::ObligationCause::new(span, self.body_id, code);
- self.register_region_obligation(ty, self.tcx.types.re_empty, cause);
- }
-
/// Registers obligations that all types appearing in `substs` are well-formed.
pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr)
{
match fulfillment_cx.select_all_or_error(self) {
Ok(()) => { }
- Err(errors) => { self.report_fulfillment_errors(&errors); }
+ Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); }
}
}
fn select_obligations_where_possible(&self) {
match self.fulfillment_cx.borrow_mut().select_where_possible(self) {
Ok(()) => { }
- Err(errors) => { self.report_fulfillment_errors(&errors); }
+ Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); }
}
}
-> ty::TypeAndMut<'tcx>
{
// extract method return type, which will be &T;
- // all LB regions should have been instantiated during method lookup
let ret_ty = method.sig.output();
// method returns &T, but the type as visible to user is T, so deref
ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
}
- ty::TyFnDef(.., f) => {
- let ptr_ty = self.tcx.mk_fn_ptr(f);
+ ty::TyFnDef(..) => {
+ let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty);
variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty));
}
"check_return_expr called outside fn body"));
let ret_ty = ret_coercion.borrow().expected_ty();
- let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty);
+ let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone());
ret_coercion.borrow_mut()
.coerce(self,
- &self.misc(return_expr.span),
+ &self.cause(return_expr.span,
+ ObligationCauseCode::ReturnType(return_expr.id)),
return_expr,
return_expr_ty,
self.diverges.get());
let mut coerce = ctxt.coerce.as_mut().unwrap();
if let Some(tail_expr_ty) = tail_expr_ty {
let tail_expr = tail_expr.unwrap();
+ let cause = self.cause(tail_expr.span,
+ ObligationCauseCode::BlockTailExpression(blk.id));
coerce.coerce(self,
- &self.misc(tail_expr.span),
+ &cause,
tail_expr,
tail_expr_ty,
self.diverges.get());
ty
}
+ /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is
+ /// `fn main` if it is a method, `None` otherwise.
+ pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
+ // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
+ // `while` before reaching it, as block tail returns are not available in them.
+ if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) {
+ let parent = self.tcx.hir.get(fn_id);
+
+ if let Node::NodeItem(&hir::Item {
+ name, node: hir::ItemFn(ref decl, ..), ..
+ }) = parent {
+ decl.clone().and_then(|decl| {
+ // This is less than ideal, it will not present the return type span on any
+ // method called `main`, regardless of whether it is actually the entry point.
+ Some((decl, name == Symbol::intern("main")))
+ })
+ } else if let Node::NodeTraitItem(&hir::TraitItem {
+ node: hir::TraitItemKind::Method(hir::MethodSig {
+ ref decl, ..
+ }, ..), ..
+ }) = parent {
+ decl.clone().and_then(|decl| {
+ Some((decl, false))
+ })
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+ }
+
+ /// On implicit return expressions with mismatched types, provide the following suggestions:
+ ///
+ /// - Point out the method's return type as the reason for the expected type
+ /// - Possible missing semicolon
+ /// - Possible missing return type if the return type is the default, and not `fn main()`
+ pub fn suggest_mismatched_types_on_tail(&self,
+ err: &mut DiagnosticBuilder<'tcx>,
+ expression: &'gcx hir::Expr,
+ expected: Ty<'tcx>,
+ found: Ty<'tcx>,
+ cause_span: Span,
+ blk_id: ast::NodeId) {
+ self.suggest_missing_semicolon(err, expression, expected, cause_span);
+
+ if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) {
+ // `fn main()` must return `()`, do not suggest changing return type
+ if !is_main {
+ self.suggest_missing_return_type(err, &fn_decl, found);
+ }
+ }
+ }
+
+ /// A common error is to forget to add a semicolon at the end of a block:
+ ///
+ /// ```
+ /// fn foo() {
+ /// bar_that_returns_u32()
+ /// }
+ /// ```
+ ///
+ /// This routine checks if the return expression in a block would make sense on its own as a
+ /// statement and the return type has been left as defaultor has been specified as `()`. If so,
+ /// it suggests adding a semicolon.
+ fn suggest_missing_semicolon(&self,
+ err: &mut DiagnosticBuilder<'tcx>,
+ expression: &'gcx hir::Expr,
+ expected: Ty<'tcx>,
+ cause_span: Span) {
+ if expected.is_nil() {
+ // `BlockTailExpression` only relevant if the tail expr would be
+ // useful on its own.
+ match expression.node {
+ hir::ExprCall(..) |
+ hir::ExprMethodCall(..) |
+ hir::ExprIf(..) |
+ hir::ExprWhile(..) |
+ hir::ExprLoop(..) |
+ hir::ExprMatch(..) |
+ hir::ExprBlock(..) => {
+ let sp = cause_span.next_point();
+ err.span_suggestion(sp,
+ "did you mean to add a semicolon here?",
+ ";".to_string());
+ }
+ _ => (),
+ }
+ }
+ }
+
+
+ /// A possible error is to forget to add a return type that is needed:
+ ///
+ /// ```
+ /// fn foo() {
+ /// bar_that_returns_u32()
+ /// }
+ /// ```
+ ///
+ /// This routine checks if the return type is left as default, the method is not part of an
+ /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return
+ /// type.
+ fn suggest_missing_return_type(&self,
+ err: &mut DiagnosticBuilder<'tcx>,
+ fn_decl: &hir::FnDecl,
+ ty: Ty<'tcx>) {
+
+ // Only recommend changing the return type for methods that
+ // haven't set a return type at all (and aren't `fn main()` or an impl).
+ if let &hir::FnDecl {
+ output: hir::FunctionRetTy::DefaultReturn(span), ..
+ } = fn_decl {
+ if ty.is_suggestable() {
+ err.span_suggestion(span,
+ "possibly return type missing here?",
+ format!("-> {} ", ty));
+ } else {
+ err.span_label(span, "possibly return type missing here?");
+ }
+ }
+ }
+
+
/// A common error is to add an extra semicolon:
///
/// ```
hi: original_span.hi,
ctxt: original_span.ctxt,
};
- err.span_help(span_semi, "consider removing this semicolon:");
+ err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string());
}
// Instantiates the given path, which must refer to an item with the given
}
ty::AssociatedKind::Method => {
reject_shadowing_type_parameters(fcx.tcx, item.def_id);
- let method_ty = fcx.tcx.type_of(item.def_id);
- let method_ty = fcx.normalize_associated_types_in(span, &method_ty);
+ let sig = fcx.tcx.fn_sig(item.def_id);
+ let sig = fcx.normalize_associated_types_in(span, &sig);
let predicates = fcx.tcx.predicates_of(item.def_id)
.instantiate_identity(fcx.tcx);
let predicates = fcx.normalize_associated_types_in(span, &predicates);
- let sig = method_ty.fn_sig();
this.check_fn_or_method(fcx, span, sig, &predicates,
item.def_id, &mut implied_bounds);
let sig_if_method = sig_if_method.expect("bad signature for method");
fn check_item_fn(&mut self, item: &hir::Item) {
self.for_item(item).with_fcx(|fcx, this| {
let def_id = fcx.tcx.hir.local_def_id(item.id);
- let ty = fcx.tcx.type_of(def_id);
- let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
- let sig = item_ty.fn_sig();
+ let sig = fcx.tcx.fn_sig(def_id);
+ let sig = fcx.normalize_associated_types_in(item.span, &sig);
let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
let span = method_sig.decl.inputs[0].span;
- let method_ty = fcx.tcx.type_of(method.def_id);
- let fty = fcx.normalize_associated_types_in(span, &method_ty);
- let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
+ let sig = fcx.tcx.fn_sig(method.def_id);
+ let sig = fcx.normalize_associated_types_in(span, &sig);
+ let sig = fcx.liberate_late_bound_regions(method.def_id, &sig);
debug!("check_method_receiver: sig={:?}", sig);
fn report_error(&self, t: Ty<'tcx>) {
if !self.tcx.sess.has_errors() {
- self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t);
+ self.infcx.need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t);
}
}
}
// Check that all transitive obligations are satisfied.
if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
- infcx.report_fulfillment_errors(&errors);
+ infcx.report_fulfillment_errors(&errors, None);
}
// Finally, resolve all regions.
type_param_predicates,
trait_def,
adt_def,
+ fn_sig,
impl_trait_ref,
impl_polarity,
is_foreign_item,
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
+ if let hir::ForeignItemFn(..) = item.node {
+ tcx.fn_sig(def_id);
+ }
}
}
hir::ItemEnum(ref enum_definition, _) => {
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
+ if let hir::ItemFn(..) = it.node {
+ tcx.fn_sig(def_id);
+ }
}
}
}
hir::TraitItemKind::Type(_, Some(_)) |
hir::TraitItemKind::Method(..) => {
tcx.type_of(def_id);
+ if let hir::TraitItemKind::Method(..) = trait_item.node {
+ tcx.fn_sig(def_id);
+ }
}
hir::TraitItemKind::Type(_, None) => {}
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
+ if let hir::ImplItemKind::Method(..) = tcx.hir.expect_impl_item(impl_item_id).node {
+ tcx.fn_sig(def_id);
+ }
}
fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
match tcx.hir.get(node_id) {
NodeTraitItem(item) => {
match item.node {
- TraitItemKind::Method(ref sig, _) => {
- let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl);
+ TraitItemKind::Method(..) => {
let substs = Substs::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id, substs, fty)
+ tcx.mk_fn_def(def_id, substs)
}
TraitItemKind::Const(ref ty, _) |
TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
NodeImplItem(item) => {
match item.node {
- ImplItemKind::Method(ref sig, _) => {
- let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl);
+ ImplItemKind::Method(..) => {
let substs = Substs::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id, substs, fty)
+ tcx.mk_fn_def(def_id, substs)
}
ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
ImplItemKind::Type(ref ty) => {
ItemTy(ref t, _) | ItemImpl(.., ref t, _) => {
icx.to_ty(t)
}
- ItemFn(ref decl, unsafety, _, abi, _, _) => {
- let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl);
+ ItemFn(..) => {
let substs = Substs::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id, substs, tofd)
+ tcx.mk_fn_def(def_id, substs)
}
ItemEnum(..) |
ItemStruct(..) |
}
NodeForeignItem(foreign_item) => {
- let abi = tcx.hir.get_foreign_abi(node_id);
-
match foreign_item.node {
- ForeignItemFn(ref fn_decl, _, _) => {
- compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
+ ForeignItemFn(..) => {
+ let substs = Substs::identity_for_item(tcx, def_id);
+ tcx.mk_fn_def(def_id, substs)
}
ForeignItemStatic(ref t, _) => icx.to_ty(t)
}
NodeStructCtor(&ref def) |
NodeVariant(&Spanned { node: hir::Variant_ { data: ref def, .. }, .. }) => {
- let ty = tcx.type_of(tcx.hir.get_parent_did(node_id));
match *def {
- VariantData::Unit(..) | VariantData::Struct(..) => ty,
- VariantData::Tuple(ref fields, _) => {
- let inputs = fields.iter().map(|f| {
- tcx.type_of(tcx.hir.local_def_id(f.id))
- });
+ VariantData::Unit(..) | VariantData::Struct(..) => {
+ tcx.type_of(tcx.hir.get_parent_did(node_id))
+ }
+ VariantData::Tuple(..) => {
let substs = Substs::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig(
- inputs,
- ty,
- false,
- hir::Unsafety::Normal,
- abi::Abi::Rust
- )))
+ tcx.mk_fn_def(def_id, substs)
}
}
}
}
}
+fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId)
+ -> ty::PolyFnSig<'tcx> {
+ use rustc::hir::map::*;
+ use rustc::hir::*;
+
+ let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+
+ let icx = ItemCtxt::new(tcx, def_id);
+
+ match tcx.hir.get(node_id) {
+ NodeTraitItem(&hir::TraitItem { node: TraitItemKind::Method(ref sig, _), .. }) |
+ NodeImplItem(&hir::ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) => {
+ AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl)
+ }
+
+ NodeItem(&hir::Item { node: ItemFn(ref decl, unsafety, _, abi, _, _), .. }) => {
+ AstConv::ty_of_fn(&icx, unsafety, abi, decl)
+ }
+
+ NodeForeignItem(&hir::ForeignItem { node: ForeignItemFn(ref fn_decl, _, _), .. }) => {
+ let abi = tcx.hir.get_foreign_abi(node_id);
+ compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
+ }
+
+ NodeStructCtor(&VariantData::Tuple(ref fields, _)) |
+ NodeVariant(&Spanned { node: hir::Variant_ {
+ data: VariantData::Tuple(ref fields, _), ..
+ }, .. }) => {
+ let ty = tcx.type_of(tcx.hir.get_parent_did(node_id));
+ let inputs = fields.iter().map(|f| {
+ tcx.type_of(tcx.hir.local_def_id(f.id))
+ });
+ ty::Binder(tcx.mk_fn_sig(
+ inputs,
+ ty,
+ false,
+ hir::Unsafety::Normal,
+ abi::Abi::Rust
+ ))
+ }
+
+ NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
+ tcx.typeck_tables_of(def_id).closure_tys[&node_id]
+ }
+
+ x => {
+ bug!("unexpected sort of node in fn_sig(): {:?}", x);
+ }
+ }
+}
+
fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> Option<ty::TraitRef<'tcx>> {
}
}
-fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
+fn compute_sig_of_foreign_fn_decl<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
decl: &hir::FnDecl,
abi: abi::Abi)
- -> Ty<'tcx>
+ -> ty::PolyFnSig<'tcx>
{
let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl);
}
}
- let substs = Substs::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id, substs, fty)
+ fty
}
fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
```
"##,
+E0604: r##"
+A cast to `char` was attempted on a type other than `u8`.
+
+Erroneous code example:
+
+```compile_fail,E0604
+0u32 as char; // error: only `u8` can be cast as `char`, not `u32`
+```
+
+As the error message indicates, only `u8` can be cast into `char`. Example:
+
+```
+let c = 86u8 as char; // ok!
+assert_eq!(c, 'V');
+```
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
+E0605: r##"
+An invalid cast was attempted.
+
+Erroneous code examples:
+
+```compile_fail,E0605
+let x = 0u8;
+x as Vec<u8>; // error: non-primitive cast: `u8` as `std::vec::Vec<u8>`
+
+// Another example
+
+let v = 0 as *const u8; // So here, `v` is a `*const u8`.
+v as &u8; // error: non-primitive cast: `*const u8` as `&u8`
+```
+
+Only primitive types can be cast into each other. Examples:
+
+```
+let x = 0u8;
+x as u32; // ok!
+
+let v = 0 as *const u8;
+v as *const i8; // ok!
+```
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
+E0606: r##"
+An incompatible cast was attempted.
+
+Erroneous code example:
+
+```compile_fail,E0606
+let x = &0u8; // Here, `x` is a `&u8`.
+let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid
+```
+
+When casting, keep in mind that only primitive types can be cast into each
+other. Example:
+
+```
+let x = &0u8;
+let y: u32 = *x as u32; // We dereference it first and then cast it.
+```
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
+E0607: r##"
+A cast between a thin and a fat pointer was attempted.
+
+Erroneous code example:
+
+```compile_fail,E0607
+let v = 0 as *const u8;
+v as *const [u8];
+```
+
+First: what are thin and fat pointers?
+
+Thin pointers are "simple" pointers: they are purely a reference to a memory
+address.
+
+Fat pointers are pointers referencing Dynamically Sized Types (also called DST).
+DST don't have a statically known size, therefore they can only exist behind
+some kind of pointers that contain additional information. Slices and trait
+objects are DSTs. In the case of slices, the additional information the fat
+pointer holds is their size.
+
+To fix this error, don't try to cast directly between thin and fat pointers.
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
E0609: r##"
Attempted to access a non-existent field in a struct.
E0568, // auto-traits can not have predicates,
E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
E0592, // duplicate definitions with name `{}`
+ E0619, // intrinsic must be a function
}
match fulfill_cx.select_all_or_error(infcx) {
Ok(()) => true,
Err(errors) => {
- infcx.report_fulfillment_errors(&errors);
+ infcx.report_fulfillment_errors(&errors, None);
false
}
}
}
_ => ()
}
- let substs = tcx.intern_substs(&[]);
- let se_ty = tcx.mk_fn_def(main_def_id, substs,
- ty::Binder(tcx.mk_fn_sig(
+ let se_ty = tcx.mk_fn_ptr(ty::Binder(
+ tcx.mk_fn_sig(
iter::empty(),
tcx.mk_nil(),
false,
hir::Unsafety::Normal,
Abi::Rust
- ))
- );
+ )
+ ));
require_same_types(
tcx,
&ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
se_ty,
- main_t);
+ tcx.mk_fn_ptr(tcx.fn_sig(main_def_id)));
}
_ => {
span_bug!(main_span,
_ => ()
}
- let substs = tcx.intern_substs(&[]);
- let se_ty = tcx.mk_fn_def(start_def_id, substs,
- ty::Binder(tcx.mk_fn_sig(
+ let se_ty = tcx.mk_fn_ptr(ty::Binder(
+ tcx.mk_fn_sig(
[
tcx.types.isize,
tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
false,
hir::Unsafety::Normal,
Abi::Rust
- ))
- );
+ )
+ ));
require_same_types(
tcx,
&ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
se_ty,
- start_t);
+ tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
}
_ => {
span_bug!(start_span,
//! We walk the set of items and, for each member, generate new constraints.
use hir::def_id::DefId;
-use middle::resolve_lifetime as rl;
use rustc::dep_graph::{AssertDepGraphSafe, DepKind};
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::hir::map as hir_map;
use syntax::ast;
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
/// }
///
/// then while we are visiting `Bar<T>`, the `CurrentItem` would have
-/// the def-id and generics of `Foo`.
-pub struct CurrentItem<'a> {
+/// the def-id and the start of `Foo`'s inferreds.
+pub struct CurrentItem {
def_id: DefId,
- generics: &'a ty::Generics,
+ inferred_start: InferredIndex,
}
pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
+ match item.node {
+ hir::ItemStruct(ref struct_def, _) |
+ hir::ItemUnion(ref struct_def, _) => {
+ self.visit_node_helper(item.id);
+
+ if let hir::VariantData::Tuple(..) = *struct_def {
+ self.visit_node_helper(struct_def.id());
+ }
+ }
+
+ hir::ItemEnum(ref enum_def, _) => {
+ self.visit_node_helper(item.id);
+
+ for variant in &enum_def.variants {
+ if let hir::VariantData::Tuple(..) = variant.node.data {
+ self.visit_node_helper(variant.node.data.id());
+ }
+ }
+ }
+
+ hir::ItemFn(..) => {
+ self.visit_node_helper(item.id);
+ }
+
+ hir::ItemForeignMod(ref foreign_mod) => {
+ for foreign_item in &foreign_mod.items {
+ if let hir::ForeignItemFn(..) = foreign_item.node {
+ self.visit_node_helper(foreign_item.id);
+ }
+ }
+ }
+
+ _ => {}
+ }
+ }
+
+ fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+ if let hir::TraitItemKind::Method(..) = trait_item.node {
+ self.visit_node_helper(trait_item.id);
+ }
+ }
+
+ fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+ if let hir::ImplItemKind::Method(..) = impl_item.node {
+ self.visit_node_helper(impl_item.id);
+ }
+ }
+}
+
+impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
+ fn visit_node_helper(&mut self, id: ast::NodeId) {
let tcx = self.terms_cx.tcx;
- let def_id = tcx.hir.local_def_id(item.id);
+ let def_id = tcx.hir.local_def_id(id);
// Encapsulate constructing the constraints into a task we can
// reference later. This can go away once the red-green
//
// See README.md for a detailed discussion
// on dep-graph management.
- match item.node {
- hir::ItemEnum(..) |
- hir::ItemStruct(..) |
- hir::ItemUnion(..) => {
- let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
- tcx.dep_graph.with_task(dep_node,
- AssertDepGraphSafe(self),
- def_id,
- visit_item_task);
- }
- _ => {
- // Nothing to do here, skip the task.
- }
- }
+ let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+ tcx.dep_graph.with_task(dep_node,
+ AssertDepGraphSafe(self),
+ def_id,
+ visit_item_task);
fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a, 'tcx>>,
def_id: DefId)
}
}
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
- }
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
- }
-}
-
-/// Is `param_id` a lifetime according to `map`?
-fn is_lifetime(map: &hir_map::Map, param_id: ast::NodeId) -> bool {
- match map.find(param_id) {
- Some(hir_map::NodeLifetime(..)) => true,
- _ => false,
- }
-}
-
-impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
self.terms_cx.tcx
}
fn build_constraints_for_item(&mut self, def_id: DefId) {
let tcx = self.tcx();
- let id = self.tcx().hir.as_local_node_id(def_id).unwrap();
- let item = tcx.hir.expect_item(id);
- debug!("visit_item item={}", tcx.hir.node_to_string(item.id));
+ debug!("build_constraints_for_item({})", tcx.item_path_str(def_id));
- match item.node {
- hir::ItemEnum(..) |
- hir::ItemStruct(..) |
- hir::ItemUnion(..) => {
- let generics = tcx.generics_of(def_id);
- let current_item = &CurrentItem { def_id, generics };
+ // Skip items with no generics - there's nothing to infer in them.
+ if tcx.generics_of(def_id).count() == 0 {
+ return;
+ }
+ let id = tcx.hir.as_local_node_id(def_id).unwrap();
+ let inferred_start = self.terms_cx.inferred_starts[&id];
+ let current_item = &CurrentItem { def_id, inferred_start };
+ match tcx.type_of(def_id).sty {
+ ty::TyAdt(def, _) => {
// Not entirely obvious: constraints on structs/enums do not
// affect the variance of their type parameters. See discussion
// in comment at top of module.
//
// self.add_constraints_from_generics(generics);
- for field in tcx.adt_def(def_id).all_fields() {
+ for field in def.all_fields() {
self.add_constraints_from_ty(current_item,
tcx.type_of(field.did),
self.covariant);
}
}
- hir::ItemTrait(..) |
- hir::ItemExternCrate(_) |
- hir::ItemUse(..) |
- hir::ItemStatic(..) |
- hir::ItemConst(..) |
- hir::ItemFn(..) |
- hir::ItemMod(..) |
- hir::ItemForeignMod(..) |
- hir::ItemGlobalAsm(..) |
- hir::ItemTy(..) |
- hir::ItemImpl(..) |
- hir::ItemDefaultImpl(..) => {
- span_bug!(item.span, "`build_constraints_for_item` invoked for non-type-def");
+ ty::TyFnDef(..) => {
+ self.add_constraints_from_sig(current_item,
+ tcx.fn_sig(def_id),
+ self.covariant);
}
- }
- }
-
- /// Load the generics for another item, adding a corresponding
- /// relation into the dependencies to indicate that the variance
- /// for `current` relies on `def_id`.
- fn read_generics(&mut self, current: &CurrentItem, def_id: DefId) -> &'tcx ty::Generics {
- let generics = self.tcx().generics_of(def_id);
- if self.tcx().dep_graph.is_fully_enabled() {
- self.dependencies.add(current.def_id, def_id);
- }
- generics
- }
- fn opt_inferred_index(&self, param_id: ast::NodeId) -> Option<&InferredIndex> {
- self.terms_cx.inferred_map.get(¶m_id)
- }
-
- fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId {
- let tcx = self.terms_cx.tcx;
- assert!(is_lifetime(&tcx.hir, param_id));
- match tcx.named_region_map.defs.get(¶m_id) {
- Some(&rl::Region::EarlyBound(_, lifetime_decl_id)) => lifetime_decl_id,
- Some(_) => bug!("should not encounter non early-bound cases"),
-
- // The lookup should only fail when `param_id` is
- // itself a lifetime binding: use it as the decl_id.
- None => param_id,
- }
-
- }
-
- /// Is `param_id` a type parameter for which we infer variance?
- fn is_to_be_inferred(&self, param_id: ast::NodeId) -> bool {
- let result = self.terms_cx.inferred_map.contains_key(¶m_id);
-
- // To safe-guard against invalid inferred_map constructions,
- // double-check if variance is inferred at some use of a type
- // parameter (by inspecting parent of its binding declaration
- // to see if it is introduced by a type or by a fn/impl).
-
- let check_result = |this: &ConstraintContext| -> bool {
- let tcx = this.terms_cx.tcx;
- let decl_id = this.find_binding_for_lifetime(param_id);
- // Currently only called on lifetimes; double-checking that.
- assert!(is_lifetime(&tcx.hir, param_id));
- let parent_id = tcx.hir.get_parent(decl_id);
- let parent = tcx.hir
- .find(parent_id)
- .unwrap_or_else(|| bug!("tcx.hir missing entry for id: {}", parent_id));
-
- let is_inferred;
- macro_rules! cannot_happen { () => { {
- bug!("invalid parent: {} for {}",
- tcx.hir.node_to_string(parent_id),
- tcx.hir.node_to_string(param_id));
- } } }
-
- match parent {
- hir_map::NodeItem(p) => {
- match p.node {
- hir::ItemTy(..) |
- hir::ItemEnum(..) |
- hir::ItemStruct(..) |
- hir::ItemUnion(..) |
- hir::ItemTrait(..) => is_inferred = true,
- hir::ItemFn(..) => is_inferred = false,
- _ => cannot_happen!(),
- }
- }
- hir_map::NodeTraitItem(..) => is_inferred = false,
- hir_map::NodeImplItem(..) => is_inferred = false,
- _ => cannot_happen!(),
- }
-
- return is_inferred;
- };
-
- assert_eq!(result, check_result(self));
-
- return result;
- }
-
- /// Returns a variance term representing the declared variance of the type/region parameter
- /// with the given id.
- fn declared_variance(&self,
- param_def_id: DefId,
- item_def_id: DefId,
- index: usize)
- -> VarianceTermPtr<'a> {
- assert_eq!(param_def_id.krate, item_def_id.krate);
-
- if let Some(param_node_id) = self.tcx().hir.as_local_node_id(param_def_id) {
- // Parameter on an item defined within current crate:
- // variance not yet inferred, so return a symbolic
- // variance.
- if let Some(&InferredIndex(index)) = self.opt_inferred_index(param_node_id) {
- self.terms_cx.inferred_infos[index].term
- } else {
- // If there is no inferred entry for a type parameter,
- // it must be declared on a (locally defiend) trait -- they don't
- // get inferreds because they are always invariant.
- if cfg!(debug_assertions) {
- let item_node_id = self.tcx().hir.as_local_node_id(item_def_id).unwrap();
- let item = self.tcx().hir.expect_item(item_node_id);
- let success = match item.node {
- hir::ItemTrait(..) => true,
- _ => false,
- };
- if !success {
- bug!("parameter {:?} has no inferred, but declared on non-trait: {:?}",
- item_def_id,
- item);
- }
- }
- self.invariant
+ _ => {
+ span_bug!(tcx.def_span(def_id),
+ "`build_constraints_for_item` unsupported for this item");
}
- } else {
- // Parameter on an item defined within another crate:
- // variance already inferred, just look it up.
- let variances = self.tcx().variances_of(item_def_id);
- self.constant_term(variances[index])
}
}
fn add_constraint(&mut self,
- InferredIndex(index): InferredIndex,
+ current: &CurrentItem,
+ index: u32,
variance: VarianceTermPtr<'a>) {
debug!("add_constraint(index={}, variance={:?})", index, variance);
self.constraints.push(Constraint {
- inferred: InferredIndex(index),
+ inferred: InferredIndex(current.inferred_start.0 + index as usize),
variance: variance,
});
}
debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
trait_ref,
variance);
+ self.add_constraints_from_invariant_substs(current, trait_ref.substs, variance);
+ }
- let trait_generics = self.tcx().generics_of(trait_ref.def_id);
+ fn add_constraints_from_invariant_substs(&mut self,
+ current: &CurrentItem,
+ substs: &Substs<'tcx>,
+ variance: VarianceTermPtr<'a>) {
+ debug!("add_constraints_from_invariant_substs: substs={:?} variance={:?}",
+ substs,
+ variance);
- self.add_constraints_from_substs(current,
- trait_ref.def_id,
- &trait_generics.types,
- &trait_generics.regions,
- trait_ref.substs,
- variance);
+ // Trait are always invariant so we can take advantage of that.
+ let variance_i = self.invariant(variance);
+ for ty in substs.types() {
+ self.add_constraints_from_ty(current, ty, variance_i);
+ }
+
+ for region in substs.regions() {
+ self.add_constraints_from_region(current, region, variance_i);
+ }
}
/// Adds constraints appropriate for an instance of `ty` appearing
// leaf type -- noop
}
- ty::TyClosure(..) |
- ty::TyAnon(..) => {
+ ty::TyFnDef(..) |
+ ty::TyClosure(..) => {
bug!("Unexpected closure type in variance computation");
}
}
ty::TyAdt(def, substs) => {
- let adt_generics = self.read_generics(current, def.did);
-
- self.add_constraints_from_substs(current,
- def.did,
- &adt_generics.types,
- &adt_generics.regions,
- substs,
- variance);
+ self.add_constraints_from_substs(current, def.did, substs, variance);
}
ty::TyProjection(ref data) => {
- let trait_ref = &data.trait_ref;
- let trait_generics = self.tcx().generics_of(trait_ref.def_id);
-
- self.add_constraints_from_substs(current,
- trait_ref.def_id,
- &trait_generics.types,
- &trait_generics.regions,
- trait_ref.substs,
- variance);
+ self.add_constraints_from_trait_ref(current, data.trait_ref, variance);
+ }
+
+ ty::TyAnon(_, substs) => {
+ self.add_constraints_from_invariant_substs(current, substs, variance);
}
ty::TyDynamic(ref data, r) => {
}
ty::TyParam(ref data) => {
- assert_eq!(current.generics.parent, None);
- let mut i = data.idx as usize;
- if !current.generics.has_self || i > 0 {
- i -= current.generics.regions.len();
- }
- let def_id = current.generics.types[i].def_id;
- let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
- match self.terms_cx.inferred_map.get(&node_id) {
- Some(&index) => {
- self.add_constraint(index, variance);
- }
- None => {
- // We do not infer variance for type parameters
- // declared on methods. They will not be present
- // in the inferred_map.
- }
- }
+ self.add_constraint(current, data.idx, variance);
}
- ty::TyFnDef(.., sig) |
ty::TyFnPtr(sig) => {
self.add_constraints_from_sig(current, sig, variance);
}
fn add_constraints_from_substs(&mut self,
current: &CurrentItem,
def_id: DefId,
- type_param_defs: &[ty::TypeParameterDef],
- region_param_defs: &[ty::RegionParameterDef],
substs: &Substs<'tcx>,
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
substs,
variance);
- for p in type_param_defs {
- let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize);
+ // We don't record `inferred_starts` entries for empty generics.
+ if substs.is_empty() {
+ return;
+ }
+
+ // Add a corresponding relation into the dependencies to
+ // indicate that the variance for `current` relies on `def_id`.
+ if self.tcx().dep_graph.is_fully_enabled() {
+ self.dependencies.add(current.def_id, def_id);
+ }
+
+ let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) {
+ (Some(self.terms_cx.inferred_starts[&id]), None)
+ } else {
+ (None, Some(self.tcx().variances_of(def_id)))
+ };
+
+ for (i, k) in substs.iter().enumerate() {
+ let variance_decl = if let Some(InferredIndex(start)) = local {
+ // Parameter on an item defined within current crate:
+ // variance not yet inferred, so return a symbolic
+ // variance.
+ self.terms_cx.inferred_terms[start + i]
+ } else {
+ // Parameter on an item defined within another crate:
+ // variance already inferred, just look it up.
+ self.constant_term(remote.as_ref().unwrap()[i])
+ };
let variance_i = self.xform(variance, variance_decl);
- let substs_ty = substs.type_for_def(p);
debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
variance_decl,
variance_i);
- self.add_constraints_from_ty(current, substs_ty, variance_i);
- }
-
- for p in region_param_defs {
- let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize);
- let variance_i = self.xform(variance, variance_decl);
- let substs_r = substs.region_for_def(p);
- self.add_constraints_from_region(current, substs_r, variance_i);
+ if let Some(ty) = k.as_type() {
+ self.add_constraints_from_ty(current, ty, variance_i);
+ } else if let Some(r) = k.as_region() {
+ self.add_constraints_from_region(current, r, variance_i);
+ } else {
+ bug!();
+ }
}
}
variance: VarianceTermPtr<'a>) {
match *region {
ty::ReEarlyBound(ref data) => {
- assert_eq!(current.generics.parent, None);
- let i = data.index as usize - current.generics.has_self as usize;
- let def_id = current.generics.regions[i].def_id;
- let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
- if self.is_to_be_inferred(node_id) {
- let &index = self.opt_inferred_index(node_id).unwrap();
- self.add_constraint(index, variance);
- }
+ self.add_constraint(current, data.index, variance);
}
ty::ReStatic => {}
ty::ReLateBound(..) => {
- // We do not infer variance for region parameters on
- // methods or in fn types.
+ // Late-bound regions do not get substituted the same
+ // way early-bound regions do, so we skip them here.
}
ty::ReFree(..) |
fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
-> Rc<Vec<ty::Variance>> {
- let item_id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id");
- let item = tcx.hir.expect_item(item_id);
- match item.node {
- hir::ItemTrait(..) => {
- // Traits are always invariant.
- let generics = tcx.generics_of(item_def_id);
- assert!(generics.parent.is_none());
- Rc::new(vec![ty::Variance::Invariant; generics.count()])
- }
+ let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id");
+ let unsupported = || {
+ // Variance not relevant.
+ span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item")
+ };
+ match tcx.hir.get(id) {
+ hir::map::NodeItem(item) => match item.node {
+ hir::ItemEnum(..) |
+ hir::ItemStruct(..) |
+ hir::ItemUnion(..) |
+ hir::ItemFn(..) => {}
- hir::ItemEnum(..) |
- hir::ItemStruct(..) |
- hir::ItemUnion(..) => {
- // Everything else must be inferred.
+ _ => unsupported()
+ },
- // Lacking red/green, we read the variances for all items here
- // but ignore the dependencies, then re-synthesize the ones we need.
- let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE));
- let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
- tcx.dep_graph.read(dep_node);
- for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) {
- if dep_def_id.is_local() {
- let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
- tcx.dep_graph.read(dep_node);
- } else {
- let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances);
- tcx.dep_graph.read(dep_node);
- }
- }
-
- crate_map.variances.get(&item_def_id)
- .unwrap_or(&crate_map.empty_variance)
- .clone()
- }
+ hir::map::NodeTraitItem(item) => match item.node {
+ hir::TraitItemKind::Method(..) => {}
+
+ _ => unsupported()
+ },
+
+ hir::map::NodeImplItem(item) => match item.node {
+ hir::ImplItemKind::Method(..) => {}
+
+ _ => unsupported()
+ },
+
+ hir::map::NodeForeignItem(item) => match item.node {
+ hir::ForeignItemFn(..) => {}
- _ => {
- // Variance not relevant.
- span_bug!(item.span, "asked to compute variance for wrong kind of item")
+ _ => unsupported()
+ },
+
+ hir::map::NodeVariant(_) | hir::map::NodeStructCtor(_) => {}
+
+ _ => unsupported()
+ }
+
+ // Everything else must be inferred.
+
+ // Lacking red/green, we read the variances for all items here
+ // but ignore the dependencies, then re-synthesize the ones we need.
+ let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE));
+ let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+ tcx.dep_graph.read(dep_node);
+ for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) {
+ if dep_def_id.is_local() {
+ let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+ tcx.dep_graph.read(dep_node);
+ } else {
+ let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances);
+ tcx.dep_graph.read(dep_node);
}
}
+
+ crate_map.variances.get(&item_def_id)
+ .unwrap_or(&crate_map.empty_variance)
+ .clone()
}
pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap {
let ConstraintContext { terms_cx, dependencies, constraints, .. } = constraints_cx;
- let solutions = terms_cx.inferred_infos
- .iter()
- .map(|ii| ii.initial_variance)
- .collect();
+ let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()];
+ for &(id, ref variances) in &terms_cx.lang_items {
+ let InferredIndex(start) = terms_cx.inferred_starts[&id];
+ for (i, &variance) in variances.iter().enumerate() {
+ solutions[start + i] = variance;
+ }
+ }
let mut solutions_cx = SolveContext {
- terms_cx: terms_cx,
- constraints: constraints,
- solutions: solutions,
+ terms_cx,
+ constraints,
+ solutions,
};
solutions_cx.solve();
let variances = solutions_cx.create_map();
let old_value = self.solutions[inferred];
let new_value = glb(variance, old_value);
if old_value != new_value {
- debug!("Updating inferred {} (node {}) \
+ debug!("Updating inferred {} \
from {:?} to {:?} due to {:?}",
inferred,
- self.terms_cx
- .inferred_infos[inferred]
- .param_id,
old_value,
new_value,
term);
}
fn create_map(&self) -> FxHashMap<DefId, Rc<Vec<ty::Variance>>> {
- // Collect all the variances for a particular item and stick
- // them into the variance map. We rely on the fact that we
- // generate all the inferreds for a particular item
- // consecutively (that is, we collect solutions for an item
- // until we see a new item id, and we assume (1) the solutions
- // are in the same order as the type parameters were declared
- // and (2) all solutions or a given item appear before a new
- // item id).
-
let tcx = self.terms_cx.tcx;
- let mut map = FxHashMap();
-
let solutions = &self.solutions;
- let inferred_infos = &self.terms_cx.inferred_infos;
- let mut index = 0;
- let num_inferred = self.terms_cx.num_inferred();
- while index < num_inferred {
- let item_id = inferred_infos[index].item_id;
-
- let mut item_variances = vec![];
-
- while index < num_inferred && inferred_infos[index].item_id == item_id {
- let info = &inferred_infos[index];
- let variance = solutions[index];
- debug!("Index {} Info {} Variance {:?}",
- index,
- info.index,
- variance);
-
- assert_eq!(item_variances.len(), info.index);
- item_variances.push(variance);
- index += 1;
- }
+ self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
+ let def_id = tcx.hir.local_def_id(id);
+ let generics = tcx.generics_of(def_id);
- debug!("item_id={} item_variances={:?}", item_id, item_variances);
+ let mut variances = solutions[start..start+generics.count()].to_vec();
- let item_def_id = tcx.hir.local_def_id(item_id);
+ debug!("id={} variances={:?}", id, variances);
- map.insert(item_def_id, Rc::new(item_variances));
- }
+ // Functions can have unused type parameters: make those invariant.
+ if let ty::TyFnDef(..) = tcx.type_of(def_id).sty {
+ for variance in &mut variances {
+ if *variance == ty::Bivariant {
+ *variance = ty::Invariant;
+ }
+ }
+ }
- map
+ (def_id, Rc::new(variances))
+ }).collect()
}
fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance {
use arena::TypedArena;
use rustc::ty::{self, TyCtxt};
use std::fmt;
-use std::rc::Rc;
use syntax::ast;
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub arena: &'a TypedArena<VarianceTerm<'a>>,
- pub empty_variances: Rc<Vec<ty::Variance>>,
-
// For marker types, UnsafeCell, and other lang items where
// variance is hardcoded, records the item-id and the hardcoded
// variance.
pub lang_items: Vec<(ast::NodeId, Vec<ty::Variance>)>,
- // Maps from the node id of a type/generic parameter to the
- // corresponding inferred index.
- pub inferred_map: NodeMap<InferredIndex>,
-
- // Maps from an InferredIndex to the info for that variable.
- pub inferred_infos: Vec<InferredInfo<'a>>,
-}
-
-pub struct InferredInfo<'a> {
- pub item_id: ast::NodeId,
- pub index: usize,
- pub param_id: ast::NodeId,
- pub term: VarianceTermPtr<'a>,
+ // Maps from the node id of an item to the first inferred index
+ // used for its type & region parameters.
+ pub inferred_starts: NodeMap<InferredIndex>,
- // Initial value to use for this parameter when inferring
- // variance. For most parameters, this is Bivariant. But for lang
- // items and input type parameters on traits, it is different.
- pub initial_variance: ty::Variance,
+ // Maps from an InferredIndex to the term for that variable.
+ pub inferred_terms: Vec<VarianceTermPtr<'a>>,
}
pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut terms_cx = TermsContext {
tcx: tcx,
arena: arena,
- inferred_map: NodeMap(),
- inferred_infos: Vec::new(),
+ inferred_starts: NodeMap(),
+ inferred_terms: vec![],
lang_items: lang_items(tcx),
-
- // cache and share the variance struct used for items with
- // no type/region parameters
- empty_variances: Rc::new(vec![]),
};
// See README.md for a discussion on dep-graph management.
}
impl<'a, 'tcx> TermsContext<'a, 'tcx> {
- fn add_inferreds_for_item(&mut self,
- item_id: ast::NodeId,
- generics: &hir::Generics) {
- //! Add "inferreds" for the generic parameters declared on this
- //! item. This has a lot of annoying parameters because we are
- //! trying to drive this from the AST, rather than the
- //! ty::Generics, so that we can get span info -- but this
- //! means we must accommodate syntactic distinctions.
- //!
+ fn add_inferreds_for_item(&mut self, id: ast::NodeId) {
+ let tcx = self.tcx;
+ let def_id = tcx.hir.local_def_id(id);
+ let count = tcx.generics_of(def_id).count();
- // NB: In the code below for writing the results back into the
- // `CrateVariancesMap`, we rely on the fact that all inferreds
- // for a particular item are assigned continuous indices.
-
- for (p, i) in generics.lifetimes.iter().zip(0..) {
- let id = p.lifetime.id;
- self.add_inferred(item_id, i, id);
- }
-
- for (p, i) in generics.ty_params.iter().zip(generics.lifetimes.len()..) {
- self.add_inferred(item_id, i, p.id);
+ if count == 0 {
+ return;
}
- }
- fn add_inferred(&mut self, item_id: ast::NodeId, index: usize, param_id: ast::NodeId) {
- let inf_index = InferredIndex(self.inferred_infos.len());
- let term = self.arena.alloc(InferredTerm(inf_index));
- let initial_variance = self.pick_initial_variance(item_id, index);
- self.inferred_infos.push(InferredInfo {
- item_id: item_id,
- index: index,
- param_id: param_id,
- term: term,
- initial_variance: initial_variance,
- });
- let newly_added = self.inferred_map.insert(param_id, inf_index).is_none();
+ // Record the start of this item's inferreds.
+ let start = self.inferred_terms.len();
+ let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none();
assert!(newly_added);
- debug!("add_inferred(item_path={}, \
- item_id={}, \
- index={}, \
- param_id={}, \
- inf_index={:?}, \
- initial_variance={:?})",
- self.tcx.item_path_str(self.tcx.hir.local_def_id(item_id)),
- item_id,
- index,
- param_id,
- inf_index,
- initial_variance);
- }
-
- fn pick_initial_variance(&self, item_id: ast::NodeId, index: usize) -> ty::Variance {
- match self.lang_items.iter().find(|&&(n, _)| n == item_id) {
- Some(&(_, ref variances)) => variances[index],
- None => ty::Bivariant,
- }
- }
+ // NB: In the code below for writing the results back into the
+ // `CrateVariancesMap`, we rely on the fact that all inferreds
+ // for a particular item are assigned continuous indices.
- pub fn num_inferred(&self) -> usize {
- self.inferred_infos.len()
+ let arena = self.arena;
+ self.inferred_terms.extend((start..start+count).map(|i| {
+ &*arena.alloc(InferredTerm(InferredIndex(i)))
+ }));
}
}
self.tcx.hir.node_to_string(item.id));
match item.node {
- hir::ItemEnum(_, ref generics) |
- hir::ItemStruct(_, ref generics) |
- hir::ItemUnion(_, ref generics) => {
- self.add_inferreds_for_item(item.id, generics);
+ hir::ItemStruct(ref struct_def, _) |
+ hir::ItemUnion(ref struct_def, _) => {
+ self.add_inferreds_for_item(item.id);
+
+ if let hir::VariantData::Tuple(..) = *struct_def {
+ self.add_inferreds_for_item(struct_def.id());
+ }
+ }
+
+ hir::ItemEnum(ref enum_def, _) => {
+ self.add_inferreds_for_item(item.id);
+
+ for variant in &enum_def.variants {
+ if let hir::VariantData::Tuple(..) = variant.node.data {
+ self.add_inferreds_for_item(variant.node.data.id());
+ }
+ }
+ }
+
+ hir::ItemFn(..) => {
+ self.add_inferreds_for_item(item.id);
}
- hir::ItemTrait(..) |
- hir::ItemExternCrate(_) |
- hir::ItemUse(..) |
- hir::ItemDefaultImpl(..) |
- hir::ItemImpl(..) |
- hir::ItemStatic(..) |
- hir::ItemConst(..) |
- hir::ItemFn(..) |
- hir::ItemMod(..) |
- hir::ItemForeignMod(..) |
- hir::ItemGlobalAsm(..) |
- hir::ItemTy(..) => {}
+ hir::ItemForeignMod(ref foreign_mod) => {
+ for foreign_item in &foreign_mod.items {
+ if let hir::ForeignItemFn(..) = foreign_item.node {
+ self.add_inferreds_for_item(foreign_item.id);
+ }
+ }
+ }
+
+ _ => {}
}
}
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+ fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+ if let hir::TraitItemKind::Method(..) = trait_item.node {
+ self.add_inferreds_for_item(trait_item.id);
+ }
}
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+ fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+ if let hir::ImplItemKind::Method(..) = impl_item.node {
+ self.add_inferreds_for_item(impl_item.id);
+ }
}
}
}
fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function {
- let sig = cx.tcx.type_of(did).fn_sig();
+ let sig = cx.tcx.fn_sig(did);
let constness = if cx.tcx.is_const_fn(did) {
hir::Constness::Const
ty::AssociatedKind::Method => {
let generics = (cx.tcx.generics_of(self.def_id),
&cx.tcx.predicates_of(self.def_id)).clean(cx);
- let sig = cx.tcx.type_of(self.def_id).fn_sig();
+ let sig = cx.tcx.fn_sig(self.def_id);
let mut decl = (self.def_id, sig).clean(cx);
if self.method_has_self_argument {
mutability: mt.mutbl.clean(cx),
type_: box mt.ty.clean(cx),
},
- ty::TyFnDef(.., sig) |
- ty::TyFnPtr(sig) => BareFunction(box BareFunctionDecl {
- unsafety: sig.unsafety(),
- generics: Generics {
- lifetimes: Vec::new(),
- type_params: Vec::new(),
- where_predicates: Vec::new()
- },
- decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
- abi: sig.abi(),
- }),
+ ty::TyFnDef(..) |
+ ty::TyFnPtr(_) => {
+ let ty = cx.tcx.lift(self).unwrap();
+ let sig = ty.fn_sig(cx.tcx);
+ BareFunction(box BareFunctionDecl {
+ unsafety: sig.unsafety(),
+ generics: Generics {
+ lifetimes: Vec::new(),
+ type_params: Vec::new(),
+ where_predicates: Vec::new()
+ },
+ decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
+ abi: sig.abi(),
+ })
+ }
ty::TyAdt(def, substs) => {
let did = def.did;
let kind = match def.adt_kind() {
block_info.should_panic, block_info.no_run,
block_info.ignore, block_info.test_harness,
block_info.compile_fail, block_info.error_codes,
- line, filename);
+ line, filename, block_info.allow_fail);
} else {
tests.add_old_test(text, filename);
}
block_info.should_panic, block_info.no_run,
block_info.ignore, block_info.test_harness,
block_info.compile_fail, block_info.error_codes,
- line, filename);
+ line, filename, block_info.allow_fail);
prev_offset = offset;
}
Event::Start(Tag::Header(level)) => {
test_harness: bool,
compile_fail: bool,
error_codes: Vec<String>,
+ allow_fail: bool,
}
impl LangString {
test_harness: false,
compile_fail: false,
error_codes: Vec::new(),
+ allow_fail: false,
}
}
}
"no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
"ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
+ "allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; }
"rust" => { data.rust = true; seen_rust_tags = true; }
"test_harness" => {
data.test_harness = true;
fn test_lang_string_parse() {
fn t(s: &str,
should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
- compile_fail: bool, error_codes: Vec<String>) {
+ compile_fail: bool, allow_fail: bool, error_codes: Vec<String>) {
assert_eq!(LangString::parse(s), LangString {
should_panic: should_panic,
no_run: no_run,
compile_fail: compile_fail,
error_codes: error_codes,
original: s.to_owned(),
+ allow_fail: allow_fail,
})
}
+ fn v() -> Vec<String> {
+ Vec::new()
+ }
+
// marker | should_panic| no_run| ignore| rust | test_harness| compile_fail
- // | error_codes
- t("", false, false, false, true, false, false, Vec::new());
- t("rust", false, false, false, true, false, false, Vec::new());
- t("sh", false, false, false, false, false, false, Vec::new());
- t("ignore", false, false, true, true, false, false, Vec::new());
- t("should_panic", true, false, false, true, false, false, Vec::new());
- t("no_run", false, true, false, true, false, false, Vec::new());
- t("test_harness", false, false, false, true, true, false, Vec::new());
- t("compile_fail", false, true, false, true, false, true, Vec::new());
- t("{.no_run .example}", false, true, false, true, false, false, Vec::new());
- t("{.sh .should_panic}", true, false, false, false, false, false, Vec::new());
- t("{.example .rust}", false, false, false, true, false, false, Vec::new());
- t("{.test_harness .rust}", false, false, false, true, true, false, Vec::new());
- t("text, no_run", false, true, false, false, false, false, Vec::new());
- t("text,no_run", false, true, false, false, false, false, Vec::new());
+ // | allow_fail | error_codes
+ t("", false, false, false, true, false, false, false, v());
+ t("rust", false, false, false, true, false, false, false, v());
+ t("sh", false, false, false, false, false, false, false, v());
+ t("ignore", false, false, true, true, false, false, false, v());
+ t("should_panic", true, false, false, true, false, false, false, v());
+ t("no_run", false, true, false, true, false, false, false, v());
+ t("test_harness", false, false, false, true, true, false, false, v());
+ t("compile_fail", false, true, false, true, false, true, false, v());
+ t("allow_fail", false, false, false, true, false, false, true, v());
+ t("{.no_run .example}", false, true, false, true, false, false, false, v());
+ t("{.sh .should_panic}", true, false, false, false, false, false, false, v());
+ t("{.example .rust}", false, false, false, true, false, false, false, v());
+ t("{.test_harness .rust}", false, false, false, true, true, false, false, v());
+ t("text, no_run", false, true, false, false, false, false, false, v());
+ t("text,no_run", false, true, false, false, false, false, false, v());
}
#[test]
pub fn add_test(&mut self, test: String,
should_panic: bool, no_run: bool, should_ignore: bool,
as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>,
- line: usize, filename: String) {
+ line: usize, filename: String, allow_fail: bool) {
let name = self.generate_name(line, &filename);
// to be removed when hoedown is removed
if self.render_type == RenderType::Pulldown {
ignore: should_ignore,
// compiler failures are test failures
should_panic: testing::ShouldPanic::No,
+ allow_fail: allow_fail,
},
testfn: testing::DynTestFn(box move |()| {
let panic = io::set_panic(None);
pub use self::hash_set::HashSet;
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(reason = "moved to std::ops", since = "1.19.0")]
+#[allow(deprecated)]
pub use alloc::range;
mod hash;
mod tests {
use super::*;
- use iter::repeat;
- use rand::{self, Rng};
- use ffi::{OsString, OsStr};
+ use ffi::OsStr;
use path::{Path, PathBuf};
- fn make_rand_name() -> OsString {
- let mut rng = rand::thread_rng();
- let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
- .collect::<String>());
- let n = OsString::from(n);
- assert!(var_os(&n).is_none());
- n
- }
-
- fn eq(a: Option<OsString>, b: Option<&str>) {
- assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
- }
-
- #[test]
- fn test_set_var() {
- let n = make_rand_name();
- set_var(&n, "VALUE");
- eq(var_os(&n), Some("VALUE"));
- }
-
- #[test]
- fn test_remove_var() {
- let n = make_rand_name();
- set_var(&n, "VALUE");
- remove_var(&n);
- eq(var_os(&n), None);
- }
-
- #[test]
- fn test_set_var_overwrite() {
- let n = make_rand_name();
- set_var(&n, "1");
- set_var(&n, "2");
- eq(var_os(&n), Some("2"));
- set_var(&n, "");
- eq(var_os(&n), Some(""));
- }
-
- #[test]
- #[cfg_attr(target_os = "emscripten", ignore)]
- fn test_var_big() {
- let mut s = "".to_string();
- let mut i = 0;
- while i < 100 {
- s.push_str("aaaaaaaaaa");
- i += 1;
- }
- let n = make_rand_name();
- set_var(&n, &s);
- eq(var_os(&n), Some(&s));
- }
-
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_self_exe_path() {
assert!(path.is_absolute());
}
- #[test]
- #[cfg_attr(target_os = "emscripten", ignore)]
- fn test_env_set_get_huge() {
- let n = make_rand_name();
- let s = repeat("x").take(10000).collect::<String>();
- set_var(&n, &s);
- eq(var_os(&n), Some(&s));
- remove_var(&n);
- eq(var_os(&n), None);
- }
-
- #[test]
- fn test_env_set_var() {
- let n = make_rand_name();
-
- let mut e = vars_os();
- set_var(&n, "VALUE");
- assert!(!e.any(|(k, v)| {
- &*k == &*n && &*v == "VALUE"
- }));
-
- assert!(vars_os().any(|(k, v)| {
- &*k == &*n && &*v == "VALUE"
- }));
- }
-
#[test]
fn test() {
assert!((!Path::new("test-path").is_absolute()));
#[inline]
pub fn signum(self) -> f32 { num::Float::signum(self) }
- /// Returns `true` if `self`'s sign bit is positive, including
- /// `+0.0` and `INFINITY`.
+ /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+ /// positive sign bit and positive infinity.
///
/// ```
- /// use std::f32;
- ///
- /// let nan = f32::NAN;
/// let f = 7.0_f32;
/// let g = -7.0_f32;
///
/// assert!(f.is_sign_positive());
/// assert!(!g.is_sign_positive());
- /// // Requires both tests to determine if is `NaN`
- /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
- /// Returns `true` if `self`'s sign is negative, including `-0.0`
- /// and `NEG_INFINITY`.
+ /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+ /// negative sign bit and negative infinity.
///
/// ```
- /// use std::f32;
- ///
- /// let nan = f32::NAN;
/// let f = 7.0f32;
/// let g = -7.0f32;
///
/// assert!(!f.is_sign_negative());
/// assert!(g.is_sign_negative());
- /// // Requires both tests to determine if is `NaN`.
- /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
assert!(!nan.is_infinite());
assert!(!nan.is_finite());
assert!(!nan.is_normal());
- assert!(!nan.is_sign_positive());
+ assert!(nan.is_sign_positive());
assert!(!nan.is_sign_negative());
assert_eq!(Fp::Nan, nan.classify());
}
assert!(!(-1f32).is_sign_positive());
assert!(!NEG_INFINITY.is_sign_positive());
assert!(!(1f32/NEG_INFINITY).is_sign_positive());
- assert!(!NAN.is_sign_positive());
+ assert!(NAN.is_sign_positive());
+ assert!(!(-NAN).is_sign_positive());
}
#[test]
assert!(NEG_INFINITY.is_sign_negative());
assert!((1f32/NEG_INFINITY).is_sign_negative());
assert!(!NAN.is_sign_negative());
+ assert!((-NAN).is_sign_negative());
}
#[test]
#[inline]
pub fn signum(self) -> f64 { num::Float::signum(self) }
- /// Returns `true` if `self`'s sign bit is positive, including
- /// `+0.0` and `INFINITY`.
+ /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+ /// positive sign bit and positive infinity.
///
/// ```
- /// use std::f64;
- ///
- /// let nan: f64 = f64::NAN;
- ///
/// let f = 7.0_f64;
/// let g = -7.0_f64;
///
/// assert!(f.is_sign_positive());
/// assert!(!g.is_sign_positive());
- /// // Requires both tests to determine if is `NaN`
- /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
#[inline]
pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
- /// Returns `true` if `self`'s sign is negative, including `-0.0`
- /// and `NEG_INFINITY`.
+ /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+ /// negative sign bit and negative infinity.
///
/// ```
- /// use std::f64;
- ///
- /// let nan = f64::NAN;
- ///
/// let f = 7.0_f64;
/// let g = -7.0_f64;
///
/// assert!(!f.is_sign_negative());
/// assert!(g.is_sign_negative());
- /// // Requires both tests to determine if is `NaN`.
- /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
assert!(!nan.is_infinite());
assert!(!nan.is_finite());
assert!(!nan.is_normal());
- assert!(!nan.is_sign_positive());
+ assert!(nan.is_sign_positive());
assert!(!nan.is_sign_negative());
assert_eq!(Fp::Nan, nan.classify());
}
assert!(!(-1f64).is_sign_positive());
assert!(!NEG_INFINITY.is_sign_positive());
assert!(!(1f64/NEG_INFINITY).is_sign_positive());
- assert!(!NAN.is_sign_positive());
+ assert!(NAN.is_sign_positive());
+ assert!(!(-NAN).is_sign_positive());
}
#[test]
assert!(NEG_INFINITY.is_sign_negative());
assert!((1f64/NEG_INFINITY).is_sign_negative());
assert!(!NAN.is_sign_negative());
+ assert!((-NAN).is_sign_negative());
}
#[test]
/// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
/// values, interpreted as UTF-16 when it is valid to do so.
///
-/// * In Rust, strings are always valid UTF-8, but may contain zeros.
+/// * In Rust, strings are always valid UTF-8, which may contain zeros.
///
/// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
/// and platform-native string values, and in particular allowing a Rust string
/// # Examples
///
/// ```
- /// #![feature(osstring_shrink_to_fit)]
- ///
/// use std::ffi::OsString;
///
/// let mut s = OsString::from("foo");
/// s.shrink_to_fit();
/// assert_eq!(3, s.capacity());
/// ```
- #[unstable(feature = "osstring_shrink_to_fit", issue = "40421")]
+ #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")]
pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit()
}
/// Basic usage:
///
/// ```no_run
- /// #![feature(command_envs)]
- ///
/// use std::process::{Command, Stdio};
/// use std::env;
/// use std::collections::HashMap;
/// .spawn()
/// .expect("printenv failed to start");
/// ```
- #[unstable(feature = "command_envs", issue = "38526")]
+ #[stable(feature = "command_envs", since = "1.19.0")]
pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
where I: IntoIterator<Item=(K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>
{
use sys::syscall::TimeSpec;
use sys_common::{AsInner, FromInner, IntoInner};
use time::Duration;
-use vec::Vec;
use super::{path_to_peer_addr, path_to_local_addr};
//FIXME: Use event based I/O multiplexing
//unimplemented!()
- p1.read_to_end(v1)?;
- p2.read_to_end(v2)?;
+ p1.0.read_to_end(v1)?;
+ p2.0.read_to_end(v2)?;
Ok(())
/// # Examples
///
/// ```
-/// #![feature(thread_id)]
-///
/// use std::thread;
///
/// let other_thread = thread::spawn(|| {
/// let other_thread_id = other_thread.join().unwrap();
/// assert!(thread::current().id() != other_thread_id);
/// ```
-#[unstable(feature = "thread_id", issue = "21507")]
+#[stable(feature = "thread_id", since = "1.19.0")]
#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
pub struct ThreadId(u64);
/// # Examples
///
/// ```
- /// #![feature(thread_id)]
- ///
/// use std::thread;
///
/// let other_thread = thread::spawn(|| {
/// let other_thread_id = other_thread.join().unwrap();
/// assert!(thread::current().id() != other_thread_id);
/// ```
- #[unstable(feature = "thread_id", issue = "21507")]
+ #[stable(feature = "thread_id", since = "1.19.0")]
pub fn id(&self) -> ThreadId {
self.inner.id
}
/// # Examples
///
/// ```
- /// #![feature(thread_id)]
- ///
/// use std::thread;
///
/// let builder = thread::Builder::new();
// rustc internal
(active, abi_thiscall, "1.19.0", None),
+
+ // Allows a test to fail without failing the whole suite
+ (active, allow_fail, "1.19.0", Some(42219)),
);
declare_features! (
"used internally by rustc",
cfg_fn!(rustc_attrs))),
+ ("allow_fail", Normal, Gated(Stability::Unstable,
+ "allow_fail",
+ "allow_fail attribute is currently unstable",
+ cfg_fn!(allow_fail))),
+
// Crate level attributes
("crate_name", CrateLevel, Ungated),
("crate_type", CrateLevel, Ungated),
Ok(codemap::Spanned { node: lit, span: lo.to(self.prev_span) })
}
- /// matches '-' lit | lit
+ /// matches '-' lit | lit (cf. ast_validation::AstValidator::check_expr_within_pat)
pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
+ maybe_whole_expr!(self);
+
let minus_lo = self.span;
let minus_present = self.eat(&token::BinOp(token::Minus));
let lo = self.span;
path: Vec<Ident> ,
bench: bool,
ignore: bool,
- should_panic: ShouldPanic
+ should_panic: ShouldPanic,
+ allow_fail: bool,
}
struct TestCtxt<'a> {
path: self.cx.path.clone(),
bench: is_bench_fn(&self.cx, &i),
ignore: is_ignored(&i),
- should_panic: should_panic(&i, &self.cx)
+ should_panic: should_panic(&i, &self.cx),
+ allow_fail: is_allowed_fail(&i),
};
self.cx.testfns.push(test);
self.tests.push(i.ident);
i.attrs.iter().any(|attr| attr.check_name("ignore"))
}
+fn is_allowed_fail(i: &ast::Item) -> bool {
+ i.attrs.iter().any(|attr| attr.check_name("allow_fail"))
+}
+
fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic {
match i.attrs.iter().find(|attr| attr.check_name("should_panic")) {
Some(attr) => {
}
}
};
+ let allow_fail_expr = ecx.expr_bool(span, test.allow_fail);
// self::test::TestDesc { ... }
let desc_expr = ecx.expr_struct(
test_path("TestDesc"),
vec![field("name", name_expr),
field("ignore", ignore_expr),
- field("should_panic", fail_expr)]);
+ field("should_panic", fail_expr),
+ field("allow_fail", allow_fail_expr)]);
let mut visible_path = match cx.toplevel_reexport {
all_fields = af;
vdata = vdata_;
}
- EnumMatching(_, variant, ref af) => {
+ EnumMatching(.., variant, ref af) => {
ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
all_fields = af;
vdata = &variant.node.data;
// based on the "shape".
let (ident, is_struct) = match *substr.fields {
Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
- EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()),
+ EnumMatching(_, _, v, _) => (v.node.name, v.node.data.is_struct()),
EnumNonMatchingCollapsed(..) |
StaticStruct(..) |
StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
blk])
}
- EnumMatching(idx, variant, ref fields) => {
+ EnumMatching(idx, _, variant, ref fields) => {
// We're not generating an AST that the borrow checker is expecting,
// so we need to generate a unique local variable to take the
// mutable loan out on, otherwise we get conflicts which don't
/// A summary of the possible sets of fields.
pub enum SubstructureFields<'a> {
Struct(&'a ast::VariantData, Vec<FieldInfo<'a>>),
- /// Matching variants of the enum: variant index, ast::Variant,
+ /// Matching variants of the enum: variant index, variant count, ast::Variant,
/// fields: the field name is only non-`None` in the case of a struct
/// variant.
- EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
+ EnumMatching(usize, usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
/// Non-matching variants of the enum, but with all state hidden from
/// the consequent code. The first component holds `Ident`s for all of
// expressions for referencing every field of every
// Self arg, assuming all are instances of VariantK.
// Build up code associated with such a case.
- let substructure = EnumMatching(index, variant, field_tuples);
+ let substructure = EnumMatching(index, variants.len(), variant, field_tuples);
let arm_expr = self.call_substructure_method(cx,
trait_,
type_ident,
// We need a default case that handles the fieldless variants.
// The index and actual variant aren't meaningful in this case,
// so just use whatever
+ let substructure = EnumMatching(0, variants.len(), v, Vec::new());
Some(self.call_substructure_method(cx,
trait_,
type_ident,
&self_args[..],
nonself_args,
- &EnumMatching(0, v, Vec::new())))
+ &substructure))
}
_ if variants.len() > 1 && self_args.len() > 1 => {
// Since we know that all the arguments will match if we reach
let mut stmts = Vec::new();
let fields = match *substr.fields {
- Struct(_, ref fs) => fs,
+ Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs,
EnumMatching(.., ref fs) => {
let variant_value = deriving::call_intrinsic(cx,
trait_span,
pub name: TestName,
pub ignore: bool,
pub should_panic: ShouldPanic,
+ pub allow_fail: bool,
}
#[derive(Clone)]
TrFailed,
TrFailedMsg(String),
TrIgnored,
+ TrAllowedFail,
TrMetrics(MetricMap),
TrBench(BenchSamples),
}
passed: usize,
failed: usize,
ignored: usize,
+ allowed_fail: usize,
filtered_out: usize,
measured: usize,
metrics: MetricMap,
passed: 0,
failed: 0,
ignored: 0,
+ allowed_fail: 0,
filtered_out: 0,
measured: 0,
metrics: MetricMap::new(),
self.write_short_result("ignored", "i", term::color::YELLOW)
}
+ pub fn write_allowed_fail(&mut self) -> io::Result<()> {
+ self.write_short_result("FAILED (allowed)", "a", term::color::YELLOW)
+ }
+
pub fn write_metric(&mut self) -> io::Result<()> {
self.write_pretty("metric", term::color::CYAN)
}
TrOk => self.write_ok(),
TrFailed | TrFailedMsg(_) => self.write_failed(),
TrIgnored => self.write_ignored(),
+ TrAllowedFail => self.write_allowed_fail(),
TrMetrics(ref mm) => {
self.write_metric()?;
self.write_plain(&format!(": {}\n", mm.fmt_metrics()))
TrFailed => "failed".to_owned(),
TrFailedMsg(ref msg) => format!("failed: {}", msg),
TrIgnored => "ignored".to_owned(),
+ TrAllowedFail => "failed (allowed)".to_owned(),
TrMetrics(ref mm) => mm.fmt_metrics(),
TrBench(ref bs) => fmt_bench_samples(bs),
},
}
pub fn write_run_finish(&mut self) -> io::Result<bool> {
- assert!(self.passed + self.failed + self.ignored + self.measured == self.total);
+ assert!(self.passed + self.failed + self.ignored + self.measured +
+ self.allowed_fail == self.total);
if self.options.display_output {
self.write_outputs()?;
} else {
self.write_pretty("FAILED", term::color::RED)?;
}
- let s = format!(". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
- self.passed,
- self.failed,
- self.ignored,
- self.measured,
- self.filtered_out);
+ let s = if self.allowed_fail > 0 {
+ format!(
+ ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n",
+ self.passed,
+ self.failed + self.allowed_fail,
+ self.allowed_fail,
+ self.ignored,
+ self.measured,
+ self.filtered_out)
+ } else {
+ format!(
+ ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
+ self.passed,
+ self.failed,
+ self.ignored,
+ self.measured,
+ self.filtered_out)
+ };
self.write_plain(&s)?;
return Ok(success);
}
st.not_failures.push((test, stdout));
}
TrIgnored => st.ignored += 1,
+ TrAllowedFail => st.allowed_fail += 1,
TrMetrics(mm) => {
let tname = test.name;
let MetricMap(mm) = mm;
name: StaticTestName("a"),
ignore: false,
should_panic: ShouldPanic::No,
+ allow_fail: false,
};
let test_b = TestDesc {
name: StaticTestName("b"),
ignore: false,
should_panic: ShouldPanic::No,
+ allow_fail: false,
};
let mut st = ConsoleTestState {
passed: 0,
failed: 0,
ignored: 0,
+ allowed_fail: 0,
filtered_out: 0,
measured: 0,
max_name_len: 10,
.unwrap_or(false) {
TrOk
} else {
- TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
+ if desc.allow_fail {
+ TrAllowedFail
+ } else {
+ TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
+ }
},
+ _ if desc.allow_fail => TrAllowedFail,
_ => TrFailed,
}
}
name: StaticTestName("whatever"),
ignore: true,
should_panic: ShouldPanic::No,
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
};
name: StaticTestName("whatever"),
ignore: true,
should_panic: ShouldPanic::No,
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
};
name: StaticTestName("whatever"),
ignore: false,
should_panic: ShouldPanic::Yes,
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
};
name: StaticTestName("whatever"),
ignore: false,
should_panic: ShouldPanic::YesWithMessage("error message"),
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
};
name: StaticTestName("whatever"),
ignore: false,
should_panic: ShouldPanic::YesWithMessage(expected),
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
};
name: StaticTestName("whatever"),
ignore: false,
should_panic: ShouldPanic::Yes,
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
};
name: StaticTestName("1"),
ignore: true,
should_panic: ShouldPanic::No,
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| {})),
},
name: StaticTestName("2"),
ignore: false,
should_panic: ShouldPanic::No,
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| {})),
}];
name: StaticTestName(name),
ignore: false,
should_panic: ShouldPanic::No,
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| {}))
})
name: DynTestName((*name).clone()),
ignore: false,
should_panic: ShouldPanic::No,
+ allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| testfn())),
};
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ 1u32 as char; //~ ERROR E0604
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let x = 0u8;
+ x as Vec<u8>; //~ ERROR E0605
+ //~| NOTE an `as` expression can only be used to convert between primitive types
+
+ let v = 0 as *const u8;
+ v as &u8; //~ ERROR E0605
+ //~| NOTE an `as` expression can only be used to convert between primitive types
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ &0u8 as u8; //~ ERROR E0606
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let v = 0 as *const u8;
+ v as *const [u8]; //~ ERROR E0607
+}
pub fn f1_uint_uint() {
f1(2u32, 4u32);
//~^ ERROR `u32: Foo` is not satisfied
+ //~| ERROR `u32: Foo` is not satisfied
}
pub fn f1_uint_int() {
f1(2u32, 4i32);
//~^ ERROR `u32: Foo` is not satisfied
+ //~| ERROR `u32: Foo` is not satisfied
}
pub fn f2_int() {
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- loop {
- true //~ ERROR mismatched types
- }
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct r;
-
-impl Drop for r {
- fn drop(&mut self) {
- true //~ ERROR mismatched types
- }
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- while true {
- true //~ ERROR mismatched types
- //~| expected type `()`
- //~| found type `bool`
- //~| expected (), found bool
- }
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern: non-scalar cast: `()` as `u32`
+// error-pattern: non-primitive cast: `()` as `u32`
fn main() { let u = (assert!(true) as u32); }
fn main() {
let v: u64 = 5;
let x = foo as extern "C" fn() -> isize;
- //~^ ERROR non-scalar cast
+ //~^ ERROR non-primitive cast
let y = v as extern "Rust" fn(isize) -> (isize, isize);
- //~^ ERROR non-scalar cast
+ //~^ ERROR non-primitive cast
y(x());
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern: non-scalar cast: `u32` as `()`
+// error-pattern: non-primitive cast: `u32` as `()`
fn main() { let u = 0u32 as (); }
fn main() {
let b = 0u8;
let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
- //~^ ERROR non-scalar cast
+ //~^ ERROR non-primitive cast
}
}
fn cast_b() {
- let y = 22 as !; //~ ERROR non-scalar cast
+ let y = 22 as !; //~ ERROR non-primitive cast
}
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.
-
-fn f() -> String { //~ ERROR mismatched types
- 0u8;
- "bla".to_string(); //~ HELP consider removing this semicolon
-}
-
-fn g() -> String { //~ ERROR mismatched types
- "this won't work".to_string();
- "removeme".to_string(); //~ HELP consider removing this semicolon
-}
-
-fn main() {}
a as isize; //~ ERROR casting
a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid
a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid
- b as usize; //~ ERROR non-scalar cast
+ b as usize; //~ ERROR non-primitive cast
p as usize;
//~^ ERROR casting
//~^^ HELP cast through a thin pointer
--- /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.
+
+// check that #[allow_fail] is feature-gated
+
+#[allow_fail] //~ ERROR allow_fail attribute is currently unstable
+fn ok_to_fail() {
+ assert!(false);
+}
+
+++ /dev/null
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- for x in 0..3 {
- x //~ ERROR mismatched types
- //~| NOTE expected ()
- //~| NOTE expected type `()`
- }
-}
#![feature(intrinsics)]
extern "rust-intrinsic" {
pub static breakpoint : unsafe extern "rust-intrinsic" fn();
- //~^ ERROR intrinsic has wrong type
+ //~^ ERROR intrinsic must be a function
}
-fn main() { unsafe { breakpoint(); } }
\ No newline at end of file
+fn main() { unsafe { breakpoint(); } }
fn main() {
let nil = ();
- let _t = nil as usize; //~ ERROR: non-scalar cast: `()` as `usize`
+ let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize`
}
+++ /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.
-
-fn blah() -> i32 { //~ ERROR mismatched types
- 1
-
- ; //~ HELP consider removing this semicolon:
-}
-
-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.
-
-// Regression test for #13428
-
-fn foo() -> String { //~ ERROR mismatched types
- format!("Hello {}",
- "world")
- // Put the trailing semicolon on its own line to test that the
- // note message gets the offending semicolon exactly
- ; //~ HELP consider removing this semicolon
-}
-
-fn bar() -> String { //~ ERROR mismatched types
- "foobar".to_string()
- ; //~ HELP consider removing this semicolon
-}
-
-pub 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.
-
-mod a {
- pub enum Enum {
- EnumStructVariant { x: u8, y: u8, z: u8 }
- }
-
- pub fn get_enum_struct_variant() -> () {
- Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
- //~^ ERROR mismatched types
- //~| expected type `()`
- //~| found type `a::Enum`
- //~| expected (), found enum `a::Enum`
- }
-}
-
-mod b {
- mod test {
- use a;
-
- fn test_enum_struct_variant() {
- let enum_struct_variant = ::a::get_enum_struct_variant();
- match enum_struct_variant {
- a::Enum::EnumStructVariant { x, y, z } => {
- //~^ ERROR mismatched types
- //~| expected type `()`
- //~| found type `a::Enum`
- //~| expected (), found enum `a::Enum`
- }
- }
- }
- }
-}
-
-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.
-
-fn foo(x: i32) {
- |y| x + y
-//~^ ERROR: mismatched types
-}
-
-fn main() {
- let x = foo(5)(2);
-//~^ ERROR: expected function, found `()`
-}
// except according to those terms.
fn main() {
- 0 as &std::any::Any; //~ ERROR non-scalar cast
+ 0 as &std::any::Any; //~ ERROR non-primitive cast
}
}
let i = y * self.columns() + x;
let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>);
- //~^ERROR non-scalar cast
+ //~^ERROR non-primitive cast
Some(indexer.index(i))
}
}
+++ /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.
-
-use std::ops::Add;
-
-trait Scalar {}
-impl Scalar for f64 {}
-
-struct Bob;
-
-impl<RHS: Scalar> Add <RHS> for Bob {
- type Output = Bob;
- fn add(self, rhs : RHS) -> Bob { Bob }
-}
-
-fn main() {
- let b = Bob + 3.5;
- b + 3 //~ ERROR E0277
- //~^ ERROR: mismatched types
-}
}
fn main() {
- let ex = |x| {
- let_(add(x,x), |y| { //~ ERROR type annotations needed
+ let ex = |x| { //~ ERROR type annotations needed
+ let_(add(x,x), |y| {
let_(add(x, x), |x|x)})};
}
// except according to those terms.
fn bad (p: *const isize) {
- let _q: &isize = p as &isize; //~ ERROR non-scalar cast
+ let _q: &isize = p as &isize; //~ ERROR non-primitive cast
}
fn main() { }
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait A {
- fn a(&self) {
- || self.b()
- //~^ ERROR no method named `b` found for type `&Self` in the current scope
- //~| ERROR mismatched types
- }
-}
-fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(rustc_attrs)]
-
fn _test(ref _p: str) {}
+//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied [E0277]
-#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+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.
+
+use std::ops::Deref;
+
+pub trait Foo {
+ fn baz(_: Self::Target) where Self: Deref {}
+ //~^ ERROR `<Self as std::ops::Deref>::Target: std::marker::Sized` is not satisfied
+}
+
+pub fn f(_: ToString) {}
+//~^ ERROR the trait bound `std::string::ToString + 'static: std::marker::Sized` is not satisfied
+
+fn main() { }
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- &panic!()
- //~^ ERROR mismatched types
- //~| expected type `()`
- //~| found type `&_`
- //~| expected (), found reference
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:non-scalar cast
-
#[derive(Debug)]
struct foo {
x: isize
}
fn main() {
- println!("{}", foo{ x: 1 } as isize);
+ println!("{}", foo{ x: 1 } as isize); //~ non-primitive cast: `foo` as `isize` [E0605]
}
//~^ ERROR E0277
//~| NOTE trait message
//~| NOTE required by
+ //~| ERROR E0277
+ //~| NOTE trait message
Index::index(&[] as &[i32], Foo(2u32));
//~^ ERROR E0277
//~| NOTE on impl for Foo
//~| NOTE required by
+ //~| ERROR E0277
+ //~| NOTE on impl for Foo
Index::index(&[] as &[i32], Bar(2u32));
//~^ ERROR E0277
//~| NOTE on impl for Bar
//~| NOTE required by
+ //~| ERROR E0277
+ //~| NOTE on impl for Bar
}
//~^ ERROR E0277
//~| NOTE a usize is required
//~| NOTE required by
+ //~| ERROR E0277
+ //~| NOTE a usize is required
}
--- /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! enum_number {
+ ($name:ident { $($variant:ident = $value:expr, )* }) => {
+ enum $name {
+ $($variant = $value,)*
+ }
+
+ fn foo(value: i32) -> Option<$name> {
+ match value {
+ $( $value => Some($name::$variant), )* // PatKind::Lit
+ $( $value ... 42 => Some($name::$variant), )* // PatKind::Range
+ _ => None
+ }
+ }
+ }
+}
+
+enum_number!(Change {
+ Pos = 1,
+ Neg = -1,
+ Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
+ //~^ ERROR arbitrary expressions aren't allowed in patterns
+ //~^^ ERROR only char and numeric types are allowed in range patterns
+});
+
+fn main() {}
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//error-pattern: non-scalar cast
-
enum non_nullary {
nullary,
other(isize),
fn main() {
let v = non_nullary::nullary;
- let val = v as isize;
+ let val = v as isize; //~ ERROR non-primitive cast: `non_nullary` as `isize` [E0605]
}
enum E {}
fn f(e: E) {
- println!("{}", (e as isize).to_string()); //~ ERROR non-scalar cast
+ println!("{}", (e as isize).to_string()); //~ ERROR non-primitive cast
}
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.
-
-// Check that `T:'a` is contravariant in T.
-
-#![feature(rustc_attrs)]
-
-#[rustc_variance]
-trait Foo: 'static { //~ ERROR [o]
-}
-
-#[rustc_variance]
-trait Bar<T> { //~ ERROR [o, o]
- fn do_it(&self)
- where T: 'static;
-}
-
-fn main() { }
// Check that bounds on type parameters (other than `Self`) do not
// influence variance.
-#[rustc_variance]
-trait Getter<T> { //~ ERROR [o, o]
+trait Getter<T> {
fn get(&self) -> T;
}
-#[rustc_variance]
-trait Setter<T> { //~ ERROR [o, o]
+trait Setter<T> {
fn get(&self, T);
}
Foo(T)
}
-#[rustc_variance]
-trait TestTrait<U,T:Setter<U>> { //~ ERROR [o, o, o]
- fn getter(&self, u: U) -> T;
-}
-
-#[rustc_variance]
-trait TestTrait2<U> : Getter<U> { //~ ERROR [o, o]
-}
-
-#[rustc_variance]
-trait TestTrait3<U> { //~ ERROR [o, o]
- fn getter<T:Getter<U>>(&self);
-}
-
#[rustc_variance]
struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [*, +]
t: T
m: TestMut<B, A>
}
-#[rustc_variance]
-trait Getter<A> { //~ ERROR [o, o]
+trait Getter<A> {
fn get(&self) -> A;
}
-#[rustc_variance]
-trait Setter<A> { //~ ERROR [o, o]
- fn set(&mut self, a: A);
-}
-
-#[rustc_variance]
-trait GetterSetter<A> { //~ ERROR [o, o]
- fn get(&self) -> A;
+trait Setter<A> {
fn set(&mut self, a: A);
}
-#[rustc_variance]
-trait GetterInTypeBound<A> { //~ ERROR [o, o]
- // Here, the use of `A` in the method bound *does* affect
- // variance. Think of it as if the method requested a dictionary
- // for `T:Getter<A>`. Since this dictionary is an input, it is
- // contravariant, and the Getter is covariant w/r/t A, yielding an
- // overall contravariant result.
- fn do_it<T:Getter<A>>(&self);
-}
-
-#[rustc_variance]
-trait SetterInTypeBound<A> { //~ ERROR [o, o]
- fn do_it<T:Setter<A>>(&self);
-}
-
#[rustc_variance]
struct TestObject<A, R> { //~ ERROR [o, o]
n: Box<Setter<A>+Send>,
--- /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(alloc, allocator_api, heap_api, unique)]
+
+extern crate alloc;
+
+use alloc::heap::HeapAlloc;
+use alloc::allocator::Alloc;
+
+fn main() {
+ unsafe {
+ let ptr = HeapAlloc.alloc_one::<i32>().unwrap_or_else(|e| {
+ HeapAlloc.oom(e)
+ });
+ *ptr.as_ptr() = 4;
+ assert_eq!(*ptr.as_ptr(), 4);
+ HeapAlloc.dealloc_one(ptr);
+ }
+}
pub trait Foo {
type A;
fn boo(&self) -> Self::A;
-
- fn baz(_: Self::Target) where Self: Deref {}
}
impl Foo for isize {
}
}
-fn fake_hash(v: &mut Vec<u8>, e: E) {
- e.hash(&mut FakeHasher(v));
+fn fake_hash<A: Hash>(v: &mut Vec<u8>, a: A) {
+ a.hash(&mut FakeHasher(v));
}
fn main() {
fake_hash(&mut va, E::A);
fake_hash(&mut vb, E::B);
assert!(va != vb);
+
+ // issue #39137: single variant enum hash should not hash discriminant
+ #[derive(Hash)]
+ enum SingleVariantEnum {
+ A(u8),
+ }
+ let mut v = vec![];
+ fake_hash(&mut v, SingleVariantEnum::A(17));
+ assert_eq!(vec![17], v);
}
}
}
+fn field_assignment(a: &Allocator, c0: bool) {
+ let mut x = (TwoPtrs(a.alloc(), a.alloc()), a.alloc());
+
+ x.1 = a.alloc();
+ x.1 = a.alloc();
+
+ let f = (x.0).0;
+ if c0 {
+ (x.0).0 = f;
+ }
+}
+
fn assignment2(a: &Allocator, c0: bool, c1: bool) {
let mut _v = a.alloc();
let mut _w = a.alloc();
run_test(|a| struct_dynamic_drop(a, true, true, false));
run_test(|a| struct_dynamic_drop(a, true, true, true));
+ run_test(|a| field_assignment(a, false));
+ run_test(|a| field_assignment(a, true));
+
run_test_nopanic(|a| union1(a));
}
--- /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: --test
+
+#![feature(rand, std_panic)]
+
+use std::env::*;
+use std::__rand as rand;
+use std::__rand::Rng;
+use std::iter::repeat;
+use std::ffi::{OsString, OsStr};
+
+
+fn make_rand_name() -> OsString {
+ let mut rng = rand::thread_rng();
+ let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
+ .collect::<String>());
+ let n = OsString::from(n);
+ assert!(var_os(&n).is_none());
+ n
+}
+
+fn eq(a: Option<OsString>, b: Option<&str>) {
+ assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
+}
+
+#[test]
+fn test_set_var() {
+ let n = make_rand_name();
+ set_var(&n, "VALUE");
+ eq(var_os(&n), Some("VALUE"));
+}
+
+#[test]
+fn test_remove_var() {
+ let n = make_rand_name();
+ set_var(&n, "VALUE");
+ remove_var(&n);
+ eq(var_os(&n), None);
+}
+
+#[test]
+fn test_set_var_overwrite() {
+ let n = make_rand_name();
+ set_var(&n, "1");
+ set_var(&n, "2");
+ eq(var_os(&n), Some("2"));
+ set_var(&n, "");
+ eq(var_os(&n), Some(""));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_var_big() {
+ let mut s = "".to_string();
+ let mut i = 0;
+ while i < 100 {
+ s.push_str("aaaaaaaaaa");
+ i += 1;
+ }
+ let n = make_rand_name();
+ set_var(&n, &s);
+ eq(var_os(&n), Some(&s));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_env_set_get_huge() {
+ let n = make_rand_name();
+ let s = repeat("x").take(10000).collect::<String>();
+ set_var(&n, &s);
+ eq(var_os(&n), Some(&s));
+ remove_var(&n);
+ eq(var_os(&n), None);
+}
+
+#[test]
+fn test_env_set_var() {
+ let n = make_rand_name();
+
+ let mut e = vars_os();
+ set_var(&n, "VALUE");
+ assert!(!e.any(|(k, v)| {
+ &*k == &*n && &*v == "VALUE"
+ }));
+
+ assert!(vars_os().any(|(k, v)| {
+ &*k == &*n && &*v == "VALUE"
+ }));
+}
--- /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.
+
+pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
+ s.clone();
+}
+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! enum_number {
+ ($name:ident { $($variant:ident = $value:expr, )* }) => {
+ enum $name {
+ $($variant = $value,)*
+ }
+
+ fn foo(value: i32) -> Option<$name> {
+ match value {
+ $( $value => Some($name::$variant), )*
+ _ => None
+ }
+ }
+ }
+}
+
+enum_number!(Change {
+ Down = -1,
+ None = 0,
+ Up = 1,
+});
+
+fn main() {
+ if let Some(Change::Down) = foo(-1) {} else { panic!() }
+}
+
// ignore-emscripten
-#![feature(command_envs)]
-
use std::process::Command;
use std::env;
use std::collections::HashMap;
--- /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.
+
+// compile-flags: --test
+#![feature(allow_fail)]
+
+#[test]
+#[allow_fail]
+fn test1() {
+ panic!();
+}
+
+#[test]
+#[allow_fail]
+fn test2() {
+ assert!(true);
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ loop {
+ true //~ ERROR mismatched types
+ }
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/block-must-not-have-result-do.rs:13:9
+ |
+13 | true //~ ERROR mismatched types
+ | ^^^^ expected (), found bool
+ |
+ = note: expected type `()`
+ found type `bool`
+
+error: aborting due to previous error(s)
+
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct r;
+
+impl Drop for r {
+ fn drop(&mut self) {
+ true //~ ERROR mismatched types
+ }
+}
+
+fn main() {
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/block-must-not-have-result-res.rs:15:9
+ |
+15 | true //~ ERROR mismatched types
+ | ^^^^ expected (), found bool
+ |
+ = note: expected type `()`
+ found type `bool`
+
+error: aborting due to previous error(s)
+
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ while true {
+ true //~ ERROR mismatched types
+ //~| expected type `()`
+ //~| found type `bool`
+ //~| expected (), found bool
+ }
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/block-must-not-have-result-while.rs:13:9
+ |
+13 | true //~ ERROR mismatched types
+ | ^^^^ expected (), found bool
+ |
+ = note: expected type `()`
+ found type `bool`
+
+error: aborting due to previous error(s)
+
--- /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.
+
+fn f() -> String { //~ ERROR mismatched types
+ 0u8;
+ "bla".to_string(); //~ HELP consider removing this semicolon
+}
+
+fn g() -> String { //~ ERROR mismatched types
+ "this won't work".to_string();
+ "removeme".to_string(); //~ HELP consider removing this semicolon
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/consider-removing-last-semi.rs:11:18
+ |
+11 | fn f() -> String { //~ ERROR mismatched types
+ | __________________^
+12 | | 0u8;
+13 | | "bla".to_string(); //~ HELP consider removing this semicolon
+ | | - help: consider removing this semicolon
+14 | | }
+ | |_^ expected struct `std::string::String`, found ()
+ |
+ = note: expected type `std::string::String`
+ found type `()`
+
+error[E0308]: mismatched types
+ --> $DIR/consider-removing-last-semi.rs:16:18
+ |
+16 | fn g() -> String { //~ ERROR mismatched types
+ | __________________^
+17 | | "this won't work".to_string();
+18 | | "removeme".to_string(); //~ HELP consider removing this semicolon
+ | | - help: consider removing this semicolon
+19 | | }
+ | |_^ expected struct `std::string::String`, found ()
+ |
+ = note: expected type `std::string::String`
+ found type `()`
+
+error: aborting due to previous error(s)
+
--- /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.
+
+fn blah() -> i32 { //~ ERROR mismatched types
+ 1
+
+ ; //~ HELP consider removing this semicolon:
+}
+
+fn main() { }
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-11714.rs:11:18
+ |
+11 | fn blah() -> i32 { //~ ERROR mismatched types
+ | __________________^
+12 | | 1
+13 | |
+14 | | ; //~ HELP consider removing this semicolon:
+ | | - help: consider removing this semicolon
+15 | | }
+ | |_^ expected i32, found ()
+ |
+ = note: expected type `i32`
+ found type `()`
+
+error: aborting due to previous error(s)
+
--- /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.
+
+// Regression test for #13428
+
+fn foo() -> String { //~ ERROR mismatched types
+ format!("Hello {}",
+ "world")
+ // Put the trailing semicolon on its own line to test that the
+ // note message gets the offending semicolon exactly
+ ; //~ HELP consider removing this semicolon
+}
+
+fn bar() -> String { //~ ERROR mismatched types
+ "foobar".to_string()
+ ; //~ HELP consider removing this semicolon
+}
+
+pub fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-13428.rs:13:20
+ |
+13 | fn foo() -> String { //~ ERROR mismatched types
+ | ____________________^
+14 | | format!("Hello {}",
+15 | | "world")
+16 | | // Put the trailing semicolon on its own line to test that the
+17 | | // note message gets the offending semicolon exactly
+18 | | ; //~ HELP consider removing this semicolon
+ | | - help: consider removing this semicolon
+19 | | }
+ | |_^ expected struct `std::string::String`, found ()
+ |
+ = note: expected type `std::string::String`
+ found type `()`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-13428.rs:21:20
+ |
+21 | fn bar() -> String { //~ ERROR mismatched types
+ | ____________________^
+22 | | "foobar".to_string()
+23 | | ; //~ HELP consider removing this semicolon
+ | | - help: consider removing this semicolon
+24 | | }
+ | |_^ expected struct `std::string::String`, found ()
+ |
+ = note: expected type `std::string::String`
+ found type `()`
+
+error: aborting due to previous error(s)
+
--- /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.
+
+mod a {
+ pub enum Enum {
+ EnumStructVariant { x: u8, y: u8, z: u8 }
+ }
+
+ pub fn get_enum_struct_variant() -> () {
+ Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
+ //~^ ERROR mismatched types
+ //~| expected type `()`
+ //~| found type `a::Enum`
+ //~| expected (), found enum `a::Enum`
+ }
+}
+
+mod b {
+ mod test {
+ use a;
+
+ fn test_enum_struct_variant() {
+ let enum_struct_variant = ::a::get_enum_struct_variant();
+ match enum_struct_variant {
+ a::Enum::EnumStructVariant { x, y, z } => {
+ //~^ ERROR mismatched types
+ //~| expected type `()`
+ //~| found type `a::Enum`
+ //~| expected (), found enum `a::Enum`
+ }
+ }
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-13624.rs:17:5
+ |
+17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
+ |
+ = note: expected type `()`
+ found type `a::Enum`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-13624.rs:32:9
+ |
+32 | a::Enum::EnumStructVariant { x, y, z } => {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
+ |
+ = note: expected type `()`
+ found type `a::Enum`
+
+error: aborting due to previous error(s)
+
--- /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.
+
+fn foo(x: i32) {
+ |y| x + y
+//~^ ERROR: mismatched types
+}
+
+fn main() {
+ let x = foo(5)(2);
+//~^ ERROR: expected function, found `()`
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-20862.rs:12:5
+ |
+11 | fn foo(x: i32) {
+ | - possibly return type missing here?
+12 | |y| x + y
+ | ^^^^^^^^^ expected (), found closure
+ |
+ = note: expected type `()`
+ found type `[closure@$DIR/issue-20862.rs:12:5: 12:14 x:_]`
+
+error[E0618]: expected function, found `()`
+ --> $DIR/issue-20862.rs:17:13
+ |
+17 | let x = foo(5)(2);
+ | ^^^^^^^^^
+
+error: aborting due to previous error(s)
+
--- /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.
+
+use std::ops::Add;
+
+trait Scalar {}
+impl Scalar for f64 {}
+
+struct Bob;
+
+impl<RHS: Scalar> Add <RHS> for Bob {
+ type Output = Bob;
+ fn add(self, rhs : RHS) -> Bob { Bob }
+}
+
+fn main() {
+ let b = Bob + 3.5;
+ b + 3 //~ ERROR E0277
+ //~^ ERROR: mismatched types
+}
--- /dev/null
+error[E0277]: the trait bound `{integer}: Scalar` is not satisfied
+ --> $DIR/issue-22645.rs:25:5
+ |
+25 | b + 3 //~ ERROR E0277
+ | ^ the trait `Scalar` is not implemented for `{integer}`
+ |
+ = help: the following implementations were found:
+ <f64 as Scalar>
+ = note: required because of the requirements on the impl of `std::ops::Add<{integer}>` for `Bob`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-22645.rs:25:3
+ |
+25 | b + 3 //~ ERROR E0277
+ | ^^^^^ expected (), found struct `Bob`
+ |
+ = note: expected type `()`
+ found type `Bob`
+
+error: aborting due to previous error(s)
+
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait A {
+ fn a(&self) {
+ || self.b()
+ //~^ ERROR no method named `b` found for type `&Self` in the current scope
+ //~| ERROR mismatched types
+ }
+}
+fn main() {}
--- /dev/null
+error[E0599]: no method named `b` found for type `&Self` in the current scope
+ --> $DIR/issue-3563.rs:13:17
+ |
+13 | || self.b()
+ | ^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-3563.rs:13:9
+ |
+12 | fn a(&self) {
+ | - possibly return type missing here?
+13 | || self.b()
+ | ^^^^^^^^^^^ expected (), found closure
+ |
+ = note: expected type `()`
+ found type `[closure@$DIR/issue-3563.rs:13:9: 13:20 self:_]`
+
+error: aborting due to previous error(s)
+
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ &panic!()
+ //~^ ERROR mismatched types
+ //~| expected type `()`
+ //~| found type `&_`
+ //~| expected (), found reference
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-5500.rs:12:5
+ |
+12 | &panic!()
+ | ^^^^^^^^^ expected (), found reference
+ |
+ = note: expected type `()`
+ found type `&_`
+
+error: aborting due to previous error(s)
+
--- /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.
+
+// Test that we do some basic error correcton in the tokeniser (and don't spew
+// too many bogus errors).
+
+fn foo() -> usize {
+ 3
+}
+
+fn bar() {
+ foo()
+}
+
+fn main() {
+ bar()
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/unexpected-return-on-unit.rs:19:5
+ |
+19 | foo()
+ | ^^^^^ expected (), found usize
+ |
+ = note: expected type `()`
+ found type `usize`
+help: did you mean to add a semicolon here?
+ | foo();
+help: possibly return type missing here?
+ | fn bar() -> usize {
+
+error: aborting due to previous error(s)
+
13 | fn plus_one(x: i32) -> i32 {
| ____________________________^
14 | | x + 1;
+ | | - help: consider removing this semicolon
15 | | }
| |_^ expected i32, found ()
|
= note: expected type `i32`
found type `()`
-help: consider removing this semicolon:
- --> $DIR/coercion-missing-tail-expected-type.rs:14:10
- |
-14 | x + 1;
- | ^
error[E0308]: mismatched types
--> $DIR/coercion-missing-tail-expected-type.rs:17:29
17 | fn foo() -> Result<u8, u64> {
| _____________________________^
18 | | Ok(1);
+ | | - help: consider removing this semicolon
19 | | }
| |_^ expected enum `std::result::Result`, found ()
|
= note: expected type `std::result::Result<u8, u64>`
found type `()`
-help: consider removing this semicolon:
- --> $DIR/coercion-missing-tail-expected-type.rs:18:10
- |
-18 | Ok(1);
- | ^
error: aborting due to previous error(s)
--- /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.
+
+// Forbidding a group (here, `unused`) overrules subsequent allowance of both
+// the group, and an individual lint in the group (here, `unused_variables`);
+// and, forbidding an individual lint (here, `non_snake_case`) overrules
+// subsequent allowance of a lint group containing it (here, `bad_style`). See
+// Issue #42873.
+
+#![forbid(unused, non_snake_case)]
+
+#[allow(unused, unused_variables, bad_style)]
+fn main() {
+ println!("hello forbidden world")
+}
--- /dev/null
+error[E0453]: allow(unused) overruled by outer forbid(unused)
+ --> $DIR/outer-forbid.rs:19:9
+ |
+17 | #![forbid(unused, non_snake_case)]
+ | ------ `forbid` level set here
+18 |
+19 | #[allow(unused, unused_variables, bad_style)]
+ | ^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
+ --> $DIR/outer-forbid.rs:19:17
+ |
+17 | #![forbid(unused, non_snake_case)]
+ | ------ `forbid` level set here
+18 |
+19 | #[allow(unused, unused_variables, bad_style)]
+ | ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case)
+ --> $DIR/outer-forbid.rs:19:35
+ |
+17 | #![forbid(unused, non_snake_case)]
+ | -------------- `forbid` level set here
+18 |
+19 | #[allow(unused, unused_variables, bad_style)]
+ | ^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to previous error(s)
+
-error: casting `*const U` as `*const V` is invalid
+error[E0606]: casting `*const U` as `*const V` is invalid
--> $DIR/cast-rfc0401.rs:13:5
|
13 | u as *const V
|
= note: vtable kinds may not match
-error: casting `*const U` as `*const str` is invalid
+error[E0606]: casting `*const U` as `*const str` is invalid
--> $DIR/cast-rfc0401.rs:18:5
|
18 | u as *const str
75 | let _ = main.f as *const u32;
| ^
-error: non-scalar cast: `*const u8` as `&u8`
+error[E0605]: non-primitive cast: `*const u8` as `&u8`
--> $DIR/cast-rfc0401.rs:39:13
|
39 | let _ = v as &u8;
| ^^^^^^^^
+ |
+ = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
-error: non-scalar cast: `*const u8` as `E`
+error[E0605]: non-primitive cast: `*const u8` as `E`
--> $DIR/cast-rfc0401.rs:40:13
|
40 | let _ = v as E;
| ^^^^^^
+ |
+ = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
-error: non-scalar cast: `*const u8` as `fn()`
+error[E0605]: non-primitive cast: `*const u8` as `fn()`
--> $DIR/cast-rfc0401.rs:41:13
|
41 | let _ = v as fn();
| ^^^^^^^^^
+ |
+ = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
-error: non-scalar cast: `*const u8` as `(u32,)`
+error[E0605]: non-primitive cast: `*const u8` as `(u32,)`
--> $DIR/cast-rfc0401.rs:42:13
|
42 | let _ = v as (u32,);
| ^^^^^^^^^^^
+ |
+ = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
-error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8`
+error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8`
--> $DIR/cast-rfc0401.rs:43:13
|
43 | let _ = Some(&v) as *const u8;
| ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
-error: casting `*const u8` as `f32` is invalid
+error[E0606]: casting `*const u8` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:45:13
|
45 | let _ = v as f32;
| ^^^^^^^^
-error: casting `fn() {main}` as `f64` is invalid
+error[E0606]: casting `fn() {main}` as `f64` is invalid
--> $DIR/cast-rfc0401.rs:46:13
|
46 | let _ = main as f64;
| ^^^^^^^^^^^
-error: casting `&*const u8` as `usize` is invalid
+error[E0606]: casting `&*const u8` as `usize` is invalid
--> $DIR/cast-rfc0401.rs:47:13
|
47 | let _ = &v as usize;
|
= help: cast through a raw pointer first
-error: casting `f32` as `*const u8` is invalid
+error[E0606]: casting `f32` as `*const u8` is invalid
--> $DIR/cast-rfc0401.rs:48:13
|
48 | let _ = f as *const u8;
|
= help: compare with zero instead
-error: only `u8` can be cast as `char`, not `u32`
+error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/cast-rfc0401.rs:51:13
|
51 | let _ = 0x61u32 as char;
| ^^^^^^^^^^^^^^^
-error: casting `bool` as `f32` is invalid
+error[E0606]: casting `bool` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:53:13
|
53 | let _ = false as f32;
|
= help: cast through an integer first
-error: casting `E` as `f32` is invalid
+error[E0606]: casting `E` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:54:13
|
54 | let _ = E::A as f32;
|
= help: cast through an integer first
-error: casting `char` as `f32` is invalid
+error[E0606]: casting `char` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:55:13
|
55 | let _ = 'a' as f32;
|
= help: cast through an integer first
-error: casting `bool` as `*const u8` is invalid
+error[E0606]: casting `bool` as `*const u8` is invalid
--> $DIR/cast-rfc0401.rs:57:13
|
57 | let _ = false as *const u8;
| ^^^^^^^^^^^^^^^^^^
-error: casting `E` as `*const u8` is invalid
+error[E0606]: casting `E` as `*const u8` is invalid
--> $DIR/cast-rfc0401.rs:58:13
|
58 | let _ = E::A as *const u8;
| ^^^^^^^^^^^^^^^^^
-error: casting `char` as `*const u8` is invalid
+error[E0606]: casting `char` as `*const u8` is invalid
--> $DIR/cast-rfc0401.rs:59:13
|
59 | let _ = 'a' as *const u8;
| ^^^^^^^^^^^^^^^^
-error: casting `usize` as `*const [u8]` is invalid
+error[E0606]: casting `usize` as `*const [u8]` is invalid
--> $DIR/cast-rfc0401.rs:61:13
|
61 | let _ = 42usize as *const [u8];
| ^^^^^^^^^^^^^^^^^^^^^^
-error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
+error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
--> $DIR/cast-rfc0401.rs:62:13
|
62 | let _ = v as *const [u8];
| ^^^^^^^^^^^^^^^^
-error: casting `&Foo` as `*const str` is invalid
+error[E0606]: casting `&Foo` as `*const str` is invalid
--> $DIR/cast-rfc0401.rs:64:13
|
64 | let _ = foo as *const str;
| ^^^^^^^^^^^^^^^^^
-error: casting `&Foo` as `*mut str` is invalid
+error[E0606]: casting `&Foo` as `*mut str` is invalid
--> $DIR/cast-rfc0401.rs:65:13
|
65 | let _ = foo as *mut str;
| ^^^^^^^^^^^^^^^
-error: casting `fn() {main}` as `*mut str` is invalid
+error[E0606]: casting `fn() {main}` as `*mut str` is invalid
--> $DIR/cast-rfc0401.rs:66:13
|
66 | let _ = main as *mut str;
| ^^^^^^^^^^^^^^^^
-error: casting `&f32` as `*mut f32` is invalid
+error[E0606]: casting `&f32` as `*mut f32` is invalid
--> $DIR/cast-rfc0401.rs:67:13
|
67 | let _ = &f as *mut f32;
| ^^^^^^^^^^^^^^
-error: casting `&f32` as `*const f64` is invalid
+error[E0606]: casting `&f32` as `*const f64` is invalid
--> $DIR/cast-rfc0401.rs:68:13
|
68 | let _ = &f as *const f64;
| ^^^^^^^^^^^^^^^^
-error: casting `*const [i8]` as `usize` is invalid
+error[E0606]: casting `*const [i8]` as `usize` is invalid
--> $DIR/cast-rfc0401.rs:69:13
|
69 | let _ = fat_sv as usize;
|
= help: cast through a thin pointer first
-error: casting `*const Foo` as `*const [u16]` is invalid
+error[E0606]: casting `*const Foo` as `*const [u16]` is invalid
--> $DIR/cast-rfc0401.rs:78:13
|
78 | let _ = cf as *const [u16];
|
= note: vtable kinds may not match
-error: casting `*const Foo` as `*const Bar` is invalid
+error[E0606]: casting `*const Foo` as `*const Bar` is invalid
--> $DIR/cast-rfc0401.rs:79:13
|
79 | let _ = cf as *const Bar;
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: required for the cast to the object type `Foo`
-error: casting `&{float}` as `f32` is invalid
+error[E0606]: casting `&{float}` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:81:30
|
81 | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ for x in 0..3 {
+ x //~ ERROR mismatched types
+ //~| NOTE expected ()
+ //~| NOTE expected type `()`
+ }
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/for-loop-has-unit-body.rs:13:9
+ |
+13 | x //~ ERROR mismatched types
+ | ^ expected (), found integral variable
+ |
+ = note: expected type `()`
+ found type `{integer}`
+
+error: aborting due to previous error(s)
+
error[E0308]: mismatched types
--> $DIR/issue-19109.rs:14:5
|
+13 | fn function(t: &mut Trait) {
+ | - help: possibly return type missing here? `-> *mut Trait `
14 | t as *mut Trait
| ^^^^^^^^^^^^^^^ expected (), found *-ptr
|
37 | write!(hello);
| -------------- in this macro invocation
-error: non-scalar cast: `{integer}` as `()`
+error[E0605]: non-primitive cast: `{integer}` as `()`
--> $DIR/issue-26480.rs:32:19
|
32 | ($x:expr) => ($x as ())
...
38 | cast!(2);
| --------- in this macro invocation
+ |
+ = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
error: aborting due to previous error(s)
--> $DIR/token-error-correct-3.rs:25:13
|
25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here? `;`
+ | |
+ | expected (), found enum `std::result::Result`
|
= note: expected type `()`
found type `std::result::Result<bool, std::io::Error>`
-Subproject commit 534ce68621ce4feec0b7e8627cfd3b077d4f3900
+Subproject commit abf01e1eddb3145c83f71b469ea7bee37141e5e1
name: make_test_name(config, testpaths),
ignore: ignore,
should_panic: should_panic,
+ allow_fail: false,
},
testfn: make_test_closure(config, testpaths),
}
}
if !debugger_run_result.status.success() {
- self.fatal("gdb failed to execute");
+ self.fatal_proc_rec("gdb failed to execute", &debugger_run_result);
}
self.check_debugger_output(&debugger_run_result, &check_lines);