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:
commit
75af15ee6c
48 changed files with 1035 additions and 655 deletions
139
src/Cargo.lock
generated
139
src/Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ fn make_win_dist(
|
|||
"libsecur32.a",
|
||||
"libsetupapi.a",
|
||||
"libshell32.a",
|
||||
"libsynchronization.a",
|
||||
"libuser32.a",
|
||||
"libuserenv.a",
|
||||
"libuuid.a",
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 trait’s
|
||||
/// [`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 key’s 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 key’s 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 key’s 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 key’s 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 doesn’t 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.
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1003,4 +1003,5 @@ impl_load_from_cache!(
|
|||
PredicatesOfItem => predicates_of,
|
||||
UsedTraitImports => used_trait_imports,
|
||||
TransFnAttrs => trans_fn_attrs,
|
||||
SpecializationGraph => specialization_graph_of,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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, '{')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
12
src/test/ui/issue-49040.rs
Normal file
12
src/test/ui/issue-49040.rs
Normal 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() {}
|
||||
8
src/test/ui/issue-49040.stderr
Normal file
8
src/test/ui/issue-49040.stderr
Normal 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
|
||||
|
||||
18
src/test/ui/suggest-remove-refs-1.rs
Normal file
18
src/test/ui/suggest-remove-refs-1.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
15
src/test/ui/suggest-remove-refs-1.stderr
Normal file
15
src/test/ui/suggest-remove-refs-1.stderr
Normal 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`.
|
||||
18
src/test/ui/suggest-remove-refs-2.rs
Normal file
18
src/test/ui/suggest-remove-refs-2.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
15
src/test/ui/suggest-remove-refs-2.stderr
Normal file
15
src/test/ui/suggest-remove-refs-2.stderr
Normal 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`.
|
||||
21
src/test/ui/suggest-remove-refs-3.rs
Normal file
21
src/test/ui/suggest-remove-refs-3.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
19
src/test/ui/suggest-remove-refs-3.stderr
Normal file
19
src/test/ui/suggest-remove-refs-3.stderr
Normal 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`.
|
||||
21
src/test/ui/suggestions/const-type-mismatch.rs
Normal file
21
src/test/ui/suggestions/const-type-mismatch.rs
Normal 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]
|
||||
}
|
||||
15
src/test/ui/suggestions/const-type-mismatch.stderr
Normal file
15
src/test/ui/suggestions/const-type-mismatch.stderr
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue