Auto merge of #49190 - kennytm:rollup, r=kennytm

Rollup of 17 pull requests

- Successful merges: #46518, #48810, #48834, #48902, #49004, #49092, #49096, #49099, #49104, #49125, #49139, #49152, #49157, #49161, #49166, #49176, #49184
- Failed merges:
This commit is contained in:
bors 2018-03-20 10:18:34 +00:00
commit 75af15ee6c
48 changed files with 1035 additions and 655 deletions

139
src/Cargo.lock generated
View file

@ -236,18 +236,6 @@ dependencies = [
"serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cargo_metadata"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cargo_metadata"
version = "0.5.3"
@ -588,15 +576,6 @@ dependencies = [
"regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.5.5"
@ -1490,7 +1469,7 @@ dependencies = [
"rls-rustc 0.2.2 (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.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustfmt-nightly 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustfmt-nightly 0.4.1",
"serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1585,7 +1564,7 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_cratesio_shim"
version = "29.0.0"
version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1594,57 +1573,62 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_data_structures"
version = "29.0.0"
version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-rustc_errors"
version = "29.0.0"
version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-serialize"
version = "29.0.0"
version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-ap-syntax"
version = "29.0.0"
version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_cratesio_shim 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_errors 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-syntax_pos"
version = "29.0.0"
version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2066,52 +2050,26 @@ dependencies = [
[[package]]
name = "rustfmt-nightly"
version = "0.3.8"
version = "0.4.1"
dependencies = [
"cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-syntax 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (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)",
]
[[package]]
name = "rustfmt-nightly"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.10 (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.5 (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)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2146,15 +2104,6 @@ name = "scopeguard"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "semver"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.9.0"
@ -2424,6 +2373,15 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "term"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termcolor"
version = "0.3.5"
@ -2737,7 +2695,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b"
"checksum cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20d6fb2b5574726329c85cdba0df0347fddfec3cf9c8b588f9931708280f5643"
"checksum cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5caae26de3704081ef638f87f05a6891b04f2b7d5ce9429a3de21095528ae22"
"checksum cc 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fedf677519ac9e865c4ff43ef8f930773b37ed6e6ea61b6b83b400a7b5787f49"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
@ -2764,7 +2721,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
"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 env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
"checksum env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0628f04f7c26ebccf40d7fc2c1cf92236c05ec88cf2132641cc956812312f0f"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
@ -2858,21 +2814,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea"
"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
"checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524"
"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad"
"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182"
"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b"
"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d"
"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0"
"checksum rustc-ap-rustc_cratesio_shim 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "adc16e4a6e50a4ffbd4633d737aedbdfcb565bdf658159e0544266908180a919"
"checksum rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ec5f0a018fbec07f64b689ac20f7343ed77939055ca07d2aceb37c832245b1b"
"checksum rustc-ap-rustc_errors 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8301221cc07002666eed552a089b15000bc954c94b14a460c0653363a7f42f4c"
"checksum rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5212ee40fc332d791cacf202ae5fb99197341857c0a14bcdf60541fea7dfc5ed"
"checksum rustc-ap-syntax 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "168571b3878c6c61aef4bacef95c86d30fa61fb1cff04395d9535c80c196e559"
"checksum rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd7a0486f56db583caa665c8b4ff02c4774fe279db1741509437bc8a84c53361"
"checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustfmt-nightly 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "554256054eae37ead2f799ffa9cf8be8249496c6c3cf005c28b7cfa55f4efaa5"
"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
"checksum schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fbaffce35eb61c5b00846e73128b0cd62717e7c0ec46abbec132370d013975b4"
"checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4"
"checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4763b773978e495252615e814d2ad04773b2c1f85421c7913869a537f35cb406"
@ -2896,6 +2850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1605d3388ceb50252952ffebab4b5dc43017ead7e4481b175961c283bb951195"
"checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e"
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
"checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"

View file

@ -221,6 +221,7 @@ fn make_win_dist(
"libsecur32.a",
"libsetupapi.a",
"libshell32.a",
"libsynchronization.a",
"libuser32.a",
"libuserenv.a",
"libuuid.a",

View file

@ -114,7 +114,7 @@
//! * *nothing* ⇒ [`Display`]
//! * `?` ⇒ [`Debug`]
//! * `x?` ⇒ [`Debug`] with lower-case hexadecimal integers
//! * `X?` ⇒ [`Debug`] with lower-case hexadecimal integers
//! * `X?` ⇒ [`Debug`] with upper-case hexadecimal integers
//! * `o` ⇒ [`Octal`](trait.Octal.html)
//! * `x` ⇒ [`LowerHex`](trait.LowerHex.html)
//! * `X` ⇒ [`UpperHex`](trait.UpperHex.html)

View file

@ -14,24 +14,154 @@
/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data. The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
/// In Rust, it is common to provide different representations of a type for
/// different use cases. For instance, storage location and management for a
/// value can be specifically chosen as appropriate for a particular use via
/// pointer types such as [`Box<T>`] or [`Rc<T>`]. Beyond these generic
/// wrappers that can be used with any type, some types provide optional
/// facets providing potentially costly functionality. An example for such a
/// type is [`String`] which adds the ability to extend a string to the basic
/// [`str`]. This requires keeping additional information unnecessary for a
/// simple, immutable string.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`. A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
/// These types provide access to the underlying data through references
/// to the type of that data. They are said to be borrowed as that type.
/// For instance, a [`Box<T>`] can be borrowed as `T` while a [`String`]
/// can be borrowed as `str`.
///
/// If you are implementing `Borrow` and both `Self` and `Borrowed` implement
/// `Hash`, `Eq`, and/or `Ord`, they must produce the same result.
/// Types express that they can be borrowed as some type `T` by implementing
/// `Borrow<T>`, providing a reference to a `T` in the traits
/// [`borrow`] method. A type is free to borrow as several different types.
/// If it wishes to mutably borrow as the type allowing the underlying data
/// to be modified, it can additionally implement [`BorrowMut<T>`].
///
/// `Borrow` is very similar to, but different than, `AsRef`. See
/// [the book][book] for more.
/// Further, when providing implementations for additional traits, it needs
/// to be considered whether they should behave identical to those of the
/// underlying type as a consequence of acting as a representation of that
/// underlying type. Generic code typically uses `Borrow<T>` when it relies
/// on the identical behavior of these additional trait implementations.
/// These traits will likely appear as additional trait bounds.
///
/// [book]: ../../book/first-edition/borrow-and-asref.html
/// If generic code merely needs to work for all types that can
/// provide a reference to related type `T`, it is often better to use
/// [`AsRef<T>`] as more types can safely implement it.
///
/// [`AsRef<T>`]: ../../std/convert/trait.AsRef.html
/// [`BorrowMut<T>`]: trait.BorrowMut.html
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
/// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
/// [`str`]: ../../std/primitive.str.html
/// [`String`]: ../../std/string/struct.String.html
/// [`borrow`]: #tymethod.borrow
///
/// # Examples
///
/// As a data collection, [`HashMap<K, V>`] owns both keys and values. If
/// the keys actual data is wrapped in a managing type of some kind, it
/// should, however, still be possible to search for a value using a
/// reference to the keys data. For instance, if the key is a string, then
/// it is likely stored with the hash map as a [`String`], while it should
/// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to
/// operate on a `String` while `get` needs to be able to use a `&str`.
///
/// Slightly simplified, the relevant parts of `HashMap<K, V>` look like
/// this:
///
/// ```
/// use std::borrow::Borrow;
/// use std::hash::Hash;
///
/// pub struct HashMap<K, V> {
/// # marker: ::std::marker::PhantomData<(K, V)>,
/// // fields omitted
/// }
///
/// impl<K, V> HashMap<K, V> {
/// pub fn insert(&self, key: K, value: V) -> Option<V>
/// where K: Hash + Eq
/// {
/// # unimplemented!()
/// // ...
/// }
///
/// pub fn get<Q>(&self, k: &Q) -> Option<&V>
/// where
/// K: Borrow<Q>,
/// Q: Hash + Eq + ?Sized
/// {
/// # unimplemented!()
/// // ...
/// }
/// }
/// ```
///
/// The entire hash map is generic over a key type `K`. Because these keys
/// are stored with the hash map, this type has to own the keys data.
/// When inserting a key-value pair, the map is given such a `K` and needs
/// to find the correct hash bucket and check if the key is already present
/// based on that `K`. It therefore requires `K: Hash + Eq`.
///
/// When searching for a value in the map, however, having to provide a
/// reference to a `K` as the key to search for would require to always
/// create such an owned value. For string keys, this would mean a `String`
/// value needs to be created just for the search for cases where only a
/// `str` is available.
///
/// Instead, the `get` method is generic over the type of the underlying key
/// data, called `Q` in the method signature above. It states that `K`
/// borrows as a `Q` by requiring that `K: Borrow<Q>`. By additionally
/// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q`
/// have implementations of the `Hash` and `Eq` traits that produce identical
/// results.
///
/// The implementation of `get` relies in particular on identical
/// implementations of `Hash` by determining the keys hash bucket by calling
/// `Hash::hash` on the `Q` value even though it inserted the key based on
/// the hash value calculated from the `K` value.
///
/// As a consequence, the hash map breaks if a `K` wrapping a `Q` value
/// produces a different hash than `Q`. For instance, imagine you have a
/// type that wraps a string but compares ASCII letters ignoring their case:
///
/// ```
/// pub struct CaseInsensitiveString(String);
///
/// impl PartialEq for CaseInsensitiveString {
/// fn eq(&self, other: &Self) -> bool {
/// self.0.eq_ignore_ascii_case(&other.0)
/// }
/// }
///
/// impl Eq for CaseInsensitiveString { }
/// ```
///
/// Because two equal values need to produce the same hash value, the
/// implementation of `Hash` needs to ignore ASCII case, too:
///
/// ```
/// # use std::hash::{Hash, Hasher};
/// # pub struct CaseInsensitiveString(String);
/// impl Hash for CaseInsensitiveString {
/// fn hash<H: Hasher>(&self, state: &mut H) {
/// for c in self.0.as_bytes() {
/// c.to_ascii_lowercase().hash(state)
/// }
/// }
/// }
/// ```
///
/// Can `CaseInsensitiveString` implement `Borrow<str>`? It certainly can
/// provide a reference to a string slice via its contained owned string.
/// But because its `Hash` implementation differs, it behaves differently
/// from `str` and therefore must not, in fact, implement `Borrow<str>`.
/// If it wants to allow others access to the underlying `str`, it can do
/// that via `AsRef<str>` which doesnt carry any extra requirements.
///
/// [`Hash`]: ../../std/hash/trait.Hash.html
/// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
/// [`String`]: ../../std/string/struct.String.html
/// [`str`]: ../../std/primitive.str.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
/// Immutably borrows from an owned value.
@ -59,7 +189,11 @@ pub trait Borrow<Borrowed: ?Sized> {
/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
/// As a companion to [`Borrow<T>`] this trait allows a type to borrow as
/// an underlying type by providing a mutable reference. See [`Borrow<T>`]
/// for more information on borrowing as another type.
///
/// [`Borrow<T>`]: trait.Borrow.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
/// Mutably borrows from an owned value.

View file

@ -49,15 +49,13 @@ doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
#[doc(hidden)]
trait GenericRadix {
/// The number of digits.
fn base(&self) -> u8;
const BASE: u8;
/// A radix-specific prefix string.
fn prefix(&self) -> &'static str {
""
}
const PREFIX: &'static str;
/// Converts an integer to corresponding radix digit.
fn digit(&self, x: u8) -> u8;
fn digit(x: u8) -> u8;
/// Format an integer using the radix using a formatter.
fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
@ -67,14 +65,14 @@ trait GenericRadix {
let is_nonnegative = x >= zero;
let mut buf = [0; 128];
let mut curr = buf.len();
let base = T::from_u8(self.base());
let base = T::from_u8(Self::BASE);
if is_nonnegative {
// Accumulate each digit of the number from the least significant
// to the most significant figure.
for byte in buf.iter_mut().rev() {
let n = x % base; // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(n.to_u8()); // Store the digit in the buffer.
let n = x % base; // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = Self::digit(n.to_u8()); // Store the digit in the buffer.
curr -= 1;
if x == zero {
// No more digits left to accumulate.
@ -84,9 +82,9 @@ trait GenericRadix {
} else {
// Do the same as above, but accounting for two's complement.
for byte in buf.iter_mut().rev() {
let n = zero - (x % base); // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(n.to_u8()); // Store the digit in the buffer.
let n = zero - (x % base); // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = Self::digit(n.to_u8()); // Store the digit in the buffer.
curr -= 1;
if x == zero {
// No more digits left to accumulate.
@ -95,7 +93,7 @@ trait GenericRadix {
}
}
let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };
f.pad_integral(is_nonnegative, self.prefix(), buf)
f.pad_integral(is_nonnegative, Self::PREFIX, buf)
}
}
@ -122,12 +120,12 @@ struct UpperHex;
macro_rules! radix {
($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
impl GenericRadix for $T {
fn base(&self) -> u8 { $base }
fn prefix(&self) -> &'static str { $prefix }
fn digit(&self, x: u8) -> u8 {
const BASE: u8 = $base;
const PREFIX: &'static str = $prefix;
fn digit(x: u8) -> u8 {
match x {
$($x => $conv,)+
x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
x => panic!("number not in the range 0..{}: {}", Self::BASE - 1, x),
}
}
}

View file

@ -317,11 +317,320 @@ macro_rules! wrapping_impl {
}
forward_ref_unop! { impl Neg, neg for Wrapping<$t>,
#[stable(feature = "wrapping_ref", since = "1.14.0")] }
)*)
}
wrapping_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
macro_rules! wrapping_int_impl {
($($t:ty)*) => ($(
impl Wrapping<$t> {
/// Returns the number of ones in the binary representation of
/// `self`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i8> = Wrapping(-0b1000_0000);
///
/// assert_eq!(n.count_ones(), 1);
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn count_ones(self) -> u32 {
self.0.count_ones()
}
/// Returns the number of zeros in the binary representation of
/// `self`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i8> = Wrapping(-0b1000_0000);
///
/// assert_eq!(n.count_zeros(), 7);
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn count_zeros(self) -> u32 {
self.0.count_zeros()
}
/// Returns the number of leading zeros in the binary representation
/// of `self`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i16> = Wrapping(-1);
///
/// assert_eq!(n.leading_zeros(), 0);
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn leading_zeros(self) -> u32 {
self.0.leading_zeros()
}
/// Returns the number of trailing zeros in the binary representation
/// of `self`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i8> = Wrapping(-4);
///
/// assert_eq!(n.trailing_zeros(), 2);
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn trailing_zeros(self) -> u32 {
self.0.trailing_zeros()
}
/// Shifts the bits to the left by a specified amount, `n`,
/// wrapping the truncated bits to the end of the resulting
/// integer.
///
/// Please note this isn't the same operation as `>>`!
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
/// let m: Wrapping<i64> = Wrapping(-0x76543210FEDCBA99);
///
/// assert_eq!(n.rotate_left(32), m);
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn rotate_left(self, n: u32) -> Self {
Wrapping(self.0.rotate_left(n))
}
/// Shifts the bits to the right by a specified amount, `n`,
/// wrapping the truncated bits to the beginning of the resulting
/// integer.
///
/// Please note this isn't the same operation as `<<`!
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
/// let m: Wrapping<i64> = Wrapping(-0xFEDCBA987654322);
///
/// assert_eq!(n.rotate_right(4), m);
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn rotate_right(self, n: u32) -> Self {
Wrapping(self.0.rotate_right(n))
}
/// Reverses the byte order of the integer.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i16> = Wrapping(0b0000000_01010101);
/// assert_eq!(n, Wrapping(85));
///
/// let m = n.swap_bytes();
///
/// assert_eq!(m, Wrapping(0b01010101_00000000));
/// assert_eq!(m, Wrapping(21760));
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn swap_bytes(self) -> Self {
Wrapping(self.0.swap_bytes())
}
/// Converts an integer from big endian to the target's endianness.
///
/// On big endian this is a no-op. On little endian the bytes are
/// swapped.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
///
/// if cfg!(target_endian = "big") {
/// assert_eq!(Wrapping::<i64>::from_be(n), n);
/// } else {
/// assert_eq!(Wrapping::<i64>::from_be(n), n.swap_bytes());
/// }
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn from_be(x: Self) -> Self {
Wrapping(<$t>::from_be(x.0))
}
/// Converts an integer from little endian to the target's endianness.
///
/// On little endian this is a no-op. On big endian the bytes are
/// swapped.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
///
/// if cfg!(target_endian = "little") {
/// assert_eq!(Wrapping::<i64>::from_le(n), n);
/// } else {
/// assert_eq!(Wrapping::<i64>::from_le(n), n.swap_bytes());
/// }
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn from_le(x: Self) -> Self {
Wrapping(<$t>::from_le(x.0))
}
/// Converts `self` to big endian from the target's endianness.
///
/// On big endian this is a no-op. On little endian the bytes are
/// swapped.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
///
/// if cfg!(target_endian = "big") {
/// assert_eq!(n.to_be(), n);
/// } else {
/// assert_eq!(n.to_be(), n.swap_bytes());
/// }
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn to_be(self) -> Self {
Wrapping(self.0.to_be())
}
/// Converts `self` to little endian from the target's endianness.
///
/// On little endian this is a no-op. On big endian the bytes are
/// swapped.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
///
/// if cfg!(target_endian = "little") {
/// assert_eq!(n.to_le(), n);
/// } else {
/// assert_eq!(n.to_le(), n.swap_bytes());
/// }
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn to_le(self) -> Self {
Wrapping(self.0.to_le())
}
/// Raises self to the power of `exp`, using exponentiation by
/// squaring.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// let x: Wrapping<i32> = Wrapping(2); // or any other integer type
///
/// assert_eq!(x.pow(4), Wrapping(16));
/// ```
///
/// Results that are too large are wrapped:
///
/// ```
/// #![feature(wrapping_int_impl)]
/// use std::num::Wrapping;
///
/// // 5 ^ 4 = 625, which is too big for a u8
/// let x: Wrapping<u8> = Wrapping(5);
///
/// assert_eq!(x.pow(4).0, 113);
/// ```
#[inline]
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
pub fn pow(self, exp: u32) -> Self {
Wrapping(self.0.wrapping_pow(exp))
}
}
)*)
}
wrapping_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
mod shift_max {
#![allow(non_upper_case_globals)]

View file

@ -1,295 +1,4 @@
# Dependency graph for incremental compilation
To learn more about how dependency tracking works in rustc, see the [rustc
guide].
This module contains the infrastructure for managing the incremental
compilation dependency graph. This README aims to explain how it ought
to be used. In this document, we'll first explain the overall
strategy, and then share some tips for handling specific scenarios.
The high-level idea is that we want to instrument the compiler to
track which parts of the AST and other IR are read/written by what.
This way, when we come back later, we can look at this graph and
determine what work needs to be redone.
### The dependency graph
The nodes of the graph are defined by the enum `DepNode`. They represent
one of three things:
1. HIR nodes (like `Hir(DefId)`) represent the HIR input itself.
2. Data nodes (like `TypeOfItem(DefId)`) represent some computed
information about a particular item.
3. Procedure nodes (like `CoherenceCheckTrait(DefId)`) represent some
procedure that is executing. Usually this procedure is
performing some kind of check for errors. You can think of them as
computed values where the value being computed is `()` (and the
value may fail to be computed, if an error results).
An edge `N1 -> N2` is added between two nodes if either:
- the value of `N1` is used to compute `N2`;
- `N1` is read by the procedure `N2`;
- the procedure `N1` writes the value `N2`.
The latter two conditions are equivalent to the first one if you think
of procedures as values.
### Basic tracking
There is a very general strategy to ensure that you have a correct, if
sometimes overconservative, dependency graph. The two main things you have
to do are (a) identify shared state and (b) identify the current tasks.
### Identifying shared state
Identify "shared state" that will be written by one pass and read by
another. In particular, we need to identify shared state that will be
read "across items" -- that is, anything where changes in one item
could invalidate work done for other items. So, for example:
1. The signature for a function is "shared state".
2. The computed type of some expression in the body of a function is
not shared state, because if it changes it does not itself
invalidate other functions (though it may be that it causes new
monomorphizations to occur, but that's handled independently).
Put another way: if the HIR for an item changes, we are going to
recompile that item for sure. But we need the dep tracking map to tell
us what *else* we have to recompile. Shared state is anything that is
used to communicate results from one item to another.
### Identifying the current task, tracking reads/writes, etc
FIXME(#42293). This text needs to be rewritten for the new red-green
system, which doesn't fully exist yet.
#### Dependency tracking map
`DepTrackingMap` is a particularly convenient way to correctly store
shared state. A `DepTrackingMap` is a special hashmap that will add
edges automatically when `get` and `insert` are called. The idea is
that, when you get/insert a value for the key `K`, we will add an edge
from/to the node `DepNode::Variant(K)` (for some variant specific to
the map).
Each `DepTrackingMap` is parameterized by a special type `M` that
implements `DepTrackingMapConfig`; this trait defines the key and value
types of the map, and also defines a fn for converting from the key to
a `DepNode` label. You don't usually have to muck about with this by
hand, there is a macro for creating it. You can see the complete set
of `DepTrackingMap` definitions in `librustc/middle/ty/maps.rs`.
As an example, let's look at the `adt_defs` map. The `adt_defs` map
maps from the def-id of a struct/enum to its `AdtDef`. It is defined
using this macro:
```rust
dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> }
// ~~~~~~~ ~~~~~~~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
// | | Key type Value type
// | DepNode variant
// Name of map id type
```
this indicates that a map id type `AdtDefs` will be created. The key
of the map will be a `DefId` and value will be
`ty::AdtDefMaster<'tcx>`. The `DepNode` will be created by
`DepNode::ItemSignature(K)` for a given key.
Once that is done, you can just use the `DepTrackingMap` like any
other map:
```rust
let mut map: DepTrackingMap<M> = DepTrackingMap::new(dep_graph);
map.insert(key, value); // registers dep_graph.write
map.get(key; // registers dep_graph.read
```
#### Memoization
One particularly interesting case is memoization. If you have some
shared state that you compute in a memoized fashion, the correct thing
to do is to define a `RefCell<DepTrackingMap>` for it and use the
`memoize` helper:
```rust
map.memoize(key, || /* compute value */)
```
This will create a graph that looks like
... -> MapVariant(key) -> CurrentTask
where `MapVariant` is the `DepNode` variant that the map is associated with,
and `...` are whatever edges the `/* compute value */` closure creates.
In particular, using the memoize helper is much better than writing
the obvious code yourself:
```rust
if let Some(result) = map.get(key) {
return result;
}
let value = /* compute value */;
map.insert(key, value);
```
If you write that code manually, the dependency graph you get will
include artificial edges that are not necessary. For example, imagine that
two tasks, A and B, both invoke the manual memoization code, but A happens
to go first. The resulting graph will be:
... -> A -> MapVariant(key) -> B
~~~~~~~~~~~~~~~~~~~~~~~~~~~ // caused by A writing to MapVariant(key)
~~~~~~~~~~~~~~~~~~~~ // caused by B reading from MapVariant(key)
This graph is not *wrong*, but it encodes a path from A to B that
should not exist. In contrast, using the memoized helper, you get:
... -> MapVariant(key) -> A
|
+----------> B
which is much cleaner.
**Be aware though that the closure is executed with `MapVariant(key)`
pushed onto the stack as the current task!** That means that you must
add explicit `read` calls for any shared state that it accesses
implicitly from its environment. See the section on "explicit calls to
read and write when starting a new subtask" above for more details.
### How to decide where to introduce a new task
Certainly, you need at least one task on the stack: any attempt to
`read` or `write` shared state will panic if there is no current
task. But where does it make sense to introduce subtasks? The basic
rule is that a subtask makes sense for any discrete unit of work you
may want to skip in the future. Adding a subtask separates out the
reads/writes from *that particular subtask* versus the larger
context. An example: you might have a 'meta' task for all of borrow
checking, and then subtasks for borrow checking individual fns. (Seen
in this light, memoized computations are just a special case where we
may want to avoid redoing the work even within the context of one
compilation.)
The other case where you might want a subtask is to help with refining
the reads/writes for some later bit of work that needs to be memoized.
For example, we create a subtask for type-checking the body of each
fn. However, in the initial version of incr. comp. at least, we do
not expect to actually *SKIP* type-checking -- we only expect to skip
trans. However, it's still useful to create subtasks for type-checking
individual items, because, otherwise, if a fn sig changes, we won't
know which callers are affected -- in fact, because the graph would be
so coarse, we'd just have to retrans everything, since we can't
distinguish which fns used which fn sigs.
### Testing the dependency graph
There are various ways to write tests against the dependency graph.
The simplest mechanism are the
`#[rustc_if_this_changed]` and `#[rustc_then_this_would_need]`
annotations. These are used in compile-fail tests to test whether the
expected set of paths exist in the dependency graph. As an example,
see `src/test/compile-fail/dep-graph-caller-callee.rs`.
The idea is that you can annotate a test like:
```rust
#[rustc_if_this_changed]
fn foo() { }
#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
fn bar() { foo(); }
#[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
fn baz() { }
```
This will check whether there is a path in the dependency graph from
`Hir(foo)` to `TypeckTables(bar)`. An error is reported for each
`#[rustc_then_this_would_need]` annotation that indicates whether a
path exists. `//~ ERROR` annotations can then be used to test if a
path is found (as demonstrated above).
### Debugging the dependency graph
#### Dumping the graph
The compiler is also capable of dumping the dependency graph for your
debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The
graph will be dumped to `dep_graph.{txt,dot}` in the current
directory. You can override the filename with the `RUST_DEP_GRAPH`
environment variable.
Frequently, though, the full dep graph is quite overwhelming and not
particularly helpful. Therefore, the compiler also allows you to filter
the graph. You can filter in three ways:
1. All edges originating in a particular set of nodes (usually a single node).
2. All edges reaching a particular set of nodes.
3. All edges that lie between given start and end nodes.
To filter, use the `RUST_DEP_GRAPH_FILTER` environment variable, which should
look like one of the following:
```
source_filter // nodes originating from source_filter
-> target_filter // nodes that can reach target_filter
source_filter -> target_filter // nodes in between source_filter and target_filter
```
`source_filter` and `target_filter` are a `&`-separated list of strings.
A node is considered to match a filter if all of those strings appear in its
label. So, for example:
```
RUST_DEP_GRAPH_FILTER='-> TypeckTables'
```
would select the predecessors of all `TypeckTables` nodes. Usually though you
want the `TypeckTables` node for some particular fn, so you might write:
```
RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar'
```
This will select only the `TypeckTables` nodes for fns with `bar` in their name.
Perhaps you are finding that when you change `foo` you need to re-type-check `bar`,
but you don't think you should have to. In that case, you might do:
```
RUST_DEP_GRAPH_FILTER='Hir&foo -> TypeckTables & bar'
```
This will dump out all the nodes that lead from `Hir(foo)` to
`TypeckTables(bar)`, from which you can (hopefully) see the source
of the erroneous edge.
#### Tracking down incorrect edges
Sometimes, after you dump the dependency graph, you will find some
path that should not exist, but you will not be quite sure how it came
to be. **When the compiler is built with debug assertions,** it can
help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE`
environment variable to a filter. Every edge created in the dep-graph
will be tested against that filter -- if it matches, a `bug!` is
reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`).
The syntax for these filters is the same as described in the previous
section. However, note that this filter is applied to every **edge**
and doesn't handle longer paths in the graph, unlike the previous
section.
Example:
You find that there is a path from the `Hir` of `foo` to the type
check of `bar` and you don't think there should be. You dump the
dep-graph as described in the previous section and open `dep-graph.txt`
to see something like:
Hir(foo) -> Collect(bar)
Collect(bar) -> TypeckTables(bar)
That first edge looks suspicious to you. So you set
`RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and
then observe the backtrace. Voila, bug fixed!
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/query.html

View file

@ -580,7 +580,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
/// the pop occurs as part of the rollback, so an explicit call is not
/// needed (but is also permitted).
///
/// See `README.md` for more details.
/// For more information about how skolemization for HRTBs works, see
/// the [rustc guide].
///
/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
pub fn skolemize_late_bound_regions<T>(&self,
binder: &ty::Binder<T>,
snapshot: &CombinedSnapshot<'a, 'tcx>)

View file

@ -1,14 +1,16 @@
# Region inference
> WARNING: This README is obsolete and will be removed soon! For
> more info on how the current borrowck works, see the [rustc guide].
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
## Terminology
Note that we use the terms region and lifetime interchangeably.
## Introduction
See the [general inference README](../README.md) for an overview of
how lexical-region-solving fits into the bigger picture.
Region inference uses a somewhat more involved algorithm than type
inference. It is not the most efficient thing ever written though it
seems to work well enough in practice (famous last words). The reason

View file

@ -1,18 +1,25 @@
# Region constraint collection
> WARNING: This README is obsolete and will be removed soon! For
> more info on how the current borrowck works, see the [rustc guide].
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
## Terminology
Note that we use the terms region and lifetime interchangeably.
## Introduction
As described in the [inference README](../README.md), and unlike
As described in the rustc guide [chapter on type inference][ti], and unlike
normal type inference, which is similar in spirit to H-M and thus
works progressively, the region type inference works by accumulating
constraints over the course of a function. Finally, at the end of
processing a function, we process and solve the constraints all at
once.
[ti]: https://rust-lang-nursery.github.io/rustc-guide/type-inference.html
The constraints are always of one of three possible forms:
- `ConstrainVarSubVar(Ri, Rj)` states that region variable Ri must be

View file

@ -468,8 +468,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
/// the APIs in `higher_ranked/mod.rs`, such as
/// `skolemize_late_bound_regions` and `plug_leaks`, which will
/// guide you on this path (ensure that the `SkolemizationMap` is
/// consumed and you are good). There are also somewhat extensive
/// comments in `higher_ranked/README.md`.
/// consumed and you are good). For more info on how skolemization
/// for HRTBs works, see the [rustc guide].
///
/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
///
/// The `snapshot` argument to this function is not really used;
/// it's just there to make it explicit which snapshot bounds the

View file

@ -402,12 +402,10 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
for pat in &arm.pats {
// for struct patterns, take note of which fields used shorthand (`x`
// rather than `x: x`)
// for struct patterns, take note of which fields used shorthand (`x` rather than `x: x`)
//
// FIXME: according to the rust-lang-nursery/rustc-guide book and
// librustc/README.md, `NodeId`s are to be phased out in favor of
// `HirId`s; however, we need to match the signature of `each_binding`,
// FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be phased
// out in favor of `HirId`s; however, we need to match the signature of `each_binding`,
// which uses `NodeIds`.
let mut shorthand_field_ids = NodeSet();
if let hir::PatKind::Struct(_, ref fields, _) = pat.node {

View file

@ -11,8 +11,10 @@
//! This file builds up the `ScopeTree`, which describes
//! the parent links in the region hierarchy.
//!
//! Most of the documentation on regions can be found in
//! `middle/infer/region_constraints/README.md`
//! For more information about how MIR-based region-checking works,
//! see the [rustc guide].
//!
//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
use ich::{StableHashingContext, NodeIdHashingMode};
use util::nodemap::{FxHashMap, FxHashSet};

View file

@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! MIR datatypes and passes. See the module-level [README] for details.
//! MIR datatypes and passes. See the [rustc guide] for more info.
//!
//! [README]: https://github.com/rust-lang/rust/blob/master/src/librustc/mir/README.md
//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html
use graphviz::IntoCow;
use middle::const_val::ConstVal;

View file

@ -606,6 +606,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
// Try to report a help message
if !trait_ref.has_infer_types() &&
@ -844,6 +845,54 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
/// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
/// suggest removing these references until we reach a type that implements the trait.
fn suggest_remove_reference(&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'tcx>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>) {
let ty::Binder(trait_ref) = trait_ref;
let span = obligation.cause.span;
if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
let refs_number = snippet.chars()
.filter(|c| !c.is_whitespace())
.take_while(|c| *c == '&')
.count();
let mut trait_type = trait_ref.self_ty();
let mut selcx = SelectionContext::new(self);
for refs_remaining in 0..refs_number {
if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) =
trait_type.sty {
trait_type = t_type;
let substs = self.tcx.mk_substs_trait(trait_type, &[]);
let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs);
let new_obligation = Obligation::new(ObligationCause::dummy(),
obligation.param_env,
new_trait_ref.to_predicate());
if selcx.evaluate_obligation(&new_obligation) {
let sp = self.tcx.sess.codemap()
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
let remove_refs = refs_remaining + 1;
let format_str = format!("consider removing {} leading `&`-references",
remove_refs);
err.span_suggestion_short(sp, &format_str, String::from(""));
break;
}
} else {
break;
}
}
}
}
/// Given some node representing a fn-like thing in the HIR map,
/// returns a span and `ArgKind` information that describes the
/// arguments it expects. This can be supplied to

View file

@ -36,6 +36,7 @@ use util::nodemap::{DefIdMap, FxHashMap};
/// parents of a given specializing impl, which is needed for extracting
/// default items amongst other things. In the simple "chain" rule, every impl
/// has at most one parent.
#[derive(RustcEncodable, RustcDecodable)]
pub struct Graph {
// all impls have a parent; the "root" impls have as their parent the def_id
// of the trait
@ -47,6 +48,7 @@ pub struct Graph {
/// Children of a given impl, grouped into blanket/non-blanket varieties as is
/// done in `TraitDef`.
#[derive(RustcEncodable, RustcDecodable)]
struct Children {
// Impls of a trait (or specializations of a given impl). To allow for
// quicker lookup, the impls are indexed by a simplified version of their

View file

@ -28,7 +28,7 @@ pub type SimplifiedType = SimplifiedTypeGen<DefId>;
/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
/// keys (in which case we use a DefPathHash as id-type) but in the general case
/// the non-stable but fast to construct DefId-version is the better choice.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
pub enum SimplifiedTypeGen<D>
where D: Copy + Debug + Ord + Eq + Hash
{

View file

@ -727,3 +727,4 @@ impl_disk_cacheable_query!(type_of, |def_id| def_id.is_local());
impl_disk_cacheable_query!(predicates_of, |def_id| def_id.is_local());
impl_disk_cacheable_query!(used_trait_imports, |def_id| def_id.is_local());
impl_disk_cacheable_query!(trans_fn_attrs, |_| true);
impl_disk_cacheable_query!(specialization_graph_of, |_| true);

View file

@ -232,6 +232,7 @@ impl<'sess> OnDiskCache<'sess> {
encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
encode_query_results::<check_match, _>(tcx, enc, qri)?;
encode_query_results::<trans_fn_attrs, _>(tcx, enc, qri)?;
encode_query_results::<specialization_graph_of, _>(tcx, enc, qri)?;
// const eval is special, it only encodes successfully evaluated constants
use ty::maps::plumbing::GetCacheInternal;

View file

@ -1003,4 +1003,5 @@ impl_load_from_cache!(
PredicatesOfItem => predicates_of,
UsedTraitImports => used_trait_imports,
TransFnAttrs => trans_fn_attrs,
SpecializationGraph => specialization_graph_of,
);

View file

@ -991,10 +991,11 @@ pub type Region<'tcx> = &'tcx RegionKind;
/// the inference variable is supposed to satisfy the relation
/// *for every value of the skolemized region*. To ensure that doesn't
/// happen, you can use `leak_check`. This is more clearly explained
/// by infer/higher_ranked/README.md.
/// by the [rustc guide].
///
/// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
pub enum RegionKind {
// Region bound in a type or fn declaration which will be

View file

@ -1,6 +1,6 @@
NB: This crate is part of the Rust compiler. For an overview of the
compiler as a whole, see
[the README.md file found in `librustc`](../librustc/README.md).
`librustc_back` contains some very low-level details that are
specific to different LLVM targets and so forth.
For more information about how trans works, see the [rustc guide].
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html

View file

@ -1,5 +1,10 @@
% The Borrow Checker
> WARNING: This README is more or less obsolete, and will be removed
> soon! The new system is described in the [rustc guide].
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
This pass has the job of enforcing memory safety. This is a subtle
topic. This docs aim to explain both the practice and the theory
behind the borrow checker. They start with a high-level overview of

View file

@ -253,28 +253,28 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> {
used_mut_nodes: RefCell<FxHashSet<HirId>>,
}
impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str,
code: DiagnosticId)
-> DiagnosticBuilder<'a>
impl<'a, 'b, 'tcx: 'b> BorrowckErrors<'a> for &'a BorrowckCtxt<'b, 'tcx> {
fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
sp: S,
msg: &str,
code: DiagnosticId)
-> DiagnosticBuilder<'a>
{
self.tcx.sess.struct_span_err_with_code(sp, msg, code)
}
fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str)
-> DiagnosticBuilder<'a>
fn struct_span_err<S: Into<MultiSpan>>(self,
sp: S,
msg: &str)
-> DiagnosticBuilder<'a>
{
self.tcx.sess.struct_span_err(sp, msg)
}
fn cancel_if_wrong_origin<'a>(&'a self,
mut diag: DiagnosticBuilder<'a>,
o: Origin)
-> DiagnosticBuilder<'a>
fn cancel_if_wrong_origin(self,
mut diag: DiagnosticBuilder<'a>,
o: Origin)
-> DiagnosticBuilder<'a>
{
if !o.should_emit_errors(self.tcx.borrowck_mode()) {
self.tcx.sess.diagnostic().cancel(&mut diag);

View file

@ -1,7 +1,3 @@
NB: This crate is part of the Rust compiler. For an overview of the
compiler as a whole, see
[the README.md file found in `librustc`](../librustc/README.md).
The `driver` crate is effectively the "main" function for the rust
compiler. It orchestrates the compilation process and "knits together"
the code from the other crates within rustc. This crate itself does
@ -9,4 +5,6 @@ not contain any of the "main logic" of the compiler (though it does
have some code related to pretty printing or other minor compiler
options).
For more information about how the driver works, see the [rustc guide].
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustc-driver.html

View file

@ -52,30 +52,30 @@ impl Origin {
}
}
pub trait BorrowckErrors {
fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str,
code: DiagnosticId)
-> DiagnosticBuilder<'a>;
pub trait BorrowckErrors<'cx>: Sized + Copy {
fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
sp: S,
msg: &str,
code: DiagnosticId)
-> DiagnosticBuilder<'cx>;
fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str)
-> DiagnosticBuilder<'a>;
fn struct_span_err<S: Into<MultiSpan>>(self,
sp: S,
msg: &str)
-> DiagnosticBuilder<'cx>;
/// Cancels the given error if we shouldn't emit errors for a given
/// origin in the current mode.
///
/// Always make sure that the error gets passed through this function
/// before you return it.
fn cancel_if_wrong_origin<'a>(&'a self,
diag: DiagnosticBuilder<'a>,
o: Origin)
-> DiagnosticBuilder<'a>;
fn cancel_if_wrong_origin(self,
diag: DiagnosticBuilder<'cx>,
o: Origin)
-> DiagnosticBuilder<'cx>;
fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin)
-> DiagnosticBuilder<'_>
fn cannot_move_when_borrowed(self, span: Span, desc: &str, o: Origin)
-> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0505,
"cannot move out of `{}` because it is borrowed{OGN}",
@ -83,13 +83,13 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_use_when_mutably_borrowed(&self,
fn cannot_use_when_mutably_borrowed(self,
span: Span,
desc: &str,
borrow_span: Span,
borrow_desc: &str,
o: Origin)
-> DiagnosticBuilder<'_>
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, span, E0503,
"cannot use `{}` because it was mutably borrowed{OGN}",
@ -101,12 +101,12 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_act_on_uninitialized_variable(&self,
fn cannot_act_on_uninitialized_variable(self,
span: Span,
verb: &str,
desc: &str,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0381,
"{} of possibly uninitialized variable: `{}`{OGN}",
@ -114,7 +114,7 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_mutably_borrow_multiply(&self,
fn cannot_mutably_borrow_multiply(self,
new_loan_span: Span,
desc: &str,
opt_via: &str,
@ -122,7 +122,7 @@ pub trait BorrowckErrors {
old_opt_via: &str,
old_load_end_span: Option<Span>,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, new_loan_span, E0499,
"cannot borrow `{}`{} as mutable more than once at a time{OGN}",
@ -148,13 +148,13 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_uniquely_borrow_by_two_closures(&self,
fn cannot_uniquely_borrow_by_two_closures(self,
new_loan_span: Span,
desc: &str,
old_loan_span: Span,
old_load_end_span: Option<Span>,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, new_loan_span, E0524,
"two closures require unique access to `{}` at the same time{OGN}",
@ -173,7 +173,7 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_uniquely_borrow_by_one_closure(&self,
fn cannot_uniquely_borrow_by_one_closure(self,
new_loan_span: Span,
desc_new: &str,
opt_via: &str,
@ -182,7 +182,7 @@ pub trait BorrowckErrors {
old_opt_via: &str,
previous_end_span: Option<Span>,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, new_loan_span, E0500,
"closure requires unique access to `{}` but {} is already borrowed{}{OGN}",
@ -197,7 +197,7 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_reborrow_already_uniquely_borrowed(&self,
fn cannot_reborrow_already_uniquely_borrowed(self,
new_loan_span: Span,
desc_new: &str,
opt_via: &str,
@ -206,7 +206,7 @@ pub trait BorrowckErrors {
old_opt_via: &str,
previous_end_span: Option<Span>,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, new_loan_span, E0501,
"cannot borrow `{}`{} as {} because previous closure \
@ -222,7 +222,7 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_reborrow_already_borrowed(&self,
fn cannot_reborrow_already_borrowed(self,
span: Span,
desc_new: &str,
msg_new: &str,
@ -233,7 +233,7 @@ pub trait BorrowckErrors {
msg_old: &str,
old_load_end_span: Option<Span>,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, span, E0502,
"cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
@ -246,8 +246,8 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_assign_to_borrowed(&self, span: Span, borrow_span: Span, desc: &str, o: Origin)
-> DiagnosticBuilder
fn cannot_assign_to_borrowed(self, span: Span, borrow_span: Span, desc: &str, o: Origin)
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, span, E0506,
"cannot assign to `{}` because it is borrowed{OGN}",
@ -259,8 +259,8 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin)
-> DiagnosticBuilder
fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin)
-> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0504,
"cannot move `{}` into closure because it is borrowed{OGN}",
@ -269,8 +269,8 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Origin)
-> DiagnosticBuilder
fn cannot_reassign_immutable(self, span: Span, desc: &str, is_arg: bool, o: Origin)
-> DiagnosticBuilder<'cx>
{
let msg = if is_arg {
"to immutable argument"
@ -284,7 +284,7 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_assign(&self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder
fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0594,
"cannot assign to {}{OGN}",
@ -292,14 +292,14 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_assign_static(&self, span: Span, desc: &str, o: Origin)
-> DiagnosticBuilder
fn cannot_assign_static(self, span: Span, desc: &str, o: Origin)
-> DiagnosticBuilder<'cx>
{
self.cannot_assign(span, &format!("immutable static item `{}`", desc), o)
}
fn cannot_move_out_of(&self, move_from_span: Span, move_from_desc: &str, o: Origin)
-> DiagnosticBuilder
fn cannot_move_out_of(self, move_from_span: Span, move_from_desc: &str, o: Origin)
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, move_from_span, E0507,
"cannot move out of {}{OGN}",
@ -311,12 +311,12 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_move_out_of_interior_noncopy(&self,
fn cannot_move_out_of_interior_noncopy(self,
move_from_span: Span,
ty: ty::Ty,
is_index: bool,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let type_name = match (&ty.sty, is_index) {
(&ty::TyArray(_, _), true) => "array",
@ -332,11 +332,11 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_move_out_of_interior_of_drop(&self,
fn cannot_move_out_of_interior_of_drop(self,
move_from_span: Span,
container_ty: ty::Ty,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, move_from_span, E0509,
"cannot move out of type `{}`, \
@ -347,13 +347,13 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_act_on_moved_value(&self,
fn cannot_act_on_moved_value(self,
use_span: Span,
verb: &str,
optional_adverb_for_moved: &str,
moved_path: &str,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, use_span, E0382,
"{} of {}moved value: `{}`{OGN}",
@ -362,11 +362,11 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_partially_reinit_an_uninit_struct(&self,
fn cannot_partially_reinit_an_uninit_struct(self,
span: Span,
uninit_path: &str,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self,
span,
@ -377,11 +377,11 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn closure_cannot_assign_to_borrowed(&self,
fn closure_cannot_assign_to_borrowed(self,
span: Span,
descr: &str,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}",
descr, OGN=o);
@ -389,11 +389,11 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_borrow_path_as_mutable(&self,
fn cannot_borrow_path_as_mutable(self,
span: Span,
path: &str,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}",
path, OGN=o);
@ -401,11 +401,11 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_borrow_across_generator_yield(&self,
fn cannot_borrow_across_generator_yield(self,
span: Span,
yield_span: Span,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self,
span,
@ -417,11 +417,11 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn path_does_not_live_long_enough(&self,
fn path_does_not_live_long_enough(self,
span: Span,
path: &str,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}",
path, OGN=o);
@ -429,11 +429,11 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn lifetime_too_short_for_reborrow(&self,
fn lifetime_too_short_for_reborrow(self,
span: Span,
path: &str,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0598,
"lifetime of {} is too short to guarantee \
@ -443,12 +443,12 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_act_on_capture_in_sharable_fn(&self,
fn cannot_act_on_capture_in_sharable_fn(self,
span: Span,
bad_thing: &str,
help: (Span, &str),
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let (help_span, help_msg) = help;
let mut err = struct_span_err!(self, span, E0387,
@ -459,11 +459,11 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_assign_into_immutable_reference(&self,
fn cannot_assign_into_immutable_reference(self,
span: Span,
bad_thing: &str,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}",
bad_thing, OGN=o);
@ -472,12 +472,12 @@ pub trait BorrowckErrors {
self.cancel_if_wrong_origin(err, o)
}
fn cannot_capture_in_long_lived_closure(&self,
fn cannot_capture_in_long_lived_closure(self,
closure_span: Span,
borrowed_path: &str,
capture_span: Span,
o: Origin)
-> DiagnosticBuilder
-> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, closure_span, E0373,
"closure may outlive the current function, \
@ -491,28 +491,28 @@ pub trait BorrowckErrors {
}
}
impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {
fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str,
code: DiagnosticId)
-> DiagnosticBuilder<'a>
impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> {
fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
sp: S,
msg: &str,
code: DiagnosticId)
-> DiagnosticBuilder<'cx>
{
self.sess.struct_span_err_with_code(sp, msg, code)
}
fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str)
-> DiagnosticBuilder<'a>
fn struct_span_err<S: Into<MultiSpan>>(self,
sp: S,
msg: &str)
-> DiagnosticBuilder<'cx>
{
self.sess.struct_span_err(sp, msg)
}
fn cancel_if_wrong_origin<'a>(&'a self,
mut diag: DiagnosticBuilder<'a>,
o: Origin)
-> DiagnosticBuilder<'a>
fn cancel_if_wrong_origin(self,
mut diag: DiagnosticBuilder<'cx>,
o: Origin)
-> DiagnosticBuilder<'cx>
{
if !o.should_emit_errors(self.borrowck_mode()) {
self.sess.diagnostic().cancel(&mut diag);

View file

@ -67,7 +67,7 @@ impl<'a> AstValidator<'a> {
E0449,
"unnecessary visibility qualifier");
if vis.node == VisibilityKind::Public {
err.span_label(vis.span, "`pub` not needed here");
err.span_label(vis.span, "`pub` not permitted here because it's implied");
}
if let Some(note) = note {
err.note(note);

View file

@ -1,7 +1,7 @@
NB: This crate is part of the Rust compiler. For an overview of the
compiler as a whole, see
[the README.md file found in `librustc`](../librustc/README.md).
The `trans` crate contains the code to convert from MIR into LLVM IR,
and then from LLVM IR into machine code. In general it contains code
that runs towards the end of the compilation process.
For more information about how trans works, see the [rustc guide].
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html

View file

@ -18,8 +18,9 @@ use syntax::ast;
use syntax::util::parser::PREC_POSTFIX;
use syntax_pos::{self, Span};
use rustc::hir;
use rustc::hir::print;
use rustc::hir::def::Def;
use rustc::hir::map::NodeItem;
use rustc::hir::{Item, ItemConst, print};
use rustc::ty::{self, Ty, AssociatedItem};
use errors::{DiagnosticBuilder, CodeMapper};
@ -318,6 +319,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
checked_ty: Ty<'tcx>,
expected_ty: Ty<'tcx>)
-> bool {
let parent_id = self.tcx.hir.get_parent_node(expr.id);
match self.tcx.hir.find(parent_id) {
Some(parent) => {
// Shouldn't suggest `.into()` on `const`s.
if let NodeItem(Item { node: ItemConst(_, _), .. }) = parent {
// FIXME(estebank): modify once we decide to suggest `as` casts
return false;
}
}
None => {}
};
let will_truncate = "will truncate the source value";
let depending_on_isize = "will truncate or zero-extend depending on the bit width of \
`isize`";

View file

@ -239,52 +239,59 @@
}
}
function handleShortcut(ev) {
if (document.activeElement.tagName === "INPUT" &&
hasClass(document.getElementById('main'), "hidden")) {
return;
function handleEscape(ev, help) {
hideModal();
var search = document.getElementById("search");
if (!hasClass(help, "hidden")) {
displayHelp(false, ev);
} else if (!hasClass(search, "hidden")) {
ev.preventDefault();
addClass(search, "hidden");
removeClass(document.getElementById("main"), "hidden");
}
defocusSearchBar();
}
function handleShortcut(ev) {
// Don't interfere with browser shortcuts
if (ev.ctrlKey || ev.altKey || ev.metaKey) {
return;
}
var help = document.getElementById("help");
switch (getVirtualKey(ev)) {
case "Escape":
hideModal();
var search = document.getElementById("search");
if (!hasClass(help, "hidden")) {
if (document.activeElement.tagName === "INPUT") {
switch (getVirtualKey(ev)) {
case "Escape":
handleEscape(ev, help);
break;
}
} else {
switch (getVirtualKey(ev)) {
case "Escape":
handleEscape(ev, help);
break;
case "s":
case "S":
displayHelp(false, ev);
} else if (!hasClass(search, "hidden")) {
ev.preventDefault();
addClass(search, "hidden");
removeClass(document.getElementById("main"), "hidden");
}
defocusSearchBar();
break;
case "s":
case "S":
displayHelp(false, ev);
hideModal();
ev.preventDefault();
focusSearchBar();
break;
case "+":
case "-":
ev.preventDefault();
toggleAllDocs();
break;
case "?":
if (ev.shiftKey) {
hideModal();
displayHelp(true, ev);
ev.preventDefault();
focusSearchBar();
break;
case "+":
case "-":
ev.preventDefault();
toggleAllDocs();
break;
case "?":
if (ev.shiftKey) {
hideModal();
displayHelp(true, ev);
}
break;
}
break;
}
}

View file

@ -168,8 +168,36 @@ impl<R: Read> BufReader<R> {
/// # }
/// ```
#[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
#[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")]
pub fn is_empty(&self) -> bool {
self.pos == self.cap
self.buffer().is_empty()
}
/// Returns a reference to the internally buffered data.
///
/// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
///
/// # Examples
///
/// ```
/// # #![feature(bufreader_buffer)]
/// use std::io::{BufReader, BufRead};
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// let f = File::open("log.txt")?;
/// let mut reader = BufReader::new(f);
/// assert!(reader.buffer().is_empty());
///
/// if reader.fill_buf()?.len() > 0 {
/// assert!(!reader.buffer().is_empty());
/// }
/// # Ok(())
/// # }
/// ```
#[unstable(feature = "bufreader_buffer", issue = "45323")]
pub fn buffer(&self) -> &[u8] {
&self.buf[self.pos..self.cap]
}
/// Unwraps this `BufReader`, returning the underlying reader.

View file

@ -1,7 +1,9 @@
NB: This crate is part of the Rust compiler. For an overview of the
compiler as a whole, see
[the README.md file found in `librustc`](../librustc/README.md).
The `syntax` crate contains those things concerned purely with syntax
that is, the AST ("abstract syntax tree"), parser, pretty-printer,
lexer, macro expander, and utilities for traversing ASTs.
For more information about how these things work in rustc, see the
rustc guide:
- [Parsing](https://rust-lang-nursery.github.io/rustc-guide/the-parser.html)
- [Macro Expansion](https://rust-lang-nursery.github.io/rustc-guide/macro-expansion.html)

View file

@ -597,21 +597,6 @@ impl CodeMap {
self.span_to_source(sp, |src, start_index, _| src[..start_index].to_string())
}
/// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char`
pub fn span_until_char(&self, sp: Span, c: char) -> Span {
match self.span_to_snippet(sp) {
Ok(snippet) => {
let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right();
if !snippet.is_empty() && !snippet.contains('\n') {
sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32))
} else {
sp
}
}
_ => sp,
}
}
/// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span
/// if no character could be found or if an error occurred while retrieving the code snippet.
pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span {
@ -646,44 +631,19 @@ impl CodeMap {
sp
}
/// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or
/// the original `Span`.
///
/// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned.
pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
if let Ok(snippet) = self.span_to_snippet(sp) {
let mut offset = 0;
// get the bytes width of all the non-whitespace characters
for c in snippet.chars().take_while(|c| !c.is_whitespace()) {
offset += c.len_utf8();
}
// get the bytes width of all the whitespace characters after that
for c in snippet[offset..].chars().take_while(|c| c.is_whitespace()) {
offset += c.len_utf8();
}
if offset > 1 {
return sp.with_hi(BytePos(sp.lo().0 + offset as u32));
/// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char`
pub fn span_until_char(&self, sp: Span, c: char) -> Span {
match self.span_to_snippet(sp) {
Ok(snippet) => {
let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right();
if !snippet.is_empty() && !snippet.contains('\n') {
sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32))
} else {
sp
}
}
_ => sp,
}
sp
}
/// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or
/// the original `Span` in case of error.
///
/// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned.
pub fn span_until_whitespace(&self, sp: Span) -> Span {
if let Ok(snippet) = self.span_to_snippet(sp) {
let mut offset = 0;
// Get the bytes width of all the non-whitespace characters
for c in snippet.chars().take_while(|c| !c.is_whitespace()) {
offset += c.len_utf8();
}
if offset > 1 {
return sp.with_hi(BytePos(sp.lo().0 + offset as u32));
}
}
sp
}
/// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char`
@ -697,6 +657,50 @@ impl CodeMap {
sp
}
/// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or
/// the original `Span`.
///
/// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned.
pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
let mut whitespace_found = false;
self.span_take_while(sp, |c| {
if !whitespace_found && c.is_whitespace() {
whitespace_found = true;
}
if whitespace_found && !c.is_whitespace() {
false
} else {
true
}
})
}
/// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or
/// the original `Span` in case of error.
///
/// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned.
pub fn span_until_whitespace(&self, sp: Span) -> Span {
self.span_take_while(sp, |c| !c.is_whitespace())
}
/// Given a `Span`, get a shorter one until `predicate` yields false.
pub fn span_take_while<P>(&self, sp: Span, predicate: P) -> Span
where P: for <'r> FnMut(&'r char) -> bool
{
if let Ok(snippet) = self.span_to_snippet(sp) {
let offset = snippet.chars()
.take_while(predicate)
.map(|c| c.len_utf8())
.sum::<usize>();
sp.with_hi(BytePos(sp.lo().0 + (offset as u32)))
} else {
sp
}
}
pub fn def_span(&self, sp: Span) -> Span {
self.span_until_char(sp, '{')
}

View file

@ -90,7 +90,7 @@ impl<'a> Parser<'a> {
debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}",
inner_parse_policy,
self.token);
let (span, path, tokens, mut style) = match self.token {
let (span, path, tokens, style) = match self.token {
token::Pound => {
let lo = self.span;
self.bump();
@ -129,15 +129,6 @@ impl<'a> Parser<'a> {
}
};
if inner_parse_policy == InnerAttributeParsePolicy::Permitted &&
self.token == token::Semi {
self.bump();
self.span_warn(span,
"this inner attribute syntax is deprecated. The new syntax is \
`#![foo]`, with a bang and no semicolon");
style = ast::AttrStyle::Inner;
}
Ok(ast::Attribute {
id: attr::mk_attr_id(),
style,

View file

@ -12,7 +12,7 @@
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
# `0.x.0` for Cargo where they were released on `date`.
date: 2018-02-20
date: 2018-03-18
rustc: beta
cargo: beta

View file

@ -2,7 +2,7 @@ error[E0449]: unnecessary visibility qualifier
--> $DIR/E0449.rs:17:1
|
LL | pub impl Bar {} //~ ERROR E0449
| ^^^ `pub` not needed here
| ^^^ `pub` not permitted here because it's implied
|
= note: place qualifiers on individual impl items instead
@ -10,13 +10,13 @@ error[E0449]: unnecessary visibility qualifier
--> $DIR/E0449.rs:19:1
|
LL | pub impl Foo for Bar { //~ ERROR E0449
| ^^^ `pub` not needed here
| ^^^ `pub` not permitted here because it's implied
error[E0449]: unnecessary visibility qualifier
--> $DIR/E0449.rs:20:5
|
LL | pub fn foo() {} //~ ERROR E0449
| ^^^ `pub` not needed here
| ^^^ `pub` not permitted here because it's implied
error: aborting due to 3 previous errors

View file

@ -0,0 +1,12 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused_variables)]; //~ ERROR expected item, found `;`
fn main() {}

View file

@ -0,0 +1,8 @@
error: expected item, found `;`
--> $DIR/issue-49040.rs:11:28
|
LL | #![allow(unused_variables)]; //~ ERROR expected item, found `;`
| ^ help: consider removing this semicolon
error: aborting due to previous error

View file

@ -0,0 +1,18 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let v = vec![0, 1, 2, 3];
for (i, n) in &v.iter().enumerate() {
//~^ ERROR the trait bound
println!("{}", i);
}
}

View file

@ -0,0 +1,15 @@
error[E0277]: the trait bound `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>: std::iter::Iterator` is not satisfied
--> $DIR/suggest-remove-refs-1.rs:14:19
|
LL | for (i, n) in &v.iter().enumerate() {
| -^^^^^^^^^^^^^^^^^^^^
| |
| `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
| help: consider removing 1 leading `&`-references
|
= help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
= note: required by `std::iter::IntoIterator::into_iter`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,18 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let v = vec![0, 1, 2, 3];
for (i, n) in & & & & &v.iter().enumerate() {
//~^ ERROR the trait bound
println!("{}", i);
}
}

View file

@ -0,0 +1,15 @@
error[E0277]: the trait bound `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>: std::iter::Iterator` is not satisfied
--> $DIR/suggest-remove-refs-2.rs:14:19
|
LL | for (i, n) in & & & & &v.iter().enumerate() {
| ---------^^^^^^^^^^^^^^^^^^^^
| |
| `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
| help: consider removing 5 leading `&`-references
|
= help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
= note: required by `std::iter::IntoIterator::into_iter`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let v = vec![0, 1, 2, 3];
for (i, n) in & & &
& &v
.iter()
.enumerate() {
//~^^^^ ERROR the trait bound
println!("{}", i);
}
}

View file

@ -0,0 +1,19 @@
error[E0277]: the trait bound `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>: std::iter::Iterator` is not satisfied
--> $DIR/suggest-remove-refs-3.rs:14:19
|
LL | for (i, n) in & & &
| ___________________^
| |___________________|
| ||
LL | || & &v
| ||___________- help: consider removing 5 leading `&`-references
LL | | .iter()
LL | | .enumerate() {
| |_____________________^ `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
|
= help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
= note: required by `std::iter::IntoIterator::into_iter`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,21 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// `const`s shouldn't suggest `.into()`
const TEN: u8 = 10;
const TWELVE: u16 = TEN + 2;
//~^ ERROR mismatched types [E0308]
fn main() {
const TEN: u8 = 10;
const ALSO_TEN: u16 = TEN;
//~^ ERROR mismatched types [E0308]
}

View file

@ -0,0 +1,15 @@
error[E0308]: mismatched types
--> $DIR/const-type-mismatch.rs:14:21
|
LL | const TWELVE: u16 = TEN + 2;
| ^^^^^^^ expected u16, found u8
error[E0308]: mismatched types
--> $DIR/const-type-mismatch.rs:19:27
|
LL | const ALSO_TEN: u16 = TEN;
| ^^^ expected u16, found u8
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

@ -1 +1 @@
Subproject commit 346238f49740d6c98102a6a59811b1625c73a9d7
Subproject commit 87180d9065e7c8070c0ba46eb48ddf8779ef89ac