"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"
}
}
- /// 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.
// 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),
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);
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);
// 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(),
}
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 => {
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 {
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))
}
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;
}
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());
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);
}
-> 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
// 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)
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());
// 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 =
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 {
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,
}
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,
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());
-> 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));
}
}
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);
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
}
}
_ => ()
}
- 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() {
}
}
clean::Import::Glob(ref src) => {
- write!(f, "use {}::*;", *src)
+ if src.path.segments.is_empty() {
+ write!(f, "use *;")
+ } else {
+ write!(f, "use {}::*;", *src)
+ }
}
}
}
fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result {
document_stability(w, cx, item)?;
- document_full(w, item, cx.render_type)?;
+ let prefix = render_assoc_const_value(item);
+ document_full(w, item, cx.render_type, &prefix)?;
Ok(())
}
fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink,
- render_type: RenderType) -> fmt::Result {
+ render_type: RenderType, prefix: &str) -> fmt::Result {
if let Some(s) = item.doc_value() {
let markdown = if s.contains('\n') {
format!("{} [Read more]({})",
} else {
format!("{}", &plain_summary_line(Some(s)))
};
- write!(w, "<div class='docblock'>{}</div>",
- Markdown(&markdown, render_type))?;
+ write!(w, "<div class='docblock'>{}{}</div>", prefix, Markdown(&markdown, render_type))?;
+ } else if !prefix.is_empty() {
+ write!(w, "<div class='docblock'>{}</div>", prefix)?;
}
Ok(())
}
-fn md_render_assoc_item(item: &clean::Item) -> String {
+fn render_assoc_const_value(item: &clean::Item) -> String {
match item.inner {
- clean::AssociatedConstItem(ref ty, ref default) => {
- if let Some(default) = default.as_ref() {
- format!("```\n{}: {:#} = {}\n```\n\n", item.name.as_ref().unwrap(), ty, default)
- } else {
- format!("```\n{}: {:#}\n```\n\n", item.name.as_ref().unwrap(), ty)
- }
+ clean::AssociatedConstItem(ref ty, Some(ref default)) => {
+ highlight::render_with_highlighting(
+ &format!("{}: {:#} = {}", item.name.as_ref().unwrap(), ty, default),
+ None,
+ None,
+ None,
+ )
}
_ => String::new(),
}
}
-fn get_doc_value(item: &clean::Item) -> Option<&str> {
- let x = item.doc_value();
- if x.is_none() {
- match item.inner {
- clean::AssociatedConstItem(_, _) => Some(""),
- _ => None,
- }
- } else {
- x
- }
-}
-
fn document_full(w: &mut fmt::Formatter, item: &clean::Item,
- render_type: RenderType) -> fmt::Result {
- if let Some(s) = get_doc_value(item) {
- write!(w, "<div class='docblock'>{}</div>",
- Markdown(&format!("{}{}", md_render_assoc_item(item), s), render_type))?;
+ render_type: RenderType, prefix: &str) -> fmt::Result {
+ if let Some(s) = item.doc_value() {
+ write!(w, "<div class='docblock'>{}{}</div>", prefix, Markdown(s, render_type))?;
+ } else if !prefix.is_empty() {
+ write!(w, "<div class='docblock'>{}</div>", prefix)?;
}
Ok(())
}
assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
write!(w, "</code></span></h4>\n")?;
}
- clean::ConstantItem(ref c) => {
- let id = derive_id(format!("{}.{}", item_type, name));
- let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
- write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
- write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
- assoc_const(w, item, &c.type_, Some(&c.expr), link.anchor(&id))?;
- write!(w, "</code></span></h4>\n")?;
- }
clean::AssociatedTypeItem(ref bounds, ref default) => {
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
}
if render_method_item || render_mode == RenderMode::Normal {
+ let prefix = render_assoc_const_value(item);
if !is_default_item {
if let Some(t) = trait_ {
// The trait item may have been stripped so we might not
// We need the stability of the item from the trait
// because impls can't have a stability.
document_stability(w, cx, it)?;
- if get_doc_value(item).is_some() {
- document_full(w, item, cx.render_type)?;
+ if item.doc_value().is_some() {
+ document_full(w, item, cx.render_type, &prefix)?;
} else {
// In case the item isn't documented,
// provide short documentation from the trait.
- document_short(w, it, link, cx.render_type)?;
+ document_short(w, it, link, cx.render_type, &prefix)?;
}
}
} else {
- document(w, cx, item)?;
+ document_stability(w, cx, item)?;
+ document_full(w, item, cx.render_type, &prefix)?;
}
} else {
document_stability(w, cx, item)?;
- document_short(w, item, link, cx.render_type)?;
+ document_short(w, item, link, cx.render_type, &prefix)?;
}
}
Ok(())
clean::TraitItem(..) | clean::FunctionItem(..) |
clean::VariantItem(..) | clean::MethodItem(..) |
clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) |
- clean::ConstantItem(..) | clean::UnionItem(..) => {
+ clean::ConstantItem(..) | clean::UnionItem(..) |
+ clean::AssociatedConstItem(..) => {
if i.def_id.is_local() {
if !self.access_levels.is_exported(i.def_id) {
return None;
// Primitives are never stripped
clean::PrimitiveItem(..) => {}
- // Associated consts and types are never stripped
- clean::AssociatedConstItem(..) |
+ // Associated types are never stripped
clean::AssociatedTypeItem(..) => {}
}
#[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
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,
--- /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() {
// 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() { }
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
#![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`
}
// 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))
}
}
// 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() { }
// 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
}
// 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>,
}
}
-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));
}
// @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
// @has - '//*[@class="docblock"]' 'FOO: usize = 12'
const FOO: usize = 12;
+ // @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool'
+ const FOO_NO_DEFAULT: bool;
+ // @!has - FOO_HIDDEN
+ #[doc(hidden)]
+ const FOO_HIDDEN: u8 = 0;
}
pub struct Bar;
+impl Foo for Bar {
+ // @has assoc_consts/struct.Bar.html '//code' 'impl Foo for Bar'
+ // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
+ // @has - '//*[@class="docblock"]' 'FOO: usize = 12'
+ const FOO: usize = 12;
+ // @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool'
+ // @has - '//*[@class="docblock"]' 'FOO_NO_DEFAULT: bool = false'
+ const FOO_NO_DEFAULT: bool = false;
+ // @!has - FOO_HIDDEN
+ #[doc(hidden)]
+ const FOO_HIDDEN: u8 = 0;
+}
+
impl Bar {
// @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.BAR"]' \
// 'const BAR: usize'
// @has - '//*[@class="docblock"]' "F: fn(_: &(ToString + 'static)) = f"
pub const F: fn(_: &(ToString + 'static)) = f;
}
+
+impl Bar {
+ // @!has assoc_consts/struct.Bar.html 'BAR_PRIVATE'
+ const BAR_PRIVATE: char = 'a';
+ // @!has assoc_consts/struct.Bar.html 'BAR_HIDDEN'
+ #[doc(hidden)]
+ pub const BAR_HIDDEN: &'static str = "a";
+}
+
+// @has assoc_consts/trait.Qux.html
+pub trait Qux {
+ // @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8'
+ // @has - '//*[@class="docblock"]' "Docs for QUX0 in trait."
+ /// Docs for QUX0 in trait.
+ const QUX0: u8;
+ // @has - '//*[@id="associatedconstant.QUX1"]' 'const QUX1: i8'
+ // @has - '//*[@class="docblock"]' "Docs for QUX1 in trait."
+ /// Docs for QUX1 in trait.
+ const QUX1: i8;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16'
+ // @has - '//*[@class="docblock"]' "QUX_DEFAULT0: u16 = 1"
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT0 in trait."
+ /// Docs for QUX_DEFAULT0 in trait.
+ const QUX_DEFAULT0: u16 = 1;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16'
+ // @has - '//*[@class="docblock"]' "QUX_DEFAULT1: i16 = 2"
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in trait."
+ /// Docs for QUX_DEFAULT1 in trait.
+ const QUX_DEFAULT1: i16 = 2;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT2"]' 'const QUX_DEFAULT2: u32'
+ // @has - '//*[@class="docblock"]' "QUX_DEFAULT2: u32 = 3"
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT2 in trait."
+ /// Docs for QUX_DEFAULT2 in trait.
+ const QUX_DEFAULT2: u32 = 3;
+}
+
+// @has assoc_consts/struct.Bar.html '//code' 'impl Qux for Bar'
+impl Qux for Bar {
+ // @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8'
+ // @has - '//*[@class="docblock"]' "QUX0: u8 = 4"
+ // @has - '//*[@class="docblock"]' "Docs for QUX0 in trait."
+ /// Docs for QUX0 in trait.
+ const QUX0: u8 = 4;
+ // @has - '//*[@id="associatedconstant.QUX1"]' 'const QUX1: i8'
+ // @has - '//*[@class="docblock"]' "QUX1: i8 = 5"
+ // @has - '//*[@class="docblock"]' "Docs for QUX1 in impl."
+ /// Docs for QUX1 in impl.
+ const QUX1: i8 = 5;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16'
+ // @has - '//*[@class="docblock"]' "QUX_DEFAULT0: u16 = 6"
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT0 in trait."
+ const QUX_DEFAULT0: u16 = 6;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16'
+ // @has - '//*[@class="docblock"]' "QUX_DEFAULT1: i16 = 7"
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in impl."
+ /// Docs for QUX_DEFAULT1 in impl.
+ const QUX_DEFAULT1: i16 = 7;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT2"]' 'const QUX_DEFAULT2: u32'
+ // @has - '//*[@class="docblock"]' "QUX_DEFAULT2: u32 = 3"
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT2 in trait."
+}
--- /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: --no-defaults
+
+#![crate_name = "foo"]
+
+// @has foo/a/index.html '//code' 'use *;'
+mod a {
+ use *;
+}
+
+// @has foo/b/index.html '//code' 'pub use *;'
+pub mod b {
+ pub use *;
+}
--- /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>>();
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)
-Subproject commit 534ce68621ce4feec0b7e8627cfd3b077d4f3900
+Subproject commit abf01e1eddb3145c83f71b469ea7bee37141e5e1
}
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);