Ensure `record_layout_for_printing()` is inlined.
This reduces instruction counts for the `ctfe-stress-2` benchmark by
about 1%.
r? @oli-obk
[[package]]
name = "dlmalloc"
-version = "0.1.2"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "proc-macro2"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "proc-macro2"
version = "0.4.24"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "quote"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "quote"
version = "0.6.10"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_apfloat 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_fs_util 0.0.0",
"rustc_target 0.0.0",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-rayon"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
+ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-rayon-core"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
+ "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_cratesio_shim 0.0.0",
"serialize 0.0.0",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_allocator 0.0.0",
"rustc_borrowck 0.0.0",
"rustc_codegen_utils 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_incremental 0.0.0",
+ "rustc_interface 0.0.0",
"rustc_lint 0.0.0",
"rustc_metadata 0.0.0",
"rustc_mir 0.0.0",
"rustc_target 0.0.0",
"rustc_traits 0.0.0",
"rustc_typeck 0.0.0",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
+[[package]]
+name = "rustc_interface"
+version = "0.0.0"
+dependencies = [
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc 0.0.0",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_allocator 0.0.0",
+ "rustc_borrowck 0.0.0",
+ "rustc_codegen_utils 0.0.0",
+ "rustc_data_structures 0.0.0",
+ "rustc_errors 0.0.0",
+ "rustc_incremental 0.0.0",
+ "rustc_lint 0.0.0",
+ "rustc_metadata 0.0.0",
+ "rustc_mir 0.0.0",
+ "rustc_passes 0.0.0",
+ "rustc_plugin 0.0.0",
+ "rustc_privacy 0.0.0",
+ "rustc_resolve 0.0.0",
+ "rustc_traits 0.0.0",
+ "rustc_typeck 0.0.0",
+ "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serialize 0.0.0",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntax 0.0.0",
+ "syntax_ext 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
[[package]]
name = "rustc_lint"
version = "0.0.0"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "scoped-tls"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
"cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
- "dlmalloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"panic_abort 0.0.0",
"phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
"precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "string_cache_codegen"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_target 0.0.0",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax_pos 0.0.0",
"arena 0.0.0",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_data_structures 0.0.0",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
"checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f"
"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
-"checksum dlmalloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d56ad71b31043818d0ee10a7fb9664882f8e45849c81647585e6a3124f185517"
+"checksum dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f283302e035e61c23f2b86b3093e8c6273a4c3125742d6087e96ade001ca5e63"
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
"checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455"
"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00"
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
"checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61"
-"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "926d0604475349f463fe44130aae73f2294b5309ab2ca0310b998bd334ef191f"
"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
"checksum racer 2.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d634483bed41bb116122b84ffe0ef8740345c2ceb2784ce86c33499700eb13a7"
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
"checksum rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e4f88a1213562373cee9de5a1d77bbf16dd706030304af041c9733492fcc952"
"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
-"checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
-"checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
+"checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544"
+"checksum rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "526e7b6d2707a5b9bec3927d424ad70fa3cfc68e0ac1b75e46cdbbc95adc5108"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c5a95edfa0c893236ae4778bb7c4752760e4c0d245e19b5eff33c5aa5eb9dc"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
"checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56"
"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
+"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
"checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
-"checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191"
+"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da"
"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c3a2071519ab6a48f465808c4c1ffdd00dfc8e93111d02b4fc5abab177676e"
# The value specified here will be passed as `-DLLVM_USE_LINKER` to CMake.
#use-linker = "lld"
+# Whether or not to specify `-DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=YES`
+#allow-old-toolchain = false
# =============================================================================
# General build configuration options
// actually downloaded, so we just always pass the `--sysroot` option.
cmd.arg("--sysroot").arg(&sysroot);
+ cmd.arg("-Zexternal-macro-backtrace");
+
// When we build Rust dylibs they're all intended for intermediate
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
// linking all deps statically into the dylib.
# x.py help <cmd> ...
if len(sys.argv) > 1 and sys.argv[1] == 'help':
- sys.argv = sys.argv[:1] + [sys.argv[2], '-h'] + sys.argv[3:]
+ sys.argv = [sys.argv[0], '-h'] + sys.argv[2:]
help_triggered = (
'-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1)
pub llvm_link_jobs: Option<u32>,
pub llvm_version_suffix: Option<String>,
pub llvm_use_linker: Option<String>,
+ pub llvm_allow_old_toolchain: Option<bool>,
pub lld_enabled: bool,
pub lldb_enabled: bool,
ldflags: Option<String>,
use_libcxx: Option<bool>,
use_linker: Option<String>,
+ allow_old_toolchain: Option<bool>,
}
#[derive(Deserialize, Default, Clone)]
config.llvm_ldflags = llvm.ldflags.clone();
set(&mut config.llvm_use_libcxx, llvm.use_libcxx);
config.llvm_use_linker = llvm.use_linker.clone();
+ config.llvm_allow_old_toolchain = llvm.allow_old_toolchain.clone();
}
if let Some(ref rust) = toml.rust {
// NOTE: When adding a book here, make sure to ALSO build the book by
// adding a build step in `src/bootstrap/builder.rs`!
book!(
- EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook1;
+ EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook2;
EmbeddedBook, "src/doc/embedded-book", "embedded-book", RustbookVersion::MdBook2;
Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook1;
Reference, "src/doc/reference", "reference", RustbookVersion::MdBook1;
cfg.define("LLVM_USE_LINKER", linker);
}
+ if let Some(true) = builder.config.llvm_allow_old_toolchain {
+ cfg.define("LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN", "YES");
+ }
+
if let Some(ref python) = builder.config.python {
cfg.define("PYTHON_EXECUTABLE", python);
}
ENV HOSTS=x86_64-unknown-netbsd
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
+ --set llvm.allow-old-toolchain
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
-Subproject commit 0e9061cbaf95adfb9f3ed36c6cef4c046f282e86
+Subproject commit fab9419503f0e34c1a06f9350a6705d0ce741dc6
-Subproject commit 419edb885ec1a98c0747b3907003d79e3e6b93a9
+Subproject commit 5f3cc2a5618700efcde3bc00799744f21fa9ad2e
--- /dev/null
+# `c_variadic`
+
+The tracking issue for this feature is: [#44930]
+
+[#44930]: https://github.com/rust-lang/rust/issues/44930
+
+------------------------
+
+The `c_variadic` language feature enables C-variadic functions to be
+defined in Rust. The may be called both from within Rust and via FFI.
+
+## Examples
+
+```rust
+#![feature(c_variadic)]
+
+pub unsafe extern "C" fn add(n: usize, mut args: ...) -> usize {
+ let mut sum = 0;
+ for _ in 0..n {
+ sum += args.arg::<usize>();
+ }
+ sum
+}
+```
--- /dev/null
+# `c_variadic`
+
+The tracking issue for this feature is: [#44930]
+
+[#44930]: https://github.com/rust-lang/rust/issues/44930
+
+------------------------
+
+The `c_variadic` library feature exposes the `VaList` structure,
+Rust's analogue of C's `va_list` type.
+
+## Examples
+
+```rust
+#![feature(c_variadic)]
+
+use std::ffi::VaList;
+
+pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize {
+ let mut sum = 0;
+ for _ in 0..n {
+ sum += args.arg::<usize>();
+ }
+ sum
+}
+```
bench_sums! {
bench_filter_sum,
bench_filter_ref_sum,
- (0i64..1000000).filter(|x| x % 2 == 0)
+ (0i64..1000000).filter(|x| x % 3 == 0)
}
bench_sums! {
bench_filter_chain_sum,
bench_filter_chain_ref_sum,
- (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0)
+ (0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0)
}
bench_sums! {
assert_eq!(s, 2009900);
});
}
+
+#[bench]
+fn bench_filter_count(b: &mut Bencher) {
+ b.iter(|| {
+ (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+ })
+}
+
+#[bench]
+fn bench_filter_ref_count(b: &mut Bencher) {
+ b.iter(|| {
+ (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+ })
+}
+
+#[bench]
+fn bench_filter_chain_count(b: &mut Bencher) {
+ b.iter(|| {
+ (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+ })
+}
+
+#[bench]
+fn bench_filter_chain_ref_count(b: &mut Bencher) {
+ b.iter(|| {
+ (0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+ })
+}
#[inline]
fn next(&mut self) -> Option<I::Item> {
- for x in &mut self.iter {
- if (self.predicate)(&x) {
- return Some(x);
- }
- }
- None
+ self.try_for_each(Err).err()
}
#[inline]
// Using the branchless version will also simplify the LLVM byte code, thus
// leaving more budget for LLVM optimizations.
#[inline]
- fn count(mut self) -> usize {
- let mut count = 0;
- for x in &mut self.iter {
- count += (self.predicate)(&x) as usize;
- }
- count
+ fn count(self) -> usize {
+ let mut predicate = self.predicate;
+ self.iter.map(|x| predicate(&x) as usize).sum()
}
#[inline]
{
#[inline]
fn next_back(&mut self) -> Option<I::Item> {
- for x in self.iter.by_ref().rev() {
- if (self.predicate)(&x) {
- return Some(x);
- }
- }
- None
+ self.try_rfold((), |_, x| Err(x)).err()
}
#[inline]
#[inline]
fn next(&mut self) -> Option<B> {
- for x in self.iter.by_ref() {
- if let Some(y) = (self.f)(x) {
- return Some(y);
- }
- }
- None
+ self.try_for_each(Err).err()
}
#[inline]
{
#[inline]
fn next_back(&mut self) -> Option<B> {
- for x in self.iter.by_ref().rev() {
- if let Some(y) = (self.f)(x) {
- return Some(y);
- }
- }
- None
+ self.try_rfold((), |_, x| Err(x)).err()
}
#[inline]
}
}
+// FIXME: Reference `MaybeUninit` from these docs, once that is stable.
/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
///
/// This wrapper is 0-cost.
///
+/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
+/// As a consequence, it has *no effect* on the assumptions that the compiler makes
+/// about all values being initialized at their type. In particular, initializing
+/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
+///
/// # Examples
///
/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
/// }
/// }
/// ```
+///
+/// [`mem::zeroed`]: fn.zeroed.html
#[stable(feature = "manually_drop", since = "1.20.0")]
#[lang = "manually_drop"]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
concat!("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 `<<`!
+Please note this isn't the same operation as the `<<` shifting operator!
# Examples
wrapping the truncated bits to the beginning of the resulting
integer.
-Please note this isn't the same operation as `>>`!
+Please note this isn't the same operation as the `>>` shifting operator!
# Examples
concat!("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 `<<`!
+Please note this isn't the same operation as the `<<` shifting operator!
# Examples
wrapping the truncated bits to the beginning of the resulting
integer.
-Please note this isn't the same operation as `>>`!
+Please note this isn't the same operation as the `>>` shifting operator!
# Examples
/// wrapping the truncated bits to the end of the resulting
/// integer.
///
- /// Please note this isn't the same operation as `>>`!
+ /// Please note this isn't the same operation as the `>>` shifting
+ /// operator!
///
/// # Examples
///
/// wrapping the truncated bits to the beginning of the resulting
/// integer.
///
- /// Please note this isn't the same operation as `<<`!
+ /// Please note this isn't the same operation as the `<<` shifting
+ /// operator!
///
/// # Examples
///
me.make_ascii_lowercase()
}
- /// Return an iterator that escapes each char in `s` with [`char::escape_debug`].
+ /// Return an iterator that escapes each char in `self` with [`char::escape_debug`].
///
/// Note: only extended grapheme codepoints that begin the string will be
/// escaped.
}
}
- /// Return an iterator that escapes each char in `s` with [`char::escape_default`].
+ /// Return an iterator that escapes each char in `self` with [`char::escape_default`].
///
/// [`char::escape_default`]: ../std/primitive.char.html#method.escape_default
///
EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) }
}
- /// Return an iterator that escapes each char in `s` with [`char::escape_unicode`].
+ /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`].
///
/// [`char::escape_unicode`]: ../std/primitive.char.html#method.escape_unicode
///
jobserver = "0.1"
lazy_static = "1.0.0"
num_cpus = "1.0"
-scoped-tls = { version = "0.1.1", features = ["nightly"] }
+scoped-tls = "1.0"
log = { version = "0.4", features = ["release_max_level_info", "std"] }
polonius-engine = "0.6.2"
-rustc-rayon = "0.1.1"
-rustc-rayon-core = "0.1.1"
+rustc-rayon = "0.1.2"
+rustc-rayon-core = "0.1.2"
rustc_apfloat = { path = "../librustc_apfloat" }
rustc_target = { path = "../librustc_target" }
rustc_data_structures = { path = "../librustc_data_structures" }
};
use crate::ty::{TyCtxt, FnSig, Instance, InstanceDef,
ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty};
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
// erase!() just makes tokens go away. It's used to specify which macro argument
// is repeated (i.e., which sub-expression of the macro we are in) but don't need
[eval_always] CoherenceInherentImplOverlapCheck,
[] CoherenceCheckTrait(DefId),
[eval_always] PrivacyAccessLevels(CrateNum),
+ [eval_always] Analysis(CrateNum),
// Represents the MIR for a fn; also used as the task node for
// things read/modify that MIR.
[] TypeOpNormalizePolyFnSig(CanonicalTypeOpNormalizeGoal<'tcx, PolyFnSig<'tcx>>),
[] TypeOpNormalizeFnSig(CanonicalTypeOpNormalizeGoal<'tcx, FnSig<'tcx>>),
- [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
+ [] SubstituteNormalizeAndTestPredicates { key: (DefId, SubstsRef<'tcx>) },
[] MethodAutoderefSteps(CanonicalTyGoal<'tcx>),
[input] TargetFeaturesWhitelist,
TyKind::Typeof(ref expression) => {
visitor.visit_anon_const(expression)
}
+ TyKind::CVarArgs(ref lt) => {
+ visitor.visit_lifetime(lt)
+ }
TyKind::Infer | TyKind::Err => {}
}
}
pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
// N.B., deliberately force a compilation error if/when new fields are added.
let ImplItem {
- id: _,
hir_id: _,
ident,
ref vis,
}
pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
- if let VisibilityKind::Restricted { ref path, id: _, hir_id } = vis.node {
+ if let VisibilityKind::Restricted { ref path, hir_id } = vis.node {
visitor.visit_id(hir_id);
visitor.visit_path(path, hir_id)
}
pub struct LoweringContext<'a> {
crate_root: Option<&'static str>,
- // Used to assign ids to HIR nodes that do not directly correspond to an AST node.
+ /// Used to assign ids to HIR nodes that do not directly correspond to an AST node.
sess: &'a Session,
cstore: &'a dyn CrateStore,
/// written at all (e.g., `&T` or `std::cell::Ref<T>`).
anonymous_lifetime_mode: AnonymousLifetimeMode,
- // Used to create lifetime definitions from in-band lifetime usages.
- // e.g., `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
- // When a named lifetime is encountered in a function or impl header and
- // has not been defined
- // (i.e., it doesn't appear in the in_scope_lifetimes list), it is added
- // to this list. The results of this list are then added to the list of
- // lifetime definitions in the corresponding impl or function generics.
+ /// Used to create lifetime definitions from in-band lifetime usages.
+ /// e.g., `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
+ /// When a named lifetime is encountered in a function or impl header and
+ /// has not been defined
+ /// (i.e., it doesn't appear in the in_scope_lifetimes list), it is added
+ /// to this list. The results of this list are then added to the list of
+ /// lifetime definitions in the corresponding impl or function generics.
lifetimes_to_define: Vec<(Span, ParamName)>,
- // Whether or not in-band lifetimes are being collected. This is used to
- // indicate whether or not we're in a place where new lifetimes will result
- // in in-band lifetime definitions, such a function or an impl header,
- // including implicit lifetimes from `impl_header_lifetime_elision`.
+ /// Whether or not in-band lifetimes are being collected. This is used to
+ /// indicate whether or not we're in a place where new lifetimes will result
+ /// in in-band lifetime definitions, such a function or an impl header,
+ /// including implicit lifetimes from `impl_header_lifetime_elision`.
is_collecting_in_band_lifetimes: bool,
- // Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
- // When `is_collectin_in_band_lifetimes` is true, each lifetime is checked
- // against this list to see if it is already in-scope, or if a definition
- // needs to be created for it.
+ /// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
+ /// When `is_collectin_in_band_lifetimes` is true, each lifetime is checked
+ /// against this list to see if it is already in-scope, or if a definition
+ /// needs to be created for it.
in_scope_lifetimes: Vec<Ident>,
current_module: NodeId,
let decl = FnDecl {
inputs: vec![],
output,
- variadic: false
+ c_variadic: false
};
let body_id = self.record_body(body_expr, Some(&decl));
self.is_generator = prev_is_generator;
fn lower_ty_binding(&mut self, b: &TypeBinding,
itctx: ImplTraitContext<'_>) -> hir::TypeBinding {
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(b.id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(b.id);
hir::TypeBinding {
- id: node_id,
hir_id,
ident: b.ident,
ty: self.lower_ty(&b.ty, itctx),
}
}
TyKind::Mac(_) => panic!("TyMac should have been expanded by now."),
+ TyKind::CVarArgs => {
+ // Create the implicit lifetime of the "spoofed" `VaList`.
+ let span = self.sess.source_map().next_point(t.span.shrink_to_lo());
+ let lt = self.new_implicit_lifetime(span);
+ hir::TyKind::CVarArgs(lt)
+ },
};
let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(t.id);
let LoweredNodeId { node_id: _, hir_id } = this.next_id();
hir::Ty { node: hir::TyKind::Tup(tys), hir_id, span }
};
- let LoweredNodeId { node_id, hir_id } = this.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = this.next_id();
(
hir::GenericArgs {
args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))],
bindings: hir_vec![
hir::TypeBinding {
- id: node_id,
hir_id,
ident: Ident::from_str(FN_OUTPUT_NAME),
ty: output
}
fn lower_local(&mut self, l: &Local) -> (hir::Local, SmallVec<[hir::ItemId; 1]>) {
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(l.id);
let mut ids = SmallVec::<[hir::ItemId; 1]>::new();
if self.sess.features_untracked().impl_trait_in_bindings {
if let Some(ref ty) = l.ty {
}
let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
(hir::Local {
- id: node_id,
hir_id,
ty: l.ty
.as_ref()
}
fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(arg.id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(arg.id);
hir::Arg {
- id: node_id,
hir_id,
pat: self.lower_pat(&arg.pat),
}
P(hir::FnDecl {
inputs,
output,
- variadic: decl.variadic,
+ c_variadic: decl.c_variadic,
implicit_self: decl.inputs.get(0).map_or(
hir::ImplicitSelfKind::None,
|arg| {
};
// "<Output = T>"
- let LoweredNodeId { node_id, hir_id } = this.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = this.next_id();
let future_params = P(hir::GenericArgs {
args: hir_vec![],
bindings: hir_vec![hir::TypeBinding {
ident: Ident::from_str(FN_OUTPUT_NAME),
ty: output_ty,
- id: node_id,
hir_id,
span,
}],
let future_path =
this.std_path(span, &["future", "Future"], Some(future_params), false);
- let LoweredNodeId { node_id, hir_id } = this.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = this.next_id();
let mut bounds = vec![
hir::GenericBound::Trait(
hir::PolyTraitRef {
trait_ref: hir::TraitRef {
path: future_path,
- ref_id: node_id,
hir_ref_id: hir_id,
},
bound_generic_params: hir_vec![],
hir::QPath::Resolved(None, path) => path.and_then(|path| path),
qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
};
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(p.ref_id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(p.ref_id);
hir::TraitRef {
path,
- ref_id: node_id,
hir_ref_id: hir_id,
}
}
}
fn lower_field(&mut self, f: &Field) -> hir::Field {
- let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = self.next_id();
hir::Field {
- id: node_id,
hir_id,
ident: f.ident,
expr: P(self.lower_expr(&f.expr)),
// `impl Future<Output = T>` here because lower_body
// only cares about the input argument patterns in the function
// declaration (decl), not the return types.
- let body_id = this.lower_async_body(decl, header.asyncness, body);
+ let body_id = this.lower_async_body(decl, header.asyncness.node, body);
let (generics, fn_decl) = this.add_in_band_defs(
generics,
decl,
Some((fn_def_id, idty)),
true,
- header.asyncness.opt_return_id()
+ header.asyncness.node.opt_return_id()
),
);
hir::VisibilityKind::Public => hir::VisibilityKind::Public,
hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
- hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => {
+ hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
let id = this.next_id();
let path = this.renumber_segment_ids(path);
hir::VisibilityKind::Restricted {
path,
- id: id.node_id,
hir_id: id.hir_id,
}
}
hir::VisibilityKind::Public => hir::VisibilityKind::Public,
hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
- hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => {
+ hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
let id = this.next_id();
let path = this.renumber_segment_ids(path);
hir::VisibilityKind::Restricted {
path: path,
- id: id.node_id,
hir_id: id.hir_id,
}
}
};
hir::TraitItem {
- id: node_id,
hir_id,
ident: i.ident,
attrs: self.lower_attrs(&i.attrs),
)
}
ImplItemKind::Method(ref sig, ref body) => {
- let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness, body);
+ let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body);
let impl_trait_return_allow = !self.is_in_trait_impl;
let (generics, sig) = self.lower_method_sig(
&i.generics,
sig,
impl_item_def_id,
impl_trait_return_allow,
- sig.header.asyncness.opt_return_id(),
+ sig.header.asyncness.node.opt_return_id(),
);
(generics, hir::ImplItemKind::Method(sig, body_id))
}
};
hir::ImplItem {
- id: node_id,
hir_id,
ident: i.ident,
attrs: self.lower_attrs(&i.attrs),
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
hir::FnHeader {
unsafety: self.lower_unsafety(h.unsafety),
- asyncness: self.lower_asyncness(h.asyncness),
+ asyncness: self.lower_asyncness(h.asyncness.node),
constness: self.lower_constness(h.constness),
abi: h.abi,
}
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
self.with_new_scopes(|this| {
- let LoweredNodeId { node_id, hir_id } = this.lower_node_id(c.id);
+ let LoweredNodeId { node_id: _, hir_id } = this.lower_node_id(c.id);
hir::AnonConst {
- id: node_id,
hir_id,
body: this.lower_body(None, |this| this.lower_expr(&c.value)),
}
let outer_decl = FnDecl {
inputs: decl.inputs.clone(),
output: FunctionRetTy::Default(fn_decl_span),
- variadic: false,
+ c_variadic: false,
};
// We need to lower the declaration outside the new scope, because we
// have to conserve the state of being inside a loop condition for the
ThinVec::new(),
))
};
- let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = self.next_id();
let match_stmt = hir::Stmt {
- id: node_id,
hir_id,
node: hir::StmtKind::Expr(match_expr),
span: head_sp,
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
let body_expr = P(self.expr_block(body_block, ThinVec::new()));
- let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = self.next_id();
let body_stmt = hir::Stmt {
- id: node_id,
hir_id,
node: hir::StmtKind::Expr(body_expr),
span: body.span,
let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids
.into_iter()
.map(|item_id| {
- let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = self.next_id();
hir::Stmt {
- id: node_id,
hir_id,
node: hir::StmtKind::Item(item_id),
span: s.span,
})
.collect();
ids.push({
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(s.id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(s.id);
hir::Stmt {
- id: node_id,
hir_id,
node: hir::StmtKind::Local(P(l)),
span: s.span,
return self.lower_item_id(it)
.into_iter()
.map(|item_id| {
- let LoweredNodeId { node_id, hir_id } = id.take()
+ let LoweredNodeId { node_id: _, hir_id } = id.take()
.map(|id| self.lower_node_id(id))
.unwrap_or_else(|| self.next_id());
hir::Stmt {
- id: node_id,
hir_id,
node: hir::StmtKind::Item(item_id),
span: s.span,
.collect();
}
StmtKind::Expr(ref e) => {
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(s.id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(s.id);
hir::Stmt {
- id: node_id,
hir_id,
node: hir::StmtKind::Expr(P(self.lower_expr(e))),
span: s.span,
}
},
StmtKind::Semi(ref e) => {
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(s.id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(s.id);
hir::Stmt {
- id: node_id,
hir_id,
node: hir::StmtKind::Semi(P(self.lower_expr(e))),
span: s.span,
ParamMode::Explicit,
explicit_owner,
)),
- id: lowered_id.node_id,
hir_id: lowered_id.hir_id,
}
},
}
fn field(&mut self, ident: Ident, expr: P<hir::Expr>, span: Span) -> hir::Field {
- let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = self.next_id();
hir::Field {
- id: node_id,
hir_id,
ident,
span,
pat: P<hir::Pat>,
source: hir::LocalSource,
) -> hir::Stmt {
- let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = self.next_id();
let local = hir::Local {
pat,
ty: None,
init: ex,
- id: node_id,
hir_id,
span: sp,
attrs: ThinVec::new(),
source,
};
- let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = self.next_id();
hir::Stmt {
- id: node_id,
hir_id,
node: hir::StmtKind::Local(P(local)),
span: sp
bound_generic_params: hir::HirVec::new(),
trait_ref: hir::TraitRef {
path: path.and_then(|path| path),
- ref_id: id.node_id,
hir_ref_id: id.hir_id,
},
span,
fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
debug_assert_eq!(ti.hir_id.owner,
- self.definitions.opt_def_index(ti.id).unwrap());
+ self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap());
self.with_dep_node_owner(ti.hir_id.owner, ti, |this| {
this.insert(ti.span, ti.hir_id, Node::TraitItem(ti));
fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
debug_assert_eq!(ii.hir_id.owner,
- self.definitions.opt_def_index(ii.id).unwrap());
+ self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap());
self.with_dep_node_owner(ii.hir_id.owner, ii, |this| {
this.insert(ii.span, ii.hir_id, Node::ImplItem(ii));
decl: &'a FnDecl,
body: &'a Block,
) {
- let (closure_id, return_impl_trait_id) = match header.asyncness {
+ let (closure_id, return_impl_trait_id) = match header.asyncness.node {
IsAsync::Async {
closure_id,
return_impl_trait_id,
}
ItemKind::Fn(
ref decl,
- ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
+ ref header,
ref generics,
ref body,
- ) => {
+ ) if header.asyncness.node.is_async() => {
return self.visit_async_fn(
i.id,
i.ident.name,
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
let def_data = match ii.node {
ImplItemKind::Method(MethodSig {
- header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
+ ref header,
ref decl,
- }, ref body) => {
+ }, ref body) if header.asyncness.node.is_async() => {
return self.visit_async_fn(
ii.id,
ii.ident.name,
}
}
Node::TraitItem(item) => {
- let def_id = self.local_def_id(item.id);
+ let def_id = self.local_def_id_from_hir_id(item.hir_id);
match item.node {
TraitItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
TraitItemKind::Method(..) => Some(Def::Method(def_id)),
}
}
Node::ImplItem(item) => {
- let def_id = self.local_def_id(item.id);
+ let def_id = self.local_def_id_from_hir_id(item.hir_id);
match item.node {
ImplItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
ImplItemKind::Method(..) => Some(Def::Method(def_id)),
Node::Block(_) |
Node::Crate => None,
Node::Local(local) => {
- Some(Def::Local(local.id))
+ Some(Def::Local(self.hir_to_node_id(local.hir_id)))
}
Node::MacroDef(macro_def) => {
Some(Def::Macro(self.local_def_id_from_hir_id(macro_def.hir_id),
/// A statement.
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct Stmt {
- pub id: NodeId,
pub hir_id: HirId,
pub node: StmtKind,
pub span: Span,
impl fmt::Debug for Stmt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "stmt({}: {})", self.id,
+ write!(f, "stmt({}: {})", self.hir_id,
print::to_string(print::NO_ANN, |s| s.print_stmt(self)))
}
}
pub ty: Option<P<Ty>>,
/// Initializer expression to set the value, if any.
pub init: Option<P<Expr>>,
- pub id: NodeId,
pub hir_id: HirId,
pub span: Span,
pub attrs: ThinVec<Attribute>,
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Field {
- pub id: NodeId,
pub hir_id: HirId,
pub ident: Ident,
pub expr: P<Expr>,
/// explicit discriminant values for enum variants.
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
pub struct AnonConst {
- pub id: NodeId,
pub hir_id: HirId,
pub body: BodyId,
}
/// signature) or provided (meaning it has a default implementation).
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct TraitItem {
- pub id: NodeId,
pub ident: Ident,
pub hir_id: HirId,
pub attrs: HirVec<Attribute>,
/// Represents anything within an `impl` block
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ImplItem {
- pub id: NodeId,
pub ident: Ident,
pub hir_id: HirId,
pub vis: Visibility,
// Bind a type to an associated type: `A=Foo`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct TypeBinding {
- pub id: NodeId,
pub hir_id: HirId,
pub ident: Ident,
pub ty: P<Ty>,
Infer,
/// Placeholder for a type that has failed to be defined.
Err,
+ /// Placeholder for C-variadic arguments. We "spoof" the `VaList` created
+ /// from the variadic arguments. This type is only valid up to typeck.
+ CVarArgs(Lifetime),
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Arg {
pub pat: P<Pat>,
- pub id: NodeId,
pub hir_id: HirId,
}
pub struct FnDecl {
pub inputs: HirVec<Ty>,
pub output: FunctionRetTy,
- pub variadic: bool,
+ pub c_variadic: bool,
/// Does the function have an implicit self?
pub implicit_self: ImplicitSelfKind,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct TraitRef {
pub path: Path,
- pub ref_id: NodeId,
pub hir_ref_id: HirId,
}
pub enum VisibilityKind {
Public,
Crate(CrateSugar),
- Restricted { path: P<Path>, id: NodeId, hir_id: HirId },
+ Restricted { path: P<Path>, hir_id: HirId },
Inherited,
}
Name(&'a ast::Name),
Block(&'a hir::Block),
Item(&'a hir::Item),
- SubItem(ast::NodeId),
+ SubItem(hir::HirId),
Expr(&'a hir::Expr),
Pat(&'a hir::Pat),
}
self.s.word("/*ERROR*/")?;
self.pclose()?;
}
+ hir::TyKind::CVarArgs(_) => {
+ self.s.word("...")?;
+ }
}
self.end()
}
}
pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
- self.ann.pre(self, AnnNode::SubItem(ti.id))?;
+ self.ann.pre(self, AnnNode::SubItem(ti.hir_id))?;
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(ti.span.lo())?;
self.print_outer_attributes(&ti.attrs)?;
default.as_ref().map(|ty| &**ty))?;
}
}
- self.ann.post(self, AnnNode::SubItem(ti.id))
+ self.ann.post(self, AnnNode::SubItem(ti.hir_id))
}
pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
- self.ann.pre(self, AnnNode::SubItem(ii.id))?;
+ self.ann.pre(self, AnnNode::SubItem(ii.hir_id))?;
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(ii.span.lo())?;
self.print_outer_attributes(&ii.attrs)?;
self.print_associated_type(ii.ident, Some(bounds), None)?;
}
}
- self.ann.post(self, AnnNode::SubItem(ii.id))
+ self.ann.post(self, AnnNode::SubItem(ii.hir_id))
}
pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
s.print_type(ty)?;
s.end()
})?;
- if decl.variadic {
+ if decl.c_variadic {
self.s.word(", ...")?;
}
self.pclose()?;
});
impl_stable_hash_for!(struct hir::TypeBinding {
- id,
hir_id,
ident -> (ident.name),
ty,
TraitObject(trait_refs, lifetime),
Typeof(body_id),
Err,
- Infer
+ Infer,
+ CVarArgs(lt),
});
impl_stable_hash_for!(struct hir::FnDecl {
inputs,
output,
- variadic,
+ c_variadic,
implicit_self
});
});
impl_stable_hash_for!(struct hir::TraitRef {
- // Don't hash the ref_id. It is tracked via the thing it is used to access
- ref_id -> _,
+ // Don't hash the hir_ref_id. It is tracked via the thing it is used to access
hir_ref_id -> _,
path,
});
});
impl_stable_hash_for!(struct hir::Stmt {
- id,
hir_id,
node,
span,
pat,
ty,
init,
- id,
hir_id,
span,
attrs,
});
impl_stable_hash_for!(struct hir::Field {
- id -> _,
hir_id -> _,
ident,
expr,
});
impl_stable_hash_for!(struct hir::AnonConst {
- id,
hir_id,
body
});
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
let hir::TraitItem {
- id: _,
hir_id: _,
ident,
ref attrs,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
let hir::ImplItem {
- id: _,
hir_id: _,
ident,
ref vis,
hir::VisibilityKind::Crate(sugar) => {
sugar.hash_stable(hcx, hasher);
}
- hir::VisibilityKind::Restricted { ref path, id, hir_id } => {
+ hir::VisibilityKind::Restricted { ref path, hir_id } => {
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
- id.hash_stable(hcx, hasher);
hir_id.hash_stable(hcx, hasher);
});
path.hash_stable(hcx, hasher);
impl_stable_hash_for!(struct hir::Arg {
pat,
- id,
hir_id
});
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
- mir::Place::Local(ref local) => {
+ mir::Place::Base(mir::PlaceBase::Local(ref local)) => {
local.hash_stable(hcx, hasher);
}
- mir::Place::Static(ref statik) => {
+ mir::Place::Base(mir::PlaceBase::Static(ref statik)) => {
statik.hash_stable(hcx, hasher);
}
- mir::Place::Promoted(ref promoted) => {
+ mir::Place::Base(mir::PlaceBase::Promoted(ref promoted)) => {
promoted.hash_stable(hcx, hasher);
}
mir::Place::Projection(ref place_projection) => {
impl_stable_hash_for!(struct ty::FnSig<'tcx> {
inputs_and_output,
- variadic,
+ c_variadic,
unsafety,
abi
});
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::error::TypeError;
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
use crate::traits::{Obligation, PredicateObligations};
use syntax::ast;
fn relate_item_substs(&mut self,
item_def_id: DefId,
- a_subst: &'tcx Substs<'tcx>,
- b_subst: &'tcx Substs<'tcx>)
- -> RelateResult<'tcx, &'tcx Substs<'tcx>>
+ a_subst: SubstsRef<'tcx>,
+ b_subst: SubstsRef<'tcx>)
+ -> RelateResult<'tcx, SubstsRef<'tcx>>
{
if self.ambient_variance == ty::Variance::Invariant {
// Avoid fetching the variance if we are in an invariant
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::TyVar;
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
/// Ensures `a` is made equal to `b`. Returns `a` on success.
fn relate_item_substs(&mut self,
_item_def_id: DefId,
- a_subst: &'tcx Substs<'tcx>,
- b_subst: &'tcx Substs<'tcx>)
- -> RelateResult<'tcx, &'tcx Substs<'tcx>>
+ a_subst: SubstsRef<'tcx>,
+ b_subst: SubstsRef<'tcx>)
+ -> RelateResult<'tcx, SubstsRef<'tcx>>
{
// N.B., once we are equating types, we don't care about
// variance, so don't try to lookup the variance here. This
use crate::middle::region;
use crate::traits::{ObligationCause, ObligationCauseCode};
use crate::ty::error::TypeError;
-use crate::ty::{self, subst::Subst, Region, Ty, TyCtxt, TyKind, TypeFoldable};
+use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TyKind, TypeFoldable};
use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
use std::{cmp, fmt};
use syntax_pos::{Pos, Span};
value: &mut DiagnosticStyledString,
other_value: &mut DiagnosticStyledString,
name: String,
- sub: &ty::subst::Substs<'tcx>,
+ sub: ty::subst::SubstsRef<'tcx>,
pos: usize,
other_ty: &Ty<'tcx>,
) {
mut t1_out: &mut DiagnosticStyledString,
mut t2_out: &mut DiagnosticStyledString,
path: String,
- sub: &ty::subst::Substs<'tcx>,
+ sub: ty::subst::SubstsRef<'tcx>,
other_path: String,
other_ty: &Ty<'tcx>,
) -> Option<()> {
fn strip_generic_default_params(
&self,
def_id: DefId,
- substs: &ty::subst::Substs<'tcx>,
- ) -> &'tcx ty::subst::Substs<'tcx> {
+ substs: ty::subst::SubstsRef<'tcx>,
+ ) -> SubstsRef<'tcx> {
let generics = self.tcx.generics_of(def_id);
let mut num_supplied_defaults = 0;
let mut type_params = generics
use crate::traits::{ObligationCause, ObligationCauseCode};
use crate::ty;
use crate::ty::error::ExpectedFound;
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
use crate::util::ppaux::RegionHighlightMode;
impl NiceRegionError<'me, 'gcx, 'tcx> {
sub_placeholder: Option<ty::Region<'tcx>>,
sup_placeholder: Option<ty::Region<'tcx>>,
trait_def_id: DefId,
- expected_substs: &'tcx Substs<'tcx>,
- actual_substs: &'tcx Substs<'tcx>,
+ expected_substs: SubstsRef<'tcx>,
+ actual_substs: SubstsRef<'tcx>,
) -> DiagnosticBuilder<'me> {
debug!(
"try_report_placeholders_trait(\
use crate::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use crate::ty::fold::TypeFoldable;
use crate::ty::relate::RelateResult;
-use crate::ty::subst::{Kind, Substs};
+use crate::ty::subst::{Kind, InternalSubsts, SubstsRef};
use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners};
use crate::ty::{FloatVid, IntVid, TyVid};
use crate::util::nodemap::FxHashMap;
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
/// type/region parameter to a fresh inference variable.
- pub fn fresh_substs_for_item(&self, span: Span, def_id: DefId) -> &'tcx Substs<'tcx> {
- Substs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param))
+ pub fn fresh_substs_for_item(&self, span: Span, def_id: DefId) -> SubstsRef<'tcx> {
+ InternalSubsts::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param))
}
/// Returns `true` if errors have been reported since this infcx was
use crate::ty::{self, Ty, TyCtxt, GenericParamDefKind};
use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
use crate::ty::outlives::Component;
-use crate::ty::subst::{Kind, Substs, UnpackedKind};
+use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, UnpackedKind};
use crate::util::nodemap::DefIdMap;
pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
/// fn foo<'a, 'b, T>() -> Foo<'a, T>
///
/// then `substs` would be `['a, T]`.
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
/// The type variable that represents the value of the abstract type
/// that we require. In other words, after we compile this function,
// lifetimes with 'static and remapping only those used in the
// `impl Trait` return type, resulting in the parameters
// shifting.
- let id_substs = Substs::identity_for_item(gcx, def_id);
+ let id_substs = InternalSubsts::identity_for_item(gcx, def_id);
let map: FxHashMap<Kind<'tcx>, Kind<'gcx>> = opaque_defn
.substs
.iter()
&mut self,
ty: Ty<'tcx>,
def_id: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
) -> Ty<'tcx> {
let infcx = self.infcx;
let tcx = infcx.tcx;
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::{GenericKind, VerifyBound};
use crate::traits;
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, InternalSubsts};
use crate::ty::{self, Ty, TyCtxt};
use crate::util::captures::Captures;
.iter()
.map(|(p, _)| *p)
.collect();
- let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id);
+ let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id);
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
self.collect_outlives_from_predicate_list(
move |ty| ty == identity_proj,
match span {
Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, msg),
None => {
- let node_id = self.tcx.hir().hir_to_node_id(hir_id); // FIXME(@ljedrz): remove later
- self.tcx.struct_lint_node(lint, node_id, msg)
+ self.tcx.struct_lint_node(lint, hir_id, msg)
},
}
}
run_lints!(self, exit_lint_attrs, attrs);
}
- fn with_param_env<F>(&mut self, id: ast::NodeId, f: F)
+ fn with_param_env<F>(&mut self, id: hir::HirId, f: F)
where F: FnOnce(&mut Self),
{
let old_param_env = self.param_env;
- self.param_env = self.tcx.param_env(self.tcx.hir().local_def_id(id));
+ self.param_env = self.tcx.param_env(self.tcx.hir().local_def_id_from_hir_id(id));
f(self);
self.param_env = old_param_env;
}
let generics = self.generics.take();
self.generics = it.node.generics();
self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
- cx.with_param_env(it.id, |cx| {
+ cx.with_param_env(it.hir_id, |cx| {
run_lints!(cx, check_item, it);
hir_visit::walk_item(cx, it);
run_lints!(cx, check_item_post, it);
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) {
self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
- cx.with_param_env(it.id, |cx| {
+ cx.with_param_env(it.hir_id, |cx| {
run_lints!(cx, check_foreign_item, it);
hir_visit::walk_foreign_item(cx, it);
run_lints!(cx, check_foreign_item_post, it);
let generics = self.generics.take();
self.generics = Some(&trait_item.generics);
self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |cx| {
- cx.with_param_env(trait_item.id, |cx| {
+ cx.with_param_env(trait_item.hir_id, |cx| {
run_lints!(cx, check_trait_item, trait_item);
hir_visit::walk_trait_item(cx, trait_item);
run_lints!(cx, check_trait_item_post, trait_item);
let generics = self.generics.take();
self.generics = Some(&impl_item.generics);
self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |cx| {
- cx.with_param_env(impl_item.id, |cx| {
+ cx.with_param_env(impl_item.hir_id, |cx| {
run_lints!(cx, check_impl_item, impl_item);
hir_visit::walk_impl_item(cx, impl_item);
run_lints!(cx, check_impl_item_post, impl_item);
#[macro_export]
macro_rules! declare_tool_lint {
- ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr) => (
- declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, false}
+ (
+ $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
+ ) => (
+ declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false}
);
- ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr,
- report_in_external_macro: $rep: expr) => (
- declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, $rep}
+ (
+ $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+ report_in_external_macro: $rep:expr
+ ) => (
+ declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep}
);
- ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
+ (
+ $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+ $external:expr
+ ) => (
+ $(#[$attr])*
$vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
name: &concat!(stringify!($tool), "::", stringify!($NAME)),
default_level: $crate::lint::$Level,
// function, then we should explore its block to check for codes that
// may need to be marked as live.
fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- node_id: ast::NodeId) -> bool {
- match tcx.hir().find(node_id) {
+ hir_id: hir::HirId) -> bool {
+ match tcx.hir().find_by_hir_id(hir_id) {
Some(Node::Item(..)) |
Some(Node::ImplItem(..)) |
Some(Node::ForeignItem(..)) |
}
struct MarkSymbolVisitor<'a, 'tcx: 'a> {
- worklist: Vec<ast::NodeId>,
+ worklist: Vec<hir::HirId>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
- live_symbols: FxHashSet<ast::NodeId>,
+ live_symbols: FxHashSet<hir::HirId>,
repr_has_repr_c: bool,
in_pat: bool,
inherited_pub_visibility: bool,
ignore_variant_stack: Vec<DefId>,
// maps from tuple struct constructors to tuple struct items
- struct_constructors: FxHashMap<ast::NodeId, ast::NodeId>,
+ struct_constructors: FxHashMap<hir::HirId, hir::HirId>,
}
impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
fn check_def_id(&mut self, def_id: DefId) {
- if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) {
- if should_explore(self.tcx, node_id) ||
- self.struct_constructors.contains_key(&node_id) {
- self.worklist.push(node_id);
+ if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
+ if should_explore(self.tcx, hir_id) ||
+ self.struct_constructors.contains_key(&hir_id) {
+ self.worklist.push(hir_id);
}
- self.live_symbols.insert(node_id);
+ self.live_symbols.insert(hir_id);
}
}
fn insert_def_id(&mut self, def_id: DefId) {
- if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) {
- debug_assert!(!should_explore(self.tcx, node_id));
- self.live_symbols.insert(node_id);
+ if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
+ debug_assert!(!should_explore(self.tcx, hir_id));
+ self.live_symbols.insert(hir_id);
}
}
// tuple struct constructor function
let id = self.struct_constructors.get(&id).cloned().unwrap_or(id);
- if let Some(node) = self.tcx.hir().find(id) {
+ if let Some(node) = self.tcx.hir().find_by_hir_id(id) {
self.live_symbols.insert(id);
self.visit_node(node);
}
let live_fields = def.fields().iter().filter(|f| {
has_repr_c || inherited_pub_visibility || f.vis.node.is_pub()
});
- self.live_symbols.extend(live_fields.map(|f| f.id));
+ self.live_symbols.extend(live_fields.map(|f| f.hir_id));
intravisit::walk_struct_def(self, def);
}
}
fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_, '_, '_>,
- id: ast::NodeId,
+ id: hir::HirId,
attrs: &[ast::Attribute]) -> bool {
if attr::contains_name(attrs, "lang") {
return true;
return true;
}
- let def_id = tcx.hir().local_def_id(id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(id);
let cg_attrs = tcx.codegen_fn_attrs(def_id);
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
// 2) We are not sure to be live or not
// * Implementation of a trait method
struct LifeSeeder<'k, 'tcx: 'k> {
- worklist: Vec<ast::NodeId>,
+ worklist: Vec<hir::HirId>,
krate: &'k hir::Crate,
tcx: TyCtxt<'k, 'tcx, 'tcx>,
// see `MarkSymbolVisitor::struct_constructors`
- struct_constructors: FxHashMap<ast::NodeId, ast::NodeId>,
+ struct_constructors: FxHashMap<hir::HirId, hir::HirId>,
}
impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
let allow_dead_code = has_allow_dead_code_or_lang_attr(self.tcx,
- item.id,
+ item.hir_id,
&item.attrs);
if allow_dead_code {
- self.worklist.push(item.id);
+ self.worklist.push(item.hir_id);
}
match item.node {
hir::ItemKind::Enum(ref enum_def, _) if allow_dead_code => {
self.worklist.extend(enum_def.variants.iter()
- .map(|variant| variant.node.data.id()));
+ .map(|variant| variant.node.data.hir_id()));
}
hir::ItemKind::Trait(.., ref trait_item_refs) => {
for trait_item_ref in trait_item_refs {
hir::TraitItemKind::Const(_, Some(_)) |
hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
if has_allow_dead_code_or_lang_attr(self.tcx,
- trait_item.id,
+ trait_item.hir_id,
&trait_item.attrs) {
- self.worklist.push(trait_item.id);
+ self.worklist.push(trait_item.hir_id);
}
}
_ => {}
let impl_item = self.krate.impl_item(impl_item_ref.id);
if opt_trait.is_some() ||
has_allow_dead_code_or_lang_attr(self.tcx,
- impl_item.id,
+ impl_item.hir_id,
&impl_item.attrs) {
- self.worklist.push(impl_item_ref.id.node_id);
+ self.worklist.push(self.tcx.hir().node_to_hir_id(impl_item_ref.id.node_id));
}
}
}
hir::ItemKind::Struct(ref variant_data, _) => {
- self.struct_constructors.insert(variant_data.id(), item.id);
+ self.struct_constructors.insert(variant_data.hir_id(), item.hir_id);
}
_ => ()
}
tcx: TyCtxt<'a, 'tcx, 'tcx>,
access_levels: &privacy::AccessLevels,
krate: &hir::Crate,
-) -> (Vec<ast::NodeId>, FxHashMap<ast::NodeId, ast::NodeId>) {
+) -> (Vec<hir::HirId>, FxHashMap<hir::HirId, hir::HirId>) {
let worklist = access_levels.map.iter().filter_map(|(&id, level)| {
if level >= &privacy::AccessLevel::Reachable {
- Some(id)
+ Some(tcx.hir().node_to_hir_id(id))
} else {
None
}
}).chain(
// Seed entry point
- tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_node_id(def_id).unwrap())
+ tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_hir_id(def_id).unwrap())
).collect::<Vec<_>>();
// Seed implemented trait items
fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
access_levels: &privacy::AccessLevels,
krate: &hir::Crate)
- -> FxHashSet<ast::NodeId> {
+ -> FxHashSet<hir::HirId> {
let (worklist, struct_constructors) = create_and_seed_worklist(tcx, access_levels, krate);
let mut symbol_visitor = MarkSymbolVisitor {
worklist,
struct DeadVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- live_symbols: FxHashSet<ast::NodeId>,
+ live_symbols: FxHashSet<hir::HirId>,
}
impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
| hir::ItemKind::Union(..) => true,
_ => false
};
- should_warn && !self.symbol_is_live(item.id)
+ should_warn && !self.symbol_is_live(item.hir_id)
}
fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
let field_type = self.tcx.type_of(self.tcx.hir().local_def_id(field.id));
!field.is_positional()
- && !self.symbol_is_live(field.id)
+ && !self.symbol_is_live(field.hir_id)
&& !field_type.is_phantom_data()
- && !has_allow_dead_code_or_lang_attr(self.tcx, field.id, &field.attrs)
+ && !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id, &field.attrs)
}
fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool {
- !self.symbol_is_live(variant.data.id())
+ !self.symbol_is_live(variant.data.hir_id())
&& !has_allow_dead_code_or_lang_attr(self.tcx,
- variant.data.id(),
+ variant.data.hir_id(),
&variant.attrs)
}
fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool {
- !self.symbol_is_live(fi.id)
- && !has_allow_dead_code_or_lang_attr(self.tcx, fi.id, &fi.attrs)
+ !self.symbol_is_live(fi.hir_id)
+ && !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id, &fi.attrs)
}
- // id := node id of an item's definition.
+ // id := HIR id of an item's definition.
fn symbol_is_live(
&mut self,
- id: ast::NodeId,
+ id: hir::HirId,
) -> bool {
if self.live_symbols.contains(&id) {
return true;
// This is done to handle the case where, for example, the static
// method of a private type is used, but the type itself is never
// called directly.
- let def_id = self.tcx.hir().local_def_id(id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(id);
let inherent_impls = self.tcx.inherent_impls(def_id);
for &impl_did in inherent_impls.iter() {
for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
- if let Some(item_node_id) = self.tcx.hir().as_local_node_id(item_did) {
- if self.live_symbols.contains(&item_node_id) {
+ if let Some(item_hir_id) = self.tcx.hir().as_local_hir_id(item_did) {
+ if self.live_symbols.contains(&item_hir_id) {
return true;
}
}
}
fn warn_dead_code(&mut self,
- id: ast::NodeId,
+ id: hir::HirId,
span: syntax_pos::Span,
name: ast::Name,
node_type: &str,
participle: &str) {
if !name.as_str().starts_with("_") {
self.tcx
- .lint_node(lint::builtin::DEAD_CODE,
- id,
- span,
- &format!("{} is never {}: `{}`",
- node_type, participle, name));
+ .lint_hir(lint::builtin::DEAD_CODE,
+ id,
+ span,
+ &format!("{} is never {}: `{}`",
+ node_type, participle, name));
}
}
}
_ => "used"
};
self.warn_dead_code(
- item.id,
+ item.hir_id,
span,
item.ident.name,
item.node.descriptive_variant(),
g: &'tcx hir::Generics,
id: hir::HirId) {
if self.should_warn_about_variant(&variant.node) {
- self.warn_dead_code(variant.node.data.id(), variant.span, variant.node.ident.name,
+ self.warn_dead_code(variant.node.data.hir_id(), variant.span, variant.node.ident.name,
"variant", "constructed");
} else {
intravisit::walk_variant(self, variant, g, id);
fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem) {
if self.should_warn_about_foreign_item(fi) {
- self.warn_dead_code(fi.id, fi.span, fi.ident.name,
+ self.warn_dead_code(fi.hir_id, fi.span, fi.ident.name,
fi.node.descriptive_variant(), "used");
}
intravisit::walk_foreign_item(self, fi);
fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
if self.should_warn_about_field(&field) {
- self.warn_dead_code(field.id, field.span, field.ident.name, "field", "used");
+ self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "used");
}
intravisit::walk_struct_field(self, field);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
match impl_item.node {
hir::ImplItemKind::Const(_, body_id) => {
- if !self.symbol_is_live(impl_item.id) {
- self.warn_dead_code(impl_item.id,
+ if !self.symbol_is_live(impl_item.hir_id) {
+ self.warn_dead_code(impl_item.hir_id,
impl_item.span,
impl_item.ident.name,
"associated const",
self.visit_nested_body(body_id)
}
hir::ImplItemKind::Method(_, body_id) => {
- if !self.symbol_is_live(impl_item.id) {
+ if !self.symbol_is_live(impl_item.hir_id) {
let span = self.tcx.sess.source_map().def_span(impl_item.span);
- self.warn_dead_code(impl_item.id, span, impl_item.ident.name, "method", "used");
+ self.warn_dead_code(impl_item.hir_id, span, impl_item.ident.name, "method",
+ "used");
}
self.visit_nested_body(body_id)
}
use std::cmp;
use std::mem;
use crate::ty;
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
/// The SymbolExportLevel of a symbols specifies from which kinds of crates
/// the symbol will be exported. `C` symbols will be exported from any
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
pub enum ExportedSymbol<'tcx> {
NonGeneric(DefId),
- Generic(DefId, &'tcx Substs<'tcx>),
+ Generic(DefId, SubstsRef<'tcx>),
NoDefId(ty::SymbolName),
}
impl_item: &hir::ImplItem,
impl_src: DefId) -> bool {
let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
- let generics = tcx.generics_of(tcx.hir().local_def_id(impl_item.id));
+ let generics = tcx.generics_of(tcx.hir().local_def_id_from_hir_id(impl_item.hir_id));
if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
return true
}
});
}
}
+ hir::TyKind::CVarArgs(ref lt) => {
+ // Resolve the generated lifetime for the C-variadic arguments.
+ // The lifetime is generated in AST -> HIR lowering.
+ if lt.name.is_elided() {
+ self.resolve_elided_lifetimes(vec![lt])
+ }
+ }
_ => intravisit::walk_ty(self, ty),
}
}
Method(ref sig, _) => {
let tcx = self.tcx;
self.visit_early_late(
- Some(tcx.hir().get_parent(trait_item.id)),
+ Some(tcx.hir().get_parent_item(trait_item.hir_id)),
&sig.decl,
&trait_item.generics,
|this| intravisit::walk_trait_item(this, trait_item),
Method(ref sig, _) => {
let tcx = self.tcx;
self.visit_early_late(
- Some(tcx.hir().get_parent(impl_item.id)),
+ Some(tcx.hir().get_parent_item(impl_item.hir_id)),
&sig.decl,
&impl_item.generics,
|this| intravisit::walk_impl_item(this, impl_item),
/// ordering is not important there.
fn visit_early_late<F>(
&mut self,
- parent_id: Option<ast::NodeId>,
+ parent_id: Option<hir::HirId>,
decl: &'tcx hir::FnDecl,
generics: &'tcx hir::Generics,
walk: F,
// Find the start of nested early scopes, e.g., in methods.
let mut index = 0;
if let Some(parent_id) = parent_id {
- let parent = self.tcx.hir().expect_item(parent_id);
+ let parent = self.tcx.hir().expect_item_by_hir_id(parent_id);
if sub_items_have_self_param(&parent.node) {
index += 1; // Self comes before lifetimes
}
if let hir::TyKind::BareFn(_) = ty.node {
self.outer_index.shift_in(1);
}
- if let hir::TyKind::TraitObject(ref bounds, ref lifetime) = ty.node {
- for bound in bounds {
- self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
- }
+ match ty.node {
+ hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
+ for bound in bounds {
+ self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
+ }
- // Stay on the safe side and don't include the object
- // lifetime default (which may not end up being used).
- if !lifetime.is_elided() {
- self.visit_lifetime(lifetime);
+ // Stay on the safe side and don't include the object
+ // lifetime default (which may not end up being used).
+ if !lifetime.is_elided() {
+ self.visit_lifetime(lifetime);
+ }
+ }
+ hir::TyKind::CVarArgs(_) => {}
+ _ => {
+ intravisit::walk_ty(self, ty);
}
- } else {
- intravisit::walk_ty(self, ty);
}
if let hir::TyKind::BareFn(_) = ty.node {
self.outer_index.shift_out(1);
use crate::session::{DiagnosticMessageId, Session};
use syntax::symbol::Symbol;
use syntax_pos::{Span, MultiSpan};
-use syntax::ast;
use syntax::ast::Attribute;
use syntax::errors::Applicability;
use syntax::feature_gate::{GateIssue, emit_feature_err};
}
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
- let impl_def_id = self.tcx.hir().local_def_id(self.tcx.hir().get_parent(ii.id));
+ let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(
+ self.tcx.hir().get_parent_item(ii.hir_id));
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
self.check_missing_stability(ii.hir_id, ii.span, "item");
}
active_features: Default::default(),
};
- let ref active_lib_features = tcx.features().declared_lib_features;
+ let active_lib_features = &tcx.features().declared_lib_features;
+ let active_lang_features = &tcx.features().declared_lang_features;
- // Put the active features into a map for quick lookup
- index.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect();
+ // Put the active features into a map for quick lookup.
+ index.active_features =
+ active_lib_features.iter().map(|&(ref s, ..)| s.clone())
+ .chain(active_lang_features.iter().map(|&(ref s, ..)| s.clone()))
+ .collect();
{
let krate = tcx.hir().krate();
feature: Symbol,
since: Symbol
) {
- tcx.lint_node(lint::builtin::STABLE_FEATURES,
- ast::CRATE_NODE_ID,
+ tcx.lint_hir(lint::builtin::STABLE_FEATURES,
+ hir::CRATE_HIR_ID,
span,
&format!("the feature `{}` has been stable since {} and no longer requires \
an attribute to enable", feature, since));
use syntax::symbol::InternedString;
use syntax_pos::{Span, DUMMY_SP};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::layout::VariantIdx;
use crate::ty::{
self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
/// changing or disturbing program state.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub enum Place<'tcx> {
+ Base(PlaceBase<'tcx>),
+
+ /// projection out of a place (access a field, deref a pointer, etc)
+ Projection(Box<PlaceProjection<'tcx>>),
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub enum PlaceBase<'tcx> {
/// local variable
Local(Local),
/// Constant code promoted to an injected static
Promoted(Box<(Promoted, Ty<'tcx>)>),
-
- /// projection out of a place (access a field, deref a pointer, etc)
- Projection(Box<PlaceProjection<'tcx>>),
}
/// The `DefId` of a static, along with its normalized type (which is
}
impl<'tcx> Place<'tcx> {
+ pub const RETURN_PLACE: Place<'tcx> = Place::Base(PlaceBase::Local(RETURN_PLACE));
+
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
self.elem(ProjectionElem::Field(f, ty))
}
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
pub fn local(&self) -> Option<Local> {
match self {
- Place::Local(local) |
+ Place::Base(PlaceBase::Local(local)) |
Place::Projection(box Projection {
- base: Place::Local(local),
+ base: Place::Base(PlaceBase::Local(local)),
elem: ProjectionElem::Deref,
}) => Some(*local),
_ => None,
/// Finds the innermost `Local` from this `Place`.
pub fn base_local(&self) -> Option<Local> {
match self {
- Place::Local(local) => Some(*local),
+ Place::Base(PlaceBase::Local(local)) => Some(*local),
Place::Projection(box Projection { base, elem: _ }) => base.base_local(),
- Place::Promoted(..) | Place::Static(..) => None,
+ Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => None,
}
}
}
use self::Place::*;
match *self {
- Local(id) => write!(fmt, "{:?}", id),
- Static(box self::Static { def_id, ty }) => write!(
+ Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
+ Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!(
fmt,
"({}: {:?})",
ty::tls::with(|tcx| tcx.item_path_str(def_id)),
ty
),
- Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1),
+ Base(PlaceBase::Promoted(ref promoted)) => write!(
+ fmt,
+ "({:?}: {:?})",
+ promoted.0,
+ promoted.1
+ ),
Projection(ref data) => match data.elem {
ProjectionElem::Downcast(ref adt_def, index) => {
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
pub fn function_handle<'a>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
span: Span,
) -> Self {
let ty = tcx.type_of(def_id).subst(tcx, substs);
Adt(
&'tcx AdtDef,
VariantIdx,
- &'tcx Substs<'tcx>,
+ SubstsRef<'tcx>,
Option<UserTypeAnnotationIndex>,
Option<usize>,
),
*/
use crate::mir::*;
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{self, AdtDef, Ty, TyCtxt};
use crate::ty::layout::VariantIdx;
use crate::hir;
/// Downcast to a particular variant of an enum.
Downcast { adt_def: &'tcx AdtDef,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
variant_index: VariantIdx },
}
where D: HasLocalDecls<'tcx>
{
match *self {
- Place::Local(index) =>
+ Place::Base(PlaceBase::Local(index)) =>
PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
- Place::Promoted(ref data) => PlaceTy::Ty { ty: data.1 },
- Place::Static(ref data) =>
+ Place::Base(PlaceBase::Promoted(ref data)) => PlaceTy::Ty { ty: data.1 },
+ Place::Base(PlaceBase::Static(ref data)) =>
PlaceTy::Ty { ty: data.ty },
Place::Projection(ref proj) =>
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
use crate::hir::def_id::DefId;
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
use crate::ty::{CanonicalUserTypeAnnotation, ClosureSubsts, GeneratorSubsts, Region, Ty};
use crate::mir::*;
use syntax_pos::Span;
}
fn visit_substs(&mut self,
- substs: & $($mutability)? &'tcx Substs<'tcx>,
+ substs: & $($mutability)? SubstsRef<'tcx>,
_: Location) {
self.super_substs(substs);
}
context: PlaceContext<'tcx>,
location: Location) {
match place {
- Place::Local(local) => {
+ Place::Base(PlaceBase::Local(local)) => {
self.visit_local(local, context, location);
}
- Place::Static(static_) => {
+ Place::Base(PlaceBase::Static(static_)) => {
self.visit_static(static_, context, location);
}
- Place::Promoted(promoted) => {
+ Place::Base(PlaceBase::Promoted(promoted)) => {
self.visit_ty(& $($mutability)? promoted.1, TyContext::Location(location));
},
Place::Projection(proj) => {
fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::LazyConst<'tcx>) {
}
- fn super_substs(&mut self, _substs: & $($mutability)? &'tcx Substs<'tcx>) {
+ fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
}
fn super_generator_substs(&mut self,
Input::Str { ref mut input, .. } => Some(input),
}
}
+
+ pub fn source_name(&self) -> FileName {
+ match *self {
+ Input::File(ref ifile) => ifile.clone().into(),
+ Input::Str { ref name, .. } => name.clone(),
+ }
+ }
}
#[derive(Clone, Hash)]
use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
use rustc_data_structures::flock;
-use jobserver::Client;
+use rustc_data_structures::jobserver;
+use ::jobserver::Client;
use std;
use std::cell::{self, Cell, RefCell};
/// Returns the number of query threads that should be used for this
/// compilation
- pub fn threads_from_opts(opts: &config::Options) -> usize {
- opts.debugging_opts.threads.unwrap_or(::num_cpus::get())
+ pub fn threads_from_count(query_threads: Option<usize>) -> usize {
+ query_threads.unwrap_or(::num_cpus::get())
}
/// Returns the number of query threads that should be used for this
/// compilation
pub fn threads(&self) -> usize {
- Self::threads_from_opts(&self.opts)
+ Self::threads_from_count(self.opts.debugging_opts.threads)
}
/// Returns the number of codegen units that should be used for this
local_crate_source_file,
registry,
Lrc::new(source_map::SourceMap::new(file_path_mapping)),
- None,
+ DiagnosticOutput::Default,
+ Default::default(),
)
}
+fn default_emitter(
+ sopts: &config::Options,
+ registry: errors::registry::Registry,
+ source_map: &Lrc<source_map::SourceMap>,
+ emitter_dest: Option<Box<dyn Write + Send>>,
+) -> Box<dyn Emitter + sync::Send> {
+ match (sopts.error_format, emitter_dest) {
+ (config::ErrorOutputType::HumanReadable(color_config), None) => Box::new(
+ EmitterWriter::stderr(
+ color_config,
+ Some(source_map.clone()),
+ false,
+ sopts.debugging_opts.teach,
+ ).ui_testing(sopts.debugging_opts.ui_testing),
+ ),
+ (config::ErrorOutputType::HumanReadable(_), Some(dst)) => Box::new(
+ EmitterWriter::new(dst, Some(source_map.clone()), false, false)
+ .ui_testing(sopts.debugging_opts.ui_testing),
+ ),
+ (config::ErrorOutputType::Json(pretty), None) => Box::new(
+ JsonEmitter::stderr(
+ Some(registry),
+ source_map.clone(),
+ pretty,
+ ).ui_testing(sopts.debugging_opts.ui_testing),
+ ),
+ (config::ErrorOutputType::Json(pretty), Some(dst)) => Box::new(
+ JsonEmitter::new(
+ dst,
+ Some(registry),
+ source_map.clone(),
+ pretty,
+ ).ui_testing(sopts.debugging_opts.ui_testing),
+ ),
+ (config::ErrorOutputType::Short(color_config), None) => Box::new(
+ EmitterWriter::stderr(color_config, Some(source_map.clone()), true, false),
+ ),
+ (config::ErrorOutputType::Short(_), Some(dst)) => {
+ Box::new(EmitterWriter::new(dst, Some(source_map.clone()), true, false))
+ }
+ }
+}
+
+pub enum DiagnosticOutput {
+ Default,
+ Raw(Box<dyn Write + Send>),
+ Emitter(Box<dyn Emitter + Send + sync::Send>)
+}
+
pub fn build_session_with_source_map(
sopts: config::Options,
local_crate_source_file: Option<PathBuf>,
registry: errors::registry::Registry,
source_map: Lrc<source_map::SourceMap>,
- emitter_dest: Option<Box<dyn Write + Send>>,
+ diagnostics_output: DiagnosticOutput,
+ lint_caps: FxHashMap<lint::LintId, lint::Level>,
) -> Session {
// FIXME: This is not general enough to make the warning lint completely override
// normal diagnostic warnings, since the warning lint can also be denied and changed
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
- let emitter: Box<dyn Emitter + sync::Send> =
- match (sopts.error_format, emitter_dest) {
- (config::ErrorOutputType::HumanReadable(color_config), None) => Box::new(
- EmitterWriter::stderr(
- color_config,
- Some(source_map.clone()),
- false,
- sopts.debugging_opts.teach,
- ).ui_testing(sopts.debugging_opts.ui_testing),
- ),
- (config::ErrorOutputType::HumanReadable(_), Some(dst)) => Box::new(
- EmitterWriter::new(dst, Some(source_map.clone()), false, false)
- .ui_testing(sopts.debugging_opts.ui_testing),
- ),
- (config::ErrorOutputType::Json(pretty), None) => Box::new(
- JsonEmitter::stderr(
- Some(registry),
- source_map.clone(),
- pretty,
- ).ui_testing(sopts.debugging_opts.ui_testing),
- ),
- (config::ErrorOutputType::Json(pretty), Some(dst)) => Box::new(
- JsonEmitter::new(
- dst,
- Some(registry),
- source_map.clone(),
- pretty,
- ).ui_testing(sopts.debugging_opts.ui_testing),
- ),
- (config::ErrorOutputType::Short(color_config), None) => Box::new(
- EmitterWriter::stderr(color_config, Some(source_map.clone()), true, false),
- ),
- (config::ErrorOutputType::Short(_), Some(dst)) => {
- Box::new(EmitterWriter::new(dst, Some(source_map.clone()), true, false))
- }
- };
+ let emitter = match diagnostics_output {
+ DiagnosticOutput::Default => default_emitter(&sopts, registry, &source_map, None),
+ DiagnosticOutput::Raw(write) => {
+ default_emitter(&sopts, registry, &source_map, Some(write))
+ }
+ DiagnosticOutput::Emitter(emitter) => emitter,
+ };
let diagnostic_handler = errors::Handler::with_emitter_and_flags(
emitter,
},
);
- build_session_(sopts, local_crate_source_file, diagnostic_handler, source_map)
+ build_session_(sopts, local_crate_source_file, diagnostic_handler, source_map, lint_caps)
}
pub fn build_session_(
local_crate_source_file: Option<PathBuf>,
span_diagnostic: errors::Handler,
source_map: Lrc<source_map::SourceMap>,
+ driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
) -> Session {
let host_triple = TargetTriple::from_triple(config::host_triple());
let host = Target::search(&host_triple).unwrap_or_else(|e|
optimization_fuel,
print_fuel_crate,
print_fuel,
- // Note that this is unsafe because it may misinterpret file descriptors
- // on Unix as jobserver file descriptors. We hopefully execute this near
- // the beginning of the process though to ensure we don't get false
- // positives, or in other words we try to execute this before we open
- // any file descriptors ourselves.
- //
- // Pick a "reasonable maximum" if we don't otherwise have
- // a jobserver in our environment, capping out at 32 so we
- // don't take everything down by hogging the process run queue.
- // The fixed number is used to have deterministic compilation
- // across machines.
- //
- // Also note that we stick this in a global because there could be
- // multiple `Session` instances in this process, and the jobserver is
- // per-process.
- jobserver: unsafe {
- static mut GLOBAL_JOBSERVER: *mut Client = 0 as *mut _;
- static INIT: std::sync::Once = std::sync::ONCE_INIT;
- INIT.call_once(|| {
- let client = Client::from_env().unwrap_or_else(|| {
- Client::new(32).expect("failed to create jobserver")
- });
- GLOBAL_JOBSERVER = Box::into_raw(Box::new(client));
- });
- (*GLOBAL_JOBSERVER).clone()
- },
+ jobserver: jobserver::client(),
has_global_allocator: Once::new(),
has_panic_handler: Once::new(),
- driver_lint_caps: Default::default(),
+ driver_lint_caps,
};
validate_commandline_args_with_session_available(&sess);
finished_map
}
- fn is_param_no_infer(&self, substs: &Substs<'_>) -> bool {
+ fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool {
return self.is_of_param(substs.type_at(0)) &&
!substs.types().any(|t| t.has_infer_types());
}
use crate::traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext,
TraitEngine, Vtable};
use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::fold::TypeFoldable;
/// Attempts to resolve an obligation to a vtable. The result is
/// types.
pub fn subst_and_normalize_erasing_regions<T>(
self,
- param_substs: &Substs<'tcx>,
+ param_substs: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>,
value: &T
) -> T
use rustc_data_structures::sync::Lrc;
use syntax::ast;
use syntax_pos::{Span, DUMMY_SP};
-use crate::ty::subst::Substs;
+use crate::ty::subst::{InternalSubsts, SubstsRef};
use crate::ty::{self, AdtKind, List, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
use crate::ty::error::{ExpectedFound, TypeError};
use crate::ty::fold::{TypeFolder, TypeFoldable, TypeVisitor};
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct VtableImplData<'tcx, N> {
pub impl_def_id: DefId,
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
pub nested: Vec<N>
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct VtableTraitAliasData<'tcx, N> {
pub alias_def_id: DefId,
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
pub nested: Vec<N>,
}
}
fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- key: (DefId, &'tcx Substs<'tcx>))
+ key: (DefId, SubstsRef<'tcx>))
-> bool
{
debug!("substitute_normalize_and_test_predicates(key={:?})",
fn vtable_methods<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>)
- -> Lrc<Vec<Option<(DefId, &'tcx Substs<'tcx>)>>>
+ -> Lrc<Vec<Option<(DefId, SubstsRef<'tcx>)>>>
{
debug!("vtable_methods({:?})", trait_ref);
let trait_methods = tcx.associated_items(trait_ref.def_id())
.filter(|item| item.kind == ty::AssociatedKind::Method);
- // Now list each method's DefId and Substs (for within its trait).
+ // Now list each method's DefId and InternalSubsts (for within its trait).
// If the method can never be called from this object, produce None.
trait_methods.map(move |trait_method| {
debug!("vtable_methods: trait_method={:?}", trait_method);
// the method may have some early-bound lifetimes, add
// regions for those
let substs = trait_ref.map_bound(|trait_ref|
- Substs::for_item(tcx, def_id, |param, _|
+ InternalSubsts::for_item(tcx, def_id, |param, _|
match param.kind {
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
GenericParamDefKind::Type {..} => {
use crate::lint;
use crate::traits::{self, Obligation, ObligationCause};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable, Predicate, ToPredicate};
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, InternalSubsts};
use std::borrow::Cow;
use std::iter::{self};
use syntax::ast::{self, Name};
self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
) -> Ty<'tcx> {
debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
- let substs = Substs::for_item(self, method_def_id, |param, _| {
+ let substs = InternalSubsts::for_item(self, method_def_id, |param, _| {
if param.index == 0 {
self_ty.into()
} else {
// U: Trait<Arg1, ..., ArgN>
let trait_predicate = {
- let substs = Substs::for_item(self, method.container.assert_trait(), |param, _| {
- if param.index == 0 {
- unsized_self_ty.into()
- } else {
- self.mk_param_from_def(param)
- }
- });
+ let substs = InternalSubsts::for_item(
+ self,
+ method.container.assert_trait(),
+ |param, _| {
+ if param.index == 0 {
+ unsized_self_ty.into()
+ } else {
+ self.mk_param_from_def(param)
+ }
+ },
+ );
ty::TraitRef {
def_id: unsize_did,
use crate::mir::interpret::{GlobalId};
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
use syntax::ast::Ident;
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, InternalSubsts};
use crate::ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
use crate::ty::fold::{TypeFoldable, TypeFolder};
use crate::util::common::FN_OUTPUT_NAME;
let tcx = self.selcx.tcx().global_tcx();
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
if substs.needs_infer() || substs.has_placeholders() {
- let identity_substs = Substs::identity_for_item(tcx, def_id);
+ let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
if let Some(instance) = instance {
let cid = GlobalId {
}
let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
let ty = if let ty::AssociatedKind::Existential = assoc_ty.item.kind {
- let item_substs = Substs::identity_for_item(tcx, assoc_ty.item.def_id);
+ let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
} else {
tcx.type_of(assoc_ty.item.def_id)
use crate::traits::project::Normalized;
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use crate::ty::fold::{TypeFoldable, TypeFolder};
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, InternalSubsts};
use crate::ty::{self, Ty, TyCtxt};
use super::NoSolution;
let tcx = self.infcx.tcx.global_tcx();
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
if substs.needs_infer() || substs.has_placeholders() {
- let identity_substs = Substs::identity_for_item(tcx, def_id);
+ let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
if let Some(instance) = instance {
let cid = GlobalId {
use crate::mir::interpret::GlobalId;
use crate::ty::fast_reject;
use crate::ty::relate::TypeRelation;
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
use crate::hir;
if let ty::FnSig {
unsafety: hir::Unsafety::Normal,
abi: Abi::Rust,
- variadic: false,
+ c_variadic: false,
..
} = self_ty.fn_sig(self.tcx()).skip_binder()
{
fn vtable_impl(
&mut self,
impl_def_id: DefId,
- mut substs: Normalized<'tcx, &'tcx Substs<'tcx>>,
+ mut substs: Normalized<'tcx, SubstsRef<'tcx>>,
cause: ObligationCause<'tcx>,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
snapshot: &CombinedSnapshot<'_, 'tcx>,
- ) -> Normalized<'tcx, &'tcx Substs<'tcx>> {
+ ) -> Normalized<'tcx, SubstsRef<'tcx>> {
match self.match_impl(impl_def_id, obligation, snapshot) {
Ok(substs) => substs,
Err(()) => {
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
snapshot: &CombinedSnapshot<'_, 'tcx>,
- ) -> Result<Normalized<'tcx, &'tcx Substs<'tcx>>, ()> {
+ ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
// Before we create the substitutions and everything, first
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId, // of impl or trait
- substs: &Substs<'tcx>, // for impl or trait
+ substs: SubstsRef<'tcx>, // for impl or trait
) -> Vec<PredicateObligation<'tcx>> {
debug!("impl_or_trait_obligations(def_id={:?})", def_id);
let tcx = self.tcx();
use syntax_pos::DUMMY_SP;
use crate::traits::select::IntercrateAmbiguityCause;
use crate::ty::{self, TyCtxt, TypeFoldable};
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, InternalSubsts, SubstsRef};
use super::{SelectionContext, FulfillmentContext};
use super::util::impl_trait_ref_and_oblig;
pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
source_impl: DefId,
- source_substs: &'tcx Substs<'tcx>,
+ source_substs: SubstsRef<'tcx>,
target_node: specialization_graph::Node)
- -> &'tcx Substs<'tcx> {
+ -> SubstsRef<'tcx> {
debug!("translate_substs({:?}, {:?}, {:?}, {:?})",
param_env, source_impl, source_substs, target_node);
let source_trait_ref = infcx.tcx
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
item: &ty::AssociatedItem,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
impl_data: &super::VtableImplData<'tcx, ()>,
-) -> (DefId, &'tcx Substs<'tcx>) {
+) -> (DefId, SubstsRef<'tcx>) {
debug!("find_associated_item({:?}, {:?}, {:?}, {:?})",
param_env, item, substs, impl_data);
assert!(!substs.needs_infer());
param_env: ty::ParamEnv<'tcx>,
source_trait_ref: ty::TraitRef<'tcx>,
target_impl: DefId)
- -> Result<&'tcx Substs<'tcx>, ()> {
+ -> Result<SubstsRef<'tcx>, ()> {
debug!("fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
param_env, source_trait_ref, target_impl);
FutureCompatOverlapErrorKind::Issue33140 =>
lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
};
- tcx.struct_span_lint_node(
+ tcx.struct_span_lint_hir(
lint,
- tcx.hir().as_local_node_id(impl_def_id).unwrap(),
+ tcx.hir().as_local_hir_id(impl_def_id).unwrap(),
impl_span,
&msg)
} else {
let mut w = "impl".to_owned();
- let substs = Substs::identity_for_item(tcx, impl_def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, impl_def_id);
// FIXME: Currently only handles ?Sized.
// Needs to support ?Move and ?DynSized when they are implemented.
use crate::traits::specialize::specialization_graph::NodeItem;
use crate::ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
use crate::ty::outlives::Component;
-use crate::ty::subst::{Kind, Subst, Substs};
+use crate::ty::subst::{Kind, Subst, SubstsRef};
use crate::util::nodemap::FxHashSet;
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
pub fn impl_trait_ref_and_oblig<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
impl_def_id: DefId,
- impl_substs: &Substs<'tcx>)
+ impl_substs: SubstsRef<'tcx>,)
-> (ty::TraitRef<'tcx>,
Vec<PredicateObligation<'tcx>>)
{
use crate::hir;
use crate::hir::def_id::DefId;
use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
/// Represents coercing a value to a different type of value.
impl<'a, 'gcx, 'tcx> OverloadedDeref<'tcx> {
pub fn method_call(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, source: Ty<'tcx>)
- -> (DefId, &'tcx Substs<'tcx>) {
+ -> (DefId, SubstsRef<'tcx>) {
let trait_def_id = match self.mutbl {
hir::MutImmutable => tcx.lang_items().deref_trait(),
hir::MutMutable => tcx.lang_items().deref_mut_trait()
use std::hash::Hash;
use std::intrinsics;
use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
use crate::mir::interpret::Allocation;
/// The shorthand encoding uses an enum's variant index `usize`
}
#[inline]
-pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error>
+pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<SubstsRef<'tcx>, D::Error>
where D: TyDecoder<'a, 'tcx>,
'tcx: 'a,
{
use $crate::infer::canonical::CanonicalVarInfos;
use $crate::ty;
use $crate::ty::codec::*;
- use $crate::ty::subst::Substs;
+ use $crate::ty::subst::SubstsRef;
use $crate::hir::def_id::{CrateNum};
use crate::rustc_serialize::{Decoder, SpecializedDecoder};
use std::borrow::Cow;
}
}
- impl<$($typaram),*> SpecializedDecoder<&'tcx Substs<'tcx>>
+ impl<$($typaram),*> SpecializedDecoder<SubstsRef<'tcx>>
for $DecoderName<$($typaram),*> {
- fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
+ fn specialized_decode(&mut self) -> Result<SubstsRef<'tcx>, Self::Error> {
decode_substs(self)
}
}
use crate::middle::stability;
use crate::mir::{self, Mir, interpret, ProjectionKind};
use crate::mir::interpret::Allocation;
-use crate::ty::subst::{Kind, Substs, Subst};
+use crate::ty::subst::{Kind, InternalSubsts, Subst, SubstsRef};
use crate::ty::ReprOptions;
use crate::traits;
use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals};
StableVec};
use arena::{TypedArena, SyncDroplessArena};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use rustc_data_structures::sync::{self, Lrc, Lock, WorkerLocal};
+use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal};
use std::any::Any;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::sync::Arc;
use std::marker::PhantomData;
use rustc_target::spec::abi;
-use syntax::ast::{self, NodeId};
+use syntax::ast;
use syntax::attr;
use syntax::source_map::MultiSpan;
use syntax::edition::Edition;
/// they're accessed quite often.
type_: InternedSet<'tcx, TyS<'tcx>>,
type_list: InternedSet<'tcx, List<Ty<'tcx>>>,
- substs: InternedSet<'tcx, Substs<'tcx>>,
+ substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo>>,
region: InternedSet<'tcx, RegionKind>,
existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
/// Generic parameters on the opaque type as passed by this function.
/// For `existential type Foo<A, B>; fn foo<T, U>() -> Foo<T, U> { .. }` this is `[T, U]`, not
/// `[A, B]`
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
}
#[derive(RustcEncodable, RustcDecodable, Debug)]
/// of this node. This only applies to nodes that refer to entities
/// parameterized by type parameters, such as generic fns, types, or
/// other items.
- node_substs: ItemLocalMap<&'tcx Substs<'tcx>>,
+ node_substs: ItemLocalMap<SubstsRef<'tcx>>,
/// This will either store the canonicalized types provided by the user
/// or the substitutions that the user explicitly gave (if any) attached
self.node_types.get(&id.local_id).cloned()
}
- pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, &'tcx Substs<'tcx>> {
+ pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
LocalTableInContextMut {
local_id_root: self.local_id_root,
data: &mut self.node_substs
}
}
- pub fn node_substs(&self, id: hir::HirId) -> &'tcx Substs<'tcx> {
+ pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
validate_hir_id_for_typeck_tables(self.local_id_root, id, false);
- self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| Substs::empty())
+ self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
}
- pub fn node_substs_opt(&self, id: hir::HirId) -> Option<&'tcx Substs<'tcx>> {
+ pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
validate_hir_id_for_typeck_tables(self.local_id_root, id, false);
self.node_substs.get(&id.local_id).cloned()
}
let gcx = arenas.global_ctxt.as_ref().unwrap();
- sync::assert_send_val(&gcx);
-
let r = tls::enter_global(gcx, f);
gcx.queries.record_computed_queries(s);
/// A trait implemented for all X<'a> types which can be safely and
/// efficiently converted to X<'tcx> as long as they are part of the
/// provided TyCtxt<'tcx>.
-/// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx>
+/// This can be done, for example, for Ty<'tcx> or SubstsRef<'tcx>
/// by looking them up in their respective interners.
///
/// However, this is still not the best implementation as it does
nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo}
nop_list_lift!{ProjectionKind<'a> => ProjectionKind<'tcx>}
-// this is the impl for `&'a Substs<'a>`
+// this is the impl for `&'a InternalSubsts<'a>`
nop_list_lift!{Kind<'a> => Kind<'tcx>}
impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation {
Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound,
Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign);
- println!("Substs interner: #{}", self.interners.substs.borrow().len());
+ println!("InternalSubsts interner: #{}", self.interners.substs.borrow().len());
println!("Region interner: #{}", self.interners.region.borrow().len());
println!("Stability interner: #{}", self.stability_interner.borrow().len());
println!("Allocation interner: #{}", self.allocation_interner.borrow().len());
}
}
-impl<'tcx: 'lcx, 'lcx> Borrow<[Kind<'lcx>]> for Interned<'tcx, Substs<'tcx>> {
+impl<'tcx: 'lcx, 'lcx> Borrow<[Kind<'lcx>]> for Interned<'tcx, InternalSubsts<'tcx>> {
fn borrow<'a>(&'a self) -> &'a [Kind<'lcx>] {
&self.0[..]
}
self.mk_fn_sig(
params_iter,
s.output(),
- s.variadic,
+ s.c_variadic,
hir::Unsafety::Normal,
abi::Abi::Rust,
)
}
#[inline]
- pub fn mk_adt(self, def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+ pub fn mk_adt(self, def: &'tcx AdtDef, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
// take a copy of substs so that we own the vectors inside
self.mk_ty(Adt(def, substs))
}
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
let adt_def = self.adt_def(def_id);
- let substs = Substs::for_item(self, def_id, |param, substs| {
+ let substs = InternalSubsts::for_item(self, def_id, |param, substs| {
match param.kind {
GenericParamDefKind::Lifetime => bug!(),
GenericParamDefKind::Type { has_default, .. } => {
#[inline]
pub fn mk_fn_def(self, def_id: DefId,
- substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+ substs: SubstsRef<'tcx>) -> Ty<'tcx> {
self.mk_ty(FnDef(def_id, substs))
}
#[inline]
pub fn mk_projection(self,
item_def_id: DefId,
- substs: &'tcx Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> Ty<'tcx> {
self.mk_ty(Projection(ProjectionTy {
item_def_id,
}
#[inline]
- pub fn mk_opaque(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+ pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
self.mk_ty(Opaque(def_id, substs))
}
pub fn mk_fn_sig<I>(self,
inputs: I,
output: I::Item,
- variadic: bool,
+ c_variadic: bool,
unsafety: hir::Unsafety,
abi: abi::Abi)
-> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output
{
inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig {
inputs_and_output: self.intern_type_list(xs),
- variadic, unsafety, abi
+ c_variadic, unsafety, abi
})
}
pub fn mk_substs_trait(self,
self_ty: Ty<'tcx>,
rest: &[Kind<'tcx>])
- -> &'tcx Substs<'tcx>
+ -> SubstsRef<'tcx>
{
self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned()))
}
self.struct_span_lint_hir(lint, hir_id, span.into(), msg).emit()
}
- pub fn lint_node<S: Into<MultiSpan>>(self,
- lint: &'static Lint,
- id: NodeId,
- span: S,
- msg: &str) {
- self.struct_span_lint_node(lint, id, span.into(), msg).emit()
- }
-
pub fn lint_hir_note<S: Into<MultiSpan>>(self,
lint: &'static Lint,
hir_id: HirId,
err.emit()
}
- pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId)
+ pub fn lint_level_at_node(self, lint: &'static Lint, mut id: hir::HirId)
-> (lint::Level, lint::LintSource)
{
// Right now we insert a `with_ignore` node in the dep graph here to
self.dep_graph.with_ignore(|| {
let sets = self.lint_levels(LOCAL_CRATE);
loop {
- let hir_id = self.hir().definitions().node_to_hir_id(id);
- if let Some(pair) = sets.level_and_source(lint, hir_id, self.sess) {
+ if let Some(pair) = sets.level_and_source(lint, id, self.sess) {
return pair
}
- let next = self.hir().get_parent_node(id);
+ let next = self.hir().get_parent_node_by_hir_id(id);
if next == id {
bug!("lint traversal reached the root of the crate");
}
msg: &str)
-> DiagnosticBuilder<'tcx>
{
- let node_id = self.hir().hir_to_node_id(hir_id);
- let (level, src) = self.lint_level_at_node(lint, node_id);
- lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
- }
-
- pub fn struct_span_lint_node<S: Into<MultiSpan>>(self,
- lint: &'static Lint,
- id: NodeId,
- span: S,
- msg: &str)
- -> DiagnosticBuilder<'tcx>
- {
- let (level, src) = self.lint_level_at_node(lint, id);
+ let (level, src) = self.lint_level_at_node(lint, hir_id);
lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
}
- pub fn struct_lint_node(self, lint: &'static Lint, id: NodeId, msg: &str)
+ pub fn struct_lint_node(self, lint: &'static Lint, id: HirId, msg: &str)
-> DiagnosticBuilder<'tcx>
{
let (level, src) = self.lint_level_at_node(lint, id);
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
use crate::ty::{self, Ty, TypeFlags, TypeFoldable};
#[derive(Debug)]
self.add_substs(projection_ty.substs);
}
- fn add_substs(&mut self, substs: &Substs<'_>) {
+ fn add_substs(&mut self, substs: SubstsRef<'_>) {
for ty in substs.types() {
self.add_ty(ty);
}
use crate::ty::context::TyCtxt;
use crate::ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
-use crate::ty::{self, DefId, Substs};
+use crate::ty::{self, DefId, SubstsRef};
use crate::ty::{AdtKind, Visibility};
use crate::ty::TyKind::*;
pub fn is_enum_variant_uninhabited_from(self,
module: DefId,
variant: &'tcx VariantDef,
- substs: &'tcx Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> bool
{
self.variant_inhabitedness_forest(variant, substs).contains(self, module)
pub fn is_variant_uninhabited_from_all_modules(self,
variant: &'tcx VariantDef,
- substs: &'tcx Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> bool
{
!self.variant_inhabitedness_forest(variant, substs).is_empty()
}
- fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: &'tcx Substs<'tcx>)
+ fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: SubstsRef<'tcx>)
-> DefIdForest {
// Determine the ADT kind:
let adt_def_id = self.adt_def_id_of_variant(variant);
fn uninhabited_from(
&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- substs: &'tcx Substs<'tcx>) -> DefIdForest
+ substs: SubstsRef<'tcx>) -> DefIdForest
{
DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
v.uninhabited_from(tcx, substs, self.adt_kind())
fn uninhabited_from(
&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
adt_kind: AdtKind) -> DefIdForest
{
let is_enum = match adt_kind {
fn uninhabited_from(
&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
is_enum: bool,
) -> DefIdForest {
let data_uninhabitedness = move || {
use crate::hir::Unsafety;
use crate::hir::def_id::DefId;
-use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, Substs, TyCtxt};
+use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt};
use crate::traits;
use rustc_target::spec::abi::Abi;
use crate::util::ppaux;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct Instance<'tcx> {
pub def: InstanceDef<'tcx>,
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
sig.map_bound(|sig| tcx.mk_fn_sig(
iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
sig.output(),
- sig.variadic,
+ sig.c_variadic,
sig.unsafety,
sig.abi
))
}
impl<'a, 'b, 'tcx> Instance<'tcx> {
- pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
+ pub fn new(def_id: DefId, substs: SubstsRef<'tcx>)
-> Instance<'tcx> {
assert!(!substs.has_escaping_bound_vars(),
"substs of instance {:?} not normalized for codegen: {:?}",
pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
- substs: &'tcx Substs<'tcx>) -> Option<Instance<'tcx>> {
+ substs: SubstsRef<'tcx>) -> Option<Instance<'tcx>> {
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
pub fn resolve_for_vtable(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
- substs: &'tcx Substs<'tcx>) -> Option<Instance<'tcx>> {
+ substs: SubstsRef<'tcx>) -> Option<Instance<'tcx>> {
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
let fn_sig = tcx.fn_sig(def_id);
let is_vtable_shim =
trait_item: &ty::AssociatedItem,
param_env: ty::ParamEnv<'tcx>,
trait_id: DefId,
- rcvr_substs: &'tcx Substs<'tcx>,
+ rcvr_substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> {
let def_id = trait_item.def_id;
debug!("resolve_associated_item(trait_item={:?}, \
use crate::traits::{self, Reveal};
use crate::ty;
use crate::ty::layout::VariantIdx;
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, InternalSubsts, SubstsRef};
use crate::ty::util::{IntTypeExt, Discr};
use crate::ty::walk::TypeWalker;
use crate::util::captures::Captures;
impl<'tcx> serialize::UseSpecializedDecodable for GenericPredicates<'tcx> {}
impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
- pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
+ pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: SubstsRef<'tcx>)
-> InstantiatedPredicates<'tcx> {
let mut instantiated = InstantiatedPredicates::empty();
self.instantiate_into(tcx, &mut instantiated, substs);
instantiated
}
- pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
+ pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: SubstsRef<'tcx>)
-> InstantiatedPredicates<'tcx> {
InstantiatedPredicates {
predicates: self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)).collect(),
fn instantiate_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
instantiated: &mut InstantiatedPredicates<'tcx>,
- substs: &Substs<'tcx>) {
+ substs: SubstsRef<'tcx>) {
if let Some(def_id) = self.parent {
tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs);
}
Subtype(PolySubtypePredicate<'tcx>),
/// Constant initializer must evaluate successfully.
- ConstEvaluatable(DefId, &'tcx Substs<'tcx>),
+ ConstEvaluatable(DefId, SubstsRef<'tcx>),
}
/// The crate outlives map is computed during typeck and contains the
) -> Option<Discr<'tcx>> {
let param_env = ParamEnv::empty();
let repr_type = self.repr.discr_type();
- let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
+ let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), expr_did);
let instance = ty::Instance::new(expr_did, substs);
let cid = GlobalId {
instance,
}
impl<'a, 'gcx, 'tcx> FieldDef {
- pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> {
+ pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
tcx.type_of(self.did).subst(tcx, subst)
}
}
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
};
use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
use crate::ty::query::queries;
use crate::ty::query::Query;
use crate::ty::query::QueryCache;
}
}
+impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
+ fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+ "running analysis passes on this crate".into()
+ }
+}
+
impl<'tcx> QueryDescription<'tcx> for queries::lint_levels<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"computing the lint levels for items in this crate".into()
}
impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> {
- fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, &'tcx Substs<'tcx>)) -> Cow<'static, str> {
+ fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, SubstsRef<'tcx>)) -> Cow<'static, str> {
format!("testing substituted normalized predicates:`{}`", tcx.item_path_str(key.0)).into()
}
}
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
use rustc_data_structures::OnDrop;
+use rustc_data_structures::jobserver;
use syntax_pos::Span;
use crate::ty::tls;
// we have to be in the `wait` call. This is ensured by the deadlock handler
// getting the self.info lock.
rayon_core::mark_blocked();
+ jobserver::release_thread();
waiter.condvar.wait(&mut info);
+ // Release the lock before we potentially block in `acquire_thread`
+ mem::drop(info);
+ jobserver::acquire_thread();
}
}
use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
use crate::traits;
use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
use crate::ty::fast_reject::SimplifiedType;
use crate::mir;
}
}
-impl<'tcx> Key for (DefId, &'tcx Substs<'tcx>) {
+impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
fn query_crate(&self) -> CrateNum {
self.0.krate
}
use crate::mir::mono::CodegenUnit;
use crate::mir;
use crate::mir::interpret::GlobalId;
-use crate::session::{CompileResult, CrateDisambiguator};
+use crate::session::CrateDisambiguator;
use crate::session::config::{EntryFnType, OutputFilenames, OptLevel};
use crate::traits::{self, Vtable};
use crate::traits::query::{
use crate::traits::Clauses;
use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, AdtSizedConstraint};
use crate::ty::steal::Steal;
-use crate::ty::subst::Substs;
use crate::ty::util::NeedsDrop;
+use crate::ty::subst::SubstsRef;
use crate::util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
use crate::util::common::{ErrorReported};
use crate::util::profiling::ProfileCategory::*;
// as they will raise an fatal error on query cycles instead.
define_queries! { <'tcx>
Other {
+ /// Run analysis passes on the crate
+ [] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
+
/// Records the type of every item.
[] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,
},
TypeChecking {
- [] fn typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult,
+ [] fn typeck_item_bodies:
+ typeck_item_bodies_dep_node(CrateNum) -> Result<(), ErrorReported>,
[] fn typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
},
Other {
[] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>)
- -> Lrc<Vec<Option<(DefId, &'tcx Substs<'tcx>)>>>,
+ -> Lrc<Vec<Option<(DefId, SubstsRef<'tcx>)>>>,
},
Codegen {
Codegen {
[] fn upstream_monomorphizations: UpstreamMonomorphizations(CrateNum)
- -> Lrc<DefIdMap<Lrc<FxHashMap<&'tcx Substs<'tcx>, CrateNum>>>>,
+ -> Lrc<DefIdMap<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>>,
[] fn upstream_monomorphizations_for: UpstreamMonomorphizationsFor(DefId)
- -> Option<Lrc<FxHashMap<&'tcx Substs<'tcx>, CrateNum>>>,
+ -> Option<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>,
},
Other {
>,
[] fn substitute_normalize_and_test_predicates:
- substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
+ substitute_normalize_and_test_predicates_node((DefId, SubstsRef<'tcx>)) -> bool,
[] fn method_autoderef_steps: MethodAutoderefSteps(
CanonicalTyGoal<'tcx>
DepConstructor::VtableMethods{ trait_ref }
}
-fn substitute_normalize_and_test_predicates_node<'tcx>(key: (DefId, &'tcx Substs<'tcx>))
+fn substitute_normalize_and_test_predicates_node<'tcx>(key: (DefId, SubstsRef<'tcx>))
-> DepConstructor<'tcx> {
DepConstructor::SubstituteNormalizeAndTestPredicates { key }
}
DepKind::CrateHash => { force!(crate_hash, krate!()); }
DepKind::OriginalCrateName => { force!(original_crate_name, krate!()); }
DepKind::ExtraFileName => { force!(extra_filename, krate!()); }
+ DepKind::Analysis => { force!(analysis, krate!()); }
DepKind::AllTraitImplementations => {
force!(all_trait_implementations, krate!());
//! subtyping, type equality, etc.
use crate::hir::def_id::DefId;
-use crate::ty::subst::{Kind, UnpackedKind, Substs};
+use crate::ty::subst::{Kind, UnpackedKind, SubstsRef};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use crate::ty::error::{ExpectedFound, TypeError};
use crate::mir::interpret::GlobalId;
/// accordingly.
fn relate_item_substs(&mut self,
item_def_id: DefId,
- a_subst: &'tcx Substs<'tcx>,
- b_subst: &'tcx Substs<'tcx>)
- -> RelateResult<'tcx, &'tcx Substs<'tcx>>
+ a_subst: SubstsRef<'tcx>,
+ b_subst: SubstsRef<'tcx>)
+ -> RelateResult<'tcx, SubstsRef<'tcx>>
{
debug!("relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})",
item_def_id,
pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
variances: Option<&Vec<ty::Variance>>,
- a_subst: &'tcx Substs<'tcx>,
- b_subst: &'tcx Substs<'tcx>)
- -> RelateResult<'tcx, &'tcx Substs<'tcx>>
+ a_subst: SubstsRef<'tcx>,
+ b_subst: SubstsRef<'tcx>)
+ -> RelateResult<'tcx, SubstsRef<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
let tcx = relation.tcx();
{
let tcx = relation.tcx();
- if a.variadic != b.variadic {
+ if a.c_variadic != b.c_variadic {
return Err(TypeError::VariadicMismatch(
- expected_found(relation, &a.variadic, &b.variadic)));
+ expected_found(relation, &a.c_variadic, &b.c_variadic)));
}
let unsafety = relation.relate(&a.unsafety, &b.unsafety)?;
let abi = relation.relate(&a.abi, &b.abi)?;
});
Ok(ty::FnSig {
inputs_and_output: tcx.mk_type_list(inputs_and_output)?,
- variadic: a.variadic,
+ c_variadic: a.c_variadic,
unsafety,
abi,
})
}
}
-impl<'tcx> Relate<'tcx> for &'tcx Substs<'tcx> {
+impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> {
fn relate<'a, 'gcx, R>(relation: &mut R,
- a: &&'tcx Substs<'tcx>,
- b: &&'tcx Substs<'tcx>)
- -> RelateResult<'tcx, &'tcx Substs<'tcx>>
+ a: &SubstsRef<'tcx>,
+ b: &SubstsRef<'tcx>)
+ -> RelateResult<'tcx, SubstsRef<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
relate_substs(relation, None, a, b)
tcx.lift(&self.inputs_and_output).map(|x| {
ty::FnSig {
inputs_and_output: x,
- variadic: self.variadic,
+ c_variadic: self.c_variadic,
unsafety: self.unsafety,
abi: self.abi,
}
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> {
- inputs_and_output, variadic, unsafety, abi
+ inputs_and_output, c_variadic, unsafety, abi
}
}
use crate::middle::region;
use polonius_engine::Atom;
use rustc_data_structures::indexed_vec::Idx;
-use crate::ty::subst::{Substs, Subst, Kind, UnpackedKind};
+use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, Kind, UnpackedKind};
use crate::ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
use crate::util::captures::Captures;
/// Structures, enumerations and unions.
///
- /// Substs here, possibly against intuition, *may* contain `Param`s.
+ /// InternalSubsts here, possibly against intuition, *may* contain `Param`s.
/// That is, even after substitution it is possible that there are type
/// variables. This happens when the `Adt` corresponds to an ADT
/// definition and not a concrete use of it.
- Adt(&'tcx AdtDef, &'tcx Substs<'tcx>),
+ Adt(&'tcx AdtDef, SubstsRef<'tcx>),
/// An unsized FFI type that is opaque to Rust. Written as `extern type T`.
Foreign(DefId),
/// fn foo() -> i32 { 1 }
/// let bar = foo; // bar: fn() -> i32 {foo}
/// ```
- FnDef(DefId, &'tcx Substs<'tcx>),
+ FnDef(DefId, SubstsRef<'tcx>),
/// A pointer to a function. Written as `fn() -> i32`.
///
/// * or the `existential type` declaration
/// The substitutions are for the generics of the function in question.
/// After typeck, the concrete type can be found in the `types` map.
- Opaque(DefId, &'tcx Substs<'tcx>),
+ Opaque(DefId, SubstsRef<'tcx>),
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}
Param(ParamTy),
///
/// These are separated out because codegen wants to pass them around
/// when monomorphizing.
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
}
/// Struct returned by `split()`. Note that these are subslices of the
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct GeneratorSubsts<'tcx> {
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
}
struct SplitGeneratorSubsts<'tcx> {
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct TraitRef<'tcx> {
pub def_id: DefId,
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
}
impl<'tcx> TraitRef<'tcx> {
- pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
+ pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
TraitRef { def_id: def_id, substs: substs }
}
pub fn identity<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> TraitRef<'tcx> {
TraitRef {
def_id,
- substs: Substs::identity_for_item(tcx, def_id),
+ substs: InternalSubsts::identity_for_item(tcx, def_id),
}
}
pub fn from_method(tcx: TyCtxt<'_, '_, 'tcx>,
trait_id: DefId,
- substs: &Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> ty::TraitRef<'tcx> {
let defs = tcx.generics_of(trait_id);
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct ExistentialTraitRef<'tcx> {
pub def_id: DefId,
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
}
impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> {
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct ProjectionTy<'tcx> {
/// The parameters of the associated item.
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
/// The `DefId` of the `TraitItem` for the associated type `N`.
///
/// Signature of a function type, which I have arbitrarily
/// decided to use to refer to the input/output types.
///
-/// - `inputs` is the list of arguments and their modes.
-/// - `output` is the return type.
-/// - `variadic` indicates whether this is a variadic function. (only true for foreign fns)
+/// - `inputs`: is the list of arguments and their modes.
+/// - `output`: is the return type.
+/// - `c_variadic`: indicates whether this is a C-variadic function.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct FnSig<'tcx> {
pub inputs_and_output: &'tcx List<Ty<'tcx>>,
- pub variadic: bool,
+ pub c_variadic: bool,
pub unsafety: hir::Unsafety,
pub abi: abi::Abi,
}
pub fn output(&self) -> ty::Binder<Ty<'tcx>> {
self.map_bound_ref(|fn_sig| fn_sig.output())
}
- pub fn variadic(&self) -> bool {
- self.skip_binder().variadic
+ pub fn c_variadic(&self) -> bool {
+ self.skip_binder().c_variadic
}
pub fn unsafety(&self) -> hir::Unsafety {
self.skip_binder().unsafety
/// These are regions that are stored behind a binder and must be substituted
/// with some concrete region before being used. There are two kind of
/// bound regions: early-bound, which are bound in an item's `Generics`,
-/// and are substituted by a `Substs`, and late-bound, which are part of
+/// and are substituted by a `InternalSubsts`, and late-bound, which are part of
/// higher-ranked types (e.g., `for<'a> fn(&'a ())`), and are substituted by
/// the likes of `liberate_late_bound_regions`. The distinction exists
/// because higher-ranked lifetimes aren't supported in all places. See [1][2].
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct ExistentialProjection<'tcx> {
pub item_def_id: DefId,
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
pub ty: Ty<'tcx>,
}
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to `Evaluated` if the
/// code is monomorphic enough for that.
pub enum LazyConst<'tcx> {
- Unevaluated(DefId, &'tcx Substs<'tcx>),
+ Unevaluated(DefId, SubstsRef<'tcx>),
Evaluated(Const<'tcx>),
}
}
/// A substitution mapping generic parameters to new values.
-pub type Substs<'tcx> = List<Kind<'tcx>>;
+pub type InternalSubsts<'tcx> = List<Kind<'tcx>>;
-impl<'a, 'gcx, 'tcx> Substs<'tcx> {
- /// Creates a `Substs` that maps each generic parameter to itself.
+pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
+
+impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
+ /// Creates a `InternalSubsts` that maps each generic parameter to itself.
pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
- -> &'tcx Substs<'tcx> {
- Substs::for_item(tcx, def_id, |param, _| {
+ -> SubstsRef<'tcx> {
+ Self::for_item(tcx, def_id, |param, _| {
tcx.mk_param_from_def(param)
})
}
- /// Creates a `Substs` that maps each generic parameter to a higher-ranked
+ /// Creates a `InternalSubsts` that maps each generic parameter to a higher-ranked
/// var bound at index `0`. For types, we use a `BoundVar` index equal to
/// the type parameter index. For regions, we use the `BoundRegion::BrNamed`
/// variant (which has a `DefId`).
pub fn bound_vars_for_item(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId
- ) -> &'tcx Substs<'tcx> {
- Substs::for_item(tcx, def_id, |param, _| {
+ ) -> SubstsRef<'tcx> {
+ Self::for_item(tcx, def_id, |param, _| {
match param.kind {
ty::GenericParamDefKind::Type { .. } => {
tcx.mk_ty(
})
}
- /// Creates a `Substs` for generic parameter definitions,
+ /// Creates a `InternalSubsts` for generic parameter definitions,
/// by calling closures to obtain each kind.
- /// The closures get to observe the `Substs` as they're
+ /// The closures get to observe the `InternalSubsts` as they're
/// being built, which can be used to correctly
/// substitute defaults of generic parameters.
pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
mut mk_kind: F)
- -> &'tcx Substs<'tcx>
+ -> SubstsRef<'tcx>
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
{
let defs = tcx.generics_of(def_id);
let count = defs.count();
let mut substs = SmallVec::with_capacity(count);
- Substs::fill_item(&mut substs, tcx, defs, &mut mk_kind);
+ Self::fill_item(&mut substs, tcx, defs, &mut mk_kind);
tcx.intern_substs(&substs)
}
tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
mut mk_kind: F)
- -> &'tcx Substs<'tcx>
+ -> SubstsRef<'tcx>
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
{
- Substs::for_item(tcx, def_id, |param, substs| {
+ Self::for_item(tcx, def_id, |param, substs| {
self.get(param.index as usize)
.cloned()
.unwrap_or_else(|| mk_kind(param, substs))
{
if let Some(def_id) = defs.parent {
let parent_defs = tcx.generics_of(def_id);
- Substs::fill_item(substs, tcx, parent_defs, mk_kind);
+ Self::fill_item(substs, tcx, parent_defs, mk_kind);
}
- Substs::fill_single(substs, defs, mk_kind)
+ Self::fill_single(substs, defs, mk_kind)
}
fn fill_single<F>(substs: &mut SmallVec<[Kind<'tcx>; 8]>,
/// parameters (e.g., method parameters) on top of that base.
pub fn rebase_onto(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
source_ancestor: DefId,
- target_substs: &Substs<'tcx>)
- -> &'tcx Substs<'tcx> {
+ target_substs: SubstsRef<'tcx>)
+ -> SubstsRef<'tcx> {
let defs = tcx.generics_of(source_ancestor);
tcx.mk_substs(target_substs.iter().chain(&self[defs.params.len()..]).cloned())
}
pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics)
- -> &'tcx Substs<'tcx> {
+ -> SubstsRef<'tcx> {
tcx.mk_substs(self.iter().take(generics.count()).cloned())
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect();
}
}
-impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {}
+impl<'tcx> serialize::UseSpecializedDecodable for SubstsRef<'tcx> {}
///////////////////////////////////////////////////////////////////////////
// Public trait `Subst`
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct UserSubsts<'tcx> {
/// The substitutions for the item as given by the user.
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
/// The self type, in the case of a `<T>::Item` path (when applied
/// to an inherent impl). See `UserSelfTy` below.
use crate::hir::def_id::DefId;
use crate::hir::map::DefPathData;
use crate::hir::{self, Node};
+use crate::mir::interpret::{sign_extend, truncate};
use crate::ich::NodeIdHashingMode;
use crate::traits::{self, ObligationCause};
use crate::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
-use crate::ty::subst::{Subst, Substs, UnpackedKind};
+use crate::ty::subst::{Subst, InternalSubsts, SubstsRef, UnpackedKind};
use crate::ty::query::TyCtxtAt;
use crate::ty::TyKind::*;
use crate::ty::layout::{Integer, IntegerExt};
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.ty.sty {
ty::Int(ity) => {
- let bits = ty::tls::with(|tcx| {
- Integer::from_attr(&tcx, SignedInt(ity)).size().bits()
+ let size = ty::tls::with(|tcx| {
+ Integer::from_attr(&tcx, SignedInt(ity)).size()
});
- let x = self.val as i128;
+ let x = self.val;
// sign extend the raw representation to be an i128
- let x = (x << (128 - bits)) >> (128 - bits);
+ let x = sign_extend(x, size) as i128;
write!(fmt, "{}", x)
},
_ => write!(fmt, "{}", self.val),
_ => bug!("non integer discriminant"),
};
+ let size = int.size();
let bit_size = int.size().bits();
let shift = 128 - bit_size;
if signed {
let sext = |u| {
- let i = u as i128;
- (i << shift) >> shift
+ sign_extend(u, size) as i128
};
let min = sext(1_u128 << (bit_size - 1));
let max = i128::max_value() >> shift;
};
// zero the upper bits
let val = val as u128;
- let val = (val << shift) >> shift;
+ let val = truncate(val, size);
(Self {
val: val as u128,
ty: self.ty,
/// Given the `DefId` of some item that has no type parameters, make
/// a suitable "empty substs" for it.
- pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
- Substs::for_item(self, item_def_id, |param, _| {
+ pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> SubstsRef<'tcx> {
+ InternalSubsts::for_item(self, item_def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => self.types.re_erased.into(),
GenericParamDefKind::Type {..} => {
pub fn try_expand_impl_trait_type(
self,
def_id: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
) -> Result<Ty<'tcx>, Ty<'tcx>> {
use crate::ty::fold::TypeFolder;
fn expand_opaque_ty(
&mut self,
def_id: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
) -> Option<Ty<'tcx>> {
if self.found_recursion {
None
(p.substs, Some(p.ty)),
ty::ExistentialPredicate::AutoTrait(_) =>
// Empty iterator
- (ty::Substs::empty(), None),
+ (ty::InternalSubsts::empty(), None),
};
substs.types().rev().chain(opt_ty)
use crate::hir;
use crate::hir::def_id::DefId;
use crate::infer::InferCtxt;
-use crate::ty::subst::Substs;
+use crate::ty::subst::SubstsRef;
use crate::traits;
use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use std::iter::once;
fn nominal_obligations(&mut self,
def_id: DefId,
- substs: &Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> Vec<traits::PredicateObligation<'tcx>>
{
let predicates =
use crate::hir::def_id::DefId;
use crate::hir::map::definitions::DefPathData;
use crate::middle::region;
-use crate::ty::subst::{self, Subst};
+use crate::ty::subst::{self, Subst, SubstsRef};
use crate::ty::{BrAnon, BrEnv, BrFresh, BrNamed};
use crate::ty::{Bool, Char, Adt};
use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
fn fn_sig<F: fmt::Write>(&mut self,
f: &mut F,
inputs: &[Ty<'_>],
- variadic: bool,
+ c_variadic: bool,
output: Ty<'_>)
-> fmt::Result {
write!(f, "(")?;
for &ty in inputs {
print!(f, self, write(", "), print_display(ty))?;
}
- if variadic {
+ if c_variadic {
write!(f, ", ...")?;
}
}
fn parameterized<F: fmt::Write>(&mut self,
f: &mut F,
- substs: &subst::Substs<'_>,
+ substs: SubstsRef<'_>,
did: DefId,
projections: &[ty::ProjectionPredicate<'_>])
-> fmt::Result {
}
pub fn parameterized<F: fmt::Write>(f: &mut F,
- substs: &subst::Substs<'_>,
+ substs: SubstsRef<'_>,
did: DefId,
projections: &[ty::ProjectionPredicate<'_>])
-> fmt::Result {
}
write!(f, "fn")?;
- cx.fn_sig(f, self.inputs(), self.variadic, self.output())
+ cx.fn_sig(f, self.inputs(), self.c_variadic, self.output())
}
debug {
- write!(f, "({:?}; variadic: {})->{:?}", self.inputs(), self.variadic, self.output())
+ write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output())
}
}
}
Ok(())
}
}
- Foreign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]),
+ Foreign(def_id) => parameterized(f, subst::InternalSubsts::empty(), def_id, &[]),
Projection(ref data) => data.print(f, cx),
UnnormalizedProjection(ref data) => {
write!(f, "Unnormalized(")?;
val
};
match self.mode {
- PassMode::Ignore => {},
+ PassMode::Ignore(_) => {}
PassMode::Pair(..) => {
OperandValue::Pair(next(), next()).store(bx, dst);
}
let mut inputs = sig.inputs();
let extra_args = if sig.abi == RustCall {
- assert!(!sig.variadic && extra_args.is_empty());
+ assert!(!sig.c_variadic && extra_args.is_empty());
match sig.inputs().last().unwrap().sty {
ty::Tuple(ref tupled_arguments) => {
}
}
} else {
- assert!(sig.variadic || extra_args.is_empty());
+ assert!(sig.c_variadic || extra_args.is_empty());
extra_args
};
}
};
+ // Store the index of the last argument. This is useful for working with
+ // C-compatible variadic arguments.
+ let last_arg_idx = if sig.inputs().is_empty() {
+ None
+ } else {
+ Some(sig.inputs().len() - 1)
+ };
+
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| {
let is_return = arg_idx.is_none();
let mut arg = mk_arg_type(ty, arg_idx);
// The same is true for s390x-unknown-linux-gnu
// and sparc64-unknown-linux-gnu.
if is_return || rust_abi || (!win_x64_gnu && !linux_s390x && !linux_sparc64) {
- arg.mode = PassMode::Ignore;
+ arg.mode = PassMode::Ignore(IgnoreMode::Zst);
+ }
+ }
+
+ // If this is a C-variadic function, this is not the return value,
+ // and there is one or more fixed arguments; ensure that the `VaList`
+ // is ignored as an argument.
+ if sig.c_variadic {
+ match (last_arg_idx, arg_idx) {
+ (Some(last_idx), Some(cur_idx)) if last_idx == cur_idx => {
+ let va_list_did = match cx.tcx.lang_items().va_list() {
+ Some(did) => did,
+ None => bug!("`va_list` lang item required for C-variadic functions"),
+ };
+ match ty.sty {
+ ty::Adt(def, _) if def.did == va_list_did => {
+ // This is the "spoofed" `VaList`. Set the arguments mode
+ // so that it will be ignored.
+ arg.mode = PassMode::Ignore(IgnoreMode::CVarArgs);
+ },
+ _ => (),
+ }
+ }
+ _ => {}
}
}
args: inputs.iter().chain(extra_args).enumerate().map(|(i, ty)| {
arg_of(ty, Some(i))
}).collect(),
- variadic: sig.variadic,
+ c_variadic: sig.c_variadic,
conv,
};
fn_ty.adjust_for_abi(cx, sig.abi);
);
let llreturn_ty = match self.ret.mode {
- PassMode::Ignore => cx.type_void(),
+ PassMode::Ignore(IgnoreMode::Zst) => cx.type_void(),
+ PassMode::Ignore(IgnoreMode::CVarArgs) =>
+ bug!("`va_list` should never be a return type"),
PassMode::Direct(_) | PassMode::Pair(..) => {
self.ret.layout.immediate_llvm_type(cx)
}
}
let llarg_ty = match arg.mode {
- PassMode::Ignore => continue,
+ PassMode::Ignore(_) => continue,
PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx),
PassMode::Pair(..) => {
llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0, true));
llargument_tys.push(llarg_ty);
}
- if self.variadic {
+ if self.c_variadic {
cx.type_variadic_func(&llargument_tys, llreturn_ty)
} else {
cx.type_func(&llargument_tys, llreturn_ty)
apply(&ArgAttributes::new());
}
match arg.mode {
- PassMode::Ignore => {}
+ PassMode::Ignore(_) => {}
PassMode::Direct(ref attrs) |
PassMode::Indirect(ref attrs, None) => apply(attrs),
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
apply(&ArgAttributes::new());
}
match arg.mode {
- PassMode::Ignore => {}
+ PassMode::Ignore(_) => {}
PassMode::Direct(ref attrs) |
PassMode::Indirect(ref attrs, None) => apply(attrs),
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
}
if sess.opts.target_triple.triple() == "wasm32-unknown-unknown" {
- wasm::rewrite_imports(&out_filename, &codegen_results.crate_info.wasm_imports);
wasm::add_producer_section(
&out_filename,
&sess.edition().to_string(),
use std::path::Path;
use std::str;
-use rustc_data_structures::fx::FxHashMap;
use serialize::leb128;
// https://webassembly.github.io/spec/core/binary/modules.html#binary-importsec
-const WASM_IMPORT_SECTION_ID: u8 = 2;
const WASM_CUSTOM_SECTION_ID: u8 = 0;
-const WASM_EXTERNAL_KIND_FUNCTION: u8 = 0;
-const WASM_EXTERNAL_KIND_TABLE: u8 = 1;
-const WASM_EXTERNAL_KIND_MEMORY: u8 = 2;
-const WASM_EXTERNAL_KIND_GLOBAL: u8 = 3;
-
-/// Rewrite the module imports are listed from in a wasm module given the field
-/// name to module name mapping in `import_map`.
-///
-/// LLVM 6 which we're using right now doesn't have the ability to configure the
-/// module a wasm symbol is import from. Rather all imported symbols come from
-/// the bland `"env"` module unconditionally. Furthermore we'd *also* need
-/// support in LLD for preserving these import modules, which it unfortunately
-/// currently does not.
-///
-/// This function is intended as a hack for now where we manually rewrite the
-/// wasm output by LLVM to have the correct import modules listed. The
-/// `#[link(wasm_import_module = "...")]` attribute in Rust translates to the
-/// module that each symbol is imported from, so here we manually go through the
-/// wasm file, decode it, rewrite imports, and then rewrite the wasm module.
-///
-/// Support for this was added to LLVM in
-/// https://github.com/llvm-mirror/llvm/commit/0f32e1365, although support still
-/// needs to be added, tracked at https://bugs.llvm.org/show_bug.cgi?id=37168
-pub fn rewrite_imports(path: &Path, import_map: &FxHashMap<String, String>) {
- if import_map.is_empty() {
- return
- }
-
- let wasm = fs::read(path).expect("failed to read wasm output");
- let mut ret = WasmEncoder::new();
- ret.data.extend(&wasm[..8]);
-
- // skip the 8 byte wasm/version header
- for (id, raw) in WasmSections(WasmDecoder::new(&wasm[8..])) {
- ret.byte(id);
- if id == WASM_IMPORT_SECTION_ID {
- info!("rewriting import section");
- let data = rewrite_import_section(
- &mut WasmDecoder::new(raw),
- import_map,
- );
- ret.bytes(&data);
- } else {
- info!("carry forward section {}, {} bytes long", id, raw.len());
- ret.bytes(raw);
- }
- }
-
- fs::write(path, &ret.data).expect("failed to write wasm output");
-
- fn rewrite_import_section(
- wasm: &mut WasmDecoder<'_>,
- import_map: &FxHashMap<String, String>,
- )
- -> Vec<u8>
- {
- let mut dst = WasmEncoder::new();
- let n = wasm.u32();
- dst.u32(n);
- info!("rewriting {} imports", n);
- for _ in 0..n {
- rewrite_import_entry(wasm, &mut dst, import_map);
- }
- return dst.data
- }
-
- fn rewrite_import_entry(wasm: &mut WasmDecoder<'_>,
- dst: &mut WasmEncoder,
- import_map: &FxHashMap<String, String>) {
- // More info about the binary format here is available at:
- // https://webassembly.github.io/spec/core/binary/modules.html#import-section
- //
- // Note that you can also find the whole point of existence of this
- // function here, where we map the `module` name to a different one if
- // we've got one listed.
- let module = wasm.str();
- let field = wasm.str();
- let new_module = if module == "env" {
- import_map.get(field).map(|s| &**s).unwrap_or(module)
- } else {
- module
- };
- info!("import rewrite ({} => {}) / {}", module, new_module, field);
- dst.str(new_module);
- dst.str(field);
- let kind = wasm.byte();
- dst.byte(kind);
- match kind {
- WASM_EXTERNAL_KIND_FUNCTION => dst.u32(wasm.u32()),
- WASM_EXTERNAL_KIND_TABLE => {
- dst.byte(wasm.byte()); // element_type
- dst.limits(wasm.limits());
- }
- WASM_EXTERNAL_KIND_MEMORY => dst.limits(wasm.limits()),
- WASM_EXTERNAL_KIND_GLOBAL => {
- dst.byte(wasm.byte()); // content_type
- dst.bool(wasm.bool()); // mutable
- }
- b => panic!("unknown kind: {}", b),
- }
- }
-}
-
/// Adds or augment the existing `producers` section to encode information about
/// the Rust compiler used to produce the wasm file.
pub fn add_producer_section(
let len = self.u32();
str::from_utf8(self.skip(len as usize)).unwrap()
}
-
- fn bool(&mut self) -> bool {
- self.byte() == 1
- }
-
- fn limits(&mut self) -> (u32, Option<u32>) {
- let has_max = self.bool();
- (self.u32(), if has_max { Some(self.u32()) } else { None })
- }
}
struct WasmEncoder {
fn str(&mut self, val: &str) {
self.bytes(val.as_bytes())
}
-
- fn bool(&mut self, b: bool) {
- self.byte(b as u8);
- }
-
- fn limits(&mut self, limits: (u32, Option<u32>)) {
- self.bool(limits.1.is_some());
- self.u32(limits.0);
- if let Some(c) = limits.1 {
- self.u32(c);
- }
- }
}
DISPFlags, DILexicalBlock};
use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
-use rustc::ty::subst::{Substs, UnpackedKind};
+use rustc::ty::subst::{SubstsRef, UnpackedKind};
use crate::abi::Abi;
use crate::common::CodegenCx;
fn get_template_parameters<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
generics: &ty::Generics,
- substs: &Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
file_metadata: &'ll DIFile,
name_to_append_suffix_to: &mut String,
) -> &'ll DIArray {
use crate::common::CodegenCx;
use rustc::hir::def_id::DefId;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty};
use rustc_codegen_ssa::traits::*;
output.pop();
}
- if sig.variadic {
+ if sig.c_variadic {
if !sig.inputs().is_empty() {
output.push_str(", ...");
} else {
}
}
- // Pushes the type parameters in the given `Substs` to the output string.
+ // Pushes the type parameters in the given `InternalSubsts` to the output string.
// This ignores region parameters, since they can't reliably be
// reconstructed for items from non-local crates. For local crates, this
// would be possible but with inlining and LTO we have to use the least
// common denominator - otherwise we would run into conflicts.
fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
- substs: &Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
output: &mut String) {
if substs.types().next().is_none() {
return;
let tp_ty = substs.type_at(0);
self.const_usize(self.size_of(tp_ty).bytes())
}
- func @ "va_start" | func @ "va_end" => {
- let va_list = match (tcx.lang_items().va_list(), &result.layout.ty.sty) {
- (Some(did), ty::Adt(def, _)) if def.did == did => args[0].immediate(),
- (Some(_), _) => self.load(args[0].immediate(),
- tcx.data_layout.pointer_align.abi),
- (None, _) => bug!("va_list language item must be defined")
- };
- let intrinsic = self.cx().get_intrinsic(&format!("llvm.{}", func));
- self.call(intrinsic, &[va_list], None)
+ "va_start" => {
+ self.va_start(args[0].immediate())
+ }
+ "va_end" => {
+ self.va_end(args[0].immediate())
}
"va_copy" => {
let va_list = match (tcx.lang_items().va_list(), &result.layout.ty.sty) {
(Some(did), ty::Adt(def, _)) if def.did == did => args[0].immediate(),
(Some(_), _) => self.load(args[0].immediate(),
tcx.data_layout.pointer_align.abi),
- (None, _) => bug!("va_list language item must be defined")
+ (None, _) => bug!("`va_list` language item must be defined")
};
let intrinsic = self.cx().get_intrinsic(&("llvm.va_copy"));
self.call(intrinsic, &[llresult, va_list], None);
let expect = self.get_intrinsic(&"llvm.expect.i1");
self.call(expect, &[cond, self.const_bool(expected)], None)
}
+
+ fn va_start(&mut self, list: &'ll Value) -> &'ll Value {
+ let target = &self.cx.tcx.sess.target.target;
+ let arch = &target.arch;
+ // A pointer to the architecture specific structure is passed to this
+ // function. For pointer variants (i686, RISC-V, Windows, etc), we
+ // should do do nothing, as the address to the pointer is needed. For
+ // architectures with a architecture specific structure (`Aarch64`,
+ // `X86_64`, etc), this function should load the structure from the
+ // address provided.
+ let va_list = match &**arch {
+ _ if target.options.is_like_windows => list,
+ "aarch64" if target.target_os == "ios" => list,
+ "aarch64" | "x86_64" | "powerpc" =>
+ self.load(list, self.tcx().data_layout.pointer_align.abi),
+ _ => list,
+ };
+ let intrinsic = self.cx().get_intrinsic("llvm.va_start");
+ self.call(intrinsic, &[va_list], None)
+ }
+
+ fn va_end(&mut self, list: &'ll Value) -> &'ll Value {
+ let target = &self.cx.tcx.sess.target.target;
+ let arch = &target.arch;
+ // See the comment in `va_start` for the purpose of the following.
+ let va_list = match &**arch {
+ _ if target.options.is_like_windows => list,
+ "aarch64" if target.target_os == "ios" => list,
+ "aarch64" | "x86_64" | "powerpc" =>
+ self.load(list, self.tcx().data_layout.pointer_align.abi),
+ _ => list,
+ };
+ let intrinsic = self.cx().get_intrinsic("llvm.va_end");
+ self.call(intrinsic, &[va_list], None)
+ }
}
fn copy_intrinsic(
}
fn predefine_fn(&self,
- instance: Instance<'tcx>,
- linkage: Linkage,
- visibility: Visibility,
- symbol_name: &str) {
+ instance: Instance<'tcx>,
+ linkage: Linkage,
+ visibility: Visibility,
+ symbol_name: &str) {
assert!(!instance.substs.needs_infer() &&
!instance.substs.has_param_types());
Align::from_bytes(4).unwrap(), true)
}
// Windows Aarch64
- ("aarch4", true) => {
+ ("aarch64", true) => {
emit_ptr_va_arg(bx, addr, target_ty, false,
Align::from_bytes(8).unwrap(), false)
}
// iOS Aarch64
- ("aarch4", _) if target.target_os == "ios" => {
+ ("aarch64", _) if target.target_os == "ios" => {
emit_ptr_va_arg(bx, addr, target_ty, false,
Align::from_bytes(8).unwrap(), true)
}
use rustc::session::config;
use rustc::ty::{TyCtxt, SymbolName};
use rustc::ty::query::Providers;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::util::nodemap::{FxHashMap, DefIdMap};
use rustc_allocator::ALLOCATOR_METHODS;
use rustc_data_structures::indexed_vec::IndexVec;
fn upstream_monomorphizations_provider<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
cnum: CrateNum)
- -> Lrc<DefIdMap<Lrc<FxHashMap<&'tcx Substs<'tcx>, CrateNum>>>>
+ -> Lrc<DefIdMap<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>>
{
debug_assert!(cnum == LOCAL_CRATE);
fn upstream_monomorphizations_for_provider<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
- -> Option<Lrc<FxHashMap<&'tcx Substs<'tcx>, CrateNum>>>
+ -> Option<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>
{
debug_assert!(!def_id.is_local());
tcx.upstream_monomorphizations(LOCAL_CRATE)
use crate::{ModuleCodegen, ModuleKind, CachedModuleCodegen};
use rustc::dep_graph::cgu_reuse_tracker::CguReuse;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::middle::lang_items::StartFnLangItem;
use rustc::middle::weak_lang_items;
use rustc::mir::mono::{Stats, CodegenUnitNameBuilder};
used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
used_crate_source: Default::default(),
- wasm_imports: Default::default(),
lang_item_to_crate: Default::default(),
missing_lang_items: Default::default(),
};
let lang_items = tcx.lang_items();
- let load_wasm_items = tcx.sess.crate_types.borrow()
- .iter()
- .any(|c| *c != config::CrateType::Rlib) &&
- tcx.sess.opts.target_triple.triple() == "wasm32-unknown-unknown";
-
- if load_wasm_items {
- info.load_wasm_imports(tcx, LOCAL_CRATE);
- }
-
let crates = tcx.crates();
let n_crates = crates.len();
if tcx.is_no_builtins(cnum) {
info.is_no_builtins.insert(cnum);
}
- if load_wasm_items {
- info.load_wasm_imports(tcx, cnum);
- }
let missing = tcx.missing_lang_items(cnum);
for &item in missing.iter() {
if let Ok(id) = lang_items.require(item) {
return info
}
-
- fn load_wasm_imports(&mut self, tcx: TyCtxt<'_, '_, '_>, cnum: CrateNum) {
- self.wasm_imports.extend(tcx.wasm_import_module_map(cnum).iter().map(|(&id, module)| {
- let instance = Instance::mono(tcx, id);
- let import_name = tcx.symbol_name(instance);
-
- (import_name.to_string(), module.clone())
- }));
- }
}
fn is_codegened_item(tcx: TyCtxt<'_, '_, '_>, id: DefId) -> bool {
use crate::traits::*;
use rustc::ty;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::hir::def_id::DefId;
pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>(
cx: &Cx,
def_id: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
) -> Cx::Value {
cx.get_fn(
ty::Instance::resolve(
>(
cx: &Cx,
def_id: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
) -> Cx::Value {
cx.get_fn(
ty::Instance::resolve_for_vtable(
pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
pub used_crates_static: Vec<(CrateNum, LibSource)>,
pub used_crates_dynamic: Vec<(CrateNum, LibSource)>,
- pub wasm_imports: FxHashMap<String, String>,
pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
}
location: Location) {
debug!("visit_assign(block={:?}, place={:?}, rvalue={:?})", block, place, rvalue);
- if let mir::Place::Local(index) = *place {
+ if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
self.assign(index, location);
if !self.fx.rvalue_creates_operand(rvalue) {
self.not_ssa(index);
}
PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
- let ty = mir::Place::Local(local).ty(self.fx.mir, self.fx.cx.tcx());
+ let ty = mir::Place::Base(mir::PlaceBase::Local(local)).ty(self.fx.mir,
+ self.fx.cx.tcx());
let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx()));
// Only need the place if we're actually dropping it.
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
use rustc::mir;
use rustc::mir::interpret::EvalErrorKind;
-use rustc_target::abi::call::{ArgType, FnType, PassMode};
+use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
use rustc_target::spec::abi::Abi;
use rustc_mir::monomorphize;
use crate::base;
use crate::traits::*;
+use std::borrow::Cow;
+
use syntax::symbol::Symbol;
use syntax_pos::Pos;
use super::{FunctionCx, LocalRef};
use super::place::PlaceRef;
-use super::operand::OperandRef;
+use super::operand::{OperandValue, OperandRef};
use super::operand::OperandValue::{Pair, Ref, Immediate};
-impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
- pub fn codegen_block(
- &mut self,
- bb: mir::BasicBlock,
- ) {
- let mut bx = self.build_block(bb);
- let data = &self.mir[bb];
+/// Used by `FunctionCx::codegen_terminator` for emitting common patterns
+/// e.g., creating a basic block, calling a function, etc.
+struct TerminatorCodegenHelper<'a, 'tcx> {
+ bb: &'a mir::BasicBlock,
+ terminator: &'a mir::Terminator<'tcx>,
+ funclet_bb: Option<mir::BasicBlock>,
+}
- debug!("codegen_block({:?}={:?})", bb, data);
+impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
+ /// Returns the associated funclet from `FunctionCx::funclets` for the
+ /// `funclet_bb` member if it is not `None`.
+ fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
+ &self,
+ fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
+ ) -> Option<&'c Bx::Funclet> {
+ match self.funclet_bb {
+ Some(funcl) => fx.funclets[funcl].as_ref(),
+ None => None,
+ }
+ }
- for statement in &data.statements {
- bx = self.codegen_statement(bx, statement);
+ fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>(
+ &self,
+ fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
+ target: mir::BasicBlock,
+ ) -> (Bx::BasicBlock, bool) {
+ let span = self.terminator.source_info.span;
+ let lltarget = fx.blocks[target];
+ let target_funclet = fx.cleanup_kinds[target].funclet_bb(target);
+ match (self.funclet_bb, target_funclet) {
+ (None, None) => (lltarget, false),
+ (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) =>
+ (lltarget, false),
+ // jump *into* cleanup - need a landing pad if GNU
+ (None, Some(_)) => (fx.landing_pad_to(target), false),
+ (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator),
+ (Some(_), Some(_)) => (fx.landing_pad_to(target), true),
}
+ }
- self.codegen_terminator(bx, bb, data.terminator());
+ /// Create a basic block.
+ fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
+ &self,
+ fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
+ target: mir::BasicBlock,
+ ) -> Bx::BasicBlock {
+ let (lltarget, is_cleanupret) = self.lltarget(fx, target);
+ if is_cleanupret {
+ // MSVC cross-funclet jump - need a trampoline
+
+ debug!("llblock: creating cleanup trampoline for {:?}", target);
+ let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target);
+ let mut trampoline = fx.new_block(name);
+ trampoline.cleanup_ret(self.funclet(fx).unwrap(),
+ Some(lltarget));
+ trampoline.llbb()
+ } else {
+ lltarget
+ }
}
- fn codegen_terminator(
- &mut self,
- mut bx: Bx,
- bb: mir::BasicBlock,
- terminator: &mir::Terminator<'tcx>
+ fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
+ &self,
+ fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
+ bx: &mut Bx,
+ target: mir::BasicBlock,
) {
- debug!("codegen_terminator: {:?}", terminator);
-
- // Create the cleanup bundle, if needed.
- let tcx = self.cx.tcx();
- let span = terminator.source_info.span;
- let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb);
+ let (lltarget, is_cleanupret) = self.lltarget(fx, target);
+ if is_cleanupret {
+ // micro-optimization: generate a `ret` rather than a jump
+ // to a trampoline.
+ bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget));
+ } else {
+ bx.br(lltarget);
+ }
+ }
- // HACK(eddyb) force the right lifetimes, NLL can't figure them out.
- fn funclet_closure_factory<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
- funclet_bb: Option<mir::BasicBlock>
- ) -> impl for<'b> Fn(
- &'b FunctionCx<'a, 'tcx, Bx>,
- ) -> Option<&'b Bx::Funclet> {
- move |this| {
- match funclet_bb {
- Some(funclet_bb) => this.funclets[funclet_bb].as_ref(),
- None => None,
- }
+ /// Call `fn_ptr` of `fn_ty` with the arguments `llargs`, the optional
+ /// return destination `destination` and the cleanup function `cleanup`.
+ fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
+ &self,
+ fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
+ bx: &mut Bx,
+ fn_ty: FnType<'tcx, Ty<'tcx>>,
+ fn_ptr: Bx::Value,
+ llargs: &[Bx::Value],
+ destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
+ cleanup: Option<mir::BasicBlock>,
+ ) {
+ if let Some(cleanup) = cleanup {
+ let ret_bx = if let Some((_, target)) = destination {
+ fx.blocks[target]
+ } else {
+ fx.unreachable_block()
+ };
+ let invokeret = bx.invoke(fn_ptr,
+ &llargs,
+ ret_bx,
+ self.llblock(fx, cleanup),
+ self.funclet(fx));
+ bx.apply_attrs_callsite(&fn_ty, invokeret);
+
+ if let Some((ret_dest, target)) = destination {
+ let mut ret_bx = fx.build_block(target);
+ fx.set_debug_loc(&mut ret_bx, self.terminator.source_info);
+ fx.store_return(&mut ret_bx, ret_dest, &fn_ty.ret, invokeret);
}
- }
- let funclet = funclet_closure_factory(funclet_bb);
-
- let lltarget = |this: &mut Self, target: mir::BasicBlock| {
- let lltarget = this.blocks[target];
- let target_funclet = this.cleanup_kinds[target].funclet_bb(target);
- match (funclet_bb, target_funclet) {
- (None, None) => (lltarget, false),
- (Some(f), Some(t_f))
- if f == t_f || !base::wants_msvc_seh(tcx.sess)
- => (lltarget, false),
- (None, Some(_)) => {
- // jump *into* cleanup - need a landing pad if GNU
- (this.landing_pad_to(target), false)
- }
- (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", terminator),
- (Some(_), Some(_)) => {
- (this.landing_pad_to(target), true)
- }
+ } else {
+ let llret = bx.call(fn_ptr, &llargs, self.funclet(fx));
+ bx.apply_attrs_callsite(&fn_ty, llret);
+ if fx.mir[*self.bb].is_cleanup {
+ // Cleanup is always the cold path. Don't inline
+ // drop glue. Also, when there is a deeply-nested
+ // struct, there are "symmetry" issues that cause
+ // exponential inlining - see issue #41696.
+ bx.do_not_inline(llret);
}
- };
-
- let llblock = |this: &mut Self, target: mir::BasicBlock| {
- let (lltarget, is_cleanupret) = lltarget(this, target);
- if is_cleanupret {
- // MSVC cross-funclet jump - need a trampoline
- debug!("llblock: creating cleanup trampoline for {:?}", target);
- let name = &format!("{:?}_cleanup_trampoline_{:?}", bb, target);
- let mut trampoline = this.new_block(name);
- trampoline.cleanup_ret(funclet(this).unwrap(), Some(lltarget));
- trampoline.llbb()
+ if let Some((ret_dest, target)) = destination {
+ fx.store_return(bx, ret_dest, &fn_ty.ret, llret);
+ self.funclet_br(fx, bx, target);
} else {
- lltarget
+ bx.unreachable();
}
- };
-
- let funclet_br =
- |this: &mut Self, bx: &mut Bx, target: mir::BasicBlock| {
- let (lltarget, is_cleanupret) = lltarget(this, target);
- if is_cleanupret {
- // micro-optimization: generate a `ret` rather than a jump
- // to a trampoline.
- bx.cleanup_ret(funclet(this).unwrap(), Some(lltarget));
- } else {
- bx.br(lltarget);
- }
- };
+ }
+ }
+}
- let do_call = |
- this: &mut Self,
- bx: &mut Bx,
- fn_ty: FnType<'tcx, Ty<'tcx>>,
- fn_ptr: Bx::Value,
- llargs: &[Bx::Value],
- destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
- cleanup: Option<mir::BasicBlock>
- | {
- if let Some(cleanup) = cleanup {
- let ret_bx = if let Some((_, target)) = destination {
- this.blocks[target]
- } else {
- this.unreachable_block()
- };
- let invokeret = bx.invoke(fn_ptr,
- &llargs,
- ret_bx,
- llblock(this, cleanup),
- funclet(this));
- bx.apply_attrs_callsite(&fn_ty, invokeret);
-
- if let Some((ret_dest, target)) = destination {
- let mut ret_bx = this.build_block(target);
- this.set_debug_loc(&mut ret_bx, terminator.source_info);
- this.store_return(&mut ret_bx, ret_dest, &fn_ty.ret, invokeret);
- }
+/// Codegen implementations for some terminator variants.
+impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
+ /// Generates code for a `Resume` terminator.
+ fn codegen_resume_terminator<'b>(
+ &mut self,
+ helper: TerminatorCodegenHelper<'b, 'tcx>,
+ mut bx: Bx,
+ ) {
+ if let Some(funclet) = helper.funclet(self) {
+ bx.cleanup_ret(funclet, None);
+ } else {
+ let slot = self.get_personality_slot(&mut bx);
+ let lp0 = slot.project_field(&mut bx, 0);
+ let lp0 = bx.load_operand(lp0).immediate();
+ let lp1 = slot.project_field(&mut bx, 1);
+ let lp1 = bx.load_operand(lp1).immediate();
+ slot.storage_dead(&mut bx);
+
+ if !bx.sess().target.target.options.custom_unwind_resume {
+ let mut lp = bx.const_undef(self.landing_pad_type());
+ lp = bx.insert_value(lp, lp0, 0);
+ lp = bx.insert_value(lp, lp1, 1);
+ bx.resume(lp);
} else {
- let llret = bx.call(fn_ptr, &llargs, funclet(this));
- bx.apply_attrs_callsite(&fn_ty, llret);
- if this.mir[bb].is_cleanup {
- // Cleanup is always the cold path. Don't inline
- // drop glue. Also, when there is a deeply-nested
- // struct, there are "symmetry" issues that cause
- // exponential inlining - see issue #41696.
- bx.do_not_inline(llret);
- }
-
- if let Some((ret_dest, target)) = destination {
- this.store_return(bx, ret_dest, &fn_ty.ret, llret);
- funclet_br(this, bx, target);
- } else {
- bx.unreachable();
- }
+ bx.call(bx.eh_unwind_resume(), &[lp0],
+ helper.funclet(self));
+ bx.unreachable();
}
- };
+ }
+ }
- self.set_debug_loc(&mut bx, terminator.source_info);
- match terminator.kind {
- mir::TerminatorKind::Resume => {
- if let Some(funclet) = funclet(self) {
- bx.cleanup_ret(funclet, None);
+ fn codegen_switchint_terminator<'b>(
+ &mut self,
+ helper: TerminatorCodegenHelper<'b, 'tcx>,
+ mut bx: Bx,
+ discr: &mir::Operand<'tcx>,
+ switch_ty: Ty<'tcx>,
+ values: &Cow<'tcx, [u128]>,
+ targets: &Vec<mir::BasicBlock>,
+ ) {
+ let discr = self.codegen_operand(&mut bx, &discr);
+ if targets.len() == 2 {
+ // If there are two targets, emit br instead of switch
+ let lltrue = helper.llblock(self, targets[0]);
+ let llfalse = helper.llblock(self, targets[1]);
+ if switch_ty == bx.tcx().types.bool {
+ // Don't generate trivial icmps when switching on bool
+ if let [0] = values[..] {
+ bx.cond_br(discr.immediate(), llfalse, lltrue);
} else {
- let slot = self.get_personality_slot(&mut bx);
- let lp0 = slot.project_field(&mut bx, 0);
- let lp0 = bx.load_operand(lp0).immediate();
- let lp1 = slot.project_field(&mut bx, 1);
- let lp1 = bx.load_operand(lp1).immediate();
- slot.storage_dead(&mut bx);
-
- if !bx.sess().target.target.options.custom_unwind_resume {
- let mut lp = bx.const_undef(self.landing_pad_type());
- lp = bx.insert_value(lp, lp0, 0);
- lp = bx.insert_value(lp, lp1, 1);
- bx.resume(lp);
- } else {
- bx.call(bx.eh_unwind_resume(), &[lp0], funclet(self));
- bx.unreachable();
- }
+ assert_eq!(&values[..], &[1]);
+ bx.cond_br(discr.immediate(), lltrue, llfalse);
}
+ } else {
+ let switch_llty = bx.immediate_backend_type(
+ bx.layout_of(switch_ty)
+ );
+ let llval = bx.const_uint_big(switch_llty, values[0]);
+ let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval);
+ bx.cond_br(cmp, lltrue, llfalse);
+ }
+ } else {
+ let (otherwise, targets) = targets.split_last().unwrap();
+ let switch = bx.switch(discr.immediate(),
+ helper.llblock(self, *otherwise),
+ values.len());
+ let switch_llty = bx.immediate_backend_type(
+ bx.layout_of(switch_ty)
+ );
+ for (&value, target) in values.iter().zip(targets) {
+ let llval = bx.const_uint_big(switch_llty, value);
+ let llbb = helper.llblock(self, *target);
+ bx.add_case(switch, llval, llbb)
}
+ }
+ }
- mir::TerminatorKind::Abort => {
- bx.abort();
- bx.unreachable();
+ fn codegen_return_terminator<'b>(
+ &mut self,
+ mut bx: Bx,
+ ) {
+ if self.fn_ty.c_variadic {
+ if let Some(va_list) = self.va_list_ref {
+ bx.va_end(va_list.llval);
+ }
+ }
+ let llval = match self.fn_ty.ret.mode {
+ PassMode::Ignore(IgnoreMode::Zst) | PassMode::Indirect(..) => {
+ bx.ret_void();
+ return;
}
- mir::TerminatorKind::Goto { target } => {
- funclet_br(self, &mut bx, target);
+ PassMode::Ignore(IgnoreMode::CVarArgs) => {
+ bug!("C-variadic arguments should never be the return type");
}
- mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
- let discr = self.codegen_operand(&mut bx, discr);
- if targets.len() == 2 {
- // If there are two targets, emit br instead of switch
- let lltrue = llblock(self, targets[0]);
- let llfalse = llblock(self, targets[1]);
- if switch_ty == bx.tcx().types.bool {
- // Don't generate trivial icmps when switching on bool
- if let [0] = values[..] {
- bx.cond_br(discr.immediate(), llfalse, lltrue);
- } else {
- assert_eq!(&values[..], &[1]);
- bx.cond_br(discr.immediate(), lltrue, llfalse);
- }
- } else {
- let switch_llty = bx.immediate_backend_type(
- bx.layout_of(switch_ty)
- );
- let llval = bx.const_uint_big(switch_llty, values[0]);
- let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval);
- bx.cond_br(cmp, lltrue, llfalse);
- }
+ PassMode::Direct(_) | PassMode::Pair(..) => {
+ let op =
+ self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE);
+ if let Ref(llval, _, align) = op.val {
+ bx.load(llval, align)
} else {
- let (otherwise, targets) = targets.split_last().unwrap();
- let switch = bx.switch(discr.immediate(),
- llblock(self, *otherwise),
- values.len());
- let switch_llty = bx.immediate_backend_type(
- bx.layout_of(switch_ty)
- );
- for (&value, target) in values.iter().zip(targets) {
- let llval = bx.const_uint_big(switch_llty, value);
- let llbb = llblock(self, *target);
- bx.add_case(switch, llval, llbb)
- }
+ op.immediate_or_packed_pair(&mut bx)
}
}
- mir::TerminatorKind::Return => {
- let llval = match self.fn_ty.ret.mode {
- PassMode::Ignore | PassMode::Indirect(..) => {
- bx.ret_void();
- return;
- }
-
- PassMode::Direct(_) | PassMode::Pair(..) => {
- let op =
- self.codegen_consume(&mut bx, &mir::Place::Local(mir::RETURN_PLACE));
- if let Ref(llval, _, align) = op.val {
- bx.load(llval, align)
- } else {
- op.immediate_or_packed_pair(&mut bx)
+ PassMode::Cast(cast_ty) => {
+ let op = match self.locals[mir::RETURN_PLACE] {
+ LocalRef::Operand(Some(op)) => op,
+ LocalRef::Operand(None) => bug!("use of return before def"),
+ LocalRef::Place(cg_place) => {
+ OperandRef {
+ val: Ref(cg_place.llval, None, cg_place.align),
+ layout: cg_place.layout
}
}
-
- PassMode::Cast(cast_ty) => {
- let op = match self.locals[mir::RETURN_PLACE] {
- LocalRef::Operand(Some(op)) => op,
- LocalRef::Operand(None) => bug!("use of return before def"),
- LocalRef::Place(cg_place) => {
- OperandRef {
- val: Ref(cg_place.llval, None, cg_place.align),
- layout: cg_place.layout
- }
- }
- LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
- };
- let llslot = match op.val {
- Immediate(_) | Pair(..) => {
- let scratch =
- PlaceRef::alloca(&mut bx, self.fn_ty.ret.layout, "ret");
- op.val.store(&mut bx, scratch);
- scratch.llval
- }
- Ref(llval, _, align) => {
- assert_eq!(align, op.layout.align.abi,
- "return place is unaligned!");
- llval
- }
- };
- let addr = bx.pointercast(llslot, bx.type_ptr_to(
- bx.cast_backend_type(&cast_ty)
- ));
- bx.load(addr, self.fn_ty.ret.layout.align.abi)
+ LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
+ };
+ let llslot = match op.val {
+ Immediate(_) | Pair(..) => {
+ let scratch =
+ PlaceRef::alloca(&mut bx, self.fn_ty.ret.layout, "ret");
+ op.val.store(&mut bx, scratch);
+ scratch.llval
+ }
+ Ref(llval, _, align) => {
+ assert_eq!(align, op.layout.align.abi,
+ "return place is unaligned!");
+ llval
}
};
- bx.ret(llval);
+ let addr = bx.pointercast(llslot, bx.type_ptr_to(
+ bx.cast_backend_type(&cast_ty)
+ ));
+ bx.load(addr, self.fn_ty.ret.layout.align.abi)
}
+ };
+ bx.ret(llval);
+ }
- mir::TerminatorKind::Unreachable => {
- bx.unreachable();
+
+ fn codegen_drop_terminator<'b>(
+ &mut self,
+ helper: TerminatorCodegenHelper<'b, 'tcx>,
+ mut bx: Bx,
+ location: &mir::Place<'tcx>,
+ target: mir::BasicBlock,
+ unwind: Option<mir::BasicBlock>,
+ ) {
+ let ty = location.ty(self.mir, bx.tcx()).to_ty(bx.tcx());
+ let ty = self.monomorphize(&ty);
+ let drop_fn = monomorphize::resolve_drop_in_place(bx.tcx(), ty);
+
+ if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
+ // we don't actually need to drop anything.
+ helper.funclet_br(self, &mut bx, target);
+ return
+ }
+
+ let place = self.codegen_place(&mut bx, location);
+ let (args1, args2);
+ let mut args = if let Some(llextra) = place.llextra {
+ args2 = [place.llval, llextra];
+ &args2[..]
+ } else {
+ args1 = [place.llval];
+ &args1[..]
+ };
+ let (drop_fn, fn_ty) = match ty.sty {
+ ty::Dynamic(..) => {
+ let sig = drop_fn.fn_sig(self.cx.tcx());
+ let sig = self.cx.tcx().normalize_erasing_late_bound_regions(
+ ty::ParamEnv::reveal_all(),
+ &sig,
+ );
+ let fn_ty = bx.new_vtable(sig, &[]);
+ let vtable = args[1];
+ args = &args[..1];
+ (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_ty), fn_ty)
+ }
+ _ => {
+ (bx.get_fn(drop_fn),
+ bx.fn_type_of_instance(&drop_fn))
}
+ };
+ helper.do_call(self, &mut bx, fn_ty, drop_fn, args,
+ Some((ReturnDest::Nothing, target)),
+ unwind);
+ }
- mir::TerminatorKind::Drop { ref location, target, unwind } => {
- let ty = location.ty(self.mir, bx.tcx()).to_ty(bx.tcx());
- let ty = self.monomorphize(&ty);
- let drop_fn = monomorphize::resolve_drop_in_place(bx.tcx(), ty);
-
- if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
- // we don't actually need to drop anything.
- funclet_br(self, &mut bx, target);
- return
- }
+ fn codegen_assert_terminator<'b>(
+ &mut self,
+ helper: TerminatorCodegenHelper<'b, 'tcx>,
+ mut bx: Bx,
+ terminator: &mir::Terminator<'tcx>,
+ cond: &mir::Operand<'tcx>,
+ expected: bool,
+ msg: &mir::AssertMessage<'tcx>,
+ target: mir::BasicBlock,
+ cleanup: Option<mir::BasicBlock>,
+ ) {
+ let span = terminator.source_info.span;
+ let cond = self.codegen_operand(&mut bx, cond).immediate();
+ let mut const_cond = bx.const_to_opt_u128(cond, false).map(|c| c == 1);
+
+ // This case can currently arise only from functions marked
+ // with #[rustc_inherit_overflow_checks] and inlined from
+ // another crate (mostly core::num generic/#[inline] fns),
+ // while the current crate doesn't use overflow checks.
+ // NOTE: Unlike binops, negation doesn't have its own
+ // checked operation, just a comparison with the minimum
+ // value, so we have to check for the assert message.
+ if !bx.check_overflow() {
+ if let mir::interpret::EvalErrorKind::OverflowNeg = *msg {
+ const_cond = Some(expected);
+ }
+ }
- let place = self.codegen_place(&mut bx, location);
- let (args1, args2);
- let mut args = if let Some(llextra) = place.llextra {
- args2 = [place.llval, llextra];
- &args2[..]
- } else {
- args1 = [place.llval];
- &args1[..]
- };
- let (drop_fn, fn_ty) = match ty.sty {
- ty::Dynamic(..) => {
- let sig = drop_fn.fn_sig(tcx);
- let sig = tcx.normalize_erasing_late_bound_regions(
- ty::ParamEnv::reveal_all(),
- &sig,
- );
- let fn_ty = bx.new_vtable(sig, &[]);
- let vtable = args[1];
- args = &args[..1];
- (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_ty), fn_ty)
- }
- _ => {
- (bx.get_fn(drop_fn),
- bx.fn_type_of_instance(&drop_fn))
- }
- };
- do_call(self, &mut bx, fn_ty, drop_fn, args,
- Some((ReturnDest::Nothing, target)),
- unwind);
+ // Don't codegen the panic block if success if known.
+ if const_cond == Some(expected) {
+ helper.funclet_br(self, &mut bx, target);
+ return;
+ }
+
+ // Pass the condition through llvm.expect for branch hinting.
+ let cond = bx.expect(cond, expected);
+
+ // Create the failure block and the conditional branch to it.
+ let lltarget = helper.llblock(self, target);
+ let panic_block = self.new_block("panic");
+ if expected {
+ bx.cond_br(cond, lltarget, panic_block.llbb());
+ } else {
+ bx.cond_br(cond, panic_block.llbb(), lltarget);
+ }
+
+ // After this point, bx is the block for the call to panic.
+ bx = panic_block;
+ self.set_debug_loc(&mut bx, terminator.source_info);
+
+ // Get the location information.
+ let loc = bx.sess().source_map().lookup_char_pos(span.lo());
+ let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
+ let filename = bx.const_str_slice(filename);
+ let line = bx.const_u32(loc.line as u32);
+ let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
+ let align = self.cx.tcx().data_layout.aggregate_align.abi
+ .max(self.cx.tcx().data_layout.i32_align.abi)
+ .max(self.cx.tcx().data_layout.pointer_align.abi);
+
+ // Put together the arguments to the panic entry point.
+ let (lang_item, args) = match *msg {
+ EvalErrorKind::BoundsCheck { ref len, ref index } => {
+ let len = self.codegen_operand(&mut bx, len).immediate();
+ let index = self.codegen_operand(&mut bx, index).immediate();
+
+ let file_line_col = bx.const_struct(&[filename, line, col], false);
+ let file_line_col = bx.static_addr_of(
+ file_line_col,
+ align,
+ Some("panic_bounds_check_loc")
+ );
+ (lang_items::PanicBoundsCheckFnLangItem,
+ vec![file_line_col, index, len])
+ }
+ _ => {
+ let str = msg.description();
+ let msg_str = Symbol::intern(str).as_str();
+ let msg_str = bx.const_str_slice(msg_str);
+ let msg_file_line_col = bx.const_struct(
+ &[msg_str, filename, line, col],
+ false
+ );
+ let msg_file_line_col = bx.static_addr_of(
+ msg_file_line_col,
+ align,
+ Some("panic_loc")
+ );
+ (lang_items::PanicFnLangItem,
+ vec![msg_file_line_col])
}
+ };
- mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
- let cond = self.codegen_operand(&mut bx, cond).immediate();
- let mut const_cond = bx.const_to_opt_u128(cond, false).map(|c| c == 1);
-
- // This case can currently arise only from functions marked
- // with #[rustc_inherit_overflow_checks] and inlined from
- // another crate (mostly core::num generic/#[inline] fns),
- // while the current crate doesn't use overflow checks.
- // NOTE: Unlike binops, negation doesn't have its own
- // checked operation, just a comparison with the minimum
- // value, so we have to check for the assert message.
- if !bx.check_overflow() {
- if let mir::interpret::EvalErrorKind::OverflowNeg = *msg {
- const_cond = Some(expected);
- }
- }
+ // Obtain the panic entry point.
+ let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
+ let instance = ty::Instance::mono(bx.tcx(), def_id);
+ let fn_ty = bx.fn_type_of_instance(&instance);
+ let llfn = bx.get_fn(instance);
- // Don't codegen the panic block if success if known.
- if const_cond == Some(expected) {
- funclet_br(self, &mut bx, target);
- return;
- }
+ // Codegen the actual panic invoke/call.
+ helper.do_call(self, &mut bx, fn_ty, llfn, &args, None, cleanup);
+ }
- // Pass the condition through llvm.expect for branch hinting.
- let cond = bx.expect(cond, expected);
+ fn codegen_call_terminator<'b>(
+ &mut self,
+ helper: TerminatorCodegenHelper<'b, 'tcx>,
+ mut bx: Bx,
+ terminator: &mir::Terminator<'tcx>,
+ func: &mir::Operand<'tcx>,
+ args: &Vec<mir::Operand<'tcx>>,
+ destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
+ cleanup: Option<mir::BasicBlock>,
+ ) {
+ let span = terminator.source_info.span;
+ // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
+ let callee = self.codegen_operand(&mut bx, func);
+
+ let (instance, mut llfn) = match callee.layout.ty.sty {
+ ty::FnDef(def_id, substs) => {
+ (Some(ty::Instance::resolve(bx.tcx(),
+ ty::ParamEnv::reveal_all(),
+ def_id,
+ substs).unwrap()),
+ None)
+ }
+ ty::FnPtr(_) => {
+ (None, Some(callee.immediate()))
+ }
+ _ => bug!("{} is not callable", callee.layout.ty),
+ };
+ let def = instance.map(|i| i.def);
+ let sig = callee.layout.ty.fn_sig(bx.tcx());
+ let sig = bx.tcx().normalize_erasing_late_bound_regions(
+ ty::ParamEnv::reveal_all(),
+ &sig,
+ );
+ let abi = sig.abi;
+
+ // Handle intrinsics old codegen wants Expr's for, ourselves.
+ let intrinsic = match def {
+ Some(ty::InstanceDef::Intrinsic(def_id)) =>
+ Some(bx.tcx().item_name(def_id).as_str()),
+ _ => None
+ };
+ let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
- // Create the failure block and the conditional branch to it.
- let lltarget = llblock(self, target);
- let panic_block = self.new_block("panic");
- if expected {
- bx.cond_br(cond, lltarget, panic_block.llbb());
- } else {
- bx.cond_br(cond, panic_block.llbb(), lltarget);
- }
+ if intrinsic == Some("transmute") {
+ if let Some(destination_ref) = destination.as_ref() {
+ let &(ref dest, target) = destination_ref;
+ self.codegen_transmute(&mut bx, &args[0], dest);
+ helper.funclet_br(self, &mut bx, target);
+ } else {
+ // If we are trying to transmute to an uninhabited type,
+ // it is likely there is no allotted destination. In fact,
+ // transmuting to an uninhabited type is UB, which means
+ // we can do what we like. Here, we declare that transmuting
+ // into an uninhabited type is impossible, so anything following
+ // it must be unreachable.
+ assert_eq!(bx.layout_of(sig.output()).abi, layout::Abi::Uninhabited);
+ bx.unreachable();
+ }
+ return;
+ }
- // After this point, bx is the block for the call to panic.
- bx = panic_block;
- self.set_debug_loc(&mut bx, terminator.source_info);
+ // The "spoofed" `VaList` added to a C-variadic functions signature
+ // should not be included in the `extra_args` calculation.
+ let extra_args_start_idx = sig.inputs().len() - if sig.c_variadic { 1 } else { 0 };
+ let extra_args = &args[extra_args_start_idx..];
+ let extra_args = extra_args.iter().map(|op_arg| {
+ let op_ty = op_arg.ty(self.mir, bx.tcx());
+ self.monomorphize(&op_ty)
+ }).collect::<Vec<_>>();
+
+ let fn_ty = match def {
+ Some(ty::InstanceDef::Virtual(..)) => {
+ bx.new_vtable(sig, &extra_args)
+ }
+ Some(ty::InstanceDef::DropGlue(_, None)) => {
+ // Empty drop glue; a no-op.
+ let &(_, target) = destination.as_ref().unwrap();
+ helper.funclet_br(self, &mut bx, target);
+ return;
+ }
+ _ => bx.new_fn_type(sig, &extra_args)
+ };
- // Get the location information.
+ // Emit a panic or a no-op for `panic_if_uninhabited`.
+ if intrinsic == Some("panic_if_uninhabited") {
+ let ty = instance.unwrap().substs.type_at(0);
+ let layout = bx.layout_of(ty);
+ if layout.abi.is_uninhabited() {
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
let filename = bx.const_str_slice(filename);
let line = bx.const_u32(loc.line as u32);
let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
- let align = tcx.data_layout.aggregate_align.abi
- .max(tcx.data_layout.i32_align.abi)
- .max(tcx.data_layout.pointer_align.abi);
-
- // Put together the arguments to the panic entry point.
- let (lang_item, args) = match *msg {
- EvalErrorKind::BoundsCheck { ref len, ref index } => {
- let len = self.codegen_operand(&mut bx, len).immediate();
- let index = self.codegen_operand(&mut bx, index).immediate();
-
- let file_line_col = bx.const_struct(&[filename, line, col], false);
- let file_line_col = bx.static_addr_of(
- file_line_col,
- align,
- Some("panic_bounds_check_loc")
- );
- (lang_items::PanicBoundsCheckFnLangItem,
- vec![file_line_col, index, len])
- }
- _ => {
- let str = msg.description();
- let msg_str = Symbol::intern(str).as_str();
- let msg_str = bx.const_str_slice(msg_str);
- let msg_file_line_col = bx.const_struct(
- &[msg_str, filename, line, col],
- false
- );
- let msg_file_line_col = bx.static_addr_of(
- msg_file_line_col,
- align,
- Some("panic_loc")
- );
- (lang_items::PanicFnLangItem,
- vec![msg_file_line_col])
- }
- };
+ let align = self.cx.tcx().data_layout.aggregate_align.abi
+ .max(self.cx.tcx().data_layout.i32_align.abi)
+ .max(self.cx.tcx().data_layout.pointer_align.abi);
+
+ let str = format!(
+ "Attempted to instantiate uninhabited type {}",
+ ty
+ );
+ let msg_str = Symbol::intern(&str).as_str();
+ let msg_str = bx.const_str_slice(msg_str);
+ let msg_file_line_col = bx.const_struct(
+ &[msg_str, filename, line, col],
+ false,
+ );
+ let msg_file_line_col = bx.static_addr_of(
+ msg_file_line_col,
+ align,
+ Some("panic_loc"),
+ );
// Obtain the panic entry point.
- let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
+ let def_id =
+ common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
let instance = ty::Instance::mono(bx.tcx(), def_id);
let fn_ty = bx.fn_type_of_instance(&instance);
let llfn = bx.get_fn(instance);
// Codegen the actual panic invoke/call.
- do_call(self, &mut bx, fn_ty, llfn, &args, None, cleanup);
+ helper.do_call(
+ self,
+ &mut bx,
+ fn_ty,
+ llfn,
+ &[msg_file_line_col],
+ destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
+ cleanup,
+ );
+ } else {
+ // a NOP
+ helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1)
}
+ return;
+ }
- mir::TerminatorKind::DropAndReplace { .. } => {
- bug!("undesugared DropAndReplace in codegen: {:?}", terminator);
- }
+ // The arguments we'll be passing. Plus one to account for outptr, if used.
+ let arg_count = fn_ty.args.len() + fn_ty.ret.is_indirect() as usize;
+ let mut llargs = Vec::with_capacity(arg_count);
- mir::TerminatorKind::Call {
- ref func,
- ref args,
- ref destination,
- cleanup,
- from_hir_call: _
- } => {
- // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
- let callee = self.codegen_operand(&mut bx, func);
-
- let (instance, mut llfn) = match callee.layout.ty.sty {
- ty::FnDef(def_id, substs) => {
- (Some(ty::Instance::resolve(bx.tcx(),
- ty::ParamEnv::reveal_all(),
- def_id,
- substs).unwrap()),
- None)
- }
- ty::FnPtr(_) => {
- (None, Some(callee.immediate()))
- }
- _ => bug!("{} is not callable", callee.layout.ty)
- };
- let def = instance.map(|i| i.def);
- let sig = callee.layout.ty.fn_sig(bx.tcx());
- let sig = bx.tcx().normalize_erasing_late_bound_regions(
- ty::ParamEnv::reveal_all(),
- &sig,
- );
- let abi = sig.abi;
+ // Prepare the return value destination
+ let ret_dest = if let Some((ref dest, _)) = *destination {
+ let is_intrinsic = intrinsic.is_some();
+ self.make_return_dest(&mut bx, dest, &fn_ty.ret, &mut llargs,
+ is_intrinsic)
+ } else {
+ ReturnDest::Nothing
+ };
- // Handle intrinsics old codegen wants Expr's for, ourselves.
- let intrinsic = match def {
- Some(ty::InstanceDef::Intrinsic(def_id))
- => Some(bx.tcx().item_name(def_id).as_str()),
- _ => None
- };
- let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
+ if intrinsic.is_some() && intrinsic != Some("drop_in_place") {
+ let dest = match ret_dest {
+ _ if fn_ty.ret.is_indirect() => llargs[0],
+ ReturnDest::Nothing =>
+ bx.const_undef(bx.type_ptr_to(bx.memory_ty(&fn_ty.ret))),
+ ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) =>
+ dst.llval,
+ ReturnDest::DirectOperand(_) =>
+ bug!("Cannot use direct operand with an intrinsic call"),
+ };
- if intrinsic == Some("transmute") {
- if let Some(destination_ref) = destination.as_ref() {
- let &(ref dest, target) = destination_ref;
- self.codegen_transmute(&mut bx, &args[0], dest);
- funclet_br(self, &mut bx, target);
- } else {
- // If we are trying to transmute to an uninhabited type,
- // it is likely there is no allotted destination. In fact,
- // transmuting to an uninhabited type is UB, which means
- // we can do what we like. Here, we declare that transmuting
- // into an uninhabited type is impossible, so anything following
- // it must be unreachable.
- assert_eq!(bx.layout_of(sig.output()).abi, layout::Abi::Uninhabited);
- bx.unreachable();
+ let args: Vec<_> = args.iter().enumerate().map(|(i, arg)| {
+ // The indices passed to simd_shuffle* in the
+ // third argument must be constant. This is
+ // checked by const-qualification, which also
+ // promotes any complex rvalues to constants.
+ if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") {
+ match *arg {
+ // The shuffle array argument is usually not an explicit constant,
+ // but specified directly in the code. This means it gets promoted
+ // and we can then extract the value by evaluating the promoted.
+ mir::Operand::Copy(
+ mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+ ) |
+ mir::Operand::Move(
+ mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+ ) => {
+ let param_env = ty::ParamEnv::reveal_all();
+ let cid = mir::interpret::GlobalId {
+ instance: self.instance,
+ promoted: Some(index),
+ };
+ let c = bx.tcx().const_eval(param_env.and(cid));
+ let (llval, ty) = self.simd_shuffle_indices(
+ &bx,
+ terminator.source_info.span,
+ ty,
+ c,
+ );
+ return OperandRef {
+ val: Immediate(llval),
+ layout: bx.layout_of(ty),
+ };
+
+ }
+ mir::Operand::Copy(_) |
+ mir::Operand::Move(_) => {
+ span_bug!(span, "shuffle indices must be constant");
+ }
+ mir::Operand::Constant(ref constant) => {
+ let c = self.eval_mir_constant(&bx, constant);
+ let (llval, ty) = self.simd_shuffle_indices(
+ &bx,
+ constant.span,
+ constant.ty,
+ c,
+ );
+ return OperandRef {
+ val: Immediate(llval),
+ layout: bx.layout_of(ty)
+ };
+ }
}
- return;
}
- let extra_args = &args[sig.inputs().len()..];
- let extra_args = extra_args.iter().map(|op_arg| {
- let op_ty = op_arg.ty(self.mir, bx.tcx());
- self.monomorphize(&op_ty)
- }).collect::<Vec<_>>();
+ self.codegen_operand(&mut bx, arg)
+ }).collect();
- let fn_ty = match def {
- Some(ty::InstanceDef::Virtual(..)) => {
- bx.new_vtable(sig, &extra_args)
- }
- Some(ty::InstanceDef::DropGlue(_, None)) => {
- // empty drop glue - a nop.
- let &(_, target) = destination.as_ref().unwrap();
- funclet_br(self, &mut bx, target);
- return;
- }
- _ => bx.new_fn_type(sig, &extra_args)
+
+ let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
+ bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
+ terminator.source_info.span);
+
+ if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
+ self.store_return(&mut bx, ret_dest, &fn_ty.ret, dst.llval);
+ }
+
+ if let Some((_, target)) = *destination {
+ helper.funclet_br(self, &mut bx, target);
+ } else {
+ bx.unreachable();
+ }
+
+ return;
+ }
+
+ // Split the rust-call tupled arguments off.
+ let (first_args, untuple) = if abi == Abi::RustCall && !args.is_empty() {
+ let (tup, args) = args.split_last().unwrap();
+ (args, Some(tup))
+ } else {
+ (&args[..], None)
+ };
+
+ // Useful determining if the current argument is the "spoofed" `VaList`
+ let last_arg_idx = if sig.inputs().is_empty() {
+ None
+ } else {
+ Some(sig.inputs().len() - 1)
+ };
+ 'make_args: for (i, arg) in first_args.iter().enumerate() {
+ // If this is a C-variadic function the function signature contains
+ // an "spoofed" `VaList`. This argument is ignored, but we need to
+ // populate it with a dummy operand so that the users real arguments
+ // are not overwritten.
+ let i = if sig.c_variadic && last_arg_idx.map(|x| x == i).unwrap_or(false) {
+ let layout = match self.cx.tcx().lang_items().va_list() {
+ Some(did) => bx.cx().layout_of(bx.tcx().type_of(did)),
+ None => bug!("`va_list` language item required for C-variadics"),
};
+ let op = OperandRef {
+ val: OperandValue::Immediate(
+ bx.cx().const_undef(bx.cx().immediate_backend_type(layout)
+ )),
+ layout: layout,
+ };
+ self.codegen_argument(&mut bx, op, &mut llargs, &fn_ty.args[i]);
+ if i + 1 < fn_ty.args.len() {
+ i + 1
+ } else {
+ break 'make_args
+ }
+ } else {
+ i
+ };
+ let mut op = self.codegen_operand(&mut bx, arg);
+
+ if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
+ if let Pair(..) = op.val {
+ // In the case of Rc<Self>, we need to explicitly pass a
+ // *mut RcBox<Self> with a Scalar (not ScalarPair) ABI. This is a hack
+ // that is understood elsewhere in the compiler as a method on
+ // `dyn Trait`.
+ // To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until
+ // we get a value of a built-in pointer type
+ 'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
+ && !op.layout.ty.is_region_ptr()
+ {
+ 'iter_fields: for i in 0..op.layout.fields.count() {
+ let field = op.extract_field(&mut bx, i);
+ if !field.layout.is_zst() {
+ // we found the one non-zero-sized field that is allowed
+ // now find *its* non-zero-sized field, or stop if it's a
+ // pointer
+ op = field;
+ continue 'descend_newtypes
+ }
+ }
- // emit a panic or a NOP for `panic_if_uninhabited`
- if intrinsic == Some("panic_if_uninhabited") {
- let ty = instance.unwrap().substs.type_at(0);
- let layout = bx.layout_of(ty);
- if layout.abi.is_uninhabited() {
- let loc = bx.sess().source_map().lookup_char_pos(span.lo());
- let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
- let filename = bx.const_str_slice(filename);
- let line = bx.const_u32(loc.line as u32);
- let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
- let align = tcx.data_layout.aggregate_align.abi
- .max(tcx.data_layout.i32_align.abi)
- .max(tcx.data_layout.pointer_align.abi);
-
- let str = format!(
- "Attempted to instantiate uninhabited type {}",
- ty
- );
- let msg_str = Symbol::intern(&str).as_str();
- let msg_str = bx.const_str_slice(msg_str);
- let msg_file_line_col = bx.const_struct(
- &[msg_str, filename, line, col],
- false,
- );
- let msg_file_line_col = bx.static_addr_of(
- msg_file_line_col,
- align,
- Some("panic_loc"),
- );
-
- // Obtain the panic entry point.
- let def_id =
- common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
- let instance = ty::Instance::mono(bx.tcx(), def_id);
- let fn_ty = bx.fn_type_of_instance(&instance);
- let llfn = bx.get_fn(instance);
-
- // Codegen the actual panic invoke/call.
- do_call(
- self,
- &mut bx,
- fn_ty,
- llfn,
- &[msg_file_line_col],
- destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
- cleanup,
- );
- } else {
- // a NOP
- funclet_br(self, &mut bx, destination.as_ref().unwrap().1);
+ span_bug!(span, "receiver has no non-zero-sized fields {:?}", op);
}
- return;
+
+ // now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
+ // data pointer and vtable. Look up the method in the vtable, and pass
+ // the data pointer as the first argument
+ match op.val {
+ Pair(data_ptr, meta) => {
+ llfn = Some(meth::VirtualIndex::from_index(idx)
+ .get_fn(&mut bx, meta, &fn_ty));
+ llargs.push(data_ptr);
+ continue 'make_args
+ }
+ other => bug!("expected a Pair, got {:?}", other),
+ }
+ } else if let Ref(data_ptr, Some(meta), _) = op.val {
+ // by-value dynamic dispatch
+ llfn = Some(meth::VirtualIndex::from_index(idx)
+ .get_fn(&mut bx, meta, &fn_ty));
+ llargs.push(data_ptr);
+ continue;
+ } else {
+ span_bug!(span, "can't codegen a virtual call on {:?}", op);
}
+ }
- // The arguments we'll be passing. Plus one to account for outptr, if used.
- let arg_count = fn_ty.args.len() + fn_ty.ret.is_indirect() as usize;
- let mut llargs = Vec::with_capacity(arg_count);
+ // The callee needs to own the argument memory if we pass it
+ // by-ref, so make a local copy of non-immediate constants.
+ match (arg, op.val) {
+ (&mir::Operand::Copy(_), Ref(_, None, _)) |
+ (&mir::Operand::Constant(_), Ref(_, None, _)) => {
+ let tmp = PlaceRef::alloca(&mut bx, op.layout, "const");
+ op.val.store(&mut bx, tmp);
+ op.val = Ref(tmp.llval, None, tmp.align);
+ }
+ _ => {}
+ }
- // Prepare the return value destination
- let ret_dest = if let Some((ref dest, _)) = *destination {
- let is_intrinsic = intrinsic.is_some();
- self.make_return_dest(&mut bx, dest, &fn_ty.ret, &mut llargs,
- is_intrinsic)
- } else {
- ReturnDest::Nothing
- };
+ self.codegen_argument(&mut bx, op, &mut llargs, &fn_ty.args[i]);
+ }
+ if let Some(tup) = untuple {
+ self.codegen_arguments_untupled(&mut bx, tup, &mut llargs,
+ &fn_ty.args[first_args.len()..])
+ }
- if intrinsic.is_some() && intrinsic != Some("drop_in_place") {
- let dest = match ret_dest {
- _ if fn_ty.ret.is_indirect() => llargs[0],
- ReturnDest::Nothing => {
- bx.const_undef(bx.type_ptr_to(bx.memory_ty(&fn_ty.ret)))
- }
- ReturnDest::IndirectOperand(dst, _) |
- ReturnDest::Store(dst) => dst.llval,
- ReturnDest::DirectOperand(_) =>
- bug!("Cannot use direct operand with an intrinsic call")
- };
+ let fn_ptr = match (llfn, instance) {
+ (Some(llfn), _) => llfn,
+ (None, Some(instance)) => bx.get_fn(instance),
+ _ => span_bug!(span, "no llfn for call"),
+ };
- let args: Vec<_> = args.iter().enumerate().map(|(i, arg)| {
- // The indices passed to simd_shuffle* in the
- // third argument must be constant. This is
- // checked by const-qualification, which also
- // promotes any complex rvalues to constants.
- if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") {
- match *arg {
- // The shuffle array argument is usually not an explicit constant,
- // but specified directly in the code. This means it gets promoted
- // and we can then extract the value by evaluating the promoted.
- mir::Operand::Copy(mir::Place::Promoted(box(index, ty))) |
- mir::Operand::Move(mir::Place::Promoted(box(index, ty))) => {
- let param_env = ty::ParamEnv::reveal_all();
- let cid = mir::interpret::GlobalId {
- instance: self.instance,
- promoted: Some(index),
- };
- let c = bx.tcx().const_eval(param_env.and(cid));
- let (llval, ty) = self.simd_shuffle_indices(
- &bx,
- terminator.source_info.span,
- ty,
- c,
- );
- return OperandRef {
- val: Immediate(llval),
- layout: bx.layout_of(ty),
- };
-
- },
- mir::Operand::Copy(_) |
- mir::Operand::Move(_) => {
- span_bug!(span, "shuffle indices must be constant");
- }
- mir::Operand::Constant(ref constant) => {
- let c = self.eval_mir_constant(&bx, constant);
- let (llval, ty) = self.simd_shuffle_indices(
- &bx,
- constant.span,
- constant.ty,
- c,
- );
- return OperandRef {
- val: Immediate(llval),
- layout: bx.layout_of(ty)
- };
- }
- }
- }
+ helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs,
+ destination.as_ref().map(|&(_, target)| (ret_dest, target)),
+ cleanup);
+ }
+}
- self.codegen_operand(&mut bx, arg)
- }).collect();
+impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
+ pub fn codegen_block(
+ &mut self,
+ bb: mir::BasicBlock,
+ ) {
+ let mut bx = self.build_block(bb);
+ let data = &self.mir[bb];
+ debug!("codegen_block({:?}={:?})", bb, data);
- let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
- bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
- terminator.source_info.span);
+ for statement in &data.statements {
+ bx = self.codegen_statement(bx, statement);
+ }
- if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
- self.store_return(&mut bx, ret_dest, &fn_ty.ret, dst.llval);
- }
+ self.codegen_terminator(bx, bb, data.terminator());
+ }
- if let Some((_, target)) = *destination {
- funclet_br(self, &mut bx, target);
- } else {
- bx.unreachable();
- }
+ fn codegen_terminator(
+ &mut self,
+ mut bx: Bx,
+ bb: mir::BasicBlock,
+ terminator: &mir::Terminator<'tcx>
+ ) {
+ debug!("codegen_terminator: {:?}", terminator);
- return;
- }
+ // Create the cleanup bundle, if needed.
+ let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb);
+ let helper = TerminatorCodegenHelper {
+ bb: &bb, terminator, funclet_bb
+ };
- // Split the rust-call tupled arguments off.
- let (first_args, untuple) = if abi == Abi::RustCall && !args.is_empty() {
- let (tup, args) = args.split_last().unwrap();
- (args, Some(tup))
- } else {
- (&args[..], None)
- };
+ self.set_debug_loc(&mut bx, terminator.source_info);
+ match terminator.kind {
+ mir::TerminatorKind::Resume => {
+ self.codegen_resume_terminator(helper, bx)
+ }
- 'make_args: for (i, arg) in first_args.iter().enumerate() {
- let mut op = self.codegen_operand(&mut bx, arg);
-
- if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
- if let Pair(..) = op.val {
- // In the case of Rc<Self>, we need to explicitly pass a
- // *mut RcBox<Self> with a Scalar (not ScalarPair) ABI. This is a hack
- // that is understood elsewhere in the compiler as a method on
- // `dyn Trait`.
- // To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until
- // we get a value of a built-in pointer type
- 'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
- && !op.layout.ty.is_region_ptr()
- {
- 'iter_fields: for i in 0..op.layout.fields.count() {
- let field = op.extract_field(&mut bx, i);
- if !field.layout.is_zst() {
- // we found the one non-zero-sized field that is allowed
- // now find *its* non-zero-sized field, or stop if it's a
- // pointer
- op = field;
- continue 'descend_newtypes
- }
- }
-
- span_bug!(span, "receiver has no non-zero-sized fields {:?}", op);
- }
+ mir::TerminatorKind::Abort => {
+ bx.abort();
+ bx.unreachable();
+ }
- // now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
- // data pointer and vtable. Look up the method in the vtable, and pass
- // the data pointer as the first argument
- match op.val {
- Pair(data_ptr, meta) => {
- llfn = Some(meth::VirtualIndex::from_index(idx)
- .get_fn(&mut bx, meta, &fn_ty));
- llargs.push(data_ptr);
- continue 'make_args
- }
- other => bug!("expected a Pair, got {:?}", other)
- }
- } else if let Ref(data_ptr, Some(meta), _) = op.val {
- // by-value dynamic dispatch
- llfn = Some(meth::VirtualIndex::from_index(idx)
- .get_fn(&mut bx, meta, &fn_ty));
- llargs.push(data_ptr);
- continue;
- } else {
- span_bug!(span, "can't codegen a virtual call on {:?}", op);
- }
- }
+ mir::TerminatorKind::Goto { target } => {
+ helper.funclet_br(self, &mut bx, target);
+ }
- // The callee needs to own the argument memory if we pass it
- // by-ref, so make a local copy of non-immediate constants.
- match (arg, op.val) {
- (&mir::Operand::Copy(_), Ref(_, None, _)) |
- (&mir::Operand::Constant(_), Ref(_, None, _)) => {
- let tmp = PlaceRef::alloca(&mut bx, op.layout, "const");
- op.val.store(&mut bx, tmp);
- op.val = Ref(tmp.llval, None, tmp.align);
- }
- _ => {}
- }
+ mir::TerminatorKind::SwitchInt {
+ ref discr, switch_ty, ref values, ref targets
+ } => {
+ self.codegen_switchint_terminator(helper, bx, discr, switch_ty,
+ values, targets);
+ }
- self.codegen_argument(&mut bx, op, &mut llargs, &fn_ty.args[i]);
- }
- if let Some(tup) = untuple {
- self.codegen_arguments_untupled(&mut bx, tup, &mut llargs,
- &fn_ty.args[first_args.len()..])
- }
+ mir::TerminatorKind::Return => {
+ self.codegen_return_terminator(bx);
+ }
- let fn_ptr = match (llfn, instance) {
- (Some(llfn), _) => llfn,
- (None, Some(instance)) => bx.get_fn(instance),
- _ => span_bug!(span, "no llfn for call"),
- };
+ mir::TerminatorKind::Unreachable => {
+ bx.unreachable();
+ }
- do_call(self, &mut bx, fn_ty, fn_ptr, &llargs,
- destination.as_ref().map(|&(_, target)| (ret_dest, target)),
- cleanup);
+ mir::TerminatorKind::Drop { ref location, target, unwind } => {
+ self.codegen_drop_terminator(helper, bx, location, target, unwind);
+ }
+
+ mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
+ self.codegen_assert_terminator(helper, bx, terminator, cond,
+ expected, msg, target, cleanup);
+ }
+
+ mir::TerminatorKind::DropAndReplace { .. } => {
+ bug!("undesugared DropAndReplace in codegen: {:?}", terminator);
+ }
+
+ mir::TerminatorKind::Call {
+ ref func,
+ ref args,
+ ref destination,
+ cleanup,
+ from_hir_call: _
+ } => {
+ self.codegen_call_terminator(helper, bx, terminator, func,
+ args, destination, cleanup);
}
mir::TerminatorKind::GeneratorDrop |
mir::TerminatorKind::Yield { .. } => bug!("generator ops in codegen"),
if fn_ret.is_ignore() {
return ReturnDest::Nothing;
}
- let dest = if let mir::Place::Local(index) = *dest {
+ let dest = if let mir::Place::Base(mir::PlaceBase::Local(index)) = *dest {
match self.locals[index] {
LocalRef::Place(dest) => dest,
LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
src: &mir::Operand<'tcx>,
dst: &mir::Place<'tcx>
) {
- if let mir::Place::Local(index) = *dst {
+ if let mir::Place::Base(mir::PlaceBase::Local(index)) = *dst {
match self.locals[index] {
LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
use rustc::ty::layout::{TyLayout, HasTyCtxt};
use rustc::mir::{self, Mir};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::session::config::DebugInfo;
use rustc_mir::monomorphize::Instance;
-use rustc_target::abi::call::{FnType, PassMode};
+use rustc_target::abi::call::{FnType, PassMode, IgnoreMode};
use crate::base;
use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext};
use crate::traits::*;
scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope<Bx::DIScope>>,
/// If this function is being monomorphized, this contains the type substitutions used.
- param_substs: &'tcx Substs<'tcx>,
+ param_substs: SubstsRef<'tcx>,
+
+ /// If this function is a C-variadic function, this contains the `PlaceRef` of the
+ /// "spoofed" `VaList`.
+ va_list_ref: Option<PlaceRef<'tcx, Bx::Value>>,
}
impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
assert!(!instance.substs.needs_infer());
instance.substs
},
+ va_list_ref: None,
};
let memory_locals = analyze::non_ssa_locals(&fx);
// Allocate variable and temp allocas
fx.locals = {
- let args = arg_local_refs(&mut bx, &fx, &fx.scopes, &memory_locals);
+ // FIXME(dlrobertson): This is ugly. Find a better way of getting the `PlaceRef` or
+ // `LocalRef` from `arg_local_refs`
+ let mut va_list_ref = None;
+ let args = arg_local_refs(&mut bx, &fx, &fx.scopes, &memory_locals, &mut va_list_ref);
+ fx.va_list_ref = va_list_ref;
let mut allocate_local = |local| {
let decl = &mir.local_decls[local];
debuginfo::MirDebugScope<Bx::DIScope>
>,
memory_locals: &BitSet<mir::Local>,
+ va_list_ref: &mut Option<PlaceRef<'tcx, Bx::Value>>,
) -> Vec<LocalRef<'tcx, Bx::Value>> {
let mir = fx.mir;
let tcx = fx.cx.tcx();
None
};
+ // Store the index of the last argument. This is used to
+ // call va_start on the va_list instead of attempting
+ // to store_fn_arg.
+ let last_arg_idx = if fx.fn_ty.args.is_empty() {
+ None
+ } else {
+ Some(fx.fn_ty.args.len() - 1)
+ };
+
mir.args_iter().enumerate().map(|(arg_index, local)| {
let arg_decl = &mir.local_decls[local];
// of putting everything in allocas just so we can use llvm.dbg.declare.
let local = |op| LocalRef::Operand(Some(op));
match arg.mode {
- PassMode::Ignore => {
+ PassMode::Ignore(IgnoreMode::Zst) => {
return local(OperandRef::new_zst(bx.cx(), arg.layout));
}
+ PassMode::Ignore(IgnoreMode::CVarArgs) => {
+ let backend_type = bx.cx().immediate_backend_type(arg.layout);
+ return local(OperandRef {
+ val: OperandValue::Immediate(bx.cx().const_undef(backend_type)),
+ layout: arg.layout,
+ });
+ }
PassMode::Direct(_) => {
let llarg = bx.get_param(bx.llfn(), llarg_idx as c_uint);
bx.set_value_name(llarg, &name);
indirect_operand.store(bx, tmp);
tmp
} else {
- let tmp = PlaceRef::alloca(bx, arg.layout, &name);
- bx.store_fn_arg(arg, &mut llarg_idx, tmp);
- tmp
+ if fx.fn_ty.c_variadic && last_arg_idx.map(|idx| arg_index == idx).unwrap_or(false) {
+ let va_list_impl = match arg_decl.ty.ty_adt_def() {
+ Some(adt) => adt.non_enum_variant(),
+ None => bug!("`va_list` language item improperly constructed")
+ };
+ match tcx.type_of(va_list_impl.fields[0].did).sty {
+ ty::Ref(_, ty, _) => {
+ // If the underlying structure the `VaList` contains is a structure,
+ // we need to allocate it (e.g., X86_64 on Linux).
+ let tmp = PlaceRef::alloca(bx, arg.layout, &name);
+ if let ty::Adt(..) = ty.sty {
+ let layout = bx.layout_of(ty);
+ // Create an unnamed allocation for the backing structure
+ // and store it in the the spoofed `VaList`.
+ let backing = PlaceRef::alloca(bx, layout, "");
+ bx.store(backing.llval, tmp.llval, layout.align.abi);
+ }
+ // Call `va_start` on the spoofed `VaList`.
+ bx.va_start(tmp.llval);
+ *va_list_ref = Some(tmp);
+ tmp
+ }
+ _ => bug!("improperly constructed `va_list` lang item"),
+ }
+ } else {
+ let tmp = PlaceRef::alloca(bx, arg.layout, &name);
+ bx.store_fn_arg(arg, &mut llarg_idx, tmp);
+ tmp
+ }
};
arg_scope.map(|scope| {
// Is this a regular argument?
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
- if let mir::Place::Local(index) = *place {
+ if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
match self.locals[index] {
LocalRef::Operand(Some(o)) => {
return Some(o);
let cx = self.cx;
let tcx = self.cx.tcx();
- if let mir::Place::Local(index) = *place {
+ if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
match self.locals[index] {
LocalRef::Place(place) => {
return place;
}
let result = match *place {
- mir::Place::Local(_) => bug!(), // handled above
- mir::Place::Promoted(box (index, ty)) => {
+ mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
+ mir::Place::Base(mir::PlaceBase::Promoted(box (index, ty))) => {
let param_env = ty::ParamEnv::reveal_all();
let cid = mir::interpret::GlobalId {
instance: self.instance,
}
}
}
- mir::Place::Static(box mir::Static { def_id, ty }) => {
+ mir::Place::Base(mir::PlaceBase::Static(box mir::Static { def_id, ty })) => {
// NB: The layout of a static may be unsized as is the case when working
// with a static that is an extern_type.
let layout = cx.layout_of(self.monomorphize(&ty));
cg_base.project_field(bx, field.index())
}
mir::ProjectionElem::Index(index) => {
- let index = &mir::Operand::Copy(mir::Place::Local(index));
+ let index = &mir::Operand::Copy(
+ mir::Place::Base(mir::PlaceBase::Local(index))
+ );
let index = self.codegen_operand(bx, index);
let llindex = index.immediate();
cg_base.project_index(bx, llindex)
) -> Bx::Value {
// ZST are passed as operands and require special handling
// because codegen_place() panics if Local is operand.
- if let mir::Place::Local(index) = *place {
+ if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
if let LocalRef::Operand(Some(op)) = self.locals[index] {
if let ty::Array(_, n) = op.layout.ty.sty {
let n = n.unwrap_usize(bx.cx().tcx());
self.set_debug_loc(&mut bx, statement.source_info);
match statement.kind {
mir::StatementKind::Assign(ref place, ref rvalue) => {
- if let mir::Place::Local(index) = *place {
+ if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
match self.locals[index] {
LocalRef::Place(cg_dest) => {
self.codegen_rvalue(bx, cg_dest, rvalue)
fn abort(&mut self);
fn assume(&mut self, val: Self::Value);
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;
+ /// Trait method used to inject `va_start` on the "spoofed" `VaList` in
+ /// Rust defined C-variadic functions.
+ fn va_start(&mut self, val: Self::Value) -> Self::Value;
+ /// Trait method used to inject `va_end` on the "spoofed" `VaList` before
+ /// Rust defined C-variadic functions return.
+ fn va_end(&mut self, val: Self::Value) -> Self::Value;
}
use rustc::ich::NodeIdHashingMode;
use rustc::ty::item_path::{self, ItemPathBuffer, RootMode};
use rustc::ty::query::Providers;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::util::common::record_time;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
// values for generic type parameters,
// if any.
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
) -> u64 {
debug!(
"get_symbol_hash(def_id={:?}, parameters={:?})",
use rustc::hir;
use rustc::ty::TyCtxt;
-use syntax::ast;
use rustc_mir::monomorphize::Instance;
impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> {
fn process_attrs(&mut self,
- node_id: ast::NodeId) {
+ hir_id: hir::HirId) {
let tcx = self.tcx;
- let def_id = tcx.hir().local_def_id(node_id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
for attr in tcx.get_attrs(def_id).iter() {
if attr.check_name(SYMBOL_NAME) {
// for now, can only use on monomorphic names
impl<'a, 'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- self.process_attrs(item.id);
+ self.process_attrs(item.hir_id);
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
- self.process_attrs(trait_item.id);
+ self.process_attrs(trait_item.hir_id);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
- self.process_attrs(impl_item.id);
+ self.process_attrs(impl_item.hir_id);
}
}
[dependencies]
ena = "0.11"
log = "0.4"
+jobserver_crate = { version = "0.1", package = "jobserver" }
+lazy_static = "1"
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
serialize = { path = "../libserialize" }
graphviz = { path = "../libgraphviz" }
cfg-if = "0.1.2"
stable_deref_trait = "1.0.0"
-rayon = { version = "0.1.1", package = "rustc-rayon" }
-rayon-core = { version = "0.1.1", package = "rustc-rayon-core" }
+rayon = { version = "0.1.2", package = "rustc-rayon" }
+rayon-core = { version = "0.1.2", package = "rustc-rayon-core" }
rustc-hash = "1.0.1"
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
--- /dev/null
+use jobserver_crate::{Client, HelperThread, Acquired};
+use lazy_static::lazy_static;
+use std::sync::{Condvar, Arc, Mutex};
+use std::mem;
+
+#[derive(Default)]
+struct LockedProxyData {
+ /// The number of free thread tokens, this may include the implicit token given to the process
+ free: usize,
+
+ /// The number of threads waiting for a token
+ waiters: usize,
+
+ /// The number of tokens we requested from the server
+ requested: usize,
+
+ /// Stored tokens which will be dropped when we no longer need them
+ tokens: Vec<Acquired>,
+}
+
+impl LockedProxyData {
+ fn request_token(&mut self, thread: &Mutex<HelperThread>) {
+ self.requested += 1;
+ thread.lock().unwrap().request_token();
+ }
+
+ fn release_token(&mut self, cond_var: &Condvar) {
+ if self.waiters > 0 {
+ self.free += 1;
+ cond_var.notify_one();
+ } else {
+ if self.tokens.is_empty() {
+ // We are returning the implicit token
+ self.free += 1;
+ } else {
+ // Return a real token to the server
+ self.tokens.pop().unwrap();
+ }
+ }
+ }
+
+ fn take_token(&mut self, thread: &Mutex<HelperThread>) -> bool {
+ if self.free > 0 {
+ self.free -= 1;
+ self.waiters -= 1;
+
+ // We stole some token reqested by someone else
+ // Request another one
+ if self.requested + self.free < self.waiters {
+ self.request_token(thread);
+ }
+
+ true
+ } else {
+ false
+ }
+ }
+
+ fn new_requested_token(&mut self, token: Acquired, cond_var: &Condvar) {
+ self.requested -= 1;
+
+ // Does anything need this token?
+ if self.waiters > 0 {
+ self.free += 1;
+ self.tokens.push(token);
+ cond_var.notify_one();
+ } else {
+ // Otherwise we'll just drop it
+ mem::drop(token);
+ }
+ }
+}
+
+#[derive(Default)]
+struct ProxyData {
+ lock: Mutex<LockedProxyData>,
+ cond_var: Condvar,
+}
+
+/// A helper type which makes managing jobserver tokens easier.
+/// It also allows you to treat the implicit token given to the process
+/// in the same manner as requested tokens.
+struct Proxy {
+ thread: Mutex<HelperThread>,
+ data: Arc<ProxyData>,
+}
+
+lazy_static! {
+ // We can only call `from_env` once per process
+
+ // Note that this is unsafe because it may misinterpret file descriptors
+ // on Unix as jobserver file descriptors. We hopefully execute this near
+ // the beginning of the process though to ensure we don't get false
+ // positives, or in other words we try to execute this before we open
+ // any file descriptors ourselves.
+ //
+ // Pick a "reasonable maximum" if we don't otherwise have
+ // a jobserver in our environment, capping out at 32 so we
+ // don't take everything down by hogging the process run queue.
+ // The fixed number is used to have deterministic compilation
+ // across machines.
+ //
+ // Also note that we stick this in a global because there could be
+ // multiple rustc instances in this process, and the jobserver is
+ // per-process.
+ static ref GLOBAL_CLIENT: Client = unsafe {
+ Client::from_env().unwrap_or_else(|| {
+ Client::new(32).expect("failed to create jobserver")
+ })
+ };
+
+ static ref GLOBAL_PROXY: Proxy = {
+ let data = Arc::new(ProxyData::default());
+
+ Proxy {
+ data: data.clone(),
+ thread: Mutex::new(client().into_helper_thread(move |token| {
+ data.lock.lock().unwrap().new_requested_token(token.unwrap(), &data.cond_var);
+ }).unwrap()),
+ }
+ };
+}
+
+pub fn client() -> Client {
+ GLOBAL_CLIENT.clone()
+}
+
+pub fn acquire_thread() {
+ GLOBAL_PROXY.acquire_token();
+}
+
+pub fn release_thread() {
+ GLOBAL_PROXY.release_token();
+}
+
+impl Proxy {
+ fn release_token(&self) {
+ self.data.lock.lock().unwrap().release_token(&self.data.cond_var);
+ }
+
+ fn acquire_token(&self) {
+ let mut data = self.data.lock.lock().unwrap();
+ data.waiters += 1;
+ if data.take_token(&self.thread) {
+ return;
+ }
+ // Request a token for us
+ data.request_token(&self.thread);
+ loop {
+ data = self.data.cond_var.wait(data).unwrap();
+ if data.take_token(&self.thread) {
+ return;
+ }
+ }
+ }
+}
pub mod graph;
pub mod indexed_vec;
pub mod interner;
+pub mod jobserver;
pub mod obligation_forest;
pub mod owning_ref;
pub mod ptr_key;
graphviz = { path = "../libgraphviz" }
log = "0.4"
env_logger = { version = "0.5", default-features = false }
-rustc-rayon = "0.1.1"
-scoped-tls = { version = "0.1.1", features = ["nightly"] }
+rustc-rayon = "0.1.2"
+scoped-tls = "1.0"
rustc = { path = "../librustc" }
rustc_allocator = { path = "../librustc_allocator" }
rustc_target = { path = "../librustc_target" }
rustc_traits = { path = "../librustc_traits" }
rustc_codegen_utils = { path = "../librustc_codegen_utils" }
rustc_typeck = { path = "../librustc_typeck" }
+rustc_interface = { path = "../librustc_interface" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
use rustc::hir;
use rustc::hir::lowering::lower_crate;
use rustc::hir::map as hir_map;
+use rustc::hir::def_id::LOCAL_CRATE;
use rustc::lint;
use rustc::middle::{self, reachable, resolve_lifetime, stability};
use rustc::ty::{self, AllArenas, Resolutions, TyCtxt};
use rustc::traits;
use rustc::util::common::{install_panic_hook, time, ErrorReported};
use rustc::util::profiling::ProfileCategory;
-use rustc::session::{CompileResult, CrateDisambiguator, Session};
+use rustc::session::{CompileResult, Session};
use rustc::session::CompileIncomplete;
use rustc::session::config::{self, Input, OutputFilenames, OutputType};
use rustc::session::search_paths::PathKind;
use rustc_allocator as allocator;
use rustc_borrowck as borrowck;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::{self, Lock};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::jobserver;
use rustc_incremental;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::{self, CStore};
use rustc_mir as mir;
-use rustc_passes::{self, ast_validation, hir_stats, loops, rvalue_promotion, layout_test};
+use rustc_passes::{self, ast_validation, hir_stats};
use rustc_plugin as plugin;
use rustc_plugin::registry::Registry;
use rustc_privacy;
use rustc_resolve::{Resolver, ResolverArenas};
use rustc_traits;
use rustc_typeck as typeck;
-use syntax::{self, ast, attr, diagnostics, visit};
+use syntax::{self, ast, diagnostics, visit};
use syntax::early_buffered_lints::BufferedEarlyLint;
use syntax::ext::base::ExtCtxt;
use syntax::mut_visit::MutVisitor;
use syntax::parse::{self, PResult};
use syntax::util::node_count::NodeCounter;
-use syntax::util::lev_distance::find_best_match_for_name;
-use syntax::symbol::Symbol;
-use syntax_pos::{FileName, hygiene};
+use syntax_pos::hygiene;
use syntax_ext;
use serialize::json;
use std::env;
use std::ffi::OsString;
use std::fs;
-use std::io::{self, Write};
use std::iter;
use std::path::{Path, PathBuf};
use std::sync::mpsc;
-use pretty::ReplaceBodyWithLoop;
-use proc_macro_decls;
-use profile;
+use rustc_interface::{util, profile, passes};
use super::Compilation;
#[cfg(not(parallel_compiler))]
let gcx_ptr = &Lock::new(0);
let config = ThreadPoolBuilder::new()
- .num_threads(Session::threads_from_opts(&opts))
+ .acquire_thread_handler(jobserver::acquire_thread)
+ .release_thread_handler(jobserver::release_thread)
+ .num_threads(Session::threads_from_count(opts.debugging_opts.threads))
.deadlock_handler(|| unsafe { ty::query::handle_deadlock() })
.stack_size(::STACK_SIZE);
(compile_state.krate.unwrap(), compile_state.registry)
};
- let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
+ let outputs = util::build_output_filenames(input, outdir, output, &krate.attrs, sess);
let crate_name =
::rustc_codegen_utils::link::find_crate_name(Some(sess), &krate.attrs, input);
install_panic_hook();
)?
};
- let output_paths = generated_output_paths(sess, &outputs, output.is_some(), &crate_name);
+ let output_paths = passes::generated_output_paths(
+ sess,
+ &outputs,
+ output.is_some(),
+ &crate_name
+ );
// Ensure the source file isn't accidentally overwritten during compilation.
if let Some(ref input_path) = *input_path {
if sess.opts.will_create_output_file() {
- if output_contains_path(&output_paths, input_path) {
+ if passes::output_contains_path(&output_paths, input_path) {
sess.err(&format!(
"the input file \"{}\" would be overwritten by the generated \
executable",
));
return Err(CompileIncomplete::Stopped);
}
- if let Some(dir_path) = output_conflicts_with_dir(&output_paths) {
+ if let Some(dir_path) = passes::output_conflicts_with_dir(&output_paths) {
sess.err(&format!(
"the generated executable for the input file \"{}\" conflicts with the \
existing directory \"{}\"",
}
}
- write_out_deps(sess, &outputs, &output_paths);
+ passes::write_out_deps(sess, &outputs, &output_paths);
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1
{
Ok((outputs.clone(), ongoing_codegen, tcx.dep_graph.clone()))
},
- )??
+ )?
};
if sess.opts.debugging_opts.print_type_sizes {
Ok(())
}
-pub fn source_name(input: &Input) -> FileName {
- match *input {
- Input::File(ref ifile) => ifile.clone().into(),
- Input::Str { ref name, .. } => name.clone(),
- }
-}
-
/// CompileController is used to customize compilation, it allows compilation to
/// be stopped and/or to call arbitrary code at various points in compilation.
/// It also allows for various flags to be set to influence what information gets
// these need to be set "early" so that expansion sees `quote` if enabled.
sess.init_features(features);
- let crate_types = collect_crate_types(sess, &krate.attrs);
+ let crate_types = util::collect_crate_types(sess, &krate.attrs);
sess.crate_types.set(crate_types);
- let disambiguator = compute_crate_disambiguator(sess);
+ let disambiguator = util::compute_crate_disambiguator(sess);
sess.crate_disambiguator.set(disambiguator);
rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator);
// If we're actually rustdoc then there's no need to actually compile
// anything, so switch everything to just looping
if sess.opts.actually_rustdoc {
- ReplaceBodyWithLoop::new(sess).visit_crate(&mut krate);
+ util::ReplaceBodyWithLoop::new(sess).visit_crate(&mut krate);
}
let (has_proc_macro_decls, has_global_allocator) = time(sess, "AST validation", || {
}
pub fn default_provide(providers: &mut ty::query::Providers) {
- proc_macro_decls::provide(providers);
+ rustc_interface::passes::provide(providers);
plugin::build::provide(providers);
hir::provide(providers);
borrowck::provide(providers);
name: &str,
output_filenames: &OutputFilenames,
f: F,
-) -> Result<R, CompileIncomplete>
+) -> R
where
F: for<'a> FnOnce(
TyCtxt<'a, 'tcx, 'tcx>,
// tcx available.
time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
- parallel!({
- time(sess, "looking for entry point", || {
- middle::entry::find_entry_point(tcx)
- });
-
- time(sess, "looking for plugin registrar", || {
- plugin::build::find_plugin_registrar(tcx)
- });
-
- time(sess, "looking for derive registrar", || {
- proc_macro_decls::find(tcx)
- });
- }, {
- time(sess, "loop checking", || loops::check_crate(tcx));
- }, {
- time(sess, "attribute checking", || {
- hir::check_attr::check_crate(tcx)
- });
- }, {
- time(sess, "stability checking", || {
- stability::check_unstable_api_usage(tcx)
- });
- });
-
- // passes are timed inside typeck
- match typeck::check_crate(tcx) {
- Ok(x) => x,
- Err(x) => {
- f(tcx, rx, Err(x));
- return Err(x);
- }
- }
-
- time(sess, "misc checking", || {
- parallel!({
- time(sess, "rvalue promotion", || {
- rvalue_promotion::check_crate(tcx)
- });
- }, {
- time(sess, "intrinsic checking", || {
- middle::intrinsicck::check_crate(tcx)
- });
- }, {
- time(sess, "match checking", || mir::matchck_crate(tcx));
- }, {
- // this must run before MIR dump, because
- // "not all control paths return a value" is reported here.
- //
- // maybe move the check to a MIR pass?
- time(sess, "liveness checking", || {
- middle::liveness::check_crate(tcx)
- });
- });
- });
-
- // Abort so we don't try to construct MIR with liveness errors.
- // We also won't want to continue with errors from rvalue promotion
- tcx.sess.abort_if_errors();
-
- time(sess, "borrow checking", || {
- if tcx.use_ast_borrowck() {
- borrowck::check_crate(tcx);
- }
- });
-
- time(sess,
- "MIR borrow checking",
- || tcx.par_body_owners(|def_id| { tcx.ensure().mir_borrowck(def_id); }));
-
- time(sess, "dumping chalk-like clauses", || {
- rustc_traits::lowering::dump_program_clauses(tcx);
- });
-
- time(sess, "MIR effect checking", || {
- for def_id in tcx.body_owners() {
- mir::transform::check_unsafety::check_unsafety(tcx, def_id)
- }
- });
-
- time(sess, "layout testing", || layout_test::test_layout(tcx));
-
- // Avoid overwhelming user with errors if borrow checking failed.
- // I'm not sure how helpful this is, to be honest, but it avoids
- // a
- // lot of annoying errors in the compile-fail tests (basically,
- // lint warnings and so on -- kindck used to do this abort, but
- // kindck is gone now). -nmatsakis
- if sess.err_count() > 0 {
- return Ok(f(tcx, rx, sess.compile_status()));
- }
+ tcx.analysis(LOCAL_CRATE).ok();
- time(sess, "misc checking", || {
- parallel!({
- time(sess, "privacy checking", || {
- rustc_privacy::check_crate(tcx)
- });
- }, {
- time(sess, "death checking", || middle::dead::check_crate(tcx));
- }, {
- time(sess, "unused lib feature checking", || {
- stability::check_unused_or_stable_features(tcx)
- });
- }, {
- time(sess, "lint checking", || lint::check_crate(tcx));
- });
- });
-
- return Ok(f(tcx, rx, tcx.sess.compile_status()));
+ f(tcx, rx, tcx.sess.compile_status())
},
)
}
codegen
}
-
-fn escape_dep_filename(filename: &FileName) -> String {
- // Apparently clang and gcc *only* escape spaces:
- // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
- filename.to_string().replace(" ", "\\ ")
-}
-
-// Returns all the paths that correspond to generated files.
-fn generated_output_paths(
- sess: &Session,
- outputs: &OutputFilenames,
- exact_name: bool,
- crate_name: &str,
-) -> Vec<PathBuf> {
- let mut out_filenames = Vec::new();
- for output_type in sess.opts.output_types.keys() {
- let file = outputs.path(*output_type);
- match *output_type {
- // If the filename has been overridden using `-o`, it will not be modified
- // by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
- OutputType::Exe if !exact_name => for crate_type in sess.crate_types.borrow().iter() {
- let p = ::rustc_codegen_utils::link::filename_for_input(
- sess,
- *crate_type,
- crate_name,
- outputs,
- );
- out_filenames.push(p);
- },
- OutputType::DepInfo if sess.opts.debugging_opts.dep_info_omit_d_target => {
- // Don't add the dep-info output when omitting it from dep-info targets
- }
- _ => {
- out_filenames.push(file);
- }
- }
- }
- out_filenames
-}
-
-// Runs `f` on every output file path and returns the first non-None result, or None if `f`
-// returns None for every file path.
-fn check_output<F, T>(output_paths: &[PathBuf], f: F) -> Option<T>
-where
- F: Fn(&PathBuf) -> Option<T>,
-{
- for output_path in output_paths {
- if let Some(result) = f(output_path) {
- return Some(result);
- }
- }
- None
-}
-
-pub fn output_contains_path(output_paths: &[PathBuf], input_path: &PathBuf) -> bool {
- let input_path = input_path.canonicalize().ok();
- if input_path.is_none() {
- return false;
- }
- let check = |output_path: &PathBuf| {
- if output_path.canonicalize().ok() == input_path {
- Some(())
- } else {
- None
- }
- };
- check_output(output_paths, check).is_some()
-}
-
-pub fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> {
- let check = |output_path: &PathBuf| {
- if output_path.is_dir() {
- Some(output_path.clone())
- } else {
- None
- }
- };
- check_output(output_paths, check)
-}
-
-fn write_out_deps(sess: &Session, outputs: &OutputFilenames, out_filenames: &[PathBuf]) {
- // Write out dependency rules to the dep-info file if requested
- if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
- return;
- }
- let deps_filename = outputs.path(OutputType::DepInfo);
-
- let result = (|| -> io::Result<()> {
- // Build a list of files used to compile the output and
- // write Makefile-compatible dependency rules
- let files: Vec<String> = sess.source_map()
- .files()
- .iter()
- .filter(|fmap| fmap.is_real_file())
- .filter(|fmap| !fmap.is_imported())
- .map(|fmap| escape_dep_filename(&fmap.name))
- .collect();
- let mut file = fs::File::create(&deps_filename)?;
- for path in out_filenames {
- writeln!(file, "{}: {}\n", path.display(), files.join(" "))?;
- }
-
- // Emit a fake target for each input file to the compilation. This
- // prevents `make` from spitting out an error if a file is later
- // deleted. For more info see #28735
- for path in files {
- writeln!(file, "{}:", path)?;
- }
- Ok(())
- })();
-
- if let Err(e) = result {
- sess.fatal(&format!(
- "error writing dependencies to `{}`: {}",
- deps_filename.display(),
- e
- ));
- }
-}
-
-pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
- // Unconditionally collect crate types from attributes to make them used
- let attr_types: Vec<config::CrateType> = attrs
- .iter()
- .filter_map(|a| {
- if a.check_name("crate_type") {
- match a.value_str() {
- Some(ref n) if *n == "rlib" => Some(config::CrateType::Rlib),
- Some(ref n) if *n == "dylib" => Some(config::CrateType::Dylib),
- Some(ref n) if *n == "cdylib" => Some(config::CrateType::Cdylib),
- Some(ref n) if *n == "lib" => Some(config::default_lib_output()),
- Some(ref n) if *n == "staticlib" => Some(config::CrateType::Staticlib),
- Some(ref n) if *n == "proc-macro" => Some(config::CrateType::ProcMacro),
- Some(ref n) if *n == "bin" => Some(config::CrateType::Executable),
- Some(ref n) => {
- let crate_types = vec![
- Symbol::intern("rlib"),
- Symbol::intern("dylib"),
- Symbol::intern("cdylib"),
- Symbol::intern("lib"),
- Symbol::intern("staticlib"),
- Symbol::intern("proc-macro"),
- Symbol::intern("bin")
- ];
-
- if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().node {
- let span = spanned.span;
- let lev_candidate = find_best_match_for_name(
- crate_types.iter(),
- &n.as_str(),
- None
- );
- if let Some(candidate) = lev_candidate {
- session.buffer_lint_with_diagnostic(
- lint::builtin::UNKNOWN_CRATE_TYPES,
- ast::CRATE_NODE_ID,
- span,
- "invalid `crate_type` value",
- lint::builtin::BuiltinLintDiagnostics::
- UnknownCrateTypes(
- span,
- "did you mean".to_string(),
- format!("\"{}\"", candidate)
- )
- );
- } else {
- session.buffer_lint(
- lint::builtin::UNKNOWN_CRATE_TYPES,
- ast::CRATE_NODE_ID,
- span,
- "invalid `crate_type` value"
- );
- }
- }
- None
- }
- None => None
- }
- } else {
- None
- }
- })
- .collect();
-
- // If we're generating a test executable, then ignore all other output
- // styles at all other locations
- if session.opts.test {
- return vec![config::CrateType::Executable];
- }
-
- // Only check command line flags if present. If no types are specified by
- // command line, then reuse the empty `base` Vec to hold the types that
- // will be found in crate attributes.
- let mut base = session.opts.crate_types.clone();
- if base.is_empty() {
- base.extend(attr_types);
- if base.is_empty() {
- base.push(::rustc_codegen_utils::link::default_output_for_target(
- session,
- ));
- } else {
- base.sort();
- base.dedup();
- }
- }
-
- base.retain(|crate_type| {
- let res = !::rustc_codegen_utils::link::invalid_output_for_target(session, *crate_type);
-
- if !res {
- session.warn(&format!(
- "dropping unsupported crate type `{}` for target `{}`",
- *crate_type, session.opts.target_triple
- ));
- }
-
- res
- });
-
- base
-}
-
-pub fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
- use std::hash::Hasher;
-
- // The crate_disambiguator is a 128 bit hash. The disambiguator is fed
- // into various other hashes quite a bit (symbol hashes, incr. comp. hashes,
- // debuginfo type IDs, etc), so we don't want it to be too wide. 128 bits
- // should still be safe enough to avoid collisions in practice.
- let mut hasher = StableHasher::<Fingerprint>::new();
-
- let mut metadata = session.opts.cg.metadata.clone();
- // We don't want the crate_disambiguator to dependent on the order
- // -C metadata arguments, so sort them:
- metadata.sort();
- // Every distinct -C metadata value is only incorporated once:
- metadata.dedup();
-
- hasher.write(b"metadata");
- for s in &metadata {
- // Also incorporate the length of a metadata string, so that we generate
- // different values for `-Cmetadata=ab -Cmetadata=c` and
- // `-Cmetadata=a -Cmetadata=bc`
- hasher.write_usize(s.len());
- hasher.write(s.as_bytes());
- }
-
- // Also incorporate crate type, so that we don't get symbol conflicts when
- // linking against a library of the same name, if this is an executable.
- let is_exe = session
- .crate_types
- .borrow()
- .contains(&config::CrateType::Executable);
- hasher.write(if is_exe { b"exe" } else { b"lib" });
-
- CrateDisambiguator::from(hasher.finish())
-}
-
-pub fn build_output_filenames(
- input: &Input,
- odir: &Option<PathBuf>,
- ofile: &Option<PathBuf>,
- attrs: &[ast::Attribute],
- sess: &Session,
-) -> OutputFilenames {
- match *ofile {
- None => {
- // "-" as input file will cause the parser to read from stdin so we
- // have to make up a name
- // We want to toss everything after the final '.'
- let dirpath = (*odir).as_ref().cloned().unwrap_or_default();
-
- // If a crate name is present, we use it as the link name
- let stem = sess.opts
- .crate_name
- .clone()
- .or_else(|| attr::find_crate_name(attrs).map(|n| n.to_string()))
- .unwrap_or_else(|| input.filestem().to_owned());
-
- OutputFilenames {
- out_directory: dirpath,
- out_filestem: stem,
- single_output_file: None,
- extra: sess.opts.cg.extra_filename.clone(),
- outputs: sess.opts.output_types.clone(),
- }
- }
-
- Some(ref out_file) => {
- let unnamed_output_types = sess.opts
- .output_types
- .values()
- .filter(|a| a.is_none())
- .count();
- let ofile = if unnamed_output_types > 1 {
- sess.warn(
- "due to multiple output types requested, the explicitly specified \
- output file name will be adapted for each output type",
- );
- None
- } else {
- Some(out_file.clone())
- };
- if *odir != None {
- sess.warn("ignoring --out-dir flag due to -o flag");
- }
- if !sess.opts.cg.extra_filename.is_empty() {
- sess.warn("ignoring -C extra-filename flag due to -o flag");
- }
-
- OutputFilenames {
- out_directory: out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
- out_filestem: out_file
- .file_stem()
- .unwrap_or_default()
- .to_str()
- .unwrap()
- .to_string(),
- single_output_file: ofile,
- extra: sess.opts.cg.extra_filename.clone(),
- outputs: sess.opts.output_types.clone(),
- }
- }
- }
-}
extern crate rustc_allocator;
extern crate rustc_target;
extern crate rustc_borrowck;
-#[macro_use]
extern crate rustc_data_structures;
extern crate rustc_errors as errors;
extern crate rustc_passes;
extern crate rustc_traits;
extern crate rustc_codegen_utils;
extern crate rustc_typeck;
+extern crate rustc_interface;
extern crate scoped_tls;
extern crate serialize;
extern crate smallvec;
use rustc_save_analysis::DumpHandler;
use rustc_data_structures::sync::{self, Lrc, Ordering::SeqCst};
use rustc_data_structures::OnDrop;
-use rustc::session::{self, config, Session, build_session, CompileResult};
+use rustc::session::{self, config, Session, build_session, CompileResult, DiagnosticOutput};
use rustc::session::CompileIncomplete;
use rustc::session::config::{Input, PrintRequest, ErrorOutputType};
use rustc::session::config::nightly_options;
-use rustc::session::filesearch;
use rustc::session::{early_error, early_warn};
use rustc::lint::Lint;
use rustc::lint;
use rustc_metadata::locator;
use rustc_metadata::cstore::CStore;
-use rustc_metadata::dynamic_lib::DynamicLibrary;
use rustc::util::common::{time, ErrorReported};
use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_interface::util::{self, get_codegen_sysroot};
use serialize::json::ToJson;
use std::borrow::Cow;
use std::cmp::max;
use std::default::Default;
-use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::env;
use std::error::Error;
use std::ffi::OsString;
use std::fmt::{self, Display};
use std::io::{self, Read, Write};
-use std::mem;
use std::panic;
-use std::path::{PathBuf, Path};
+use std::path::PathBuf;
use std::process::{self, Command, Stdio};
use std::str;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::{Once, ONCE_INIT};
use std::thread;
use syntax::ast;
#[cfg(test)]
mod test;
-pub mod profile;
pub mod driver;
pub mod pretty;
-mod proc_macro_decls;
-
-pub mod target_features {
- use syntax::ast;
- use syntax::symbol::Symbol;
- use rustc::session::Session;
- use rustc_codegen_utils::codegen_backend::CodegenBackend;
-
- /// Adds `target_feature = "..."` cfgs for a variety of platform
- /// specific features (SSE, NEON etc.).
- ///
- /// This is performed by checking whether a whitelisted set of
- /// features is available on the target machine, by querying LLVM.
- pub fn add_configuration(cfg: &mut ast::CrateConfig,
- sess: &Session,
- codegen_backend: &dyn CodegenBackend) {
- let tf = Symbol::intern("target_feature");
-
- cfg.extend(codegen_backend.target_features(sess).into_iter().map(|feat| (tf, Some(feat))));
-
- if sess.crt_static_feature() {
- cfg.insert((tf, Some(Symbol::intern("crt-static"))));
- }
- }
-}
/// Exit status code used for successful compilation and help output.
pub const EXIT_SUCCESS: isize = 0;
}
}
-fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
- let lib = DynamicLibrary::open(Some(path)).unwrap_or_else(|err| {
- let err = format!("couldn't load codegen backend {:?}: {:?}", path, err);
- early_error(ErrorOutputType::default(), &err);
- });
- unsafe {
- match lib.symbol("__rustc_codegen_backend") {
- Ok(f) => {
- mem::forget(lib);
- mem::transmute::<*mut u8, _>(f)
- }
- Err(e) => {
- let err = format!("couldn't load codegen backend as it \
- doesn't export the `__rustc_codegen_backend` \
- symbol: {:?}", e);
- early_error(ErrorOutputType::default(), &err);
- }
- }
- }
-}
-
-pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
- static INIT: Once = ONCE_INIT;
-
- #[allow(deprecated)]
- #[no_debug]
- static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
-
- INIT.call_once(|| {
- let codegen_name = sess.opts.debugging_opts.codegen_backend.as_ref()
- .unwrap_or(&sess.target.target.options.codegen_backend);
- let backend = match &codegen_name[..] {
- "metadata_only" => {
- rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::boxed
- }
- filename if filename.contains(".") => {
- load_backend_from_dylib(filename.as_ref())
- }
- codegen_name => get_codegen_sysroot(codegen_name),
- };
-
- unsafe {
- LOAD = backend;
- }
- });
- let backend = unsafe { LOAD() };
- backend.init(sess);
- backend
-}
-
-fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
- // For now we only allow this function to be called once as it'll dlopen a
- // few things, which seems to work best if we only do that once. In
- // general this assertion never trips due to the once guard in `get_codegen_backend`,
- // but there's a few manual calls to this function in this file we protect
- // against.
- static LOADED: AtomicBool = AtomicBool::new(false);
- assert!(!LOADED.fetch_or(true, Ordering::SeqCst),
- "cannot load the default codegen backend twice");
-
- // When we're compiling this library with `--test` it'll run as a binary but
- // not actually exercise much functionality. As a result most of the logic
- // here is defunkt (it assumes we're a dynamic library in a sysroot) so
- // let's just return a dummy creation function which won't be used in
- // general anyway.
- if cfg!(test) {
- return rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::boxed
- }
-
- let target = session::config::host_triple();
- let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()];
- let path = current_dll_path()
- .and_then(|s| s.canonicalize().ok());
- if let Some(dll) = path {
- // use `parent` twice to chop off the file name and then also the
- // directory containing the dll which should be either `lib` or `bin`.
- if let Some(path) = dll.parent().and_then(|p| p.parent()) {
- // The original `path` pointed at the `rustc_driver` crate's dll.
- // Now that dll should only be in one of two locations. The first is
- // in the compiler's libdir, for example `$sysroot/lib/*.dll`. The
- // other is the target's libdir, for example
- // `$sysroot/lib/rustlib/$target/lib/*.dll`.
- //
- // We don't know which, so let's assume that if our `path` above
- // ends in `$target` we *could* be in the target libdir, and always
- // assume that we may be in the main libdir.
- sysroot_candidates.push(path.to_owned());
-
- if path.ends_with(target) {
- sysroot_candidates.extend(path.parent() // chop off `$target`
- .and_then(|p| p.parent()) // chop off `rustlib`
- .and_then(|p| p.parent()) // chop off `lib`
- .map(|s| s.to_owned()));
- }
- }
- }
-
- let sysroot = sysroot_candidates.iter()
- .map(|sysroot| {
- let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
- sysroot.join(libdir).with_file_name(
- option_env!("CFG_CODEGEN_BACKENDS_DIR").unwrap_or("codegen-backends"))
- })
- .filter(|f| {
- info!("codegen backend candidate: {}", f.display());
- f.exists()
- })
- .next();
- let sysroot = sysroot.unwrap_or_else(|| {
- let candidates = sysroot_candidates.iter()
- .map(|p| p.display().to_string())
- .collect::<Vec<_>>()
- .join("\n* ");
- let err = format!("failed to find a `codegen-backends` folder \
- in the sysroot candidates:\n* {}", candidates);
- early_error(ErrorOutputType::default(), &err);
- });
- info!("probing {} for a codegen backend", sysroot.display());
-
- let d = sysroot.read_dir().unwrap_or_else(|e| {
- let err = format!("failed to load default codegen backend, couldn't \
- read `{}`: {}", sysroot.display(), e);
- early_error(ErrorOutputType::default(), &err);
- });
-
- let mut file: Option<PathBuf> = None;
-
- let expected_name = format!("rustc_codegen_llvm-{}", backend_name);
- for entry in d.filter_map(|e| e.ok()) {
- let path = entry.path();
- let filename = match path.file_name().and_then(|s| s.to_str()) {
- Some(s) => s,
- None => continue,
- };
- if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) {
- continue
- }
- let name = &filename[DLL_PREFIX.len() .. filename.len() - DLL_SUFFIX.len()];
- if name != expected_name {
- continue
- }
- if let Some(ref prev) = file {
- let err = format!("duplicate codegen backends found\n\
- first: {}\n\
- second: {}\n\
- ", prev.display(), path.display());
- early_error(ErrorOutputType::default(), &err);
- }
- file = Some(path.clone());
- }
-
- match file {
- Some(ref s) => return load_backend_from_dylib(s),
- None => {
- let err = format!("failed to load default codegen backend for `{}`, \
- no appropriate codegen dylib found in `{}`",
- backend_name, sysroot.display());
- early_error(ErrorOutputType::default(), &err);
- }
- }
-
- #[cfg(unix)]
- fn current_dll_path() -> Option<PathBuf> {
- use std::ffi::{OsStr, CStr};
- use std::os::unix::prelude::*;
-
- unsafe {
- let addr = current_dll_path as usize as *mut _;
- let mut info = mem::zeroed();
- if libc::dladdr(addr, &mut info) == 0 {
- info!("dladdr failed");
- return None
- }
- if info.dli_fname.is_null() {
- info!("dladdr returned null pointer");
- return None
- }
- let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
- let os = OsStr::from_bytes(bytes);
- Some(PathBuf::from(os))
- }
- }
-
- #[cfg(windows)]
- fn current_dll_path() -> Option<PathBuf> {
- use std::ffi::OsString;
- use std::os::windows::prelude::*;
-
- extern "system" {
- fn GetModuleHandleExW(dwFlags: u32,
- lpModuleName: usize,
- phModule: *mut usize) -> i32;
- fn GetModuleFileNameW(hModule: usize,
- lpFilename: *mut u16,
- nSize: u32) -> u32;
- }
-
- const GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS: u32 = 0x00000004;
-
- unsafe {
- let mut module = 0;
- let r = GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
- current_dll_path as usize,
- &mut module);
- if r == 0 {
- info!("GetModuleHandleExW failed: {}", io::Error::last_os_error());
- return None
- }
- let mut space = Vec::with_capacity(1024);
- let r = GetModuleFileNameW(module,
- space.as_mut_ptr(),
- space.capacity() as u32);
- if r == 0 {
- info!("GetModuleFileNameW failed: {}", io::Error::last_os_error());
- return None
- }
- let r = r as usize;
- if r >= space.capacity() {
- info!("our buffer was too small? {}",
- io::Error::last_os_error());
- return None
- }
- space.set_len(r);
- let os = OsString::from_wide(&space);
- Some(PathBuf::from(os))
- }
- }
-}
-
// Parse args and run the compiler. This is the primary entry point for rustc.
// See comments on CompilerCalls below for details about the callbacks argument.
// The FileLoader provides a way to load files from sources other than the file system.
let loader = file_loader.unwrap_or(box RealFileLoader);
let source_map = Lrc::new(SourceMap::with_file_loader(loader, sopts.file_path_mapping()));
let mut sess = session::build_session_with_source_map(
- sopts, input_file_path.clone(), descriptions, source_map, emitter_dest,
+ sopts,
+ input_file_path.clone(),
+ descriptions,
+ source_map,
+ emitter_dest.map(|e| DiagnosticOutput::Raw(e)).unwrap_or(DiagnosticOutput::Default),
+ Default::default(),
);
if let Some(err) = input_err {
return (Err(CompileIncomplete::Stopped), Some(sess));
}
- let codegen_backend = get_codegen_backend(&sess);
+ let codegen_backend = util::get_codegen_backend(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, cfg);
- target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
+ util::add_configuration(&mut cfg, &sess, &*codegen_backend);
sess.parse_sess.config = cfg;
let result = {
}
fn handle_explain(code: &str,
- descriptions: &errors::registry::Registry,
output: ErrorOutputType) {
+ let descriptions = rustc_interface::util::diagnostics_registry();
let normalised = if code.starts_with("E") {
code.to_string()
} else {
matches: &getopts::Matches,
_: &config::Options,
_: &ast::CrateConfig,
- descriptions: &errors::registry::Registry,
+ _: &errors::registry::Registry,
output: ErrorOutputType)
-> Compilation {
if let Some(ref code) = matches.opt_str("explain") {
- handle_explain(code, descriptions, output);
+ handle_explain(code, output);
return Compilation::Stop;
}
}
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, cfg.clone());
- let codegen_backend = get_codegen_backend(&sess);
- target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
+ let codegen_backend = util::get_codegen_backend(&sess);
+ util::add_configuration(&mut cfg, &sess, &*codegen_backend);
sess.parse_sess.config = cfg;
let should_stop = RustcDefaultCalls::print_crate_info(
&*codegen_backend,
let input = input.unwrap_or_else(||
early_error(ErrorOutputType::default(), "no input file provided"));
let attrs = attrs.as_ref().unwrap();
- let t_outputs = driver::build_output_filenames(input, odir, ofile, attrs, sess);
+ let t_outputs = rustc_interface::util::build_output_filenames(
+ input,
+ odir,
+ ofile,
+ attrs,
+ sess
+ );
let id = rustc_codegen_utils::link::find_crate_name(Some(sess), attrs, input);
if *req == PrintRequest::CrateName {
println!("{}", id);
continue;
}
- let crate_types = driver::collect_crate_types(sess, attrs);
+ let crate_types = rustc_interface::util::collect_crate_types(sess, attrs);
for &style in &crate_types {
let fname = rustc_codegen_utils::link::filename_for_input(
sess,
use rustc::session::Session;
use rustc::session::config::{Input, OutputFilenames};
use rustc::ty::{self, TyCtxt, Resolutions, AllArenas};
+use rustc_interface::util;
use rustc_borrowck as borrowck;
use rustc_borrowck::graphviz as borrowck_dot;
-use rustc_data_structures::thin_vec::ThinVec;
use rustc_metadata::cstore::CStore;
use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};
-use syntax::ast::{self, BlockCheckMode};
-use syntax::mut_visit::{*, MutVisitor, visit_clobber};
+use syntax::ast;
+use syntax::mut_visit::MutVisitor;
use syntax::print::{pprust};
use syntax::print::pprust::PrintState;
-use syntax::ptr::P;
-use syntax_pos::{self, FileName};
+use syntax_pos::FileName;
use graphviz as dot;
-use smallvec::SmallVec;
use std::cell::Cell;
use std::fs::File;
use std::io::{self, Write};
-use std::ops::DerefMut;
use std::option;
use std::path::Path;
use std::str::FromStr;
-use std::mem;
pub use self::UserIdentifiedItem::*;
pub use self::PpSourceMode::*;
pub use self::PpMode::*;
use self::NodesMatchingUII::*;
-use {abort_on_err, driver};
+use abort_on_err;
+use driver;
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpSourceMode {
}
PpmTyped => {
let control = &driver::CompileController::basic();
- let codegen_backend = ::get_codegen_backend(sess);
+ let codegen_backend = util::get_codegen_backend(sess);
let mut arenas = AllArenas::new();
- abort_on_err(driver::phase_3_run_analysis_passes(&*codegen_backend,
- control,
- sess,
- cstore,
- hir_map.clone(),
- resolutions.clone(),
- &mut arenas,
- id,
- output_filenames,
- |tcx, _, _| {
+ driver::phase_3_run_analysis_passes(&*codegen_backend,
+ control,
+ sess,
+ cstore,
+ hir_map.clone(),
+ resolutions.clone(),
+ &mut arenas,
+ id,
+ output_filenames,
+ |tcx, _, result| {
+ abort_on_err(result, tcx.sess);
let empty_tables = ty::TypeckTables::empty(None);
let annotation = TypedAnnotation {
tcx,
tcx.dep_graph.with_ignore(|| {
f(&annotation, hir_map.forest.krate())
})
- }),
- sess)
+ })
}
_ => panic!("Should use call_with_pp_support"),
}
}
}
-// Note: Also used by librustdoc, see PR #43348. Consider moving this struct elsewhere.
-//
-// FIXME: Currently the `everybody_loops` transformation is not applied to:
-// * `const fn`, due to issue #43636 that `loop` is not supported for const evaluation. We are
-// waiting for miri to fix that.
-// * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging.
-// Solving this may require `!` to implement every trait, which relies on the an even more
-// ambitious form of the closed RFC #1637. See also [#34511].
-//
-// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401
-pub struct ReplaceBodyWithLoop<'a> {
- within_static_or_const: bool,
- nested_blocks: Option<Vec<ast::Block>>,
- sess: &'a Session,
-}
-
-impl<'a> ReplaceBodyWithLoop<'a> {
- pub fn new(sess: &'a Session) -> ReplaceBodyWithLoop<'a> {
- ReplaceBodyWithLoop {
- within_static_or_const: false,
- nested_blocks: None,
- sess
- }
- }
-
- fn run<R, F: FnOnce(&mut Self) -> R>(&mut self, is_const: bool, action: F) -> R {
- let old_const = mem::replace(&mut self.within_static_or_const, is_const);
- let old_blocks = self.nested_blocks.take();
- let ret = action(self);
- self.within_static_or_const = old_const;
- self.nested_blocks = old_blocks;
- ret
- }
-
- fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool {
- if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output {
- fn involves_impl_trait(ty: &ast::Ty) -> bool {
- match ty.node {
- ast::TyKind::ImplTrait(..) => true,
- ast::TyKind::Slice(ref subty) |
- ast::TyKind::Array(ref subty, _) |
- ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) |
- ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) |
- ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
- ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
- ast::TyKind::Path(_, ref path) => path.segments.iter().any(|seg| {
- match seg.args.as_ref().map(|generic_arg| &**generic_arg) {
- None => false,
- Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
- let types = data.args.iter().filter_map(|arg| match arg {
- ast::GenericArg::Type(ty) => Some(ty),
- _ => None,
- });
- any_involves_impl_trait(types.into_iter()) ||
- any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty))
- },
- Some(&ast::GenericArgs::Parenthesized(ref data)) => {
- any_involves_impl_trait(data.inputs.iter()) ||
- any_involves_impl_trait(data.output.iter())
- }
- }
- }),
- _ => false,
- }
- }
-
- fn any_involves_impl_trait<'a, I: Iterator<Item = &'a P<ast::Ty>>>(mut it: I) -> bool {
- it.any(|subty| involves_impl_trait(subty))
- }
-
- involves_impl_trait(ty)
- } else {
- false
- }
- }
-}
-
-impl<'a> MutVisitor for ReplaceBodyWithLoop<'a> {
- fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
- let is_const = match i {
- ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
- ast::ItemKind::Fn(ref decl, ref header, _, _) =>
- header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
- _ => false,
- };
- self.run(is_const, |s| noop_visit_item_kind(i, s))
- }
-
- fn flat_map_trait_item(&mut self, i: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
- let is_const = match i.node {
- ast::TraitItemKind::Const(..) => true,
- ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
- header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
- _ => false,
- };
- self.run(is_const, |s| noop_flat_map_trait_item(i, s))
- }
-
- fn flat_map_impl_item(&mut self, i: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
- let is_const = match i.node {
- ast::ImplItemKind::Const(..) => true,
- ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
- header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
- _ => false,
- };
- self.run(is_const, |s| noop_flat_map_impl_item(i, s))
- }
-
- fn visit_anon_const(&mut self, c: &mut ast::AnonConst) {
- self.run(true, |s| noop_visit_anon_const(c, s))
- }
-
- fn visit_block(&mut self, b: &mut P<ast::Block>) {
- fn stmt_to_block(rules: ast::BlockCheckMode,
- s: Option<ast::Stmt>,
- sess: &Session) -> ast::Block {
- ast::Block {
- stmts: s.into_iter().collect(),
- rules,
- id: sess.next_node_id(),
- span: syntax_pos::DUMMY_SP,
- }
- }
-
- fn block_to_stmt(b: ast::Block, sess: &Session) -> ast::Stmt {
- let expr = P(ast::Expr {
- id: sess.next_node_id(),
- node: ast::ExprKind::Block(P(b), None),
- span: syntax_pos::DUMMY_SP,
- attrs: ThinVec::new(),
- });
-
- ast::Stmt {
- id: sess.next_node_id(),
- node: ast::StmtKind::Expr(expr),
- span: syntax_pos::DUMMY_SP,
- }
- }
-
- let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.sess);
- let loop_expr = P(ast::Expr {
- node: ast::ExprKind::Loop(P(empty_block), None),
- id: self.sess.next_node_id(),
- span: syntax_pos::DUMMY_SP,
- attrs: ThinVec::new(),
- });
-
- let loop_stmt = ast::Stmt {
- id: self.sess.next_node_id(),
- span: syntax_pos::DUMMY_SP,
- node: ast::StmtKind::Expr(loop_expr),
- };
-
- if self.within_static_or_const {
- noop_visit_block(b, self)
- } else {
- visit_clobber(b.deref_mut(), |b| {
- let mut stmts = vec![];
- for s in b.stmts {
- let old_blocks = self.nested_blocks.replace(vec![]);
-
- stmts.extend(self.flat_map_stmt(s).into_iter().filter(|s| s.is_item()));
-
- // we put a Some in there earlier with that replace(), so this is valid
- let new_blocks = self.nested_blocks.take().unwrap();
- self.nested_blocks = old_blocks;
- stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, &self.sess)));
- }
-
- let mut new_block = ast::Block {
- stmts,
- ..b
- };
-
- if let Some(old_blocks) = self.nested_blocks.as_mut() {
- //push our fresh block onto the cache and yield an empty block with `loop {}`
- if !new_block.stmts.is_empty() {
- old_blocks.push(new_block);
- }
-
- stmt_to_block(b.rules, Some(loop_stmt), self.sess)
- } else {
- //push `loop {}` onto the end of our fresh block and yield that
- new_block.stmts.push(loop_stmt);
-
- new_block
- }
- })
- }
- }
-
- // in general the pretty printer processes unexpanded code, so
- // we override the default `visit_mac` method which panics.
- fn visit_mac(&mut self, mac: &mut ast::Mac) {
- noop_visit_mac(mac, self)
- }
-}
-
fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
code: blocks::Code<'tcx>,
pub fn visit_crate(sess: &Session, krate: &mut ast::Crate, ppm: PpMode) {
if let PpmSource(PpmEveryBodyLoops) = ppm {
- ReplaceBodyWithLoop::new(sess).visit_crate(krate);
+ util::ReplaceBodyWithLoop::new(sess).visit_crate(krate);
}
}
fn get_source(input: &Input, sess: &Session) -> (Vec<u8>, FileName) {
- let src_name = driver::source_name(input);
+ let src_name = input.source_name();
let src = sess.source_map()
.get_source_file(&src_name)
.unwrap()
let mut out = Vec::new();
let control = &driver::CompileController::basic();
- let codegen_backend = ::get_codegen_backend(sess);
+ let codegen_backend = util::get_codegen_backend(sess);
let mut arenas = AllArenas::new();
- abort_on_err(driver::phase_3_run_analysis_passes(&*codegen_backend,
- control,
- sess,
- cstore,
- hir_map.clone(),
- resolutions.clone(),
- &mut arenas,
- crate_name,
- output_filenames,
- |tcx, _, _| {
+ driver::phase_3_run_analysis_passes(&*codegen_backend,
+ control,
+ sess,
+ cstore,
+ hir_map.clone(),
+ resolutions.clone(),
+ &mut arenas,
+ crate_name,
+ output_filenames,
+ |tcx, _, result| {
+ abort_on_err(result, tcx.sess);
match ppm {
PpmMir | PpmMirCFG => {
if let Some(nodeid) = nodeid {
}
_ => unreachable!(),
}
- }),
- sess)
- .unwrap();
+ }).unwrap();
write_output(out, ofile);
}
+++ /dev/null
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::hir;
-use rustc::ty::TyCtxt;
-use rustc::ty::query::Providers;
-use syntax::ast;
-use syntax::attr;
-
-pub fn find<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> Option<DefId> {
- tcx.proc_macro_decls_static(LOCAL_CRATE)
-}
-
-fn proc_macro_decls_static<'tcx>(
- tcx: TyCtxt<'_, 'tcx, 'tcx>,
- cnum: CrateNum,
-) -> Option<DefId> {
- assert_eq!(cnum, LOCAL_CRATE);
-
- let mut finder = Finder { decls: None };
- tcx.hir().krate().visit_all_item_likes(&mut finder);
-
- finder.decls.map(|id| tcx.hir().local_def_id(id))
-}
-
-struct Finder {
- decls: Option<ast::NodeId>,
-}
-
-impl<'v> ItemLikeVisitor<'v> for Finder {
- fn visit_item(&mut self, item: &hir::Item) {
- if attr::contains_name(&item.attrs, "rustc_proc_macro_decls") {
- self.decls = Some(item.id);
- }
- }
-
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
- }
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
- }
-}
-
-pub(crate) fn provide(providers: &mut Providers<'_>) {
- *providers = Providers {
- proc_macro_decls_static,
- ..*providers
- };
-}
+++ /dev/null
-use rustc::session::Session;
-use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan};
-use std::sync::mpsc::{Receiver};
-use std::io::{Write};
-use rustc::dep_graph::{DepNode};
-use std::time::{Duration, Instant};
-
-pub mod trace;
-
-/// begin a profile thread, if not already running
-pub fn begin(sess: &Session) {
- use std::thread;
- use std::sync::mpsc::{channel};
- let (tx, rx) = channel();
- if profq_set_chan(sess, tx) {
- thread::spawn(move || profile_queries_thread(rx));
- }
-}
-
-/// dump files with profiling information to the given base path, and
-/// wait for this dump to complete.
-///
-/// wraps the RPC (send/recv channel logic) of requesting a dump.
-pub fn dump(sess: &Session, path: String) {
- use std::sync::mpsc::{channel};
- let (tx, rx) = channel();
- let params = ProfQDumpParams {
- path,
- ack: tx,
- // FIXME: Add another compiler flag to toggle whether this log
- // is written; false for now
- dump_profq_msg_log: true,
- };
- profq_msg(sess, ProfileQueriesMsg::Dump(params));
- let _ = rx.recv().unwrap();
-}
-
-// State for parsing recursive trace structure in separate thread, via messages
-#[derive(Clone, Eq, PartialEq)]
-enum ParseState {
- // No (local) parse state; may be parsing a tree, focused on a
- // sub-tree that could be anything.
- Clear,
- // Have Query information from the last message
- HaveQuery(trace::Query, Instant),
- // Have "time-begin" information from the last message (doit flag, and message)
- HaveTimeBegin(String, Instant),
- // Have "task-begin" information from the last message
- HaveTaskBegin(DepNode, Instant),
-}
-struct StackFrame {
- pub parse_st: ParseState,
- pub traces: Vec<trace::Rec>,
-}
-
-fn total_duration(traces: &[trace::Rec]) -> Duration {
- Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum()
-}
-
-// profiling thread; retains state (in local variables) and dump traces, upon request.
-fn profile_queries_thread(r: Receiver<ProfileQueriesMsg>) {
- use self::trace::*;
- use std::fs::File;
- use std::time::{Instant};
-
- let mut profq_msgs: Vec<ProfileQueriesMsg> = vec![];
- let mut frame: StackFrame = StackFrame { parse_st: ParseState::Clear, traces: vec![] };
- let mut stack: Vec<StackFrame> = vec![];
- loop {
- let msg = r.recv();
- if let Err(_recv_err) = msg {
- // FIXME: Perhaps do something smarter than simply quitting?
- break
- };
- let msg = msg.unwrap();
- debug!("profile_queries_thread: {:?}", msg);
-
- // Meta-level versus _actual_ queries messages
- match msg {
- ProfileQueriesMsg::Halt => return,
- ProfileQueriesMsg::Dump(params) => {
- assert!(stack.is_empty());
- assert!(frame.parse_st == ParseState::Clear);
-
- // write log of all messages
- if params.dump_profq_msg_log {
- let mut log_file =
- File::create(format!("{}.log.txt", params.path)).unwrap();
- for m in profq_msgs.iter() {
- writeln!(&mut log_file, "{:?}", m).unwrap()
- };
- }
-
- // write HTML file, and counts file
- let html_path = format!("{}.html", params.path);
- let mut html_file = File::create(&html_path).unwrap();
-
- let counts_path = format!("{}.counts.txt", params.path);
- let mut counts_file = File::create(&counts_path).unwrap();
-
- writeln!(html_file,
- "<html>\n<head>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">",
- "profile_queries.css").unwrap();
- writeln!(html_file, "<style>").unwrap();
- trace::write_style(&mut html_file);
- writeln!(html_file, "</style>\n</head>\n<body>").unwrap();
- trace::write_traces(&mut html_file, &mut counts_file, &frame.traces);
- writeln!(html_file, "</body>\n</html>").unwrap();
-
- let ack_path = format!("{}.ack", params.path);
- let ack_file = File::create(&ack_path).unwrap();
- drop(ack_file);
-
- // Tell main thread that we are done, e.g., so it can exit
- params.ack.send(()).unwrap();
- }
- // Actual query message:
- msg => {
- // Record msg in our log
- profq_msgs.push(msg.clone());
- // Respond to the message, knowing that we've already handled Halt and Dump, above.
- match (frame.parse_st.clone(), msg) {
- (_, ProfileQueriesMsg::Halt) | (_, ProfileQueriesMsg::Dump(_)) => {
- unreachable!();
- },
- // Parse State: Clear
- (ParseState::Clear,
- ProfileQueriesMsg::QueryBegin(span, querymsg)) => {
- let start = Instant::now();
- frame.parse_st = ParseState::HaveQuery
- (Query { span, msg: querymsg }, start)
- },
- (ParseState::Clear,
- ProfileQueriesMsg::CacheHit) => {
- panic!("parse error: unexpected CacheHit; expected QueryBegin")
- },
- (ParseState::Clear,
- ProfileQueriesMsg::ProviderBegin) => {
- panic!("parse error: expected QueryBegin before beginning a provider")
- },
- (ParseState::Clear,
- ProfileQueriesMsg::ProviderEnd) => {
- let provider_extent = frame.traces;
- match stack.pop() {
- None =>
- panic!("parse error: expected a stack frame; found an empty stack"),
- Some(old_frame) => {
- match old_frame.parse_st {
- ParseState::HaveQuery(q, start) => {
- let duration = start.elapsed();
- frame = StackFrame{
- parse_st: ParseState::Clear,
- traces: old_frame.traces
- };
- let dur_extent = total_duration(&provider_extent);
- let trace = Rec {
- effect: Effect::QueryBegin(q, CacheCase::Miss),
- extent: Box::new(provider_extent),
- start: start,
- dur_self: duration - dur_extent,
- dur_total: duration,
- };
- frame.traces.push( trace );
- },
- _ => panic!("internal parse error: malformed parse stack")
- }
- }
- }
- },
- (ParseState::Clear,
- ProfileQueriesMsg::TimeBegin(msg)) => {
- let start = Instant::now();
- frame.parse_st = ParseState::HaveTimeBegin(msg, start);
- stack.push(frame);
- frame = StackFrame{parse_st: ParseState::Clear, traces: vec![]};
- },
- (_, ProfileQueriesMsg::TimeBegin(_)) => {
- panic!("parse error; did not expect time begin here");
- },
- (ParseState::Clear,
- ProfileQueriesMsg::TimeEnd) => {
- let provider_extent = frame.traces;
- match stack.pop() {
- None =>
- panic!("parse error: expected a stack frame; found an empty stack"),
- Some(old_frame) => {
- match old_frame.parse_st {
- ParseState::HaveTimeBegin(msg, start) => {
- let duration = start.elapsed();
- frame = StackFrame{
- parse_st: ParseState::Clear,
- traces: old_frame.traces
- };
- let dur_extent = total_duration(&provider_extent);
- let trace = Rec {
- effect: Effect::TimeBegin(msg),
- extent: Box::new(provider_extent),
- start: start,
- dur_total: duration,
- dur_self: duration - dur_extent,
- };
- frame.traces.push( trace );
- },
- _ => panic!("internal parse error: malformed parse stack")
- }
- }
- }
- },
- (_, ProfileQueriesMsg::TimeEnd) => {
- panic!("parse error")
- },
- (ParseState::Clear,
- ProfileQueriesMsg::TaskBegin(key)) => {
- let start = Instant::now();
- frame.parse_st = ParseState::HaveTaskBegin(key, start);
- stack.push(frame);
- frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] };
- },
- (_, ProfileQueriesMsg::TaskBegin(_)) => {
- panic!("parse error; did not expect time begin here");
- },
- (ParseState::Clear,
- ProfileQueriesMsg::TaskEnd) => {
- let provider_extent = frame.traces;
- match stack.pop() {
- None =>
- panic!("parse error: expected a stack frame; found an empty stack"),
- Some(old_frame) => {
- match old_frame.parse_st {
- ParseState::HaveTaskBegin(key, start) => {
- let duration = start.elapsed();
- frame = StackFrame{
- parse_st: ParseState::Clear,
- traces: old_frame.traces
- };
- let dur_extent = total_duration(&provider_extent);
- let trace = Rec {
- effect: Effect::TaskBegin(key),
- extent: Box::new(provider_extent),
- start: start,
- dur_total: duration,
- dur_self: duration - dur_extent,
- };
- frame.traces.push( trace );
- },
- _ => panic!("internal parse error: malformed parse stack")
- }
- }
- }
- },
- (_, ProfileQueriesMsg::TaskEnd) => {
- panic!("parse error")
- },
- // Parse State: HaveQuery
- (ParseState::HaveQuery(q,start),
- ProfileQueriesMsg::CacheHit) => {
- let duration = start.elapsed();
- let trace : Rec = Rec{
- effect: Effect::QueryBegin(q, CacheCase::Hit),
- extent: Box::new(vec![]),
- start: start,
- dur_self: duration,
- dur_total: duration,
- };
- frame.traces.push( trace );
- frame.parse_st = ParseState::Clear;
- },
- (ParseState::HaveQuery(_, _),
- ProfileQueriesMsg::ProviderBegin) => {
- stack.push(frame);
- frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] };
- },
-
- // Parse errors:
-
- (ParseState::HaveQuery(q, _),
- ProfileQueriesMsg::ProviderEnd) => {
- panic!("parse error: unexpected ProviderEnd; \
- expected something else to follow BeginQuery for {:?}", q)
- },
- (ParseState::HaveQuery(q1, _),
- ProfileQueriesMsg::QueryBegin(span2, querymsg2)) => {
- panic!("parse error: unexpected QueryBegin; \
- earlier query is unfinished: {:?} and now {:?}",
- q1, Query{span:span2, msg: querymsg2})
- },
- (ParseState::HaveTimeBegin(_, _), _) => {
- unreachable!()
- },
- (ParseState::HaveTaskBegin(_, _), _) => {
- unreachable!()
- },
- }
- }
- }
- }
-}
+++ /dev/null
-use super::*;
-use syntax_pos::SpanData;
-use rustc_data_structures::fx::FxHashMap;
-use rustc::util::common::QueryMsg;
-use std::fs::File;
-use std::time::{Duration, Instant};
-use rustc::dep_graph::{DepNode};
-
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct Query {
- pub span: SpanData,
- pub msg: QueryMsg,
-}
-pub enum Effect {
- QueryBegin(Query, CacheCase),
- TimeBegin(String),
- TaskBegin(DepNode),
-}
-pub enum CacheCase {
- Hit, Miss
-}
-/// Recursive trace structure
-pub struct Rec {
- pub effect: Effect,
- pub start: Instant,
- pub dur_self: Duration,
- pub dur_total: Duration,
- pub extent: Box<Vec<Rec>>,
-}
-pub struct QueryMetric {
- pub count: usize,
- pub dur_self: Duration,
- pub dur_total: Duration,
-}
-
-fn cons(s: &str) -> String {
- let first = s.split(|d| d == '(' || d == '{').next();
- assert!(first.is_some() && first != Some(""));
- first.unwrap().to_owned()
-}
-
-pub fn cons_of_query_msg(q: &trace::Query) -> String {
- cons(&format!("{:?}", q.msg))
-}
-
-pub fn cons_of_key(k: &DepNode) -> String {
- cons(&format!("{:?}", k))
-}
-
-// First return value is text; second return value is a CSS class
-pub fn html_of_effect(eff: &Effect) -> (String, String) {
- match *eff {
- Effect::TimeBegin(ref msg) => {
- (msg.clone(),
- "time-begin".to_string())
- },
- Effect::TaskBegin(ref key) => {
- let cons = cons_of_key(key);
- (cons.clone(), format!("{} task-begin", cons))
- },
- Effect::QueryBegin(ref qmsg, ref cc) => {
- let cons = cons_of_query_msg(qmsg);
- (cons.clone(),
- format!("{} {}",
- cons,
- match *cc {
- CacheCase::Hit => "hit",
- CacheCase::Miss => "miss",
- }))
- }
- }
-}
-
-// First return value is text; second return value is a CSS class
-fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) {
- use rustc::util::common::duration_to_secs_str;
- (duration_to_secs_str(dur.clone()), String::new())
-}
-
-fn html_of_fraction(frac: f64) -> (String, &'static str) {
- let css = {
- if frac > 0.50 { "frac-50" }
- else if frac > 0.40 { "frac-40" }
- else if frac > 0.30 { "frac-30" }
- else if frac > 0.20 { "frac-20" }
- else if frac > 0.10 { "frac-10" }
- else if frac > 0.05 { "frac-05" }
- else if frac > 0.02 { "frac-02" }
- else if frac > 0.01 { "frac-01" }
- else if frac > 0.001 { "frac-001" }
- else { "frac-0" }
- };
- let percent = frac * 100.0;
-
- if percent > 0.1 {
- (format!("{:.1}%", percent), css)
- } else {
- ("< 0.1%".to_string(), css)
- }
-}
-
-fn total_duration(traces: &[Rec]) -> Duration {
- Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum()
-}
-
-fn duration_div(nom: Duration, den: Duration) -> f64 {
- fn to_nanos(d: Duration) -> u64 {
- d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64
- }
-
- to_nanos(nom) as f64 / to_nanos(den) as f64
-}
-
-fn write_traces_rec(file: &mut File, traces: &[Rec], total: Duration, depth: usize) {
- for t in traces {
- let (eff_text, eff_css_classes) = html_of_effect(&t.effect);
- let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.dur_total);
- let fraction = duration_div(t.dur_total, total);
- let percent = fraction * 100.0;
- let (frc_text, frc_css_classes) = html_of_fraction(fraction);
- writeln!(file, "<div class=\"trace depth-{} extent-{}{} {} {} {}\">",
- depth,
- t.extent.len(),
- /* Heuristic for 'important' CSS class: */
- if t.extent.len() > 5 || percent >= 1.0 { " important" } else { "" },
- eff_css_classes,
- dur_css_classes,
- frc_css_classes,
- ).unwrap();
- writeln!(file, "<div class=\"eff\">{}</div>", eff_text).unwrap();
- writeln!(file, "<div class=\"dur\">{}</div>", dur_text).unwrap();
- writeln!(file, "<div class=\"frc\">{}</div>", frc_text).unwrap();
- write_traces_rec(file, &t.extent, total, depth + 1);
- writeln!(file, "</div>").unwrap();
- }
-}
-
-fn compute_counts_rec(counts: &mut FxHashMap<String,QueryMetric>, traces: &[Rec]) {
- counts.reserve(traces.len());
- for t in traces.iter() {
- match t.effect {
- Effect::TimeBegin(ref msg) => {
- let qm = match counts.get(msg) {
- Some(_qm) => panic!("TimeBegin with non-unique, repeat message"),
- None => QueryMetric {
- count: 1,
- dur_self: t.dur_self,
- dur_total: t.dur_total,
- }
- };
- counts.insert(msg.clone(), qm);
- },
- Effect::TaskBegin(ref key) => {
- let cons = cons_of_key(key);
- let qm = match counts.get(&cons) {
- Some(qm) =>
- QueryMetric {
- count: qm.count + 1,
- dur_self: qm.dur_self + t.dur_self,
- dur_total: qm.dur_total + t.dur_total,
- },
- None => QueryMetric {
- count: 1,
- dur_self: t.dur_self,
- dur_total: t.dur_total,
- }
- };
- counts.insert(cons, qm);
- },
- Effect::QueryBegin(ref qmsg, ref _cc) => {
- let qcons = cons_of_query_msg(qmsg);
- let qm = match counts.get(&qcons) {
- Some(qm) =>
- QueryMetric {
- count: qm.count + 1,
- dur_total: qm.dur_total + t.dur_total,
- dur_self: qm.dur_self + t.dur_self
- },
- None => QueryMetric {
- count: 1,
- dur_total: t.dur_total,
- dur_self: t.dur_self,
- }
- };
- counts.insert(qcons, qm);
- }
- }
- compute_counts_rec(counts, &t.extent)
- }
-}
-
-pub fn write_counts(count_file: &mut File, counts: &mut FxHashMap<String, QueryMetric>) {
- use rustc::util::common::duration_to_secs_str;
- use std::cmp::Reverse;
-
- let mut data = counts.iter().map(|(ref cons, ref qm)|
- (cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone())
- ).collect::<Vec<_>>();
-
- data.sort_by_key(|k| Reverse(k.3));
- for (cons, count, dur_total, dur_self) in data {
- writeln!(count_file, "{}, {}, {}, {}",
- cons, count,
- duration_to_secs_str(dur_total),
- duration_to_secs_str(dur_self)
- ).unwrap();
- }
-}
-
-pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &[Rec]) {
- let capacity = traces.iter().fold(0, |acc, t| acc + 1 + t.extent.len());
- let mut counts = FxHashMap::with_capacity_and_hasher(capacity, Default::default());
- compute_counts_rec(&mut counts, traces);
- write_counts(counts_file, &mut counts);
-
- let total: Duration = total_duration(traces);
- write_traces_rec(html_file, traces, total, 0)
-}
-
-pub fn write_style(html_file: &mut File) {
- write!(html_file, "{}", "
-body {
- font-family: sans-serif;
- background: black;
-}
-.trace {
- color: black;
- display: inline-block;
- border-style: solid;
- border-color: red;
- border-width: 1px;
- border-radius: 5px;
- padding: 0px;
- margin: 1px;
- font-size: 0px;
-}
-.task-begin {
- border-width: 1px;
- color: white;
- border-color: #ff8;
- font-size: 0px;
-}
-.miss {
- border-color: red;
- border-width: 1px;
-}
-.extent-0 {
- padding: 2px;
-}
-.time-begin {
- border-width: 4px;
- font-size: 12px;
- color: white;
- border-color: #afa;
-}
-.important {
- border-width: 3px;
- font-size: 12px;
- color: white;
- border-color: #f77;
-}
-.hit {
- padding: 0px;
- border-color: blue;
- border-width: 3px;
-}
-.eff {
- color: #fff;
- display: inline-block;
-}
-.frc {
- color: #7f7;
- display: inline-block;
-}
-.dur {
- display: none
-}
-.frac-50 {
- padding: 10px;
- border-width: 10px;
- font-size: 32px;
-}
-.frac-40 {
- padding: 8px;
- border-width: 8px;
- font-size: 24px;
-}
-.frac-30 {
- padding: 6px;
- border-width: 6px;
- font-size: 18px;
-}
-.frac-20 {
- padding: 4px;
- border-width: 6px;
- font-size: 16px;
-}
-.frac-10 {
- padding: 2px;
- border-width: 6px;
- font-size: 14px;
-}
-").unwrap();
-}
use rustc::ty::subst::Subst;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_data_structures::sync::{self, Lrc};
+use rustc_interface::util;
use rustc_lint;
use rustc_metadata::cstore::CStore;
use rustc_target::spec::abi::Abi;
options.debugging_opts.verbose = true;
options.unstable_features = UnstableFeatures::Allow;
+ // When we're compiling this library with `--test` it'll run as a binary but
+ // not actually exercise much functionality.
+ // As a result most of the logic loading the codegen backend is defunkt
+ // (it assumes we're a dynamic library in a sysroot)
+ // so let's just use the metadata only backend which doesn't need to load any libraries.
+ options.debugging_opts.codegen_backend = Some("metadata_only".to_owned());
+
driver::spawn_thread_pool(options, |options| {
test_env_with_pool(options, source_string, args, body)
})
None,
diagnostic_handler,
Lrc::new(SourceMap::new(FilePathMapping::empty())),
+ Default::default(),
);
- let cstore = CStore::new(::get_codegen_backend(&sess).metadata_loader());
+ let cstore = CStore::new(util::get_codegen_backend(&sess).metadata_loader());
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let input = config::Input::Str {
name: FileName::anon_source_code(&source_string),
let mut visitor = IfThisChanged { tcx,
if_this_changed: vec![],
then_this_would_need: vec![] };
- visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir().krate().attrs);
+ visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().attrs);
tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
(visitor.if_this_changed, visitor.then_this_would_need)
};
}
type Sources = Vec<(Span, DefId, DepNode)>;
-type Targets = Vec<(Span, ast::Name, ast::NodeId, DepNode)>;
+type Targets = Vec<(Span, ast::Name, hir::HirId, DepNode)>;
struct IfThisChanged<'a, 'tcx:'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
value
}
- fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
- let def_id = self.tcx.hir().local_def_id(node_id);
+ fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) {
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(hir_id);
let def_path_hash = self.tcx.def_path_hash(def_id);
for attr in attrs {
if attr.check_name(ATTR_IF_THIS_CHANGED) {
};
self.then_this_would_need.push((attr.span,
dep_node_interned.unwrap(),
- node_id,
+ hir_id,
dep_node));
}
}
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
- self.process_attrs(item.id, &item.attrs);
+ self.process_attrs(item.hir_id, &item.attrs);
intravisit::walk_item(self, item);
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
- self.process_attrs(trait_item.id, &trait_item.attrs);
+ self.process_attrs(trait_item.hir_id, &trait_item.attrs);
intravisit::walk_trait_item(self, trait_item);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
- self.process_attrs(impl_item.id, &impl_item.attrs);
+ self.process_attrs(impl_item.hir_id, &impl_item.attrs);
intravisit::walk_impl_item(self, impl_item);
}
fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
- self.process_attrs(s.id, &s.attrs);
+ self.process_attrs(s.hir_id, &s.attrs);
intravisit::walk_struct_field(self, s);
}
}
impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
/// Possibly "deserialize" the attribute into a clean/dirty assertion
- fn assertion_maybe(&mut self, item_id: ast::NodeId, attr: &Attribute)
+ fn assertion_maybe(&mut self, item_id: hir::HirId, attr: &Attribute)
-> Option<Assertion>
{
let is_clean = if attr.check_name(ATTR_DIRTY) {
}
/// Gets the "auto" assertion on pre-validated attr, along with the `except` labels.
- fn assertion_auto(&mut self, item_id: ast::NodeId, attr: &Attribute, is_clean: bool)
+ fn assertion_auto(&mut self, item_id: hir::HirId, attr: &Attribute, is_clean: bool)
-> Assertion
{
let (name, mut auto) = self.auto_labels(item_id, attr);
/// Return all DepNode labels that should be asserted for this item.
/// index=0 is the "name" used for error messages
- fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static str, Labels) {
- let node = self.tcx.hir().get(item_id);
+ fn auto_labels(&mut self, item_id: hir::HirId, attr: &Attribute) -> (&'static str, Labels) {
+ let node = self.tcx.hir().get_by_hir_id(item_id);
let (name, labels) = match node {
HirNode::Item(item) => {
match item.node {
}
}
- fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) {
- let def_id = self.tcx.hir().local_def_id(item_id);
+ fn check_item(&mut self, item_id: hir::HirId, item_span: Span) {
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item_id);
for attr in self.tcx.get_attrs(def_id).iter() {
let assertion = match self.assertion_maybe(item_id, attr) {
Some(a) => a,
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- self.check_item(item.id, item.span);
+ self.check_item(item.hir_id, item.span);
}
fn visit_trait_item(&mut self, item: &hir::TraitItem) {
- self.check_item(item.id, item.span);
+ self.check_item(item.hir_id, item.span);
}
fn visit_impl_item(&mut self, item: &hir::ImplItem) {
- self.check_item(item.id, item.span);
+ self.check_item(item.hir_id, item.span);
}
}
--- /dev/null
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_interface"
+version = "0.0.0"
+
+[lib]
+name = "rustc_interface"
+path = "lib.rs"
+crate-type = ["dylib"]
+
+[dependencies]
+log = "0.4"
+rustc-rayon = "0.1.1"
+smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
+scoped-tls = { version = "0.1.1", features = ["nightly"] }
+syntax = { path = "../libsyntax" }
+syntax_ext = { path = "../libsyntax_ext" }
+syntax_pos = { path = "../libsyntax_pos" }
+serialize = { path = "../libserialize" }
+rustc = { path = "../librustc" }
+rustc_allocator = { path = "../librustc_allocator" }
+rustc_borrowck = { path = "../librustc_borrowck" }
+rustc_incremental = { path = "../librustc_incremental" }
+rustc_traits = { path = "../librustc_traits" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_codegen_utils = { path = "../librustc_codegen_utils" }
+rustc_metadata = { path = "../librustc_metadata" }
+rustc_mir = { path = "../librustc_mir" }
+rustc_passes = { path = "../librustc_passes" }
+rustc_typeck = { path = "../librustc_typeck" }
+rustc_lint = { path = "../librustc_lint" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_plugin = { path = "../librustc_plugin" }
+rustc_privacy = { path = "../librustc_privacy" }
+rustc_resolve = { path = "../librustc_resolve" }
--- /dev/null
+#![feature(box_syntax)]
+#![feature(set_stdio)]
+#![feature(nll)]
+#![feature(arbitrary_self_types)]
+#![feature(generator_trait)]
+#![cfg_attr(unix, feature(libc))]
+
+#![allow(unused_imports)]
+
+#![recursion_limit="256"]
+
+#[cfg(unix)]
+extern crate libc;
+#[macro_use]
+extern crate log;
+extern crate rustc;
+extern crate rustc_codegen_utils;
+extern crate rustc_allocator;
+extern crate rustc_borrowck;
+extern crate rustc_incremental;
+extern crate rustc_traits;
+#[macro_use]
+extern crate rustc_data_structures;
+extern crate rustc_errors;
+extern crate rustc_lint;
+extern crate rustc_metadata;
+extern crate rustc_mir;
+extern crate rustc_passes;
+extern crate rustc_plugin;
+extern crate rustc_privacy;
+extern crate rustc_rayon as rayon;
+extern crate rustc_resolve;
+extern crate rustc_typeck;
+extern crate smallvec;
+extern crate serialize;
+extern crate syntax;
+extern crate syntax_pos;
+extern crate syntax_ext;
+
+pub mod passes;
+pub mod profile;
+pub mod util;
+pub mod proc_macro_decls;
--- /dev/null
+use util;
+use proc_macro_decls;
+
+use rustc::dep_graph::DepGraph;
+use rustc::hir;
+use rustc::hir::lowering::lower_crate;
+use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc::lint;
+use rustc::middle::{self, reachable, resolve_lifetime, stability};
+use rustc::middle::privacy::AccessLevels;
+use rustc::ty::{self, AllArenas, Resolutions, TyCtxt};
+use rustc::ty::steal::Steal;
+use rustc::traits;
+use rustc::util::common::{time, ErrorReported};
+use rustc::util::profiling::ProfileCategory;
+use rustc::session::{CompileResult, CrateDisambiguator, Session};
+use rustc::session::config::{self, Input, OutputFilenames, OutputType};
+use rustc::session::search_paths::PathKind;
+use rustc_allocator as allocator;
+use rustc_borrowck as borrowck;
+use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::sync::Lrc;
+use rustc_incremental;
+use rustc_metadata::creader::CrateLoader;
+use rustc_metadata::cstore::{self, CStore};
+use rustc_mir as mir;
+use rustc_passes::{self, ast_validation, hir_stats, loops, rvalue_promotion, layout_test};
+use rustc_plugin as plugin;
+use rustc_plugin::registry::Registry;
+use rustc_privacy;
+use rustc_resolve::{Resolver, ResolverArenas};
+use rustc_traits;
+use rustc_typeck as typeck;
+use syntax::{self, ast, attr, diagnostics, visit};
+use syntax::early_buffered_lints::BufferedEarlyLint;
+use syntax::ext::base::ExtCtxt;
+use syntax::mut_visit::MutVisitor;
+use syntax::parse::{self, PResult};
+use syntax::util::node_count::NodeCounter;
+use syntax::util::lev_distance::find_best_match_for_name;
+use syntax::symbol::Symbol;
+use syntax_pos::{FileName, hygiene};
+use syntax_ext;
+
+use serialize::json;
+
+use std::any::Any;
+use std::env;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{self, Write};
+use std::iter;
+use std::path::{Path, PathBuf};
+use std::sync::mpsc;
+use std::cell::RefCell;
+use std::rc::Rc;
+use std::mem;
+use std::ops::Generator;
+
+/// Returns all the paths that correspond to generated files.
+pub fn generated_output_paths(
+ sess: &Session,
+ outputs: &OutputFilenames,
+ exact_name: bool,
+ crate_name: &str,
+) -> Vec<PathBuf> {
+ let mut out_filenames = Vec::new();
+ for output_type in sess.opts.output_types.keys() {
+ let file = outputs.path(*output_type);
+ match *output_type {
+ // If the filename has been overridden using `-o`, it will not be modified
+ // by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
+ OutputType::Exe if !exact_name => for crate_type in sess.crate_types.borrow().iter() {
+ let p = ::rustc_codegen_utils::link::filename_for_input(
+ sess,
+ *crate_type,
+ crate_name,
+ outputs,
+ );
+ out_filenames.push(p);
+ },
+ OutputType::DepInfo if sess.opts.debugging_opts.dep_info_omit_d_target => {
+ // Don't add the dep-info output when omitting it from dep-info targets
+ }
+ _ => {
+ out_filenames.push(file);
+ }
+ }
+ }
+ out_filenames
+}
+
+// Runs `f` on every output file path and returns the first non-None result, or None if `f`
+// returns None for every file path.
+fn check_output<F, T>(output_paths: &[PathBuf], f: F) -> Option<T>
+where
+ F: Fn(&PathBuf) -> Option<T>,
+{
+ for output_path in output_paths {
+ if let Some(result) = f(output_path) {
+ return Some(result);
+ }
+ }
+ None
+}
+
+pub fn output_contains_path(output_paths: &[PathBuf], input_path: &PathBuf) -> bool {
+ let input_path = input_path.canonicalize().ok();
+ if input_path.is_none() {
+ return false;
+ }
+ let check = |output_path: &PathBuf| {
+ if output_path.canonicalize().ok() == input_path {
+ Some(())
+ } else {
+ None
+ }
+ };
+ check_output(output_paths, check).is_some()
+}
+
+pub fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> {
+ let check = |output_path: &PathBuf| {
+ if output_path.is_dir() {
+ Some(output_path.clone())
+ } else {
+ None
+ }
+ };
+ check_output(output_paths, check)
+}
+
+fn escape_dep_filename(filename: &FileName) -> String {
+ // Apparently clang and gcc *only* escape spaces:
+ // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
+ filename.to_string().replace(" ", "\\ ")
+}
+
+pub fn write_out_deps(sess: &Session, outputs: &OutputFilenames, out_filenames: &[PathBuf]) {
+ // Write out dependency rules to the dep-info file if requested
+ if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
+ return;
+ }
+ let deps_filename = outputs.path(OutputType::DepInfo);
+
+ let result = (|| -> io::Result<()> {
+ // Build a list of files used to compile the output and
+ // write Makefile-compatible dependency rules
+ let files: Vec<String> = sess.source_map()
+ .files()
+ .iter()
+ .filter(|fmap| fmap.is_real_file())
+ .filter(|fmap| !fmap.is_imported())
+ .map(|fmap| escape_dep_filename(&fmap.name))
+ .collect();
+ let mut file = fs::File::create(&deps_filename)?;
+ for path in out_filenames {
+ writeln!(file, "{}: {}\n", path.display(), files.join(" "))?;
+ }
+
+ // Emit a fake target for each input file to the compilation. This
+ // prevents `make` from spitting out an error if a file is later
+ // deleted. For more info see #28735
+ for path in files {
+ writeln!(file, "{}:", path)?;
+ }
+ Ok(())
+ })();
+
+ if let Err(e) = result {
+ sess.fatal(&format!(
+ "error writing dependencies to `{}`: {}",
+ deps_filename.display(),
+ e
+ ));
+ }
+}
+
+pub fn provide(providers: &mut ty::query::Providers) {
+ providers.analysis = analysis;
+ proc_macro_decls::provide(providers);
+}
+
+fn analysis<'tcx>(
+ tcx: TyCtxt<'_, 'tcx, 'tcx>,
+ cnum: CrateNum,
+) -> Result<(), ErrorReported> {
+ assert_eq!(cnum, LOCAL_CRATE);
+
+ let sess = tcx.sess;
+
+ parallel!({
+ time(sess, "looking for entry point", || {
+ middle::entry::find_entry_point(tcx)
+ });
+
+ time(sess, "looking for plugin registrar", || {
+ plugin::build::find_plugin_registrar(tcx)
+ });
+
+ time(sess, "looking for derive registrar", || {
+ proc_macro_decls::find(tcx)
+ });
+ }, {
+ time(sess, "loop checking", || loops::check_crate(tcx));
+ }, {
+ time(sess, "attribute checking", || {
+ hir::check_attr::check_crate(tcx)
+ });
+ }, {
+ time(sess, "stability checking", || {
+ stability::check_unstable_api_usage(tcx)
+ });
+ });
+
+ // passes are timed inside typeck
+ typeck::check_crate(tcx)?;
+
+ time(sess, "misc checking", || {
+ parallel!({
+ time(sess, "rvalue promotion", || {
+ rvalue_promotion::check_crate(tcx)
+ });
+ }, {
+ time(sess, "intrinsic checking", || {
+ middle::intrinsicck::check_crate(tcx)
+ });
+ }, {
+ time(sess, "match checking", || mir::matchck_crate(tcx));
+ }, {
+ // this must run before MIR dump, because
+ // "not all control paths return a value" is reported here.
+ //
+ // maybe move the check to a MIR pass?
+ time(sess, "liveness checking", || {
+ middle::liveness::check_crate(tcx)
+ });
+ });
+ });
+
+ // Abort so we don't try to construct MIR with liveness errors.
+ // We also won't want to continue with errors from rvalue promotion
+ tcx.sess.abort_if_errors();
+
+ time(sess, "borrow checking", || {
+ if tcx.use_ast_borrowck() {
+ borrowck::check_crate(tcx);
+ }
+ });
+
+ time(sess,
+ "MIR borrow checking",
+ || tcx.par_body_owners(|def_id| { tcx.ensure().mir_borrowck(def_id); }));
+
+ time(sess, "dumping chalk-like clauses", || {
+ rustc_traits::lowering::dump_program_clauses(tcx);
+ });
+
+ time(sess, "MIR effect checking", || {
+ for def_id in tcx.body_owners() {
+ mir::transform::check_unsafety::check_unsafety(tcx, def_id)
+ }
+ });
+
+ time(sess, "layout testing", || layout_test::test_layout(tcx));
+
+ // Avoid overwhelming user with errors if borrow checking failed.
+ // I'm not sure how helpful this is, to be honest, but it avoids
+ // a
+ // lot of annoying errors in the compile-fail tests (basically,
+ // lint warnings and so on -- kindck used to do this abort, but
+ // kindck is gone now). -nmatsakis
+ if sess.err_count() > 0 {
+ return Err(ErrorReported);
+ }
+
+ time(sess, "misc checking", || {
+ parallel!({
+ time(sess, "privacy checking", || {
+ rustc_privacy::check_crate(tcx)
+ });
+ }, {
+ time(sess, "death checking", || middle::dead::check_crate(tcx));
+ }, {
+ time(sess, "unused lib feature checking", || {
+ stability::check_unused_or_stable_features(tcx)
+ });
+ }, {
+ time(sess, "lint checking", || lint::check_crate(tcx));
+ });
+ });
+
+ Ok(())
+}
--- /dev/null
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::hir;
+use rustc::ty::TyCtxt;
+use rustc::ty::query::Providers;
+use syntax::ast;
+use syntax::attr;
+
+pub fn find<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> Option<DefId> {
+ tcx.proc_macro_decls_static(LOCAL_CRATE)
+}
+
+fn proc_macro_decls_static<'tcx>(
+ tcx: TyCtxt<'_, 'tcx, 'tcx>,
+ cnum: CrateNum,
+) -> Option<DefId> {
+ assert_eq!(cnum, LOCAL_CRATE);
+
+ let mut finder = Finder { decls: None };
+ tcx.hir().krate().visit_all_item_likes(&mut finder);
+
+ finder.decls.map(|id| tcx.hir().local_def_id(id))
+}
+
+struct Finder {
+ decls: Option<ast::NodeId>,
+}
+
+impl<'v> ItemLikeVisitor<'v> for Finder {
+ fn visit_item(&mut self, item: &hir::Item) {
+ if attr::contains_name(&item.attrs, "rustc_proc_macro_decls") {
+ self.decls = Some(item.id);
+ }
+ }
+
+ fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+ }
+
+ fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+ }
+}
+
+pub(crate) fn provide(providers: &mut Providers<'_>) {
+ *providers = Providers {
+ proc_macro_decls_static,
+ ..*providers
+ };
+}
--- /dev/null
+use rustc::session::Session;
+use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan};
+use std::sync::mpsc::{Receiver};
+use std::io::{Write};
+use rustc::dep_graph::{DepNode};
+use std::time::{Duration, Instant};
+
+pub mod trace;
+
+/// begin a profile thread, if not already running
+pub fn begin(sess: &Session) {
+ use std::thread;
+ use std::sync::mpsc::{channel};
+ let (tx, rx) = channel();
+ if profq_set_chan(sess, tx) {
+ thread::spawn(move || profile_queries_thread(rx));
+ }
+}
+
+/// dump files with profiling information to the given base path, and
+/// wait for this dump to complete.
+///
+/// wraps the RPC (send/recv channel logic) of requesting a dump.
+pub fn dump(sess: &Session, path: String) {
+ use std::sync::mpsc::{channel};
+ let (tx, rx) = channel();
+ let params = ProfQDumpParams {
+ path,
+ ack: tx,
+ // FIXME: Add another compiler flag to toggle whether this log
+ // is written; false for now
+ dump_profq_msg_log: true,
+ };
+ profq_msg(sess, ProfileQueriesMsg::Dump(params));
+ let _ = rx.recv().unwrap();
+}
+
+// State for parsing recursive trace structure in separate thread, via messages
+#[derive(Clone, Eq, PartialEq)]
+enum ParseState {
+ // No (local) parse state; may be parsing a tree, focused on a
+ // sub-tree that could be anything.
+ Clear,
+ // Have Query information from the last message
+ HaveQuery(trace::Query, Instant),
+ // Have "time-begin" information from the last message (doit flag, and message)
+ HaveTimeBegin(String, Instant),
+ // Have "task-begin" information from the last message
+ HaveTaskBegin(DepNode, Instant),
+}
+struct StackFrame {
+ pub parse_st: ParseState,
+ pub traces: Vec<trace::Rec>,
+}
+
+fn total_duration(traces: &[trace::Rec]) -> Duration {
+ Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum()
+}
+
+// profiling thread; retains state (in local variables) and dump traces, upon request.
+fn profile_queries_thread(r: Receiver<ProfileQueriesMsg>) {
+ use self::trace::*;
+ use std::fs::File;
+ use std::time::{Instant};
+
+ let mut profq_msgs: Vec<ProfileQueriesMsg> = vec![];
+ let mut frame: StackFrame = StackFrame { parse_st: ParseState::Clear, traces: vec![] };
+ let mut stack: Vec<StackFrame> = vec![];
+ loop {
+ let msg = r.recv();
+ if let Err(_recv_err) = msg {
+ // FIXME: Perhaps do something smarter than simply quitting?
+ break
+ };
+ let msg = msg.unwrap();
+ debug!("profile_queries_thread: {:?}", msg);
+
+ // Meta-level versus _actual_ queries messages
+ match msg {
+ ProfileQueriesMsg::Halt => return,
+ ProfileQueriesMsg::Dump(params) => {
+ assert!(stack.is_empty());
+ assert!(frame.parse_st == ParseState::Clear);
+
+ // write log of all messages
+ if params.dump_profq_msg_log {
+ let mut log_file =
+ File::create(format!("{}.log.txt", params.path)).unwrap();
+ for m in profq_msgs.iter() {
+ writeln!(&mut log_file, "{:?}", m).unwrap()
+ };
+ }
+
+ // write HTML file, and counts file
+ let html_path = format!("{}.html", params.path);
+ let mut html_file = File::create(&html_path).unwrap();
+
+ let counts_path = format!("{}.counts.txt", params.path);
+ let mut counts_file = File::create(&counts_path).unwrap();
+
+ writeln!(html_file,
+ "<html>\n<head>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">",
+ "profile_queries.css").unwrap();
+ writeln!(html_file, "<style>").unwrap();
+ trace::write_style(&mut html_file);
+ writeln!(html_file, "</style>\n</head>\n<body>").unwrap();
+ trace::write_traces(&mut html_file, &mut counts_file, &frame.traces);
+ writeln!(html_file, "</body>\n</html>").unwrap();
+
+ let ack_path = format!("{}.ack", params.path);
+ let ack_file = File::create(&ack_path).unwrap();
+ drop(ack_file);
+
+ // Tell main thread that we are done, e.g., so it can exit
+ params.ack.send(()).unwrap();
+ }
+ // Actual query message:
+ msg => {
+ // Record msg in our log
+ profq_msgs.push(msg.clone());
+ // Respond to the message, knowing that we've already handled Halt and Dump, above.
+ match (frame.parse_st.clone(), msg) {
+ (_, ProfileQueriesMsg::Halt) | (_, ProfileQueriesMsg::Dump(_)) => {
+ unreachable!();
+ },
+ // Parse State: Clear
+ (ParseState::Clear,
+ ProfileQueriesMsg::QueryBegin(span, querymsg)) => {
+ let start = Instant::now();
+ frame.parse_st = ParseState::HaveQuery
+ (Query { span, msg: querymsg }, start)
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::CacheHit) => {
+ panic!("parse error: unexpected CacheHit; expected QueryBegin")
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::ProviderBegin) => {
+ panic!("parse error: expected QueryBegin before beginning a provider")
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::ProviderEnd) => {
+ let provider_extent = frame.traces;
+ match stack.pop() {
+ None =>
+ panic!("parse error: expected a stack frame; found an empty stack"),
+ Some(old_frame) => {
+ match old_frame.parse_st {
+ ParseState::HaveQuery(q, start) => {
+ let duration = start.elapsed();
+ frame = StackFrame{
+ parse_st: ParseState::Clear,
+ traces: old_frame.traces
+ };
+ let dur_extent = total_duration(&provider_extent);
+ let trace = Rec {
+ effect: Effect::QueryBegin(q, CacheCase::Miss),
+ extent: Box::new(provider_extent),
+ start: start,
+ dur_self: duration - dur_extent,
+ dur_total: duration,
+ };
+ frame.traces.push( trace );
+ },
+ _ => panic!("internal parse error: malformed parse stack")
+ }
+ }
+ }
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::TimeBegin(msg)) => {
+ let start = Instant::now();
+ frame.parse_st = ParseState::HaveTimeBegin(msg, start);
+ stack.push(frame);
+ frame = StackFrame{parse_st: ParseState::Clear, traces: vec![]};
+ },
+ (_, ProfileQueriesMsg::TimeBegin(_)) => {
+ panic!("parse error; did not expect time begin here");
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::TimeEnd) => {
+ let provider_extent = frame.traces;
+ match stack.pop() {
+ None =>
+ panic!("parse error: expected a stack frame; found an empty stack"),
+ Some(old_frame) => {
+ match old_frame.parse_st {
+ ParseState::HaveTimeBegin(msg, start) => {
+ let duration = start.elapsed();
+ frame = StackFrame{
+ parse_st: ParseState::Clear,
+ traces: old_frame.traces
+ };
+ let dur_extent = total_duration(&provider_extent);
+ let trace = Rec {
+ effect: Effect::TimeBegin(msg),
+ extent: Box::new(provider_extent),
+ start: start,
+ dur_total: duration,
+ dur_self: duration - dur_extent,
+ };
+ frame.traces.push( trace );
+ },
+ _ => panic!("internal parse error: malformed parse stack")
+ }
+ }
+ }
+ },
+ (_, ProfileQueriesMsg::TimeEnd) => {
+ panic!("parse error")
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::TaskBegin(key)) => {
+ let start = Instant::now();
+ frame.parse_st = ParseState::HaveTaskBegin(key, start);
+ stack.push(frame);
+ frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] };
+ },
+ (_, ProfileQueriesMsg::TaskBegin(_)) => {
+ panic!("parse error; did not expect time begin here");
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::TaskEnd) => {
+ let provider_extent = frame.traces;
+ match stack.pop() {
+ None =>
+ panic!("parse error: expected a stack frame; found an empty stack"),
+ Some(old_frame) => {
+ match old_frame.parse_st {
+ ParseState::HaveTaskBegin(key, start) => {
+ let duration = start.elapsed();
+ frame = StackFrame{
+ parse_st: ParseState::Clear,
+ traces: old_frame.traces
+ };
+ let dur_extent = total_duration(&provider_extent);
+ let trace = Rec {
+ effect: Effect::TaskBegin(key),
+ extent: Box::new(provider_extent),
+ start: start,
+ dur_total: duration,
+ dur_self: duration - dur_extent,
+ };
+ frame.traces.push( trace );
+ },
+ _ => panic!("internal parse error: malformed parse stack")
+ }
+ }
+ }
+ },
+ (_, ProfileQueriesMsg::TaskEnd) => {
+ panic!("parse error")
+ },
+ // Parse State: HaveQuery
+ (ParseState::HaveQuery(q,start),
+ ProfileQueriesMsg::CacheHit) => {
+ let duration = start.elapsed();
+ let trace : Rec = Rec{
+ effect: Effect::QueryBegin(q, CacheCase::Hit),
+ extent: Box::new(vec![]),
+ start: start,
+ dur_self: duration,
+ dur_total: duration,
+ };
+ frame.traces.push( trace );
+ frame.parse_st = ParseState::Clear;
+ },
+ (ParseState::HaveQuery(_, _),
+ ProfileQueriesMsg::ProviderBegin) => {
+ stack.push(frame);
+ frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] };
+ },
+
+ // Parse errors:
+
+ (ParseState::HaveQuery(q, _),
+ ProfileQueriesMsg::ProviderEnd) => {
+ panic!("parse error: unexpected ProviderEnd; \
+ expected something else to follow BeginQuery for {:?}", q)
+ },
+ (ParseState::HaveQuery(q1, _),
+ ProfileQueriesMsg::QueryBegin(span2, querymsg2)) => {
+ panic!("parse error: unexpected QueryBegin; \
+ earlier query is unfinished: {:?} and now {:?}",
+ q1, Query{span:span2, msg: querymsg2})
+ },
+ (ParseState::HaveTimeBegin(_, _), _) => {
+ unreachable!()
+ },
+ (ParseState::HaveTaskBegin(_, _), _) => {
+ unreachable!()
+ },
+ }
+ }
+ }
+ }
+}
--- /dev/null
+use super::*;
+use syntax_pos::SpanData;
+use rustc_data_structures::fx::FxHashMap;
+use rustc::util::common::QueryMsg;
+use std::fs::File;
+use std::time::{Duration, Instant};
+use rustc::dep_graph::{DepNode};
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Query {
+ pub span: SpanData,
+ pub msg: QueryMsg,
+}
+pub enum Effect {
+ QueryBegin(Query, CacheCase),
+ TimeBegin(String),
+ TaskBegin(DepNode),
+}
+pub enum CacheCase {
+ Hit, Miss
+}
+/// Recursive trace structure
+pub struct Rec {
+ pub effect: Effect,
+ pub start: Instant,
+ pub dur_self: Duration,
+ pub dur_total: Duration,
+ pub extent: Box<Vec<Rec>>,
+}
+pub struct QueryMetric {
+ pub count: usize,
+ pub dur_self: Duration,
+ pub dur_total: Duration,
+}
+
+fn cons(s: &str) -> String {
+ let first = s.split(|d| d == '(' || d == '{').next();
+ assert!(first.is_some() && first != Some(""));
+ first.unwrap().to_owned()
+}
+
+pub fn cons_of_query_msg(q: &trace::Query) -> String {
+ cons(&format!("{:?}", q.msg))
+}
+
+pub fn cons_of_key(k: &DepNode) -> String {
+ cons(&format!("{:?}", k))
+}
+
+// First return value is text; second return value is a CSS class
+pub fn html_of_effect(eff: &Effect) -> (String, String) {
+ match *eff {
+ Effect::TimeBegin(ref msg) => {
+ (msg.clone(),
+ "time-begin".to_string())
+ },
+ Effect::TaskBegin(ref key) => {
+ let cons = cons_of_key(key);
+ (cons.clone(), format!("{} task-begin", cons))
+ },
+ Effect::QueryBegin(ref qmsg, ref cc) => {
+ let cons = cons_of_query_msg(qmsg);
+ (cons.clone(),
+ format!("{} {}",
+ cons,
+ match *cc {
+ CacheCase::Hit => "hit",
+ CacheCase::Miss => "miss",
+ }))
+ }
+ }
+}
+
+// First return value is text; second return value is a CSS class
+fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) {
+ use rustc::util::common::duration_to_secs_str;
+ (duration_to_secs_str(dur.clone()), String::new())
+}
+
+fn html_of_fraction(frac: f64) -> (String, &'static str) {
+ let css = {
+ if frac > 0.50 { "frac-50" }
+ else if frac > 0.40 { "frac-40" }
+ else if frac > 0.30 { "frac-30" }
+ else if frac > 0.20 { "frac-20" }
+ else if frac > 0.10 { "frac-10" }
+ else if frac > 0.05 { "frac-05" }
+ else if frac > 0.02 { "frac-02" }
+ else if frac > 0.01 { "frac-01" }
+ else if frac > 0.001 { "frac-001" }
+ else { "frac-0" }
+ };
+ let percent = frac * 100.0;
+
+ if percent > 0.1 {
+ (format!("{:.1}%", percent), css)
+ } else {
+ ("< 0.1%".to_string(), css)
+ }
+}
+
+fn total_duration(traces: &[Rec]) -> Duration {
+ Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum()
+}
+
+fn duration_div(nom: Duration, den: Duration) -> f64 {
+ fn to_nanos(d: Duration) -> u64 {
+ d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64
+ }
+
+ to_nanos(nom) as f64 / to_nanos(den) as f64
+}
+
+fn write_traces_rec(file: &mut File, traces: &[Rec], total: Duration, depth: usize) {
+ for t in traces {
+ let (eff_text, eff_css_classes) = html_of_effect(&t.effect);
+ let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.dur_total);
+ let fraction = duration_div(t.dur_total, total);
+ let percent = fraction * 100.0;
+ let (frc_text, frc_css_classes) = html_of_fraction(fraction);
+ writeln!(file, "<div class=\"trace depth-{} extent-{}{} {} {} {}\">",
+ depth,
+ t.extent.len(),
+ /* Heuristic for 'important' CSS class: */
+ if t.extent.len() > 5 || percent >= 1.0 { " important" } else { "" },
+ eff_css_classes,
+ dur_css_classes,
+ frc_css_classes,
+ ).unwrap();
+ writeln!(file, "<div class=\"eff\">{}</div>", eff_text).unwrap();
+ writeln!(file, "<div class=\"dur\">{}</div>", dur_text).unwrap();
+ writeln!(file, "<div class=\"frc\">{}</div>", frc_text).unwrap();
+ write_traces_rec(file, &t.extent, total, depth + 1);
+ writeln!(file, "</div>").unwrap();
+ }
+}
+
+fn compute_counts_rec(counts: &mut FxHashMap<String,QueryMetric>, traces: &[Rec]) {
+ counts.reserve(traces.len());
+ for t in traces.iter() {
+ match t.effect {
+ Effect::TimeBegin(ref msg) => {
+ let qm = match counts.get(msg) {
+ Some(_qm) => panic!("TimeBegin with non-unique, repeat message"),
+ None => QueryMetric {
+ count: 1,
+ dur_self: t.dur_self,
+ dur_total: t.dur_total,
+ }
+ };
+ counts.insert(msg.clone(), qm);
+ },
+ Effect::TaskBegin(ref key) => {
+ let cons = cons_of_key(key);
+ let qm = match counts.get(&cons) {
+ Some(qm) =>
+ QueryMetric {
+ count: qm.count + 1,
+ dur_self: qm.dur_self + t.dur_self,
+ dur_total: qm.dur_total + t.dur_total,
+ },
+ None => QueryMetric {
+ count: 1,
+ dur_self: t.dur_self,
+ dur_total: t.dur_total,
+ }
+ };
+ counts.insert(cons, qm);
+ },
+ Effect::QueryBegin(ref qmsg, ref _cc) => {
+ let qcons = cons_of_query_msg(qmsg);
+ let qm = match counts.get(&qcons) {
+ Some(qm) =>
+ QueryMetric {
+ count: qm.count + 1,
+ dur_total: qm.dur_total + t.dur_total,
+ dur_self: qm.dur_self + t.dur_self
+ },
+ None => QueryMetric {
+ count: 1,
+ dur_total: t.dur_total,
+ dur_self: t.dur_self,
+ }
+ };
+ counts.insert(qcons, qm);
+ }
+ }
+ compute_counts_rec(counts, &t.extent)
+ }
+}
+
+pub fn write_counts(count_file: &mut File, counts: &mut FxHashMap<String, QueryMetric>) {
+ use rustc::util::common::duration_to_secs_str;
+ use std::cmp::Reverse;
+
+ let mut data = counts.iter().map(|(ref cons, ref qm)|
+ (cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone())
+ ).collect::<Vec<_>>();
+
+ data.sort_by_key(|k| Reverse(k.3));
+ for (cons, count, dur_total, dur_self) in data {
+ writeln!(count_file, "{}, {}, {}, {}",
+ cons, count,
+ duration_to_secs_str(dur_total),
+ duration_to_secs_str(dur_self)
+ ).unwrap();
+ }
+}
+
+pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &[Rec]) {
+ let capacity = traces.iter().fold(0, |acc, t| acc + 1 + t.extent.len());
+ let mut counts = FxHashMap::with_capacity_and_hasher(capacity, Default::default());
+ compute_counts_rec(&mut counts, traces);
+ write_counts(counts_file, &mut counts);
+
+ let total: Duration = total_duration(traces);
+ write_traces_rec(html_file, traces, total, 0)
+}
+
+pub fn write_style(html_file: &mut File) {
+ write!(html_file, "{}", "
+body {
+ font-family: sans-serif;
+ background: black;
+}
+.trace {
+ color: black;
+ display: inline-block;
+ border-style: solid;
+ border-color: red;
+ border-width: 1px;
+ border-radius: 5px;
+ padding: 0px;
+ margin: 1px;
+ font-size: 0px;
+}
+.task-begin {
+ border-width: 1px;
+ color: white;
+ border-color: #ff8;
+ font-size: 0px;
+}
+.miss {
+ border-color: red;
+ border-width: 1px;
+}
+.extent-0 {
+ padding: 2px;
+}
+.time-begin {
+ border-width: 4px;
+ font-size: 12px;
+ color: white;
+ border-color: #afa;
+}
+.important {
+ border-width: 3px;
+ font-size: 12px;
+ color: white;
+ border-color: #f77;
+}
+.hit {
+ padding: 0px;
+ border-color: blue;
+ border-width: 3px;
+}
+.eff {
+ color: #fff;
+ display: inline-block;
+}
+.frc {
+ color: #7f7;
+ display: inline-block;
+}
+.dur {
+ display: none
+}
+.frac-50 {
+ padding: 10px;
+ border-width: 10px;
+ font-size: 32px;
+}
+.frac-40 {
+ padding: 8px;
+ border-width: 8px;
+ font-size: 24px;
+}
+.frac-30 {
+ padding: 6px;
+ border-width: 6px;
+ font-size: 18px;
+}
+.frac-20 {
+ padding: 4px;
+ border-width: 6px;
+ font-size: 16px;
+}
+.frac-10 {
+ padding: 2px;
+ border-width: 6px;
+ font-size: 14px;
+}
+").unwrap();
+}
--- /dev/null
+use rustc::session::config::{Input, OutputFilenames, ErrorOutputType};
+use rustc::session::{self, config, early_error, filesearch, Session, DiagnosticOutput};
+use rustc::session::CrateDisambiguator;
+use rustc::ty;
+use rustc::lint;
+use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_data_structures::sync::{Lock, Lrc};
+use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::thin_vec::ThinVec;
+use rustc_data_structures::fx::{FxHashSet, FxHashMap};
+use rustc_errors::registry::Registry;
+use rustc_lint;
+use rustc_metadata::dynamic_lib::DynamicLibrary;
+use rustc_mir;
+use rustc_passes;
+use rustc_plugin;
+use rustc_privacy;
+use rustc_resolve;
+use rustc_typeck;
+use std::collections::HashSet;
+use std::env;
+use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
+use std::io::{self, Write};
+use std::mem;
+use std::path::{Path, PathBuf};
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::{Arc, Mutex, Once};
+use std::ops::DerefMut;
+use smallvec::SmallVec;
+use syntax::ptr::P;
+use syntax::mut_visit::{*, MutVisitor, visit_clobber};
+use syntax::ast::BlockCheckMode;
+use syntax::util::lev_distance::find_best_match_for_name;
+use syntax::source_map::{FileLoader, RealFileLoader, SourceMap};
+use syntax::symbol::Symbol;
+use syntax::{self, ast, attr};
+#[cfg(not(parallel_compiler))]
+use std::{thread, panic};
+
+pub fn diagnostics_registry() -> Registry {
+ let mut all_errors = Vec::new();
+ all_errors.extend_from_slice(&rustc::DIAGNOSTICS);
+ all_errors.extend_from_slice(&rustc_typeck::DIAGNOSTICS);
+ all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
+ all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
+ // FIXME: need to figure out a way to get these back in here
+ // all_errors.extend_from_slice(get_codegen_backend(sess).diagnostics());
+ all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
+ all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS);
+ all_errors.extend_from_slice(&rustc_plugin::DIAGNOSTICS);
+ all_errors.extend_from_slice(&rustc_mir::DIAGNOSTICS);
+ all_errors.extend_from_slice(&syntax::DIAGNOSTICS);
+
+ Registry::new(&all_errors)
+}
+
+/// Adds `target_feature = "..."` cfgs for a variety of platform
+/// specific features (SSE, NEON etc.).
+///
+/// This is performed by checking whether a whitelisted set of
+/// features is available on the target machine, by querying LLVM.
+pub fn add_configuration(
+ cfg: &mut ast::CrateConfig,
+ sess: &Session,
+ codegen_backend: &dyn CodegenBackend,
+) {
+ let tf = Symbol::intern("target_feature");
+
+ cfg.extend(
+ codegen_backend
+ .target_features(sess)
+ .into_iter()
+ .map(|feat| (tf, Some(feat))),
+ );
+
+ if sess.crt_static_feature() {
+ cfg.insert((tf, Some(Symbol::intern("crt-static"))));
+ }
+}
+
+fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
+ let lib = DynamicLibrary::open(Some(path)).unwrap_or_else(|err| {
+ let err = format!("couldn't load codegen backend {:?}: {:?}", path, err);
+ early_error(ErrorOutputType::default(), &err);
+ });
+ unsafe {
+ match lib.symbol("__rustc_codegen_backend") {
+ Ok(f) => {
+ mem::forget(lib);
+ mem::transmute::<*mut u8, _>(f)
+ }
+ Err(e) => {
+ let err = format!("couldn't load codegen backend as it \
+ doesn't export the `__rustc_codegen_backend` \
+ symbol: {:?}", e);
+ early_error(ErrorOutputType::default(), &err);
+ }
+ }
+ }
+}
+
+pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
+ static INIT: Once = Once::new();
+
+ static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
+
+ INIT.call_once(|| {
+ let codegen_name = sess.opts.debugging_opts.codegen_backend.as_ref()
+ .unwrap_or(&sess.target.target.options.codegen_backend);
+ let backend = match &codegen_name[..] {
+ "metadata_only" => {
+ rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::boxed
+ }
+ filename if filename.contains(".") => {
+ load_backend_from_dylib(filename.as_ref())
+ }
+ codegen_name => get_codegen_sysroot(codegen_name),
+ };
+
+ unsafe {
+ LOAD = backend;
+ }
+ });
+ let backend = unsafe { LOAD() };
+ backend.init(sess);
+ backend
+}
+
+pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
+ // For now we only allow this function to be called once as it'll dlopen a
+ // few things, which seems to work best if we only do that once. In
+ // general this assertion never trips due to the once guard in `get_codegen_backend`,
+ // but there's a few manual calls to this function in this file we protect
+ // against.
+ static LOADED: AtomicBool = AtomicBool::new(false);
+ assert!(!LOADED.fetch_or(true, Ordering::SeqCst),
+ "cannot load the default codegen backend twice");
+
+ let target = session::config::host_triple();
+ let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()];
+ let path = current_dll_path()
+ .and_then(|s| s.canonicalize().ok());
+ if let Some(dll) = path {
+ // use `parent` twice to chop off the file name and then also the
+ // directory containing the dll which should be either `lib` or `bin`.
+ if let Some(path) = dll.parent().and_then(|p| p.parent()) {
+ // The original `path` pointed at the `rustc_driver` crate's dll.
+ // Now that dll should only be in one of two locations. The first is
+ // in the compiler's libdir, for example `$sysroot/lib/*.dll`. The
+ // other is the target's libdir, for example
+ // `$sysroot/lib/rustlib/$target/lib/*.dll`.
+ //
+ // We don't know which, so let's assume that if our `path` above
+ // ends in `$target` we *could* be in the target libdir, and always
+ // assume that we may be in the main libdir.
+ sysroot_candidates.push(path.to_owned());
+
+ if path.ends_with(target) {
+ sysroot_candidates.extend(path.parent() // chop off `$target`
+ .and_then(|p| p.parent()) // chop off `rustlib`
+ .and_then(|p| p.parent()) // chop off `lib`
+ .map(|s| s.to_owned()));
+ }
+ }
+ }
+
+ let sysroot = sysroot_candidates.iter()
+ .map(|sysroot| {
+ let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
+ sysroot.join(libdir).with_file_name(
+ option_env!("CFG_CODEGEN_BACKENDS_DIR").unwrap_or("codegen-backends"))
+ })
+ .filter(|f| {
+ info!("codegen backend candidate: {}", f.display());
+ f.exists()
+ })
+ .next();
+ let sysroot = sysroot.unwrap_or_else(|| {
+ let candidates = sysroot_candidates.iter()
+ .map(|p| p.display().to_string())
+ .collect::<Vec<_>>()
+ .join("\n* ");
+ let err = format!("failed to find a `codegen-backends` folder \
+ in the sysroot candidates:\n* {}", candidates);
+ early_error(ErrorOutputType::default(), &err);
+ });
+ info!("probing {} for a codegen backend", sysroot.display());
+
+ let d = sysroot.read_dir().unwrap_or_else(|e| {
+ let err = format!("failed to load default codegen backend, couldn't \
+ read `{}`: {}", sysroot.display(), e);
+ early_error(ErrorOutputType::default(), &err);
+ });
+
+ let mut file: Option<PathBuf> = None;
+
+ let expected_name = format!("rustc_codegen_llvm-{}", backend_name);
+ for entry in d.filter_map(|e| e.ok()) {
+ let path = entry.path();
+ let filename = match path.file_name().and_then(|s| s.to_str()) {
+ Some(s) => s,
+ None => continue,
+ };
+ if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) {
+ continue
+ }
+ let name = &filename[DLL_PREFIX.len() .. filename.len() - DLL_SUFFIX.len()];
+ if name != expected_name {
+ continue
+ }
+ if let Some(ref prev) = file {
+ let err = format!("duplicate codegen backends found\n\
+ first: {}\n\
+ second: {}\n\
+ ", prev.display(), path.display());
+ early_error(ErrorOutputType::default(), &err);
+ }
+ file = Some(path.clone());
+ }
+
+ match file {
+ Some(ref s) => return load_backend_from_dylib(s),
+ None => {
+ let err = format!("failed to load default codegen backend for `{}`, \
+ no appropriate codegen dylib found in `{}`",
+ backend_name, sysroot.display());
+ early_error(ErrorOutputType::default(), &err);
+ }
+ }
+
+ #[cfg(unix)]
+ fn current_dll_path() -> Option<PathBuf> {
+ use std::ffi::{OsStr, CStr};
+ use std::os::unix::prelude::*;
+
+ unsafe {
+ let addr = current_dll_path as usize as *mut _;
+ let mut info = mem::zeroed();
+ if libc::dladdr(addr, &mut info) == 0 {
+ info!("dladdr failed");
+ return None
+ }
+ if info.dli_fname.is_null() {
+ info!("dladdr returned null pointer");
+ return None
+ }
+ let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
+ let os = OsStr::from_bytes(bytes);
+ Some(PathBuf::from(os))
+ }
+ }
+
+ #[cfg(windows)]
+ fn current_dll_path() -> Option<PathBuf> {
+ use std::ffi::OsString;
+ use std::os::windows::prelude::*;
+
+ extern "system" {
+ fn GetModuleHandleExW(dwFlags: u32,
+ lpModuleName: usize,
+ phModule: *mut usize) -> i32;
+ fn GetModuleFileNameW(hModule: usize,
+ lpFilename: *mut u16,
+ nSize: u32) -> u32;
+ }
+
+ const GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS: u32 = 0x00000004;
+
+ unsafe {
+ let mut module = 0;
+ let r = GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ current_dll_path as usize,
+ &mut module);
+ if r == 0 {
+ info!("GetModuleHandleExW failed: {}", io::Error::last_os_error());
+ return None
+ }
+ let mut space = Vec::with_capacity(1024);
+ let r = GetModuleFileNameW(module,
+ space.as_mut_ptr(),
+ space.capacity() as u32);
+ if r == 0 {
+ info!("GetModuleFileNameW failed: {}", io::Error::last_os_error());
+ return None
+ }
+ let r = r as usize;
+ if r >= space.capacity() {
+ info!("our buffer was too small? {}",
+ io::Error::last_os_error());
+ return None
+ }
+ space.set_len(r);
+ let os = OsString::from_wide(&space);
+ Some(PathBuf::from(os))
+ }
+ }
+}
+
+pub fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
+ use std::hash::Hasher;
+
+ // The crate_disambiguator is a 128 bit hash. The disambiguator is fed
+ // into various other hashes quite a bit (symbol hashes, incr. comp. hashes,
+ // debuginfo type IDs, etc), so we don't want it to be too wide. 128 bits
+ // should still be safe enough to avoid collisions in practice.
+ let mut hasher = StableHasher::<Fingerprint>::new();
+
+ let mut metadata = session.opts.cg.metadata.clone();
+ // We don't want the crate_disambiguator to dependent on the order
+ // -C metadata arguments, so sort them:
+ metadata.sort();
+ // Every distinct -C metadata value is only incorporated once:
+ metadata.dedup();
+
+ hasher.write(b"metadata");
+ for s in &metadata {
+ // Also incorporate the length of a metadata string, so that we generate
+ // different values for `-Cmetadata=ab -Cmetadata=c` and
+ // `-Cmetadata=a -Cmetadata=bc`
+ hasher.write_usize(s.len());
+ hasher.write(s.as_bytes());
+ }
+
+ // Also incorporate crate type, so that we don't get symbol conflicts when
+ // linking against a library of the same name, if this is an executable.
+ let is_exe = session
+ .crate_types
+ .borrow()
+ .contains(&config::CrateType::Executable);
+ hasher.write(if is_exe { b"exe" } else { b"lib" });
+
+ CrateDisambiguator::from(hasher.finish())
+}
+
+pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
+ // Unconditionally collect crate types from attributes to make them used
+ let attr_types: Vec<config::CrateType> = attrs
+ .iter()
+ .filter_map(|a| {
+ if a.check_name("crate_type") {
+ match a.value_str() {
+ Some(ref n) if *n == "rlib" => Some(config::CrateType::Rlib),
+ Some(ref n) if *n == "dylib" => Some(config::CrateType::Dylib),
+ Some(ref n) if *n == "cdylib" => Some(config::CrateType::Cdylib),
+ Some(ref n) if *n == "lib" => Some(config::default_lib_output()),
+ Some(ref n) if *n == "staticlib" => Some(config::CrateType::Staticlib),
+ Some(ref n) if *n == "proc-macro" => Some(config::CrateType::ProcMacro),
+ Some(ref n) if *n == "bin" => Some(config::CrateType::Executable),
+ Some(ref n) => {
+ let crate_types = vec![
+ Symbol::intern("rlib"),
+ Symbol::intern("dylib"),
+ Symbol::intern("cdylib"),
+ Symbol::intern("lib"),
+ Symbol::intern("staticlib"),
+ Symbol::intern("proc-macro"),
+ Symbol::intern("bin")
+ ];
+
+ if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().node {
+ let span = spanned.span;
+ let lev_candidate = find_best_match_for_name(
+ crate_types.iter(),
+ &n.as_str(),
+ None
+ );
+ if let Some(candidate) = lev_candidate {
+ session.buffer_lint_with_diagnostic(
+ lint::builtin::UNKNOWN_CRATE_TYPES,
+ ast::CRATE_NODE_ID,
+ span,
+ "invalid `crate_type` value",
+ lint::builtin::BuiltinLintDiagnostics::
+ UnknownCrateTypes(
+ span,
+ "did you mean".to_string(),
+ format!("\"{}\"", candidate)
+ )
+ );
+ } else {
+ session.buffer_lint(
+ lint::builtin::UNKNOWN_CRATE_TYPES,
+ ast::CRATE_NODE_ID,
+ span,
+ "invalid `crate_type` value"
+ );
+ }
+ }
+ None
+ }
+ None => None
+ }
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ // If we're generating a test executable, then ignore all other output
+ // styles at all other locations
+ if session.opts.test {
+ return vec![config::CrateType::Executable];
+ }
+
+ // Only check command line flags if present. If no types are specified by
+ // command line, then reuse the empty `base` Vec to hold the types that
+ // will be found in crate attributes.
+ let mut base = session.opts.crate_types.clone();
+ if base.is_empty() {
+ base.extend(attr_types);
+ if base.is_empty() {
+ base.push(::rustc_codegen_utils::link::default_output_for_target(
+ session,
+ ));
+ } else {
+ base.sort();
+ base.dedup();
+ }
+ }
+
+ base.retain(|crate_type| {
+ let res = !::rustc_codegen_utils::link::invalid_output_for_target(session, *crate_type);
+
+ if !res {
+ session.warn(&format!(
+ "dropping unsupported crate type `{}` for target `{}`",
+ *crate_type, session.opts.target_triple
+ ));
+ }
+
+ res
+ });
+
+ base
+}
+
+pub fn build_output_filenames(
+ input: &Input,
+ odir: &Option<PathBuf>,
+ ofile: &Option<PathBuf>,
+ attrs: &[ast::Attribute],
+ sess: &Session,
+) -> OutputFilenames {
+ match *ofile {
+ None => {
+ // "-" as input file will cause the parser to read from stdin so we
+ // have to make up a name
+ // We want to toss everything after the final '.'
+ let dirpath = (*odir).as_ref().cloned().unwrap_or_default();
+
+ // If a crate name is present, we use it as the link name
+ let stem = sess.opts
+ .crate_name
+ .clone()
+ .or_else(|| attr::find_crate_name(attrs).map(|n| n.to_string()))
+ .unwrap_or_else(|| input.filestem().to_owned());
+
+ OutputFilenames {
+ out_directory: dirpath,
+ out_filestem: stem,
+ single_output_file: None,
+ extra: sess.opts.cg.extra_filename.clone(),
+ outputs: sess.opts.output_types.clone(),
+ }
+ }
+
+ Some(ref out_file) => {
+ let unnamed_output_types = sess.opts
+ .output_types
+ .values()
+ .filter(|a| a.is_none())
+ .count();
+ let ofile = if unnamed_output_types > 1 {
+ sess.warn(
+ "due to multiple output types requested, the explicitly specified \
+ output file name will be adapted for each output type",
+ );
+ None
+ } else {
+ Some(out_file.clone())
+ };
+ if *odir != None {
+ sess.warn("ignoring --out-dir flag due to -o flag");
+ }
+ if !sess.opts.cg.extra_filename.is_empty() {
+ sess.warn("ignoring -C extra-filename flag due to -o flag");
+ }
+
+ OutputFilenames {
+ out_directory: out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
+ out_filestem: out_file
+ .file_stem()
+ .unwrap_or_default()
+ .to_str()
+ .unwrap()
+ .to_string(),
+ single_output_file: ofile,
+ extra: sess.opts.cg.extra_filename.clone(),
+ outputs: sess.opts.output_types.clone(),
+ }
+ }
+ }
+}
+
+// Note: Also used by librustdoc, see PR #43348. Consider moving this struct elsewhere.
+//
+// FIXME: Currently the `everybody_loops` transformation is not applied to:
+// * `const fn`, due to issue #43636 that `loop` is not supported for const evaluation. We are
+// waiting for miri to fix that.
+// * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging.
+// Solving this may require `!` to implement every trait, which relies on the an even more
+// ambitious form of the closed RFC #1637. See also [#34511].
+//
+// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401
+pub struct ReplaceBodyWithLoop<'a> {
+ within_static_or_const: bool,
+ nested_blocks: Option<Vec<ast::Block>>,
+ sess: &'a Session,
+}
+
+impl<'a> ReplaceBodyWithLoop<'a> {
+ pub fn new(sess: &'a Session) -> ReplaceBodyWithLoop<'a> {
+ ReplaceBodyWithLoop {
+ within_static_or_const: false,
+ nested_blocks: None,
+ sess
+ }
+ }
+
+ fn run<R, F: FnOnce(&mut Self) -> R>(&mut self, is_const: bool, action: F) -> R {
+ let old_const = mem::replace(&mut self.within_static_or_const, is_const);
+ let old_blocks = self.nested_blocks.take();
+ let ret = action(self);
+ self.within_static_or_const = old_const;
+ self.nested_blocks = old_blocks;
+ ret
+ }
+
+ fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool {
+ if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output {
+ fn involves_impl_trait(ty: &ast::Ty) -> bool {
+ match ty.node {
+ ast::TyKind::ImplTrait(..) => true,
+ ast::TyKind::Slice(ref subty) |
+ ast::TyKind::Array(ref subty, _) |
+ ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) |
+ ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) |
+ ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
+ ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
+ ast::TyKind::Path(_, ref path) => path.segments.iter().any(|seg| {
+ match seg.args.as_ref().map(|generic_arg| &**generic_arg) {
+ None => false,
+ Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
+ let types = data.args.iter().filter_map(|arg| match arg {
+ ast::GenericArg::Type(ty) => Some(ty),
+ _ => None,
+ });
+ any_involves_impl_trait(types.into_iter()) ||
+ any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty))
+ },
+ Some(&ast::GenericArgs::Parenthesized(ref data)) => {
+ any_involves_impl_trait(data.inputs.iter()) ||
+ any_involves_impl_trait(data.output.iter())
+ }
+ }
+ }),
+ _ => false,
+ }
+ }
+
+ fn any_involves_impl_trait<'a, I: Iterator<Item = &'a P<ast::Ty>>>(mut it: I) -> bool {
+ it.any(|subty| involves_impl_trait(subty))
+ }
+
+ involves_impl_trait(ty)
+ } else {
+ false
+ }
+ }
+}
+
+impl<'a> MutVisitor for ReplaceBodyWithLoop<'a> {
+ fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
+ let is_const = match i {
+ ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
+ ast::ItemKind::Fn(ref decl, ref header, _, _) =>
+ header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
+ _ => false,
+ };
+ self.run(is_const, |s| noop_visit_item_kind(i, s))
+ }
+
+ fn flat_map_trait_item(&mut self, i: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
+ let is_const = match i.node {
+ ast::TraitItemKind::Const(..) => true,
+ ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
+ header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
+ _ => false,
+ };
+ self.run(is_const, |s| noop_flat_map_trait_item(i, s))
+ }
+
+ fn flat_map_impl_item(&mut self, i: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
+ let is_const = match i.node {
+ ast::ImplItemKind::Const(..) => true,
+ ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
+ header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
+ _ => false,
+ };
+ self.run(is_const, |s| noop_flat_map_impl_item(i, s))
+ }
+
+ fn visit_anon_const(&mut self, c: &mut ast::AnonConst) {
+ self.run(true, |s| noop_visit_anon_const(c, s))
+ }
+
+ fn visit_block(&mut self, b: &mut P<ast::Block>) {
+ fn stmt_to_block(rules: ast::BlockCheckMode,
+ s: Option<ast::Stmt>,
+ sess: &Session) -> ast::Block {
+ ast::Block {
+ stmts: s.into_iter().collect(),
+ rules,
+ id: sess.next_node_id(),
+ span: syntax_pos::DUMMY_SP,
+ }
+ }
+
+ fn block_to_stmt(b: ast::Block, sess: &Session) -> ast::Stmt {
+ let expr = P(ast::Expr {
+ id: sess.next_node_id(),
+ node: ast::ExprKind::Block(P(b), None),
+ span: syntax_pos::DUMMY_SP,
+ attrs: ThinVec::new(),
+ });
+
+ ast::Stmt {
+ id: sess.next_node_id(),
+ node: ast::StmtKind::Expr(expr),
+ span: syntax_pos::DUMMY_SP,
+ }
+ }
+
+ let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.sess);
+ let loop_expr = P(ast::Expr {
+ node: ast::ExprKind::Loop(P(empty_block), None),
+ id: self.sess.next_node_id(),
+ span: syntax_pos::DUMMY_SP,
+ attrs: ThinVec::new(),
+ });
+
+ let loop_stmt = ast::Stmt {
+ id: self.sess.next_node_id(),
+ span: syntax_pos::DUMMY_SP,
+ node: ast::StmtKind::Expr(loop_expr),
+ };
+
+ if self.within_static_or_const {
+ noop_visit_block(b, self)
+ } else {
+ visit_clobber(b.deref_mut(), |b| {
+ let mut stmts = vec![];
+ for s in b.stmts {
+ let old_blocks = self.nested_blocks.replace(vec![]);
+
+ stmts.extend(self.flat_map_stmt(s).into_iter().filter(|s| s.is_item()));
+
+ // we put a Some in there earlier with that replace(), so this is valid
+ let new_blocks = self.nested_blocks.take().unwrap();
+ self.nested_blocks = old_blocks;
+ stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, &self.sess)));
+ }
+
+ let mut new_block = ast::Block {
+ stmts,
+ ..b
+ };
+
+ if let Some(old_blocks) = self.nested_blocks.as_mut() {
+ //push our fresh block onto the cache and yield an empty block with `loop {}`
+ if !new_block.stmts.is_empty() {
+ old_blocks.push(new_block);
+ }
+
+ stmt_to_block(b.rules, Some(loop_stmt), self.sess)
+ } else {
+ //push `loop {}` onto the end of our fresh block and yield that
+ new_block.stmts.push(loop_stmt);
+
+ new_block
+ }
+ })
+ }
+ }
+
+ // in general the pretty printer processes unexpanded code, so
+ // we override the default `visit_mac` method which panics.
+ fn visit_mac(&mut self, mac: &mut ast::Mac) {
+ noop_visit_mac(mac, self)
+ }
+}
doc_hidden_stack: Vec<bool>,
/// Private traits or trait items that leaked through. Don't check their methods.
- private_traits: FxHashSet<ast::NodeId>,
+ private_traits: FxHashSet<hir::HirId>,
}
fn has_doc(attr: &ast::Attribute) -> bool {
fn check_missing_docs_attrs(&self,
cx: &LateContext<'_, '_>,
- id: Option<ast::NodeId>,
+ id: Option<hir::HirId>,
attrs: &[ast::Attribute],
sp: Span,
desc: &'static str) {
// It's an option so the crate root can also use this function (it doesn't
// have a NodeId).
if let Some(id) = id {
- if !cx.access_levels.is_exported(id) {
+ let node_id = cx.tcx.hir().hir_to_node_id(id);
+ if !cx.access_levels.is_exported(node_id) {
return;
}
}
hir::ItemKind::Trait(.., ref trait_item_refs) => {
// Issue #11592, traits are always considered exported, even when private.
if let hir::VisibilityKind::Inherited = it.vis.node {
- self.private_traits.insert(it.id);
+ self.private_traits.insert(it.hir_id);
for trait_item_ref in trait_item_refs {
- self.private_traits.insert(trait_item_ref.id.node_id);
+ let hir_id = cx.tcx.hir().node_to_hir_id(trait_item_ref.id.node_id);
+ self.private_traits.insert(hir_id);
}
return;
}
Some(Node::Item(item)) => {
if let hir::VisibilityKind::Inherited = item.vis.node {
for impl_item_ref in impl_item_refs {
- self.private_traits.insert(impl_item_ref.id.node_id);
+ let hir_id = cx.tcx.hir().node_to_hir_id(
+ impl_item_ref.id.node_id);
+ self.private_traits.insert(hir_id);
}
}
}
_ => return,
};
- self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc);
+ self.check_missing_docs_attrs(cx, Some(it.hir_id), &it.attrs, it.span, desc);
}
fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, trait_item: &hir::TraitItem) {
- if self.private_traits.contains(&trait_item.id) {
+ if self.private_traits.contains(&trait_item.hir_id) {
return;
}
};
self.check_missing_docs_attrs(cx,
- Some(trait_item.id),
+ Some(trait_item.hir_id),
&trait_item.attrs,
trait_item.span,
desc);
hir::ImplItemKind::Existential(_) => "an associated existential type",
};
self.check_missing_docs_attrs(cx,
- Some(impl_item.id),
+ Some(impl_item.hir_id),
&impl_item.attrs,
impl_item.span,
desc);
fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, sf: &hir::StructField) {
if !sf.is_positional() {
self.check_missing_docs_attrs(cx,
- Some(sf.id),
+ Some(sf.hir_id),
&sf.attrs,
sf.span,
"a struct field")
fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) {
self.check_missing_docs_attrs(cx,
- Some(v.node.data.id()),
+ Some(v.node.data.hir_id()),
&v.node.attrs,
v.span,
"a variant");
}
impl UnreachablePub {
- fn perform_lint(&self, cx: &LateContext<'_, '_>, what: &str, id: ast::NodeId,
+ fn perform_lint(&self, cx: &LateContext<'_, '_>, what: &str, id: hir::HirId,
vis: &hir::Visibility, span: Span, exportable: bool) {
let mut applicability = Applicability::MachineApplicable;
+ let node_id = cx.tcx.hir().hir_to_node_id(id);
match vis.node {
- hir::VisibilityKind::Public if !cx.access_levels.is_reachable(id) => {
+ hir::VisibilityKind::Public if !cx.access_levels.is_reachable(node_id) => {
if span.ctxt().outer().expn_info().is_some() {
applicability = Applicability::MaybeIncorrect;
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
- self.perform_lint(cx, "item", item.id, &item.vis, item.span, true);
+ self.perform_lint(cx, "item", item.hir_id, &item.vis, item.span, true);
}
fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, foreign_item: &hir::ForeignItem) {
- self.perform_lint(cx, "item", foreign_item.id, &foreign_item.vis,
+ self.perform_lint(cx, "item", foreign_item.hir_id, &foreign_item.vis,
foreign_item.span, true);
}
fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &hir::StructField) {
- self.perform_lint(cx, "field", field.id, &field.vis, field.span, false);
+ self.perform_lint(cx, "field", field.hir_id, &field.vis, field.span, false);
}
fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, impl_item: &hir::ImplItem) {
- self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false);
+ self.perform_lint(cx, "item", impl_item.hir_id, &impl_item.vis, impl_item.span, false);
}
}
#![allow(non_snake_case)]
use rustc::hir::Node;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx};
use rustc::{lint, util};
/// FIXME: This duplicates code in codegen.
fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def: &'tcx ty::AdtDef,
- substs: &Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> bool {
if def.variants.len() == 2 {
let data_idx;
let def_id = self.cx.tcx.hir().local_def_id(id);
let sig = self.cx.tcx.fn_sig(def_id);
let sig = self.cx.tcx.erase_late_bound_regions(&sig);
+ let inputs = if sig.c_variadic {
+ // Don't include the spoofed `VaList` in the functions list
+ // of inputs.
+ &sig.inputs()[..sig.inputs().len() - 1]
+ } else {
+ &sig.inputs()[..]
+ };
- for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
+ for (input_ty, input_hir) in inputs.iter().zip(&decl.inputs) {
self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty);
}
intravisit::walk_variant(self, v, g, id);
if let Some(ref discr) = v.node.disr_expr {
- let def_id = self.index.tcx.hir().local_def_id(discr.id);
+ let def_id = self.index.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
}
}
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
match ty.node {
hir::TyKind::Array(_, ref length) => {
- let def_id = self.tcx.hir().local_def_id(length.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id);
self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
}
_ => {}
// TEMP = &foo
//
// so extract `temp`.
- let temp = if let &mir::Place::Local(temp) = assigned_place {
+ let temp = if let &mir::Place::Base(mir::PlaceBase::Local(temp)) = assigned_place {
temp
} else {
span_bug!(
use rustc::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
- Place, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
+ Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
TerminatorKind, VarBindingForm,
};
use rustc::ty::{self, DefIdTree};
);
}
}
- if let Place::Local(local) = place {
+ if let Place::Base(PlaceBase::Local(local)) = place {
let decl = &self.mir.local_decls[*local];
err.span_label(
decl.source_info.span,
let borrow_span = borrow_spans.var_or_use();
let proper_span = match *root_place {
- Place::Local(local) => self.mir.local_decls[local].source_info.span,
+ Place::Base(PlaceBase::Local(local)) => self.mir.local_decls[local].source_info.span,
_ => drop_span,
};
let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
let local_kind = match borrow.borrowed_place {
- Place::Local(local) => {
+ Place::Base(PlaceBase::Local(local)) => {
match self.mir.local_kind(local) {
LocalKind::ReturnPointer
| LocalKind::Temp => bug!("temporary or return pointer with a name"),
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
.last()
.unwrap();
- let local = if let Place::Local(local) = *root_place {
+ let local = if let Place::Base(PlaceBase::Local(local)) = *root_place {
local
} else {
bug!("report_cannot_return_reference_to_local: not a local")
assigned_span: Span,
err_place: &Place<'tcx>,
) {
- let (from_arg, local_decl) = if let Place::Local(local) = *err_place {
+ let (from_arg, local_decl) = if let Place::Base(PlaceBase::Local(local)) = *err_place {
if let LocalKind::Arg = self.mir.local_kind(local) {
(true, Some(&self.mir.local_decls[local]))
} else {
including_downcast: &IncludingDowncast,
) -> Result<(), ()> {
match *place {
- Place::Promoted(_) => {
+ Place::Base(PlaceBase::Promoted(_)) => {
buf.push_str("promoted");
}
- Place::Local(local) => {
+ Place::Base(PlaceBase::Local(local)) => {
self.append_local_to_string(local, buf)?;
}
- Place::Static(ref static_) => {
+ Place::Base(PlaceBase::Static(ref static_)) => {
buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
}
Place::Projection(ref proj) => {
autoderef,
&including_downcast,
)?;
- } else if let Place::Local(local) = proj.base {
+ } else if let Place::Base(PlaceBase::Local(local)) = proj.base {
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
self.mir.local_decls[local].is_user_variable
{
/// End-user visible description of the `field`nth field of `base`
fn describe_field(&self, base: &Place<'_>, field: Field) -> String {
match *base {
- Place::Local(local) => {
+ Place::Base(PlaceBase::Local(local)) => {
let local = &self.mir.local_decls[local];
self.describe_field_from_ty(&local.ty, field)
}
- Place::Promoted(ref prom) => self.describe_field_from_ty(&prom.1, field),
- Place::Static(ref static_) => self.describe_field_from_ty(&static_.ty, field),
+ Place::Base(PlaceBase::Promoted(ref prom)) =>
+ self.describe_field_from_ty(&prom.1, field),
+ Place::Base(PlaceBase::Static(ref static_)) =>
+ self.describe_field_from_ty(&static_.ty, field),
Place::Projection(ref proj) => match proj.elem {
ProjectionElem::Deref => self.describe_field(&proj.base, field),
ProjectionElem::Downcast(def, variant_index) =>
/// Checks if a place is a thread-local static.
pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
- if let Place::Static(statik) = place {
+ if let Place::Base(PlaceBase::Static(statik)) = place {
let attrs = self.infcx.tcx.get_attrs(statik.def_id);
let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> {
let tcx = self.infcx.tcx;
match place {
- Place::Local(_) | Place::Static(_) | Place::Promoted(_) => {
+ Place::Base(PlaceBase::Local(_)) |
+ Place::Base(PlaceBase::Static(_)) |
+ Place::Base(PlaceBase::Promoted(_)) => {
StorageDeadOrDrop::LocalStorageDead
}
Place::Projection(box PlaceProjection { base, elem }) => {
);
// Check that the initial assignment of the reserve location is into a temporary.
let mut target = *match reservation {
- Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local,
+ Place::Base(PlaceBase::Local(local))
+ if self.mir.local_kind(*local) == LocalKind::Temp => local,
_ => return None,
};
"annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
target, stmt
);
- if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind
- {
+ if let StatementKind::Assign(
+ Place::Base(PlaceBase::Local(assigned_to)),
+ box rvalue
+ ) = &stmt.kind {
debug!(
"annotate_argument_and_return_for_borrow: assigned_to={:?} \
rvalue={:?}",
target, terminator
);
if let TerminatorKind::Call {
- destination: Some((Place::Local(assigned_to), _)),
+ destination: Some((Place::Base(PlaceBase::Local(assigned_to)), _)),
args,
..
} = &terminator.kind
.get(location.statement_index)
{
Some(&Statement {
- kind: StatementKind::Assign(Place::Local(local), _),
+ kind: StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _),
..
}) => local,
_ => return OtherUse(use_span),
def_id, is_generator, places
);
if let Some((args_span, var_span)) = self.closure_span(
- *def_id, &Place::Local(target), places
+ *def_id, &Place::Base(PlaceBase::Local(target)), places
) {
return ClosureUse {
is_generator,
use rustc::lint::builtin::UNUSED_MUT;
use rustc::middle::borrowck::SignalledError;
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
-use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
+use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase};
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind};
use rustc::ty::query::Providers;
StatementKind::StorageDead(local) => {
self.access_place(
ContextKind::StorageDead.new(location),
- (&Place::Local(local), span),
+ (&Place::Base(PlaceBase::Local(local)), span),
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
LocalMutationIsAllowed::Yes,
flow_state,
// Special case: you can assign a immutable local variable
// (e.g., `x = ...`) so long as it has never been initialized
// before (at this point in the flow).
- if let &Place::Local(local) = place_span.0 {
+ if let &Place::Base(PlaceBase::Local(local)) = place_span.0 {
if let Mutability::Not = self.mir.local_decls[local].mutability {
// check for reassignments to immutable local variables
self.check_if_reassignment_to_immutable_state(
// captures of a closure are copied/moved directly
// when generating MIR.
match operands[field.index()] {
- Operand::Move(Place::Local(local))
- | Operand::Copy(Place::Local(local)) => {
+ Operand::Move(Place::Base(PlaceBase::Local(local)))
+ | Operand::Copy(Place::Base(PlaceBase::Local(local))) => {
self.used_mut.insert(local);
}
Operand::Move(ref place @ Place::Projection(_))
self.used_mut_upvars.push(field);
}
}
- Operand::Move(Place::Static(..))
- | Operand::Copy(Place::Static(..))
- | Operand::Move(Place::Promoted(..))
- | Operand::Copy(Place::Promoted(..))
+ Operand::Move(Place::Base(PlaceBase::Static(..)))
+ | Operand::Copy(Place::Base(PlaceBase::Static(..)))
+ | Operand::Move(Place::Base(PlaceBase::Promoted(..)))
+ | Operand::Copy(Place::Base(PlaceBase::Promoted(..)))
| Operand::Constant(..) => {}
}
}
//
// FIXME: allow thread-locals to borrow other thread locals?
let (might_be_alive, will_be_dropped) = match root_place {
- Place::Promoted(_) => (true, false),
- Place::Static(_) => {
+ Place::Base(PlaceBase::Promoted(_)) => (true, false),
+ Place::Base(PlaceBase::Static(_)) => {
// Thread-locals might be dropped after the function exits, but
// "true" statics will never be.
let is_thread_local = self.is_place_thread_local(&root_place);
(true, is_thread_local)
}
- Place::Local(_) => {
+ Place::Base(PlaceBase::Local(_)) => {
// Locals are always dropped at function exit, and if they
// have a destructor it would've been called already.
(false, self.locals_are_invalidated_at_exit)
last_prefix = prefix;
}
match *last_prefix {
- Place::Local(_) => panic!("should have move path for every Local"),
+ Place::Base(PlaceBase::Local(_)) => panic!("should have move path for every Local"),
Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"),
- Place::Promoted(_) |
- Place::Static(_) => Err(NoMovePathFound::ReachedStatic),
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Static(_)) => Err(NoMovePathFound::ReachedStatic),
}
}
let mut place = place;
loop {
match *place {
- Place::Promoted(_) |
- Place::Local(_) | Place::Static(_) => {
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
// assigning to `x` does not require `x` be initialized.
break;
}
) {
match root_place {
RootPlace {
- place: Place::Local(local),
+ place: Place::Base(PlaceBase::Local(local)),
is_local_mutation_allowed,
} => {
// If the local may have been initialized, and it is now currently being
}
}
RootPlace {
- place: Place::Promoted(..),
+ place: Place::Base(PlaceBase::Promoted(..)),
is_local_mutation_allowed: _,
} => {}
RootPlace {
- place: Place::Static(..),
+ place: Place::Base(PlaceBase::Static(..)),
is_local_mutation_allowed: _,
} => {}
}
is_local_mutation_allowed: LocalMutationIsAllowed,
) -> Result<RootPlace<'d, 'tcx>, &'d Place<'tcx>> {
match *place {
- Place::Local(local) => {
+ Place::Base(PlaceBase::Local(local)) => {
let local = &self.mir.local_decls[local];
match local.mutability {
Mutability::Not => match is_local_mutation_allowed {
}
// The rules for promotion are made by `qualify_consts`, there wouldn't even be a
// `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
- Place::Promoted(_) => Ok(RootPlace {
+ Place::Base(PlaceBase::Promoted(_)) => Ok(RootPlace {
place,
is_local_mutation_allowed,
}),
- Place::Static(ref static_) => {
+ Place::Base(PlaceBase::Static(ref static_)) => {
if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
Err(place)
} else {
// If that ever stops being the case, then the ever initialized
// flow could be used.
if let Some(StatementKind::Assign(
- Place::Local(local),
+ Place::Base(PlaceBase::Local(local)),
box Rvalue::Use(Operand::Move(move_from)),
)) = self.mir.basic_blocks()[location.block]
.statements
use rustc::hir;
use rustc::hir::Node;
use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
-use rustc::mir::{Mutability, Operand, Place, Projection, ProjectionElem, Static, Terminator};
-use rustc::mir::TerminatorKind;
+use rustc::mir::{Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static};
+use rustc::mir::{Terminator, TerminatorKind};
use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
use rustc_data_structures::indexed_vec::Idx;
use syntax_pos::Span;
debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
match the_place_err {
- Place::Local(local) => {
+ Place::Base(PlaceBase::Local(local)) => {
item_msg = format!("`{}`", access_place_desc.unwrap());
- if let Place::Local(_) = access_place {
+ if let Place::Base(PlaceBase::Local(_)) = access_place {
reason = ", as it is not declared as mutable".to_string();
} else {
let name = self.mir.local_decls[*local]
base,
elem: ProjectionElem::Deref,
}) => {
- if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() {
+ if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
+ !self.mir.upvar_decls.is_empty() {
item_msg = format!("`{}`", access_place_desc.unwrap());
debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
debug_assert!(is_closure_or_generator(
", as `Fn` closures cannot mutate their captured variables".to_string()
}
} else if {
- if let Place::Local(local) = *base {
+ if let Place::Base(PlaceBase::Local(local)) = *base {
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard))
= self.mir.local_decls[local].is_user_variable {
true
}
}
- Place::Promoted(_) => unreachable!(),
+ Place::Base(PlaceBase::Promoted(_)) => unreachable!(),
- Place::Static(box Static { def_id, ty: _ }) => {
- if let Place::Static(_) = access_place {
+ Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
+ if let Place::Base(PlaceBase::Static(_)) = access_place {
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
reason = String::new();
} else {
},
// Suggest removing a `&mut` from the use of a mutable reference.
- Place::Local(local)
+ Place::Base(PlaceBase::Local(local))
if {
self.mir.local_decls.get(*local).map(|local_decl| {
if let ClearCrossCrate::Set(
// We want to suggest users use `let mut` for local (user
// variable) mutations...
- Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => {
+ Place::Base(PlaceBase::Local(local))
+ if self.mir.local_decls[*local].can_be_made_mutable() => {
// ... but it doesn't make sense to suggest it on
// variables that are `ref x`, `ref mut x`, `&self`,
// or `&mut self` (such variables are simply not
// complete hack to approximate old AST-borrowck
// diagnostic: if the span starts with a mutable borrow of
// a local variable, then just suggest the user remove it.
- Place::Local(_)
+ Place::Base(PlaceBase::Local(_))
if {
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
snippet.starts_with("&mut ")
}
Place::Projection(box Projection {
- base: Place::Local(local),
+ base: Place::Base(PlaceBase::Local(local)),
elem: ProjectionElem::Deref,
}) if {
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
// FIXME: can this case be generalized to work for an
// arbitrary base for the projection?
Place::Projection(box Projection {
- base: Place::Local(local),
+ base: Place::Base(PlaceBase::Local(local)),
elem: ProjectionElem::Deref,
}) if self.mir.local_decls[*local].is_user_variable.is_some() =>
{
Place::Projection(box Projection {
base,
elem: ProjectionElem::Deref,
- }) if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() =>
+ }) if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
+ !self.mir.upvar_decls.is_empty() =>
{
err.span_label(span, format!("cannot {ACT}", ACT = act));
err.span_help(
}
Place::Projection(box Projection {
- base: Place::Local(local),
+ base: Place::Base(PlaceBase::Local(local)),
elem: ProjectionElem::Deref,
}) if error_access == AccessKind::MutableBorrow => {
err.span_label(span, format!("cannot {ACT}", ACT = act));
use rustc::infer::InferCtxt;
use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
+use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, PlaceBase, Rvalue};
use rustc::mir::{SourceInfo, Statement, Terminator};
use rustc::mir::UserTypeProjection;
use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::Substs;
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid};
+use rustc::ty::subst::SubstsRef;
pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
/// We sometimes have `substs` within an rvalue, or within a
/// call. Make them live at the location where they appear.
- fn visit_substs(&mut self, substs: &&'tcx Substs<'tcx>, location: Location) {
+ fn visit_substs(&mut self, substs: &SubstsRef<'tcx>, location: Location) {
self.add_regular_live_constraint(*substs, location);
self.super_substs(substs);
}
// When we see `X = ...`, then kill borrows of
// `(*X).foo` and so forth.
if let Some(all_facts) = self.all_facts {
- if let Place::Local(temp) = place {
+ if let Place::Base(PlaceBase::Local(temp)) = place {
if let Some(borrow_indices) = self.borrow_set.local_map.get(temp) {
all_facts.killed.reserve(borrow_indices.len());
for &borrow_index in borrow_indices {
use crate::borrow_check::nll::ConstraintDescription;
use crate::borrow_check::{Context, MirBorrowckCtxt, WriteKind};
use rustc::mir::{
- CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, Projection,
- ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
+ CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, PlaceBase,
+ Projection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
};
use rustc::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
Some(Cause::LiveVar(local, location)) => {
let span = mir.source_info(location).span;
let spans = self
- .move_spans(&Place::Local(local), location)
+ .move_spans(&Place::Base(PlaceBase::Local(local)), location)
.or_else(|| self.borrow_spans(span, location));
let borrow_location = context.loc;
let mut should_note_order = false;
if mir.local_decls[local].name.is_some() {
if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
- if let Place::Local(borrowed_local) = place {
+ if let Place::Base(PlaceBase::Local(borrowed_local)) = place {
let dropped_local_scope = mir.local_decls[local].visibility_scope;
let borrowed_local_scope =
mir.local_decls[*borrowed_local].visibility_scope;
// Just point to the function, to reduce the chance of overlapping spans.
let function_span = match func {
Operand::Constant(c) => c.span,
- Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => {
+ Operand::Copy(Place::Base(PlaceBase::Local(l))) |
+ Operand::Move(Place::Base(PlaceBase::Local(l))) => {
let local_decl = &self.mir.local_decls[*l];
if local_decl.name.is_none() {
local_decl.source_info.span
// it which simplifies the termination logic.
let mut queue = vec![location];
let mut target = if let Some(&Statement {
- kind: StatementKind::Assign(Place::Local(local), _),
+ kind: StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _),
..
}) = stmt
{
// The only kind of statement that we care about is assignments...
if let StatementKind::Assign(place, box rvalue) = &stmt.kind {
let into = match place {
- Place::Local(into) => into,
+ Place::Base(PlaceBase::Local(into)) => into,
Place::Projection(box Projection {
- base: Place::Local(into),
+ base: Place::Base(PlaceBase::Local(into)),
elem: ProjectionElem::Deref,
}) => into,
_ => {
// If we see a use, we should check whether it is our data, and if so
// update the place that we're looking for to that new place.
Rvalue::Use(operand) => match operand {
- Operand::Copy(Place::Local(from))
- | Operand::Move(Place::Local(from))
+ Operand::Copy(Place::Base(PlaceBase::Local(from)))
+ | Operand::Move(Place::Base(PlaceBase::Local(from)))
if *from == target =>
{
target = *into;
// If we see a unsized cast, then if it is our data we should check
// whether it is being cast to a trait object.
Rvalue::Cast(CastKind::Unsize, operand, ty) => match operand {
- Operand::Copy(Place::Local(from))
- | Operand::Move(Place::Local(from))
+ Operand::Copy(Place::Base(PlaceBase::Local(from)))
+ | Operand::Move(Place::Base(PlaceBase::Local(from)))
if *from == target =>
{
debug!("was_captured_by_trait_object: ty={:?}", ty);
debug!("was_captured_by_trait_object: terminator={:?}", terminator);
if let TerminatorKind::Call {
- destination: Some((Place::Local(dest), block)),
+ destination: Some((Place::Base(PlaceBase::Local(dest)), block)),
args,
..
} = &terminator.kind
);
// Check if one of the arguments to this function is the target place.
let found_target = args.iter().any(|arg| {
- if let Operand::Move(Place::Local(potential)) = arg {
+ if let Operand::Move(Place::Base(PlaceBase::Local(potential))) = arg {
*potential == target
} else {
false
use crate::dataflow::move_paths::indexes::BorrowIndex;
use rustc::ty::TyCtxt;
use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, Location, Mir, Place, Rvalue};
+use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase, Rvalue};
use rustc::mir::{Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind};
use rustc::mir::{Operand, BorrowKind};
StatementKind::StorageDead(local) => {
self.access_place(
ContextKind::StorageDead.new(location),
- &Place::Local(local),
+ &Place::Base(PlaceBase::Local(local)),
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
LocalMutationIsAllowed::Yes,
);
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
use rustc::mir::Mir;
-use rustc::ty::subst::{Substs, UnpackedKind};
+use rustc::ty::subst::{SubstsRef, UnpackedKind};
use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt};
use rustc::util::ppaux::RegionHighlightMode;
use rustc_errors::DiagnosticBuilder;
/// types+hir to search through).
fn match_adt_and_segment<'hir>(
&self,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
needle_fr: RegionVid,
last_segment: &'hir hir::PathSegment,
counter: &mut usize,
/// `search_stack` the types+hir to search through.
fn try_match_adt_and_generic_args<'hir>(
&self,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
needle_fr: RegionVid,
args: &'hir hir::GenericArgs,
search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>,
ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
ConstraintCategory, Local, Location, Mir,
};
-use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
use rustc::util::common::{self, ErrorReported};
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
tcx: TyCtxt<'_, 'gcx, 'tcx>,
location: Location,
closure_def_id: DefId,
- closure_substs: &'tcx ty::subst::Substs<'tcx>,
+ closure_substs: SubstsRef<'tcx>,
) -> Vec<QueryRegionConstraint<'tcx>>;
fn subst_closure_mapping<T>(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
location: Location,
closure_def_id: DefId,
- closure_substs: &'tcx ty::subst::Substs<'tcx>,
+ closure_substs: SubstsRef<'tcx>,
) -> Vec<QueryRegionConstraint<'tcx>> {
debug!(
"apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})",
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
use rustc::mir::{Location, Mir};
use rustc::mir::visit::{MutVisitor, TyContext};
debug!("visit_ty: ty={:?}", ty);
}
- fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
+ fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
debug!("visit_substs(substs={:?}, location={:?})", substs, location);
*substs = self.renumber_regions(&{ *substs });
use rustc::traits::query::{Fallible, NoSolution};
use rustc::traits::{ObligationCause, PredicateObligations};
use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts};
+use rustc::ty::subst::{Subst, SubstsRef, UnpackedKind, UserSubsts};
use rustc::ty::{
self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserType,
CanonicalUserTypeAnnotation, UserTypeAnnotationIndex,
) -> PlaceTy<'tcx> {
debug!("sanitize_place: {:?}", place);
let place_ty = match *place {
- Place::Local(index) => PlaceTy::Ty {
+ Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
ty: self.mir.local_decls[index].ty,
},
- Place::Promoted(box (_index, sty)) => {
+ Place::Base(PlaceBase::Promoted(box (_index, sty))) => {
let sty = self.sanitize_type(place, sty);
// FIXME -- promoted MIR return types reference
// various "free regions" (e.g., scopes and things)
// promoted_mir.return_ty()
PlaceTy::Ty { ty: sty }
}
- Place::Static(box Static { def_id, ty: sty }) => {
+ Place::Base(PlaceBase::Static(box Static { def_id, ty: sty })) => {
let sty = self.sanitize_type(place, sty);
let ty = self.tcx().type_of(def_id);
let ty = self.cx.normalize(ty, location);
}
}
ProjectionElem::Index(i) => {
- let index_ty = Place::Local(i).ty(self.mir, tcx).to_ty(tcx);
+ let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).to_ty(tcx);
if index_ty != tcx.types.usize {
PlaceTy::Ty {
ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
// of lowering. Assignments to other sorts of places *are* interesting
// though.
let category = match *place {
- Place::Local(RETURN_PLACE) => if let Some(BorrowCheckContext {
+ Place::Base(PlaceBase::Local(RETURN_PLACE)) => if let Some(BorrowCheckContext {
universal_regions:
UniversalRegions {
defining_ty: DefiningTy::Const(def_id, _),
} else {
ConstraintCategory::Return
},
- Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
+ Place::Base(PlaceBase::Local(l))
+ if !mir.local_decls[l].is_user_variable.is_some() => {
ConstraintCategory::Boring
}
_ => ConstraintCategory::Assignment,
Some((ref dest, _target_block)) => {
let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
let category = match *dest {
- Place::Local(RETURN_PLACE) => {
+ Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
if let Some(BorrowCheckContext {
universal_regions:
UniversalRegions {
ConstraintCategory::Return
}
}
- Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
+ Place::Base(PlaceBase::Local(l))
+ if !mir.local_decls[l].is_user_variable.is_some() => {
ConstraintCategory::Boring
}
_ => ConstraintCategory::Assignment,
from_hir_call: bool,
) {
debug!("check_call_inputs({:?}, {:?})", sig, args);
- if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.variadic) {
+ // Do not count the `VaList` argument as a "true" argument to
+ // a C-variadic function.
+ let inputs = if sig.c_variadic {
+ &sig.inputs()[..sig.inputs().len() - 1]
+ } else {
+ &sig.inputs()[..]
+ };
+ if args.len() < inputs.len() || (args.len() > inputs.len() && !sig.c_variadic) {
span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
}
- for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() {
+ for (n, (fn_arg, op_arg)) in inputs.iter().zip(args).enumerate() {
let op_arg_ty = op_arg.ty(mir, self.tcx());
let category = if from_hir_call {
ConstraintCategory::CallArgument
&mut self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
location: Location,
) -> ty::InstantiatedPredicates<'tcx> {
if let Some(closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
use rustc::hir::{self, BodyOwnerKind, HirId};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty, TyCtxt};
use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
/// The MIR is a fn item with the given `DefId` and substs. The signature
/// of the function can be bound then with the `fn_sig` query.
- FnDef(DefId, &'tcx Substs<'tcx>),
+ FnDef(DefId, SubstsRef<'tcx>),
/// The MIR represents some form of constant. The signature then
/// is that it has no inputs and a single return value, which is
/// the value of the constant.
- Const(DefId, &'tcx Substs<'tcx>),
+ Const(DefId, SubstsRef<'tcx>),
}
impl<'tcx> DefiningTy<'tcx> {
/// used because trait matching and type-checking will feed us
/// region constraints that reference those regions and we need to
/// be able to map them our internal `RegionVid`. This is
- /// basically equivalent to a `Substs`, except that it also
+ /// basically equivalent to a `InternalSubsts`, except that it also
/// contains an entry for `ReStatic` -- it might be nice to just
/// use a substs, and then handle `ReStatic` another way.
indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
/// `V[1]: V[2]`.
pub fn closure_mapping(
tcx: TyCtxt<'_, '_, 'tcx>,
- closure_substs: &'tcx Substs<'tcx>,
+ closure_substs: SubstsRef<'tcx>,
expected_num_vars: usize,
closure_base_def_id: DefId,
) -> IndexVec<RegionVid, ty::Region<'tcx>> {
BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
assert_eq!(closure_base_def_id, self.mir_def_id);
- let identity_substs = Substs::identity_for_item(tcx, closure_base_def_id);
+ let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
let substs = self.infcx
.replace_free_regions_with_nll_infer_vars(FR, &identity_substs);
DefiningTy::Const(self.mir_def_id, substs)
let tcx = self.infcx.tcx;
let gcx = tcx.global_tcx();
let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id);
- let identity_substs = Substs::identity_for_item(gcx, closure_base_def_id);
+ let identity_substs = InternalSubsts::identity_for_item(gcx, closure_base_def_id);
let fr_substs = match defining_ty {
DefiningTy::Closure(_, ClosureSubsts { ref substs })
| DefiningTy::Generator(_, GeneratorSubsts { ref substs }, _) => {
use crate::borrow_check::Context;
use crate::borrow_check::AccessDepth;
use crate::dataflow::indexes::BorrowIndex;
-use rustc::mir::{BasicBlock, Location, Mir, Place};
+use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase};
use rustc::mir::{ProjectionElem, BorrowKind};
use rustc::ty::TyCtxt;
use rustc_data_structures::graph::dominators::Dominators;
/// This is called for all Yield statements on movable generators
pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
match place {
- Place::Promoted(_) |
- Place::Static(..) => false,
- Place::Local(..) => true,
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Static(..)) => false,
+ Place::Base(PlaceBase::Local(..)) => true,
Place::Projection(box proj) => {
match proj.elem {
// Reborrow of already borrowed data is ignored
use rustc::hir;
use rustc::mir::ProjectionElem;
-use rustc::mir::{Local, Mir, Place, Mutability};
+use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability};
use rustc::ty::{self, TyCtxt};
use crate::borrow_check::borrow_set::LocalsStateAtExit;
locals_state_at_exit: &LocalsStateAtExit,
) -> bool {
match self {
- Place::Promoted(_) => false,
+ Place::Base(PlaceBase::Promoted(_)) => false,
// If a local variable is immutable, then we only need to track borrows to guard
// against two kinds of errors:
//
// In particular, the variable cannot be mutated -- the "access checks" will fail --
// so we don't have to worry about mutation while borrowed.
- Place::Local(index) => {
+ Place::Base(PlaceBase::Local(index)) => {
match locals_state_at_exit {
LocalsStateAtExit::AllAreInvalidated => false,
LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
}
}
}
- Place::Static(static_) => {
+ Place::Base(PlaceBase::Static(static_)) => {
tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
}
Place::Projection(proj) => match proj.elem {
loop {
match p {
Place::Projection(pi) => p = &pi.base,
- Place::Promoted(_) |
- Place::Static(_) => return None,
- Place::Local(l) => return Some(*l),
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Static(_)) => return None,
+ Place::Base(PlaceBase::Local(l)) => return Some(*l),
}
}
}
use crate::borrow_check::Overlap;
use crate::borrow_check::{Deep, Shallow, AccessDepth};
use rustc::hir;
-use rustc::mir::{BorrowKind, Mir, Place};
-use rustc::mir::{Projection, ProjectionElem};
+use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem};
use rustc::ty::{self, TyCtxt};
use std::cmp::max;
// This Local/Local case is handled by the more general code below, but
// it's so common that it's a speed win to check for it first.
- if let Place::Local(l1) = borrow_place {
- if let Place::Local(l2) = access_place {
+ if let Place::Base(PlaceBase::Local(l1)) = borrow_place {
+ if let Place::Base(PlaceBase::Local(l2)) = access_place {
return l1 == l2;
}
}
op,
),
- Place::Promoted(_) |
- Place::Local(_) | Place::Static(_) => {
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
let list = PlaceComponents {
component: place,
next,
bias: PlaceConflictBias,
) -> Overlap {
match (elem1, elem2) {
- (Place::Local(l1), Place::Local(l2)) => {
+ (Place::Base(PlaceBase::Local(l1)), Place::Base(PlaceBase::Local(l2))) => {
if l1 == l2 {
// the same local - base case, equal
debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
Overlap::Disjoint
}
}
- (Place::Static(static1), Place::Static(static2)) => {
+ (Place::Base(PlaceBase::Static(static1)), Place::Base(PlaceBase::Static(static2))) => {
if static1.def_id != static2.def_id {
debug!("place_element_conflict: DISJOINT-STATIC");
Overlap::Disjoint
Overlap::EqualOrDisjoint
}
}
- (Place::Promoted(p1), Place::Promoted(p2)) => {
+ (Place::Base(PlaceBase::Promoted(p1)), Place::Base(PlaceBase::Promoted(p2))) => {
if p1.0 == p2.0 {
if let ty::Array(_, size) = p1.1.sty {
if size.unwrap_usize(tcx) == 0 {
Overlap::Disjoint
}
}
- (Place::Local(_), Place::Promoted(_)) | (Place::Promoted(_), Place::Local(_)) |
- (Place::Promoted(_), Place::Static(_)) | (Place::Static(_), Place::Promoted(_)) |
- (Place::Local(_), Place::Static(_)) | (Place::Static(_), Place::Local(_)) => {
+ (Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Promoted(_))) |
+ (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Local(_))) |
+ (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Static(_))) |
+ (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Promoted(_))) |
+ (Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Static(_))) |
+ (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Local(_))) => {
debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
Overlap::Disjoint
}
use rustc::hir;
use rustc::ty::{self, TyCtxt};
-use rustc::mir::{Mir, Place, ProjectionElem};
+use rustc::mir::{Mir, Place, PlaceBase, ProjectionElem};
pub trait IsPrefixOf<'tcx> {
fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
}
match *cursor {
- Place::Promoted(_) |
- Place::Local(_) | Place::Static(_) => return false,
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Local(_)) |
+ Place::Base(PlaceBase::Static(_)) => return false,
Place::Projection(ref proj) => {
cursor = &proj.base;
}
'cursor: loop {
let proj = match *cursor {
- Place::Promoted(_) |
- Place::Local(_) | // search yielded this leaf
- Place::Static(_) => {
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Local(_)) | // search yielded this leaf
+ Place::Base(PlaceBase::Static(_)) => {
self.next = None;
return Some(cursor);
}
use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{BasicBlock, Local, Location, Place, Statement, StatementKind, TerminatorKind};
+use rustc::mir::{
+ BasicBlock, Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind
+};
use rustc_data_structures::fx::FxHashSet;
"assignment of {:?} to {:?}, adding {:?} to used mutable set",
path.place, local, path.place
);
- if let Place::Local(user_local) = path.place {
+ if let Place::Base(PlaceBase::Local(user_local)) = path.place {
self.mbcx.used_mut.insert(user_local);
}
}
}
Category::Place | Category::Rvalue(..) => {
let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
- block.and(Operand::Move(Place::Local(operand)))
+ block.and(Operand::Move(Place::Base(PlaceBase::Local(operand))))
}
}
}
<,
Rvalue::BinaryOp(
BinOp::Lt,
- Operand::Copy(Place::Local(idx)),
+ Operand::Copy(Place::Base(PlaceBase::Local(idx))),
Operand::Copy(len.clone()),
),
);
let msg = BoundsCheck {
len: Operand::Move(len),
- index: Operand::Copy(Place::Local(idx)),
+ index: Operand::Copy(Place::Base(PlaceBase::Local(idx))),
};
let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
success.and(slice.index(idx))
}
- ExprKind::SelfRef => block.and(Place::Local(Local::new(1))),
+ ExprKind::SelfRef => block.and(Place::Base(PlaceBase::Local(Local::new(1)))),
ExprKind::VarRef { id } => {
let place = if this.is_bound_var_in_guard(id) && this
.hir
.all_pat_vars_are_implicit_refs_within_guards()
{
let index = this.var_local_id(id, RefWithinGuard);
- Place::Local(index).deref()
+ Place::Base(PlaceBase::Local(index)).deref()
} else {
let index = this.var_local_id(id, OutsideGuard);
- Place::Local(index)
+ Place::Base(PlaceBase::Local(index))
};
block.and(place)
}
- ExprKind::StaticRef { id } => block.and(Place::Static(Box::new(Static {
+ ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static {
def_id: id,
ty: expr.ty,
- }))),
+ })))),
ExprKind::PlaceTypeAscription { source, user_ty } => {
let place = unpack!(block = this.as_place(block, source));
Statement {
source_info,
kind: StatementKind::AscribeUserType(
- Place::Local(temp.clone()),
+ Place::Base(PlaceBase::Local(temp.clone())),
Variance::Invariant,
box UserTypeProjection { base: annotation_index, projs: vec![], },
),
},
);
}
- block.and(Place::Local(temp))
+ block.and(Place::Base(PlaceBase::Local(temp)))
}
ExprKind::Array { .. }
});
let temp =
unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability));
- block.and(Place::Local(temp))
+ block.and(Place::Base(PlaceBase::Local(temp)))
}
}
}
this.schedule_drop_storage_and_value(
expr_span,
scope,
- &Place::Local(result),
+ &Place::Base(PlaceBase::Local(result)),
value.ty,
);
}
// malloc some memory of suitable type (thus far, uninitialized):
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
this.cfg
- .push_assign(block, source_info, &Place::Local(result), box_);
+ .push_assign(block, source_info, &Place::Base(PlaceBase::Local(result)), box_);
// initialize the box contents:
- unpack!(block = this.into(&Place::Local(result).deref(), block, value));
- block.and(Rvalue::Use(Operand::Move(Place::Local(result))))
+ unpack!(
+ block = this.into(
+ &Place::Base(PlaceBase::Local(result)).deref(),
+ block, value
+ )
+ );
+ block.and(Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(result)))))
}
ExprKind::Cast { source } => {
let source = this.hir.mirror(source);
let arg_place = unpack!(block = this.as_place(block, arg));
let mutability = match arg_place {
- Place::Local(local) => this.local_decls[local].mutability,
+ Place::Base(PlaceBase::Local(local)) => this.local_decls[local].mutability,
Place::Projection(box Projection {
- base: Place::Local(local),
+ base: Place::Base(PlaceBase::Local(local)),
elem: ProjectionElem::Deref,
}) => {
debug_assert!(
// Not projected from the implicit `self` in a closure.
debug_assert!(
match *base {
- Place::Local(local) => local == Local::new(1),
+ Place::Base(PlaceBase::Local(local)) => local == Local::new(1),
Place::Projection(box Projection {
ref base,
elem: ProjectionElem::Deref,
- }) => *base == Place::Local(Local::new(1)),
+ }) => *base == Place::Base(PlaceBase::Local(Local::new(1))),
_ => false,
},
"Unexpected capture place"
this.cfg.push_assign(
block,
source_info,
- &Place::Local(temp),
+ &Place::Base(PlaceBase::Local(temp)),
Rvalue::Ref(this.hir.tcx().types.re_erased, borrow_kind, arg_place),
);
this.schedule_drop_storage_and_value(
upvar_span,
temp_lifetime,
- &Place::Local(temp),
+ &Place::Base(PlaceBase::Local(temp)),
upvar_ty,
);
}
- block.and(Operand::Move(Place::Local(temp)))
+ block.and(Operand::Move(Place::Base(PlaceBase::Local(temp))))
}
// Helper to get a `-1` value of the appropriate type
);
}
- unpack!(block = this.into(&Place::Local(temp), block, expr));
+ unpack!(block = this.into(&Place::Base(PlaceBase::Local(temp)), block, expr));
// In constants, temp_lifetime is None for temporaries that live for the
// 'static lifetime. Thus we do not drop these temporaries and simply leak them.
this.schedule_drop_storage_and_value(
expr_span,
temp_lifetime,
- &Place::Local(temp),
+ &Place::Base(PlaceBase::Local(temp)),
expr_ty,
);
}
is_user_variable: None,
is_block_tail: None,
});
- let ptr_temp = Place::Local(ptr_temp);
+ let ptr_temp = Place::Base(PlaceBase::Local(ptr_temp));
let block = unpack!(this.into(&ptr_temp, block, ptr));
this.into(&ptr_temp.deref(), block, val)
} else {
Some(value) => {
debug!("stmt_expr Return val block_context.push(SubExpr) : {:?}", expr2);
this.block_context.push(BlockFrame::SubExpr);
- let result = unpack!(this.into(&Place::Local(RETURN_PLACE), block, value));
+ let result = unpack!(
+ this.into(
+ &Place::RETURN_PLACE,
+ block,
+ value
+ )
+ );
this.block_context.pop();
result
}
None => {
- this.cfg
- .push_assign_unit(block, source_info, &Place::Local(RETURN_PLACE));
+ this.cfg.push_assign_unit(
+ block,
+ source_info,
+ &Place::RETURN_PLACE,
+ );
block
}
};
}
}
let temp = this.local_decls.push(local_decl);
- let place = Place::Local(temp);
+ let place = Place::Base(PlaceBase::Local(temp));
debug!("created temp {:?} for expr {:?} in block_context: {:?}",
temp, expr, this.block_context);
place
kind: StatementKind::StorageLive(local_id),
},
);
- let place = Place::Local(local_id);
+ let place = Place::Base(PlaceBase::Local(local_id));
let var_ty = self.local_decls[local_id].ty;
let hir_id = self.hir.tcx().hir().node_to_hir_id(var);
let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id);
self.schedule_drop(
span,
region_scope,
- &Place::Local(local_id),
+ &Place::Base(PlaceBase::Local(local_id)),
var_ty,
DropKind::Value {
cached_block: CachedBlock::default(),
self.cfg.push_assign(
block,
scrutinee_source_info,
- &Place::Local(temp),
+ &Place::Base(PlaceBase::Local(temp)),
borrow,
);
}
source_info: guard_end,
kind: StatementKind::FakeRead(
FakeReadCause::ForMatchGuard,
- Place::Local(temp),
+ Place::Base(PlaceBase::Local(temp)),
),
});
}
// place they refer to can't be modified by the guard.
for binding in by_value_bindings.clone() {
let local_id = self.var_local_id(binding.var_id, RefWithinGuard);
- let place = Place::Local(local_id);
+ let place = Place::Base(PlaceBase::Local(local_id));
self.cfg.push(
block,
Statement {
/// call `schedule_drop` once the temporary is initialized.
pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
- let place = Place::Local(temp);
+ let place = Place::Base(PlaceBase::Local(temp));
debug!("temp: created temp {:?} with type {:?}",
place, self.local_decls[temp].ty);
place
use rustc::mir::*;
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::util::nodemap::NodeMap;
use rustc_target::spec::PanicStrategy;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
}
}
- fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) {
+ fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) {
if let Some(lifted) = self.tcx.lift(substs) {
*substs = lifted;
} else {
let mut block = START_BLOCK;
let expr = builder.hir.mirror(ast_expr);
- unpack!(block = builder.into_expr(&Place::Local(RETURN_PLACE), block, expr));
+ unpack!(block = builder.into_expr(&Place::RETURN_PLACE, block, expr));
let source_info = builder.source_info(span);
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
for (index, arg_info) in arguments.iter().enumerate() {
// Function arguments always get the first Local indices after the return place
let local = Local::new(index + 1);
- let place = Place::Local(local);
+ let place = Place::Base(PlaceBase::Local(local));
let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
// Make sure we drop (parts of) the argument even when not matched on.
}
let body = self.hir.mirror(ast_body);
- self.into(&Place::Local(RETURN_PLACE), block, body)
+ self.into(&Place::RETURN_PLACE, block, body)
}
fn get_unit_temp(&mut self) -> Place<'tcx> {
DropKind::Value { .. } => if !needs_drop { return },
DropKind::Storage => {
match *place {
- Place::Local(index) => if index.index() <= self.arg_count {
+ Place::Base(PlaceBase::Local(index)) => if index.index() <= self.arg_count {
span_bug!(
span, "`schedule_drop` called with index {} and arg_count {}",
index.index(),
// Drop the storage for both value and storage drops.
// Only temps and vars need their storage dead.
match drop_data.location {
- Place::Local(index) if index.index() > arg_count => {
+ Place::Base(PlaceBase::Local(index)) if index.index() > arg_count => {
cfg.push(block, Statement {
source_info,
kind: StatementKind::StorageDead(index)
{
let move_data = &ctxt.move_data;
for arg in mir.args_iter() {
- let place = mir::Place::Local(arg);
+ let place = mir::Place::Base(mir::PlaceBase::Local(arg));
let lookup_result = move_data.rev_lookup.find(&place);
on_lookup_result_bits(tcx, mir, move_data,
lookup_result,
fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
match *place {
- Place::Local(l) => Some(l),
- Place::Promoted(_) |
- Place::Static(..) => None,
+ Place::Base(PlaceBase::Local(l)) => Some(l),
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Static(..)) => None,
Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref => None,
use crate::borrow_check::borrow_set::{BorrowSet, BorrowData};
use crate::borrow_check::place_ext::PlaceExt;
-use rustc::mir::{self, Location, Place, Mir};
+use rustc::mir::{self, Location, Place, PlaceBase, Mir};
use rustc::ty::TyCtxt;
use rustc::ty::RegionVid;
) {
debug!("kill_borrows_on_place: place={:?}", place);
// Handle the `Place::Local(..)` case first and exit early.
- if let Place::Local(local) = place {
+ if let Place::Base(PlaceBase::Local(local)) = place {
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
debug!("kill_borrows_on_place: borrow_indices={:?}", borrow_indices);
sets.kill_all(borrow_indices);
mir::StatementKind::StorageDead(local) => {
// Make sure there are no remaining borrows for locals that
// are gone out of scope.
- self.kill_borrows_on_place(sets, &Place::Local(local));
+ self.kill_borrows_on_place(sets, &Place::Base(PlaceBase::Local(local)));
}
mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => {
// storagedeads after everything ends, so if we don't regard the
// storagelive as killing storage, we would have a multiple assignment
// to immutable data error.
- if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) {
+ if let LookupResult::Exact(mpi) =
+ rev_lookup.find(&mir::Place::Base(mir::PlaceBase::Local(local))) {
debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
stmt, location, &init_path_map[mpi]);
sets.kill_all(&init_path_map[mpi]);
moves: IndexVec::new(),
loc_map: LocationMap::new(mir),
rev_lookup: MovePathLookup {
- locals: mir.local_decls.indices().map(Place::Local).map(|v| {
+ locals: mir.local_decls.indices().map(PlaceBase::Local).map(|v| {
Self::new_move_path(
&mut move_paths,
&mut path_map,
&mut init_path_map,
None,
- v,
+ Place::Base(v),
)
}).collect(),
projections: Default::default(),
{
debug!("lookup({:?})", place);
match *place {
- Place::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]),
- Place::Promoted(..) |
- Place::Static(..) => {
+ Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]),
+ Place::Base(PlaceBase::Promoted(..)) |
+ Place::Base(PlaceBase::Static(..)) => {
Err(MoveError::cannot_move_out_of(self.loc, Static))
}
Place::Projection(ref proj) => {
}
StatementKind::StorageLive(_) => {}
StatementKind::StorageDead(local) => {
- self.gather_move(&Place::Local(local));
+ self.gather_move(&Place::Base(PlaceBase::Local(local)));
}
StatementKind::SetDiscriminant{ .. } => {
span_bug!(stmt.source_info.span,
TerminatorKind::Unreachable => { }
TerminatorKind::Return => {
- self.gather_move(&Place::Local(RETURN_PLACE));
+ self.gather_move(&Place::RETURN_PLACE);
}
TerminatorKind::Assert { ref cond, .. } => {
// parent.
pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
match *place {
- Place::Local(local) => LookupResult::Exact(self.locals[local]),
- Place::Promoted(_) |
- Place::Static(..) => LookupResult::Parent(None),
+ Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
Place::Projection(ref proj) => {
match self.find(&proj.base) {
LookupResult::Exact(base_path) => {
pub fn base_local(&self, mut mpi: MovePathIndex) -> Option<Local> {
loop {
let path = &self.move_paths[mpi];
- if let Place::Local(l) = path.place { return Some(l); }
+ if let Place::Base(PlaceBase::Local(l)) = path.place { return Some(l); }
if let Some(parent) = path.parent { mpi = parent; continue } else { return None }
}
}
use rustc::ty::{self, AdtKind, Ty};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
use rustc::ty::cast::CastKind as TyCastKind;
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::hir;
use rustc::hir::def_id::LocalDefId;
use rustc::mir::BorrowKind;
// Now comes the rote stuff:
hir::ExprKind::Repeat(ref v, ref count) => {
- let def_id = cx.tcx.hir().local_def_id(count.id);
- let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
+ let def_id = cx.tcx.hir().local_def_id_from_hir_id(count.hir_id);
+ let substs = InternalSubsts::identity_for_item(cx.tcx.global_tcx(), def_id);
let instance = ty::Instance::resolve(
cx.tcx.global_tcx(),
cx.param_env,
Some(did) => {
// in case we are offsetting from a computed discriminant
// and not the beginning of discriminants (which is always `0`)
- let substs = Substs::identity_for_item(cx.tcx(), did);
+ let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
let lhs = mk_const(ty::LazyConst::Unevaluated(did, substs));
let bin = ExprKind::Binary {
op: BinOp::Add,
cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &hir::Expr,
span: Span,
- overloaded_callee: Option<(DefId, &'tcx Substs<'tcx>)>,
+ overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
) -> Expr<'tcx> {
let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
let (def_id, substs, user_ty) = match overloaded_callee {
cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr,
place_ty: Ty<'tcx>,
- overloaded_callee: Option<(DefId, &'tcx Substs<'tcx>)>,
+ overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
args: Vec<ExprRef<'tcx>>,
) -> ExprKind<'tcx> {
// For an overloaded *x or x[y] expression of type T, the method
use rustc::infer::InferCtxt;
use rustc::ty::subst::Subst;
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::{Kind, Substs};
+use rustc::ty::subst::{Kind, InternalSubsts};
use rustc::ty::layout::VariantIdx;
use syntax::ast;
use syntax::attr;
pub root_lint_level: hir::HirId,
pub param_env: ty::ParamEnv<'gcx>,
- /// Identity `Substs` for use with const-evaluation.
- pub identity_substs: &'gcx Substs<'gcx>,
+ /// Identity `InternalSubsts` for use with const-evaluation.
+ pub identity_substs: &'gcx InternalSubsts<'gcx>,
pub region_scope_tree: Lrc<region::ScopeTree>,
pub tables: &'a ty::TypeckTables<'gcx>,
infcx,
root_lint_level: lint_level,
param_env: tcx.param_env(src_def_id),
- identity_substs: Substs::identity_for_item(tcx.global_tcx(), src_def_id),
+ identity_substs: InternalSubsts::identity_for_item(tcx.global_tcx(), src_def_id),
region_scope_tree: tcx.region_scope_tree(src_def_id),
tables: tcx.typeck_tables_of(src_def_id),
constness,
use rustc::hir::def_id::DefId;
use rustc::infer::canonical::Canonical;
use rustc::middle::region;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserType};
use rustc::ty::layout::VariantIdx;
use rustc::hir;
Adt {
adt_def: &'tcx AdtDef,
variant_index: VariantIdx,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
/// Optional user-given substs: for something like `let x =
/// Bar::<T> { ... }`.
use rustc::hir::def_id::DefId;
use rustc::hir::RangeEnd;
-use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const};
+use rustc::ty::{self, subst::SubstsRef, Ty, TyCtxt, TypeFoldable, Const};
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
use rustc::mir::Field;
fn is_variant_uninhabited(&self,
variant: &'tcx ty::VariantDef,
- substs: &'tcx ty::subst::Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> bool
{
if self.tcx.features().exhaustive_patterns {
use rustc::middle::region;
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::lint;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc::util::common::ErrorReported;
tables: tcx.body_tables(body_id),
region_scope_tree: &tcx.region_scope_tree(def_id),
param_env: tcx.param_env(def_id),
- identity_substs: Substs::identity_for_item(tcx, def_id),
+ identity_substs: InternalSubsts::identity_for_item(tcx, def_id),
}.visit_body(tcx.hir().body(body_id));
})
}
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- identity_substs: &'tcx Substs<'tcx>,
+ identity_substs: SubstsRef<'tcx>,
region_scope_tree: &'a region::ScopeTree,
}
NotUseful => {
match source {
hir::MatchSource::IfLetDesugar { .. } => {
- cx.tcx.lint_node(
+ cx.tcx.lint_hir(
lint::builtin::IRREFUTABLE_LET_PATTERNS,
- hir_pat.id,
+ hir_pat.hir_id,
pat.span,
"irrefutable if-let pattern",
);
match arm_index {
// The arm with the user-specified pattern.
0 => {
- cx.tcx.lint_node(
+ cx.tcx.lint_hir(
lint::builtin::UNREACHABLE_PATTERNS,
- hir_pat.id, pat.span,
+ hir_pat.hir_id, pat.span,
"unreachable pattern");
},
// The arm with the wildcard pattern.
1 => {
- cx.tcx.lint_node(
+ cx.tcx.lint_hir(
lint::builtin::IRREFUTABLE_LET_PATTERNS,
- hir_pat.id,
+ hir_pat.hir_id,
pat.span,
"irrefutable while-let pattern",
);
hir::MatchSource::ForLoopDesugar |
hir::MatchSource::Normal => {
- let mut err = cx.tcx.struct_span_lint_node(
+ let mut err = cx.tcx.struct_span_lint_hir(
lint::builtin::UNREACHABLE_PATTERNS,
- hir_pat.id,
+ hir_pat.hir_id,
pat.span,
"unreachable pattern",
);
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift, UserType};
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
-use rustc::ty::subst::{Substs, Kind};
+use rustc::ty::subst::{SubstsRef, Kind};
use rustc::ty::layout::VariantIdx;
use rustc::hir::{self, PatKind, RangeEnd};
use rustc::hir::def::{Def, CtorKind};
/// multiple variants.
Variant {
adt_def: &'tcx AdtDef,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
variant_index: VariantIdx,
subpatterns: Vec<FieldPattern<'tcx>>,
},
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
pub tables: &'a ty::TypeckTables<'tcx>,
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
pub errors: Vec<PatternError>,
}
impl<'a, 'tcx> Pattern<'tcx> {
pub fn from_hir(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
+ param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
tables: &'a ty::TypeckTables<'tcx>,
pat: &'tcx hir::Pat) -> Self {
let mut pcx = PatternContext::new(tcx, param_env_and_substs, tables);
impl<'a, 'tcx> PatternContext<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
+ param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
tables: &'a ty::TypeckTables<'tcx>) -> Self {
PatternContext {
tcx,
debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
let kind = match cv.ty.sty {
ty::Float(_) => {
- let id = self.tcx.hir().hir_to_node_id(id);
- self.tcx.lint_node(
+ self.tcx.lint_hir(
::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
id,
span,
CloneImpls!{ <'tcx>
Span, Field, Mutability, ast::Name, ast::NodeId, usize, ty::Const<'tcx>,
Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
- &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserType<'tcx>,
+ SubstsRef<'tcx>, &'tcx Kind<'tcx>, UserType<'tcx>,
UserTypeProjection<'tcx>, PatternTypeProjection<'tcx>
}
use rustc::ty::layout::{
self, Size, Align, HasDataLayout, LayoutOf, TyLayout
};
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, SubstsRef};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::query::TyCtxtAt;
use rustc_data_structures::indexed_vec::IndexVec;
pub(super) fn resolve(
&self,
def_id: DefId,
- substs: &'tcx Substs<'tcx>
+ substs: SubstsRef<'tcx>
) -> EvalResult<'tcx, ty::Instance<'tcx>> {
trace!("resolve: {:?}, {:#?}", def_id, substs);
trace!("param_env: {:#?}", self.param_env);
fn monomorphize_with_substs<T: TypeFoldable<'tcx> + Subst<'tcx>>(
&self,
t: T,
- substs: &'tcx Substs<'tcx>
+ substs: SubstsRef<'tcx>
) -> T {
// miri doesn't care about lifetimes, and will choke on some crazy ones
// let's simply get rid of them
layout: Option<TyLayout<'tcx>>,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
use rustc::mir::Place::*;
+ use rustc::mir::PlaceBase;
let op = match *mir_place {
- Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
- Local(local) => self.access_local(self.frame(), local, layout)?,
+ Base(PlaceBase::Local(mir::RETURN_PLACE)) => return err!(ReadFromReturnPointer),
+ Base(PlaceBase::Local(local)) => self.access_local(self.frame(), local, layout)?,
Projection(ref proj) => {
let op = self.eval_place_to_op(&proj.base, None)?;
mir_place: &mir::Place<'tcx>
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
use rustc::mir::Place::*;
+ use rustc::mir::PlaceBase;
Ok(match *mir_place {
- Promoted(ref promoted) => {
+ Base(PlaceBase::Promoted(ref promoted)) => {
let instance = self.frame().instance;
self.const_eval_raw(GlobalId {
instance,
})?
}
- Static(ref static_) => {
+ Base(PlaceBase::Static(ref static_)) => {
assert!(!static_.ty.needs_subst());
let layout = self.layout_of(static_.ty)?;
let instance = ty::Instance::mono(*self.tcx, static_.def_id);
mir_place: &mir::Place<'tcx>
) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
use rustc::mir::Place::*;
+ use rustc::mir::PlaceBase;
let place = match *mir_place {
- Local(mir::RETURN_PLACE) => match self.frame().return_place {
+ Base(PlaceBase::Local(mir::RETURN_PLACE)) => match self.frame().return_place {
Some(return_place) =>
// We use our layout to verify our assumption; caller will validate
// their layout on return.
},
None => return err!(InvalidNullPointerUsage),
},
- Local(local) => PlaceTy {
+ Base(PlaceBase::Local(local)) => PlaceTy {
place: Place::Local {
frame: self.cur_frame(),
local,
// not advance `caller_iter` for ZSTs.
let mut locals_iter = mir.args_iter();
while let Some(local) = locals_iter.next() {
- let dest = self.eval_place(&mir::Place::Local(local))?;
+ let dest = self.eval_place(
+ &mir::Place::Base(mir::PlaceBase::Local(local))
+ )?;
if Some(local) == mir.spread_arg {
// Must be a tuple
for i in 0..dest.layout.fields.count() {
}
// Don't forget to check the return type!
if let Some(caller_ret) = dest {
- let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
+ let callee_ret = self.eval_place(
+ &mir::Place::RETURN_PLACE
+ )?;
if !Self::check_argument_compat(
rust_abi,
caller_ret.layout,
use rustc::lint::builtin::UNCONDITIONAL_RECURSION;
use rustc::mir::{self, Mir, TerminatorKind};
use rustc::ty::{AssociatedItem, AssociatedItemContainer, Instance, TyCtxt, TyKind};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::InternalSubsts;
pub fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
}) => tcx.generics_of(trait_def_id).count(),
_ => 0
};
- let caller_substs = &Substs::identity_for_item(tcx, def_id)[..trait_substs_count];
+ let caller_substs = &InternalSubsts::identity_for_item(tcx, def_id)[..trait_substs_count];
while let Some(bb) = reachable_without_self_call_queue.pop() {
if visited.contains(bb) {
// no break */ }`) shouldn't be linted unless it actually
// recurs.
if !reached_exit_without_self_call && !self_call_locations.is_empty() {
- let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
- let sp = tcx.sess.source_map().def_span(tcx.hir().span(node_id));
- let mut db = tcx.struct_span_lint_node(UNCONDITIONAL_RECURSION,
- node_id,
- sp,
- "function cannot return without recursing");
+ let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
+ let sp = tcx.sess.source_map().def_span(tcx.hir().span_by_hir_id(hir_id));
+ let mut db = tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION,
+ hir_id,
+ sp,
+ "function cannot return without recursing");
db.span_label(sp, "cannot return without recursing");
// offer some help to the programmer.
for location in &self_call_locations {
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::mir::interpret::{AllocId, ConstValue};
use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
use rustc::ty::adjustment::CustomCoerceUnsized;
use rustc::session::config::EntryFnType;
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &'a mir::Mir<'tcx>,
output: &'a mut Vec<MonoItem<'tcx>>,
- param_substs: &'tcx Substs<'tcx>,
+ param_substs: SubstsRef<'tcx>,
}
impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
fn is_available_upstream_generic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
- substs: &'tcx Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> bool {
debug_assert!(!def_id.is_local());
debug!("RootCollector: ADT drop-glue for {}",
def_id_to_string(self.tcx, def_id));
- let ty = Instance::new(def_id, Substs::empty()).ty(self.tcx);
+ let ty = Instance::new(def_id, InternalSubsts::empty()).ty(self.tcx);
visit_drop_use(self.tcx, ty, true, self.output);
}
}
fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
match ii.node {
hir::ImplItemKind::Method(hir::MethodSig { .. }, _) => {
- let def_id = self.tcx.hir().local_def_id(ii.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(ii.hir_id);
self.push_if_root(def_id);
}
_ => { /* Nothing to do here */ }
continue;
}
- let substs = Substs::for_item(tcx, method.def_id, |param, _| {
+ let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
GenericParamDefKind::Type {..} => {
fn collect_lazy_const<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
constant: &ty::LazyConst<'tcx>,
- param_substs: &'tcx Substs<'tcx>,
+ param_substs: SubstsRef<'tcx>,
output: &mut Vec<MonoItem<'tcx>>,
) {
let (def_id, substs) = match *constant {
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::session::config::OptLevel;
use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{SubstsRef, InternalSubsts};
use syntax::ast;
use syntax::attr::InlineAttr;
use std::fmt::{self, Write};
debug!("is_instantiable({:?})", self);
let (def_id, substs) = match *self.as_mono_item() {
MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
- MonoItem::Static(def_id) => (def_id, Substs::empty()),
+ MonoItem::Static(def_id) => (def_id, InternalSubsts::empty()),
// global asm never has predicates
MonoItem::GlobalAsm(..) => return true
};
output.pop();
}
- if sig.variadic {
+ if sig.c_variadic {
if !sig.inputs().is_empty() {
output.push_str(", ...");
} else {
}
fn push_type_params<I>(&self,
- substs: &Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
projections: I,
output: &mut String,
debug: bool)
use rustc::mir::*;
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind};
use rustc::ty::layout::VariantIdx;
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::ty::query::Providers;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
let substs = if let Some(ty) = ty {
tcx.intern_substs(&[ty.into()])
} else {
- Substs::identity_for_item(tcx, def_id)
+ InternalSubsts::identity_for_item(tcx, def_id)
};
let sig = tcx.fn_sig(def_id).subst(tcx, substs);
let sig = tcx.erase_late_bound_regions(&sig);
if let Some(..) = ty {
// The first argument (index 0), but add 1 for the return value.
- let dropee_ptr = Place::Local(Local::new(1+0));
+ let dropee_ptr = Place::Base(PlaceBase::Local(Local::new(1+0)));
if tcx.sess.opts.debugging_opts.mir_emit_retag {
// Function arguments should be retagged, and we make this one raw.
mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
let is_copy = self_ty.is_copy_modulo_regions(tcx, tcx.param_env(def_id), builder.span);
- let dest = Place::Local(RETURN_PLACE);
- let src = Place::Local(Local::new(1+0)).deref();
+ let dest = Place::RETURN_PLACE;
+ let src = Place::Base(PlaceBase::Local(Local::new(1+0))).deref();
match self_ty.sty {
_ if is_copy => builder.copy_shim(),
}
fn copy_shim(&mut self) {
- let rcvr = Place::Local(Local::new(1+0)).deref();
+ let rcvr = Place::Base(PlaceBase::Local(Local::new(1+0))).deref();
let ret_statement = self.make_statement(
StatementKind::Assign(
- Place::Local(RETURN_PLACE),
+ Place::RETURN_PLACE,
box Rvalue::Use(Operand::Copy(rcvr))
)
);
fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
let span = self.span;
- Place::Local(
+ Place::Base(PlaceBase::Local(
self.local_decls.push(temp_decl(mutability, ty, span))
- )
+ ))
}
fn make_clone_call(
) {
let tcx = self.tcx;
- let substs = Substs::for_item(tcx, self.def_id, |param, _| {
+ let substs = InternalSubsts::for_item(tcx, self.def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
GenericParamDefKind::Type {..} => ty.into(),
let inits = vec![
self.make_statement(
StatementKind::Assign(
- Place::Local(beg),
+ Place::Base(PlaceBase::Local(beg)),
box Rvalue::Use(Operand::Constant(self.make_usize(0)))
)
),
// BB #3;
// }
// BB #4;
- self.loop_header(Place::Local(beg), end, BasicBlock::new(2), BasicBlock::new(4), false);
+ self.loop_header(Place::Base(PlaceBase::Local(beg)),
+ end,
+ BasicBlock::new(2),
+ BasicBlock::new(4),
+ false);
// BB #2
// `dest[i] = Clone::clone(src[beg])`;
let statements = vec![
self.make_statement(
StatementKind::Assign(
- Place::Local(beg),
+ Place::Base(PlaceBase::Local(beg)),
box Rvalue::BinaryOp(
BinOp::Add,
- Operand::Copy(Place::Local(beg)),
+ Operand::Copy(Place::Base(PlaceBase::Local(beg))),
Operand::Constant(self.make_usize(1))
)
)
let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
let init = self.make_statement(
StatementKind::Assign(
- Place::Local(beg),
+ Place::Base(PlaceBase::Local(beg)),
box Rvalue::Use(Operand::Constant(self.make_usize(0)))
)
);
// BB #8;
// }
// BB #9;
- self.loop_header(Place::Local(beg), Place::Local(end),
+ self.loop_header(Place::Base(PlaceBase::Local(beg)), Place::Base(PlaceBase::Local(end)),
BasicBlock::new(7), BasicBlock::new(9), true);
// BB #7 (cleanup)
// `goto #6;`
let statement = self.make_statement(
StatementKind::Assign(
- Place::Local(beg),
+ Place::Base(PlaceBase::Local(beg)),
box Rvalue::BinaryOp(
BinOp::Add,
- Operand::Copy(Place::Local(beg)),
+ Operand::Copy(Place::Base(PlaceBase::Local(beg))),
Operand::Constant(self.make_usize(1))
)
)
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
let rcvr_arg = Local::new(1+0);
- let rcvr_l = Place::Local(rcvr_arg);
+ let rcvr_l = Place::Base(PlaceBase::Local(rcvr_arg));
let mut statements = vec![];
let rcvr = match rcvr_adjustment {
statements.push(Statement {
source_info,
kind: StatementKind::Assign(
- Place::Local(ref_rcvr),
+ Place::Base(PlaceBase::Local(ref_rcvr)),
box Rvalue::Ref(tcx.types.re_erased, borrow_kind, rcvr_l)
)
});
- Operand::Move(Place::Local(ref_rcvr))
+ Operand::Move(Place::Base(PlaceBase::Local(ref_rcvr)))
}
};
if let Some(untuple_args) = untuple_args {
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
- let arg_place = Place::Local(Local::new(1+1));
+ let arg_place = Place::Base(PlaceBase::Local(Local::new(1+1)));
Operand::Move(arg_place.field(Field::new(i), *ity))
}));
} else {
args.extend((1..sig.inputs().len()).map(|i| {
- Operand::Move(Place::Local(Local::new(1+i)))
+ Operand::Move(Place::Base(PlaceBase::Local(Local::new(1+i))))
}));
}
block(&mut blocks, statements, TerminatorKind::Call {
func: callee,
args,
- destination: Some((Place::Local(RETURN_PLACE),
+ destination: Some((Place::RETURN_PLACE,
BasicBlock::new(1))),
cleanup: if let Adjustment::RefMut = rcvr_adjustment {
Some(BasicBlock::new(3))
if let Adjustment::RefMut = rcvr_adjustment {
// BB #1 - drop for Self
block(&mut blocks, vec![], TerminatorKind::Drop {
- location: Place::Local(rcvr_arg),
+ location: Place::Base(PlaceBase::Local(rcvr_arg)),
target: BasicBlock::new(2),
unwind: None
}, false);
if let Adjustment::RefMut = rcvr_adjustment {
// BB #3 - drop if closure panics
block(&mut blocks, vec![], TerminatorKind::Drop {
- location: Place::Local(rcvr_arg),
+ location: Place::Base(PlaceBase::Local(rcvr_arg)),
target: BasicBlock::new(4),
unwind: None
}, true);
statements: vec![Statement {
source_info,
kind: StatementKind::Assign(
- Place::Local(RETURN_PLACE),
+ Place::RETURN_PLACE,
box Rvalue::Aggregate(
box AggregateKind::Adt(adt_def, variant_no, substs, None, None),
(1..sig.inputs().len()+1).map(|i| {
- Operand::Move(Place::Local(Local::new(i)))
+ Operand::Move(Place::Base(PlaceBase::Local(Local::new(i))))
}).collect()
)
)
patch.add_statement(
loc, StatementKind::StorageLive(temp));
- patch.add_assign(loc, Place::Local(temp),
+ patch.add_assign(loc, Place::Base(PlaceBase::Local(temp)),
Rvalue::Use(Operand::Move(location.clone())));
patch.patch_terminator(loc.block, TerminatorKind::Drop {
- location: Place::Local(temp),
+ location: Place::Base(PlaceBase::Local(temp)),
target: storage_dead_block,
unwind
});
match *place {
// Locals and statics have stable addresses, for sure
- Local { .. } |
- Promoted { .. } |
- Static { .. } =>
+ Base(PlaceBase::Local { .. }) |
+ Base(PlaceBase::Promoted { .. }) |
+ Base(PlaceBase::Static { .. }) =>
true,
// Recurse for projections
Projection(ref proj) => {
};
// Gather all arguments, skip return value.
let places = local_decls.iter_enumerated().skip(1).take(arg_count)
- .map(|(local, _)| Place::Local(local))
+ .map(|(local, _)| Place::Base(PlaceBase::Local(local)))
.filter(needs_retag)
.collect::<Vec<_>>();
// Emit their retags.
);
}
let old_source_info = self.source_info;
- if let &Place::Local(local) = base {
+ if let &Place::Base(PlaceBase::Local(local)) = base {
if self.mir.local_decls[local].internal {
// Internal locals are used in the `move_val_init` desugaring.
// We want to check unsafety against the source info of the
}
self.source_info = old_source_info;
}
- &Place::Local(..) => {
+ &Place::Base(PlaceBase::Local(..)) => {
// locals are safe
}
- &Place::Promoted(_) => {
+ &Place::Base(PlaceBase::Promoted(_)) => {
bug!("unsafety checking should happen before promotion")
}
- &Place::Static(box Static { def_id, ty: _ }) => {
+ &Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
self.require_unsafe("use of mutable static",
"mutable statics can be mutated by multiple threads: aliasing violations \
}
fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
- let lint_node_id = match tcx.hir().as_local_node_id(def_id) {
- Some(node_id) => node_id,
- None => bug!("checking unsafety for non-local def id {:?}", def_id)
- };
+ let lint_hir_id = tcx.hir().as_local_hir_id(def_id).unwrap_or_else(||
+ bug!("checking unsafety for non-local def id {:?}", def_id));
// FIXME: when we make this a hard error, this should have its
// own error code.
"#[derive] can't be used on a #[repr(packed)] struct that \
does not derive Copy (error E0133)".to_string()
};
- tcx.lint_node(SAFE_PACKED_BORROWS,
- lint_node_id,
- tcx.def_span(def_id),
- &message);
+ tcx.lint_hir(SAFE_PACKED_BORROWS,
+ lint_hir_id,
+ tcx.def_span(def_id),
+ &message);
}
/// Returns the `HirId` for an enclosing scope that is also `unsafe`.
use rustc::hir::def::Def;
-use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local};
+use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
use rustc::mir::interpret::{EvalErrorKind, Scalar, GlobalId, EvalResult};
use rustc::ty::{TyCtxt, self, Instance};
use syntax::source_map::{Span, DUMMY_SP};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::InternalSubsts;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::ty::ParamEnv;
use rustc::ty::layout::{
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
match *place {
- Place::Local(loc) => self.places[loc].clone(),
+ Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
Place::Projection(ref proj) => match proj.elem {
ProjectionElem::Field(field, _) => {
trace!("field proj on {:?}", proj.base);
// an `Index` projection would throw us off-track.
_ => None,
},
- Place::Promoted(ref promoted) => {
+ Place::Base(PlaceBase::Promoted(ref promoted)) => {
let generics = self.tcx.generics_of(self.source.def_id());
if generics.requires_monomorphization(self.tcx) {
// FIXME: can't handle code with generics
return None;
}
- let substs = Substs::identity_for_item(self.tcx, self.source.def_id());
+ let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
let instance = Instance::new(self.source.def_id(), substs);
let cid = GlobalId {
instance,
.to_ty(self.tcx);
if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
- if let Place::Local(local) = *place {
+ if let Place::Base(PlaceBase::Local(local)) = *place {
trace!("checking whether {:?} can be stored to {:?}", value, local);
if self.can_const_prop[local] {
trace!("storing {:?} to {:?}", value, local);
while let Place::Projection(ref proj) = *place {
place = &proj.base;
}
- if let Place::Local(local) = *place {
+ if let Place::Base(PlaceBase::Local(local)) = *place {
self.places[local] = None;
}
},
.unwrap()
.source_info
.span;
- let node_id = self
+ let hir_id = self
.tcx
.hir()
- .as_local_node_id(self.source.def_id())
+ .as_local_hir_id(self.source.def_id())
.expect("some part of a failing const eval must be local");
use rustc::mir::interpret::EvalErrorKind::*;
let msg = match msg {
// Need proper const propagator for these
_ => return,
};
- self.tcx.lint_node(
+ self.tcx.lint_hir(
::rustc::lint::builtin::CONST_ERR,
- node_id,
+ hir_id,
span,
&msg,
);
//! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
//! future.
-use rustc::mir::{Constant, Local, LocalKind, Location, Place, Mir, Operand, Rvalue, StatementKind};
+use rustc::mir::{
+ Constant, Local, LocalKind, Location, Place, PlaceBase, Mir, Operand, Rvalue, StatementKind
+};
use rustc::mir::visit::MutVisitor;
use rustc::ty::TyCtxt;
use crate::transform::{MirPass, MirSource};
// That use of the source must be an assignment.
match statement.kind {
- StatementKind::Assign(Place::Local(local), box Rvalue::Use(ref operand)) if
- local == dest_local => {
+ StatementKind::Assign(
+ Place::Base(PlaceBase::Local(local)),
+ box Rvalue::Use(ref operand)
+ ) if local == dest_local => {
let maybe_action = match *operand {
Operand::Copy(ref src_place) |
Operand::Move(ref src_place) => {
if let Some(stmt) = mir[location.block].statements.get(location.statement_index) {
match stmt.kind {
StatementKind::Assign(
- Place::Local(local),
- box Rvalue::Use(Operand::Copy(Place::Local(src_local))),
+ Place::Base(PlaceBase::Local(local)),
+ box Rvalue::Use(Operand::Copy(Place::Base(PlaceBase::Local(src_local)))),
) |
StatementKind::Assign(
- Place::Local(local),
- box Rvalue::Use(Operand::Move(Place::Local(src_local))),
+ Place::Base(PlaceBase::Local(local)),
+ box Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(src_local)))),
) if local == dest_local && dest_local == src_local => {}
_ => {
continue;
fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis<'_>, src_place: &Place<'tcx>)
-> Option<Action<'tcx>> {
// The source must be a local.
- let src_local = if let Place::Local(local) = *src_place {
+ let src_local = if let Place::Base(PlaceBase::Local(local)) = *src_place {
local
} else {
debug!(" Can't copy-propagate local: source is not a local");
self.super_operand(operand, location);
match *operand {
- Operand::Copy(Place::Local(local)) |
- Operand::Move(Place::Local(local)) if local == self.dest_local => {}
+ Operand::Copy(Place::Base(PlaceBase::Local(local))) |
+ Operand::Move(Place::Base(PlaceBase::Local(local))) if local == self.dest_local => {}
_ => return,
}
}
fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
- self.drop_flags.get(&index).map(|t| Place::Local(*t))
+ self.drop_flags.get(&index).map(|t| Place::Base(PlaceBase::Local(*t)))
}
/// create a patch that elaborates all drops in the input
if let Some(&flag) = self.drop_flags.get(&path) {
let span = self.patch.source_info_for_location(self.mir, loc).span;
let val = self.constant_bool(span, val.value());
- self.patch.add_assign(loc, Place::Local(flag), val);
+ self.patch.add_assign(loc, Place::Base(PlaceBase::Local(flag)), val);
}
}
let span = self.patch.source_info_for_location(self.mir, loc).span;
let false_ = self.constant_bool(span, false);
for flag in self.drop_flags.values() {
- self.patch.add_assign(loc, Place::Local(*flag), false_.clone());
+ self.patch.add_assign(loc, Place::Base(PlaceBase::Local(*flag)), false_.clone());
}
}
//! N.B., we do _not_ erase regions of statements that are relevant for
//! "types-as-contracts"-validation, namely, `AcquireValid` and `ReleaseValid`.
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::mir::*;
use rustc::mir::visit::{MutVisitor, TyContext};
*constant = self.tcx.erase_regions(constant);
}
- fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) {
+ fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) {
*substs = self.tcx.erase_regions(substs);
}
use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
use rustc::ty::{self, TyCtxt, AdtDef, Ty};
use rustc::ty::layout::VariantIdx;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::bit_set::BitSet;
place: &mut Place<'tcx>,
context: PlaceContext<'tcx>,
location: Location) {
- if *place == Place::Local(self_arg()) {
+ if *place == Place::Base(PlaceBase::Local(self_arg())) {
*place = Place::Projection(Box::new(Projection {
base: place.clone(),
elem: ProjectionElem::Deref,
place: &mut Place<'tcx>,
context: PlaceContext<'tcx>,
location: Location) {
- if *place == Place::Local(self_arg()) {
+ if *place == Place::Base(PlaceBase::Local(self_arg())) {
*place = Place::Projection(Box::new(Projection {
base: place.clone(),
elem: ProjectionElem::Field(Field::new(0), self.ref_gen_ty),
struct TransformVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
state_adt_ref: &'tcx AdtDef,
- state_substs: &'tcx Substs<'tcx>,
+ state_substs: SubstsRef<'tcx>,
// The index of the generator state in the generator struct
state_field: usize,
// Create a Place referencing a generator struct field
fn make_field(&self, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
- let base = Place::Local(self_arg());
+ let base = Place::Base(PlaceBase::Local(self_arg()));
let field = Projection {
base: base,
elem: ProjectionElem::Field(Field::new(idx), ty),
place: &mut Place<'tcx>,
context: PlaceContext<'tcx>,
location: Location) {
- if let Place::Local(l) = *place {
+ if let Place::Base(PlaceBase::Local(l)) = *place {
// Replace an Local in the remap with a generator struct access
if let Some(&(ty, idx)) = self.remap.get(&l) {
*place = self.make_field(idx, ty);
let ret_val = match data.terminator().kind {
TerminatorKind::Return => Some((VariantIdx::new(1),
None,
- Operand::Move(Place::Local(self.new_ret_local)),
+ Operand::Move(Place::Base(PlaceBase::Local(self.new_ret_local))),
None)),
TerminatorKind::Yield { ref value, resume, drop } => Some((VariantIdx::new(0),
Some(resume),
// We must assign the value first in case it gets declared dead below
data.statements.push(Statement {
source_info,
- kind: StatementKind::Assign(Place::Local(RETURN_PLACE),
+ kind: StatementKind::Assign(Place::RETURN_PLACE,
box self.make_state(state_idx, v)),
});
let state = if let Some(resume) = resume { // Yield
&Terminator {
source_info,
kind: TerminatorKind::Drop {
- location: Place::Local(local),
+ location: Place::Base(PlaceBase::Local(local)),
target,
unwind
}
elaborate_drop(
&mut elaborator,
source_info,
- &Place::Local(gen),
+ &Place::Base(PlaceBase::Local(gen)),
(),
target,
unwind,
// Alias tracking must know we changed the type
mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
source_info,
- kind: StatementKind::Retag(RetagKind::Raw, Place::Local(self_arg())),
+ kind: StatementKind::Retag(RetagKind::Raw, Place::Base(PlaceBase::Local(self_arg()))),
})
}
// Create a block to destroy an unresumed generators. This can only destroy upvars.
let drop_clean = BasicBlock::new(mir.basic_blocks().len());
let term = TerminatorKind::Drop {
- location: Place::Local(self_arg()),
+ location: Place::Base(PlaceBase::Local(self_arg())),
target: return_block,
unwind: None,
};
use rustc::mir::*;
use rustc::mir::visit::*;
use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
-use rustc::ty::subst::{Subst,Substs};
+use rustc::ty::subst::{Subst, SubstsRef};
use std::collections::VecDeque;
use std::iter;
#[derive(Copy, Clone, Debug)]
struct CallSite<'tcx> {
callee: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
bb: BasicBlock,
location: SourceInfo,
}
}
// Static variables need a borrow because the callee
// might modify the same static.
- Place::Static(_) => true,
+ Place::Base(PlaceBase::Static(_)) => true,
_ => false
}
}
let temp = LocalDecl::new_temp(ty, callsite.location.span);
let tmp = caller_mir.local_decls.push(temp);
- let tmp = Place::Local(tmp);
+ let tmp = Place::Base(PlaceBase::Local(tmp));
let stmt = Statement {
source_info: callsite.location,
let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir);
assert!(args.next().is_none());
- let tuple = Place::Local(tuple);
+ let tuple = Place::Base(PlaceBase::Local(tuple));
let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
s
} else {
// FIXME: Analysis of the usage of the arguments to avoid
// unnecessary temporaries.
- if let Operand::Move(Place::Local(local)) = arg {
+ if let Operand::Move(Place::Base(PlaceBase::Local(local))) = arg {
if caller_mir.local_kind(local) == LocalKind::Temp {
// Reuse the operand if it's a temporary already
return local;
let stmt = Statement {
source_info: callsite.location,
- kind: StatementKind::Assign(Place::Local(arg_tmp), box arg),
+ kind: StatementKind::Assign(Place::Base(PlaceBase::Local(arg_tmp)), box arg),
};
caller_mir[callsite.bb].statements.push(stmt);
arg_tmp
_location: Location) {
if *local == RETURN_PLACE {
match self.destination {
- Place::Local(l) => {
+ Place::Base(PlaceBase::Local(l)) => {
*local = l;
return;
},
_location: Location) {
match place {
- Place::Local(RETURN_PLACE) => {
+ Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
// Return pointer; update the place itself
*place = self.destination.clone();
},
- Place::Promoted(ref mut promoted) => {
+ Place::Base(PlaceBase::Promoted(ref mut promoted)) => {
if let Some(p) = self.promoted_map.get(promoted.0).cloned() {
promoted.0 = p;
}
//! Performs various peephole optimizations.
-use rustc::mir::{Constant, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local};
+use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, ProjectionElem, Rvalue, Local};
use rustc::mir::visit::{MutVisitor, Visitor};
use rustc::ty::{TyCtxt, TyKind};
use rustc::util::nodemap::{FxHashMap, FxHashSet};
let new_place = match *rvalue {
Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
// Replace with dummy
- mem::replace(&mut projection.base, Place::Local(Local::new(0)))
+ mem::replace(&mut projection.base, Place::Base(PlaceBase::Local(Local::new(0))))
}
_ => bug!("Detected `&*` but didn't find `&*`!"),
};
block.statements.push(Statement {
source_info: source_info,
kind: StatementKind::Assign(
- Place::Local(local),
+ Place::Base(PlaceBase::Local(local)),
box Rvalue::Cast(
CastKind::Misc,
rhs,
rhs_override_ty.unwrap())),
});
- rhs = Operand::Move(Place::Local(local));
+ rhs = Operand::Move(Place::Base(PlaceBase::Local(local)));
}
let call_did = check_lang_item_type(
span,
scope: OUTERMOST_SOURCE_SCOPE
},
- kind: StatementKind::Assign(Place::Local(dest), box rvalue)
+ kind: StatementKind::Assign(Place::Base(PlaceBase::Local(dest)), box rvalue)
});
}
func,
args,
cleanup: None,
- destination: Some((Place::Local(new_temp), new_target)),
+ destination: Some(
+ (Place::Base(PlaceBase::Local(new_temp)), new_target)
+ ),
from_hir_call,
},
..terminator
promoted.span = span;
promoted.local_decls[RETURN_PLACE] =
LocalDecl::new_return_place(ty, span);
- Place::Promoted(box (promoted_id, ty))
+ Place::Base(PlaceBase::Promoted(box (promoted_id, ty)))
};
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
match candidate {
match candidate {
Candidate::Ref(Location { block, statement_index }) => {
match mir[block].statements[statement_index].kind {
- StatementKind::Assign(Place::Local(local), _) => {
+ StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _) => {
if temps[local] == TempState::PromotedOut {
// Already promoted.
continue;
for block in mir.basic_blocks_mut() {
block.statements.retain(|statement| {
match statement.kind {
- StatementKind::Assign(Place::Local(index), _) |
+ StatementKind::Assign(Place::Base(PlaceBase::Local(index)), _) |
StatementKind::StorageLive(index) |
StatementKind::StorageDead(index) => {
!promoted(index)
});
let terminator = block.terminator_mut();
match terminator.kind {
- TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
+ TerminatorKind::Drop { location: Place::Base(PlaceBase::Local(index)), target, .. } => {
if promoted(index) {
terminator.kind = TerminatorKind::Goto {
target,
fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool {
match *place {
- Place::Local(local) => Self::in_local(cx, local),
- Place::Promoted(_) => bug!("qualifying already promoted MIR"),
- Place::Static(ref static_) => Self::in_static(cx, static_),
+ Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local),
+ Place::Base(PlaceBase::Promoted(_)) => bug!("qualifying already promoted MIR"),
+ Place::Base(PlaceBase::Static(ref static_)) => Self::in_static(cx, static_),
Place::Projection(ref proj) => Self::in_projection(cx, proj),
}
}
place = &proj.base;
}
debug!("qualify_consts: promotion candidate: place={:?}", place);
- if let Place::Local(local) = *place {
+ if let Place::Base(PlaceBase::Local(local)) = *place {
if self.mir.local_kind(local) == LocalKind::Temp {
debug!("qualify_consts: promotion candidate: local={:?}", local);
// The borrowed place doesn't have `HasMutInterior`
let index = loop {
match dest {
// We treat all locals equal in constants
- Place::Local(index) => break *index,
+ Place::Base(PlaceBase::Local(index)) => break *index,
// projections are transparent for assignments
// we qualify the entire destination at once, even if just a field would have
// stricter qualification
);
dest = &proj.base;
},
- Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"),
- Place::Static(..) => {
+ Place::Base(PlaceBase::Promoted(..)) =>
+ bug!("promoteds don't exist yet during promotion"),
+ Place::Base(PlaceBase::Static(..)) => {
// Catch more errors in the destination. `visit_place` also checks that we
// do not try to access statics from constants or try to mutate statics
self.visit_place(
match *candidate {
Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
match self.mir[bb].statements[stmt_idx].kind {
- StatementKind::Assign(_, box Rvalue::Ref(_, _, Place::Local(index))) => {
+ StatementKind::Assign(
+ _,
+ box Rvalue::Ref(_, _, Place::Base(PlaceBase::Local(index)))
+ ) => {
promoted_temps.insert(index);
}
_ => {}
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
self.super_place(place, context, location);
match *place {
- Place::Local(_) |
- Place::Promoted(_) => {}
- Place::Static(ref global) => {
+ Place::Base(PlaceBase::Local(_)) |
+ Place::Base(PlaceBase::Promoted(_)) => {}
+ Place::Base(PlaceBase::Static(ref global)) => {
if self.tcx
.get_attrs(global.def_id)
.iter()
match *operand {
Operand::Move(ref place) => {
// Mark the consumed locals to indicate later drops are noops.
- if let Place::Local(local) = *place {
+ if let Place::Base(PlaceBase::Local(local)) = *place {
self.cx.per_local[NeedsDrop].remove(local);
}
}
unleash_miri!(self);
// HACK(eddyb): emulate a bit of dataflow analysis,
// conservatively, that drop elaboration will do.
- let needs_drop = if let Place::Local(local) = *place {
+ let needs_drop = if let Place::Base(PlaceBase::Local(local)) = *place {
if NeedsDrop::in_local(self, local) {
Some(self.mir.local_decls[local].source_info.span)
} else {
});
let terminator = block.terminator_mut();
match terminator.kind {
- TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
+ TerminatorKind::Drop {
+ location: Place::Base(PlaceBase::Local(index)),
+ target,
+ ..
+ } => {
if promoted_temps.contains(index) {
terminator.kind = TerminatorKind::Goto {
target,
span: Span,
) -> McfResult {
match place {
- Place::Local(_) => Ok(()),
+ Place::Base(PlaceBase::Local(_)) => Ok(()),
// promoteds are always fine, they are essentially constants
- Place::Promoted(_) => Ok(()),
- Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
+ Place::Base(PlaceBase::Promoted(_)) => Ok(()),
+ Place::Base(PlaceBase::Static(_)) =>
+ Err((span, "cannot access `static` items in const fn".into())),
Place::Projection(proj) => {
match proj.elem {
| ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. }
// These are all nops in a landing pad
}
- StatementKind::Assign(Place::Local(_), box Rvalue::Use(_)) => {
+ StatementKind::Assign(Place::Base(PlaceBase::Local(_)), box Rvalue::Use(_)) => {
// Writing to a local (e.g., a drop flag) does not
// turn a landing pad to a non-nop
}
};
assert!(args.len() == 1);
let peek_arg_place = match args[0] {
- mir::Operand::Copy(ref place @ mir::Place::Local(_)) |
- mir::Operand::Move(ref place @ mir::Place::Local(_)) => Some(place),
+ mir::Operand::Copy(ref place @ mir::Place::Base(mir::PlaceBase::Local(_))) |
+ mir::Operand::Move(ref place @ mir::Place::Base(mir::PlaceBase::Local(_))) => Some(place),
_ => None,
};
let temp = self.patch.new_temp(item_ty, self.mir.source_info(location).span);
self.patch.add_statement(location, StatementKind::StorageLive(temp));
self.patch.add_assign(location,
- Place::Local(temp),
+ Place::Base(PlaceBase::Local(temp)),
Rvalue::Use(
Operand::Move(
Place::Projection(box PlaceProjection{
}))));
temp
}).collect();
- self.patch.add_assign(location,
- dst_place.clone(),
- Rvalue::Aggregate(box AggregateKind::Array(item_ty),
- temps.iter().map(
- |x| Operand::Move(Place::Local(*x))).collect()
- ));
+ self.patch.add_assign(
+ location,
+ dst_place.clone(),
+ Rvalue::Aggregate(
+ box AggregateKind::Array(item_ty),
+ temps.iter().map(
+ |x| Operand::Move(Place::Base(PlaceBase::Local(*x)))
+ ).collect()
+ )
+ );
for temp in temps {
self.patch.add_statement(location, StatementKind::StorageDead(temp));
}
if let StatementKind::Assign(ref dst_place, ref rval) = statement.kind {
if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = **rval {
let items : Vec<_> = items.iter().map(|item| {
- if let Operand::Move(Place::Local(local)) = item {
+ if let Operand::Move(Place::Base(PlaceBase::Local(local))) = item {
let local_use = &visitor.locals_use[*local];
let opt_index_and_place = Self::try_get_item_source(local_use, mir);
// each local should be used twice:
if block.statements.len() > location.statement_index {
let statement = &block.statements[location.statement_index];
if let StatementKind::Assign(
- Place::Local(_),
+ Place::Base(PlaceBase::Local(_)),
box Rvalue::Use(Operand::Move(Place::Projection(box PlaceProjection{
ref base, elem: ProjectionElem::ConstantIndex{
offset, min_length: _, from_end: false}})))) = statement.kind {
use rustc::traits::Reveal;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::VariantIdx;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::ty::util::IntTypeExt;
use rustc_data_structures::indexed_vec::Idx;
use crate::util::patch::MirPatch;
base_place: &Place<'tcx>,
variant_path: D::Path,
variant: &'tcx ty::VariantDef,
- substs: &'tcx Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> Vec<(Place<'tcx>, Option<D::Path>)>
{
variant.fields.iter().enumerate().map(|(i, f)| {
self.drop_ladder(fields, succ, unwind).0
}
- fn open_drop_for_box<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>)
+ fn open_drop_for_box<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>)
-> BasicBlock
{
debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs);
self.drop_subpath(&interior, interior_path, succ, unwind_succ)
}
- fn open_drop_for_adt<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>)
+ fn open_drop_for_adt<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>)
-> BasicBlock {
debug!("open_drop_for_adt({:?}, {:?}, {:?})", self, adt, substs);
if adt.variants.len() == 0 {
}
fn open_drop_for_adt_contents(&mut self, adt: &'tcx ty::AdtDef,
- substs: &'tcx Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> (BasicBlock, Unwind) {
let (succ, unwind) = self.drop_ladder_bottom();
if !adt.is_enum() {
}
fn open_drop_for_multivariant(&mut self, adt: &'tcx ty::AdtDef,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
succ: BasicBlock,
unwind: Unwind)
-> (BasicBlock, Unwind) {
// discriminant after it is free-ed, because that
// way lies only trouble.
let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
- let discr = Place::Local(self.new_temp(discr_ty));
+ let discr = Place::Base(PlaceBase::Local(self.new_temp(discr_ty)));
let discr_rv = Rvalue::Discriminant(self.place.clone());
let switch_block = BasicBlockData {
statements: vec![self.assign(&discr, discr_rv)],
mutbl: hir::Mutability::MutMutable
});
let ref_place = self.new_temp(ref_ty);
- let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
+ let unit_temp = Place::Base(PlaceBase::Local(self.new_temp(tcx.mk_unit())));
let result = BasicBlockData {
statements: vec![self.assign(
- &Place::Local(ref_place),
+ &Place::Base(PlaceBase::Local(ref_place)),
Rvalue::Ref(tcx.types.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
self.place.clone())
kind: TerminatorKind::Call {
func: Operand::function_handle(tcx, drop_fn.def_id, substs,
self.source_info.span),
- args: vec![Operand::Move(Place::Local(ref_place))],
+ args: vec![Operand::Move(Place::Base(PlaceBase::Local(ref_place)))],
destination: Some((unit_temp, succ)),
cleanup: unwind.into_option(),
from_hir_call: true,
ty: ety,
mutbl: hir::Mutability::MutMutable
});
- let ptr = &Place::Local(self.new_temp(ref_ty));
- let can_go = &Place::Local(self.new_temp(tcx.types.bool));
+ let ptr = &Place::Base(PlaceBase::Local(self.new_temp(ref_ty)));
+ let can_go = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
let one = self.constant_usize(1);
let (ptr_next, cur_next) = if ptr_based {
tcx.types.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
Place::Projection(Box::new(Projection {
- base: Place::Local(cur),
+ base: Place::Base(PlaceBase::Local(cur)),
elem: ProjectionElem::Deref,
}))
),
- Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Local(cur)), one))
+ Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Base(PlaceBase::Local(cur))), one))
} else {
(Rvalue::Ref(
tcx.types.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
self.place.clone().index(cur)),
- Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one))
+ Rvalue::BinaryOp(BinOp::Add, copy(&Place::Base(PlaceBase::Local(cur))), one))
};
let drop_block = BasicBlockData {
statements: vec![
self.assign(ptr, ptr_next),
- self.assign(&Place::Local(cur), cur_next)
+ self.assign(&Place::Base(PlaceBase::Local(cur)), cur_next)
],
is_cleanup: unwind.is_cleanup(),
terminator: Some(Terminator {
let loop_block = BasicBlockData {
statements: vec![
self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq,
- copy(&Place::Local(cur)),
+ copy(&Place::Base(PlaceBase::Local(cur))),
copy(length_or_end)))
],
is_cleanup: unwind.is_cleanup(),
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
let tcx = self.tcx();
- let size = &Place::Local(self.new_temp(tcx.types.usize));
- let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
+ let size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
+ let size_is_zero = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
let base_block = BasicBlockData {
statements: vec![
self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
};
let cur = self.new_temp(iter_ty);
- let length = Place::Local(self.new_temp(tcx.types.usize));
+ let length = Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
let length_or_end = if ptr_based {
- Place::Local(self.new_temp(iter_ty))
+ // FIXME check if we want to make it return a `Place` directly
+ // if all use sites want a `Place::Base` anyway.
+ let temp = self.new_temp(iter_ty);
+ Place::Base(PlaceBase::Local(temp))
} else {
length.clone()
};
unwind,
ptr_based);
- let cur = Place::Local(cur);
+ let cur = Place::Base(PlaceBase::Local(cur));
let zero = self.constant_usize(0);
let mut drop_block_stmts = vec![];
drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone())));
if ptr_based {
let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
- let tmp = Place::Local(self.new_temp(tmp_ty));
+ let tmp = Place::Base(PlaceBase::Local(self.new_temp(tmp_ty)));
// tmp = &mut P;
// cur = tmp as *mut T;
// end = Offset(cur, len);
fn box_free_block<'a>(
&mut self,
adt: &'tcx ty::AdtDef,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
target: BasicBlock,
unwind: Unwind,
) -> BasicBlock {
fn unelaborated_free_block<'a>(
&mut self,
adt: &'tcx ty::AdtDef,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
target: BasicBlock,
unwind: Unwind
) -> BasicBlock {
let tcx = self.tcx();
- let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
+ let unit_temp = Place::Base(PlaceBase::Local(self.new_temp(tcx.mk_unit())));
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| {
let field = Field::new(i);
if i > 0 {
write!(w, ", ")?;
}
- write!(w, "{:?}: {}", Place::Local(arg), escape(&mir.local_decls[arg].ty))?;
+ write!(w,
+ "{:?}: {}",
+ Place::Base(PlaceBase::Local(arg)),
+ escape(&mir.local_decls[arg].ty)
+ )?;
}
write!(w, ") -> {}", escape(mir.return_ty()))?;
if let Some(name) = decl.name {
write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
- Place::Local(local), escape(&decl.ty), name)?;
+ Place::Base(PlaceBase::Local(local)), escape(&decl.ty), name)?;
} else {
write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
- Place::Local(local), escape(&decl.ty))?;
+ Place::Base(PlaceBase::Local(local)), escape(&decl.ty))?;
}
}
if i != 0 {
write!(w, ", ")?;
}
- write!(w, "{:?}: {}", Place::Local(arg), mir.local_decls[arg].ty)?;
+ write!(w, "{:?}: {}", Place::Base(PlaceBase::Local(arg)), mir.local_decls[arg].ty)?;
}
write!(w, ") -> {}", mir.return_ty())?;
self.invalid_visibility(&impl_item.vis, None);
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
self.check_trait_fn_not_const(sig.header.constness);
- self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness);
+ self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
}
}
}
.note("only trait implementations may be annotated with default").emit();
}
}
- ItemKind::Fn(_, header, ref generics, _) => {
+ ItemKind::Fn(_, ref header, ref generics, _) => {
// We currently do not permit const generics in `const fn`, as
// this is tantamount to allowing compile-time dependent typing.
+ self.visit_fn_header(header);
if header.constness.node == Constness::Const {
// Look for const generics and error if we find any.
for param in &generics.params {
self.no_questions_in_bounds(bounds, "supertraits", true);
for trait_item in trait_items {
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
- self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness);
+ self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
self.check_trait_fn_not_const(sig.header.constness);
if block.is_none() {
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
.span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \
the relevant `fold_*()` method in `PlaceholderExpander`?");
}
+
+ fn visit_fn_header(&mut self, header: &'a FnHeader) {
+ if header.asyncness.node.is_async() && self.session.rust_2015() {
+ struct_span_err!(self.session, header.asyncness.span, E0670,
+ "`async fn` is not permitted in the 2015 edition").emit();
+ }
+ }
}
pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) {
break;
}
```
+"##,
+
+E0670: r##"
+Rust 2015 does not permit the use of `async fn`.
+
+Example of erroneous code:
+
+```compile_fail,E0670
+async fn foo() {}
+```
+
+Switch to the Rust 2018 edition to use `async fn`.
"##
}
use rustc::middle::mem_categorization::Categorization;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::query::Providers;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::util::nodemap::{ItemLocalSet, HirIdSet};
use rustc::hir;
use rustc_data_structures::sync::Lrc;
in_static: false,
mut_rvalue_borrows: Default::default(),
param_env: ty::ParamEnv::empty(),
- identity_substs: Substs::empty(),
+ identity_substs: InternalSubsts::empty(),
result: ItemLocalSet::default(),
};
in_static: bool,
mut_rvalue_borrows: HirIdSet,
param_env: ty::ParamEnv<'tcx>,
- identity_substs: &'tcx Substs<'tcx>,
+ identity_substs: SubstsRef<'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
result: ItemLocalSet,
}
self.tables = self.tcx.typeck_tables_of(item_def_id);
self.param_env = self.tcx.param_env(item_def_id);
- self.identity_substs = Substs::identity_for_item(self.tcx, item_def_id);
+ self.identity_substs = InternalSubsts::identity_for_item(self.tcx, item_def_id);
let body = self.tcx.hir().body(body_id);
use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind};
use rustc::ty::fold::TypeVisitor;
use rustc::ty::query::Providers;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::InternalSubsts;
use rustc::util::nodemap::HirIdSet;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
{
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
let tcx = self.def_id_visitor.tcx();
- // Substs are not visited here because they are visited below in `super_visit_with`.
+ // InternalSubsts are not visited here because they are visited below in `super_visit_with`.
match ty.sty {
ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) |
ty::Foreign(def_id) |
ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
ty::ExistentialPredicate::AutoTrait(def_id) =>
- ty::ExistentialTraitRef { def_id, substs: Substs::empty() },
+ ty::ExistentialTraitRef { def_id, substs: InternalSubsts::empty() },
};
let ty::ExistentialTraitRef { def_id, substs: _ } = trait_ref;
if self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) {
// Set the correct `TypeckTables` for the given `item_id` (or an empty table if
// there is no `TypeckTables` for the item).
fn item_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- node_id: ast::NodeId,
+ hir_id: hir::HirId,
empty_tables: &'a ty::TypeckTables<'tcx>)
-> &'a ty::TypeckTables<'tcx> {
- let def_id = tcx.hir().local_def_id(node_id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables }
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
let orig_current_item = mem::replace(&mut self.current_item, item.id);
let orig_tables =
- mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables));
+ mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
intravisit::walk_item(self, item);
self.current_item = orig_current_item;
self.tables = orig_tables;
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
let orig_tables =
- mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables));
+ mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
intravisit::walk_trait_item(self, ti);
self.tables = orig_tables;
}
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
let orig_tables =
- mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables));
+ mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
intravisit::walk_impl_item(self, ii);
self.tables = orig_tables;
}
mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id));
let orig_in_body = mem::replace(&mut self.in_body, false);
let orig_tables =
- mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables));
+ mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
intravisit::walk_item(self, item);
self.tables = orig_tables;
self.in_body = orig_in_body;
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
let orig_tables =
- mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables));
+ mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
intravisit::walk_trait_item(self, ti);
self.tables = orig_tables;
}
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
let orig_tables =
- mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables));
+ mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
intravisit::walk_impl_item(self, ii);
self.tables = orig_tables;
}
match impl_item.node {
hir::ImplItemKind::Const(..) |
hir::ImplItemKind::Method(..) => {
- self.access_levels.is_reachable(impl_item.id)
+ let node_id = self.tcx.hir().hir_to_node_id(
+ impl_item.hir_id);
+ self.access_levels.is_reachable(node_id)
}
hir::ImplItemKind::Existential(..) |
hir::ImplItemKind::Type(_) => false,
// don't erroneously report errors for private
// types in private items.
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
+ let node_id = self.tcx.hir().hir_to_node_id(impl_item.hir_id);
match impl_item.node {
hir::ImplItemKind::Const(..) |
hir::ImplItemKind::Method(..)
- if self.item_is_public(&impl_item.id, &impl_item.vis) =>
+ if self.item_is_public(&node_id, &impl_item.vis) =>
{
intravisit::walk_impl_item(self, impl_item)
}
struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- item_id: ast::NodeId,
+ item_id: hir::HirId,
item_def_id: DefId,
span: Span,
/// The visitor checks that each component type is at least this visible.
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
if self.leaks_private_dep(def_id) {
- self.tcx.lint_node(lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
- self.item_id,
- self.span,
- &format!("{} `{}` from private dependency '{}' in public \
- interface", kind, descr,
- self.tcx.crate_name(def_id.krate)));
+ self.tcx.lint_hir(lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
+ self.item_id,
+ self.span,
+ &format!("{} `{}` from private dependency '{}' in public \
+ interface", kind, descr,
+ self.tcx.crate_name(def_id.krate)));
}
- let node_id = match self.tcx.hir().as_local_node_id(def_id) {
- Some(node_id) => node_id,
+ let hir_id = match self.tcx.hir().as_local_hir_id(def_id) {
+ Some(hir_id) => hir_id,
None => return false,
};
err.emit();
} else {
let err_code = if kind == "trait" { "E0445" } else { "E0446" };
- self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, node_id, self.span,
- &format!("{} (error {})", msg, err_code));
+ self.tcx.lint_hir(lint::builtin::PRIVATE_IN_PUBLIC, hir_id, self.span,
+ &format!("{} (error {})", msg, err_code));
}
}
}
impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
- fn check(&self, item_id: ast::NodeId, required_visibility: ty::Visibility)
+ fn check(&self, item_id: hir::HirId, required_visibility: ty::Visibility)
-> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
let mut has_old_errors = false;
// Slow path taken only if there any errors in the crate.
for &id in self.old_error_set {
// Walk up the nodes until we find `item_id` (or we hit a root).
- let mut id = self.tcx.hir().hir_to_node_id(id);
+ let mut id = id;
loop {
if id == item_id {
has_old_errors = true;
break;
}
- let parent = self.tcx.hir().get_parent_node(id);
+ let parent = self.tcx.hir().get_parent_node_by_hir_id(id);
if parent == id {
break;
}
SearchInterfaceForPrivateItemsVisitor {
tcx: self.tcx,
item_id,
- item_def_id: self.tcx.hir().local_def_id(item_id),
- span: self.tcx.hir().span(item_id),
+ item_def_id: self.tcx.hir().local_def_id_from_hir_id(item_id),
+ span: self.tcx.hir().span_by_hir_id(item_id),
required_visibility,
has_pub_restricted: self.has_pub_restricted,
has_old_errors,
}
}
- fn check_trait_or_impl_item(&self, node_id: ast::NodeId, assoc_item_kind: AssociatedItemKind,
+ fn check_trait_or_impl_item(&self, hir_id: hir::HirId, assoc_item_kind: AssociatedItemKind,
defaultness: hir::Defaultness, vis: ty::Visibility) {
- let mut check = self.check(node_id, vis);
+ let mut check = self.check(hir_id, vis);
let (check_ty, is_assoc_ty) = match assoc_item_kind {
AssociatedItemKind::Const | AssociatedItemKind::Method { .. } => (true, false),
// Subitems of these items have inherited publicity.
hir::ItemKind::Const(..) | hir::ItemKind::Static(..) |
hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) => {
- self.check(item.id, item_visibility).generics().predicates().ty();
+ self.check(item.hir_id, item_visibility).generics().predicates().ty();
}
hir::ItemKind::Existential(..) => {
// `ty()` for existential types is the underlying type,
// it's not a part of interface, so we skip it.
- self.check(item.id, item_visibility).generics().predicates();
+ self.check(item.hir_id, item_visibility).generics().predicates();
}
hir::ItemKind::Trait(.., ref trait_item_refs) => {
- self.check(item.id, item_visibility).generics().predicates();
+ self.check(item.hir_id, item_visibility).generics().predicates();
for trait_item_ref in trait_item_refs {
- self.check_trait_or_impl_item(trait_item_ref.id.node_id, trait_item_ref.kind,
+ let hir_id = tcx.hir().node_to_hir_id(trait_item_ref.id.node_id);
+ self.check_trait_or_impl_item(hir_id, trait_item_ref.kind,
trait_item_ref.defaultness, item_visibility);
}
}
hir::ItemKind::TraitAlias(..) => {
- self.check(item.id, item_visibility).generics().predicates();
+ self.check(item.hir_id, item_visibility).generics().predicates();
}
hir::ItemKind::Enum(ref def, _) => {
- self.check(item.id, item_visibility).generics().predicates();
+ self.check(item.hir_id, item_visibility).generics().predicates();
for variant in &def.variants {
for field in variant.node.data.fields() {
- self.check(field.id, item_visibility).ty();
+ self.check(field.hir_id, item_visibility).ty();
}
}
}
hir::ItemKind::ForeignMod(ref foreign_mod) => {
for foreign_item in &foreign_mod.items {
let vis = ty::Visibility::from_hir(&foreign_item.vis, item.id, tcx);
- self.check(foreign_item.id, vis).generics().predicates().ty();
+ self.check(foreign_item.hir_id, vis).generics().predicates().ty();
}
}
// Subitems of structs and unions have their own publicity.
hir::ItemKind::Struct(ref struct_def, _) |
hir::ItemKind::Union(ref struct_def, _) => {
- self.check(item.id, item_visibility).generics().predicates();
+ self.check(item.hir_id, item_visibility).generics().predicates();
for field in struct_def.fields() {
let field_visibility = ty::Visibility::from_hir(&field.vis, item.id, tcx);
- self.check(field.id, min(item_visibility, field_visibility, tcx)).ty();
+ self.check(field.hir_id, min(item_visibility, field_visibility, tcx)).ty();
}
}
// An inherent impl is public when its type is public
// Subitems of trait impls have inherited publicity.
hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => {
let impl_vis = ty::Visibility::of_impl(item.id, tcx, &Default::default());
- self.check(item.id, impl_vis).generics().predicates();
+ self.check(item.hir_id, impl_vis).generics().predicates();
for impl_item_ref in impl_item_refs {
let impl_item = tcx.hir().impl_item(impl_item_ref.id);
let impl_item_vis = if trait_ref.is_none() {
} else {
impl_vis
};
- self.check_trait_or_impl_item(impl_item_ref.id.node_id, impl_item_ref.kind,
+ let hir_id = tcx.hir().node_to_hir_id(impl_item_ref.id.node_id);
+ self.check_trait_or_impl_item(hir_id, impl_item_ref.kind,
impl_item_ref.defaultness, impl_item_vis);
}
}
debug!("(resolving function) entering function");
let (rib_kind, asyncness) = match function_kind {
FnKind::ItemFn(_, ref header, ..) =>
- (ItemRibKind, header.asyncness),
+ (ItemRibKind, header.asyncness.node),
FnKind::Method(_, ref sig, _, _) =>
- (TraitOrImplItemRibKind, sig.header.asyncness),
+ (TraitOrImplItemRibKind, sig.header.asyncness.node),
FnKind::Closure(_) =>
// Async closures aren't resolved through `visit_fn`-- they're
// processed separately
fn visit_generics(&mut self, generics: &'tcx Generics) {
// For type parameter defaults, we have to ban access
- // to following type parameters, as the Substs can only
+ // to following type parameters, as the InternalSubsts can only
// provide previous type parameters as they're built. We
// put all the parameters on the ban list and then remove
// them one by one as they are processed and become available.
Ok(replace_text(nested, text))
}
ast::TyKind::Never => Ok(text_sig("!".to_owned())),
+ ast::TyKind::CVarArgs => Ok(text_sig("...".to_owned())),
ast::TyKind::Tup(ref ts) => {
let mut text = "(".to_owned();
let mut defs = vec![];
if header.constness.node == ast::Constness::Const {
text.push_str("const ");
}
- if header.asyncness.is_async() {
+ if header.asyncness.node.is_async() {
text.push_str("async ");
}
if header.unsafety == ast::Unsafety::Unsafe {
if m.header.constness.node == ast::Constness::Const {
text.push_str("const ");
}
- if m.header.asyncness.is_async() {
+ if m.header.asyncness.node.is_async() {
text.push_str("async ");
}
if m.header.unsafety == ast::Unsafety::Unsafe {
// `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
let vfp = cx.target_spec().llvm_target.ends_with("hf")
&& fty.conv != Conv::ArmAapcs
- && !fty.variadic;
+ && !fty.c_variadic;
if !fty.ret.is_ignore() {
classify_ret_ty(cx, &mut fty.ret, vfp);
mod x86_win64;
mod wasm32;
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum IgnoreMode {
+ /// C-variadic arguments.
+ CVarArgs,
+ /// A zero-sized type.
+ Zst,
+}
+
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum PassMode {
- /// Ignore the argument (useful for empty struct).
- Ignore,
+ /// Ignore the argument (useful for empty structs and C-variadic args).
+ Ignore(IgnoreMode),
/// Pass the argument directly.
Direct(ArgAttributes),
/// Pass a pair's elements directly in two arguments.
}
pub fn is_ignore(&self) -> bool {
- self.mode == PassMode::Ignore
+ match self.mode {
+ PassMode::Ignore(_) => true,
+ _ => false
+ }
}
}
/// LLVM return type.
pub ret: ArgType<'a, Ty>,
- pub variadic: bool,
+ pub c_variadic: bool,
pub conv: Conv,
}
for arg in &mut fty.args {
let attrs = match arg.mode {
- PassMode::Ignore |
+ PassMode::Ignore(_) |
PassMode::Indirect(_, None) => continue,
PassMode::Direct(ref mut attrs) => attrs,
PassMode::Pair(..) |
Environment,
};
use rustc::ty;
-use rustc::ty::subst::{Substs, Subst};
+use rustc::ty::subst::{InternalSubsts, Subst};
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc_target::spec::abi;
let fn_ptr = generic_types::fn_ptr(
tcx,
fn_ptr.inputs_and_output.len(),
- fn_ptr.variadic,
+ fn_ptr.c_variadic,
fn_ptr.unsafety,
fn_ptr.abi
);
// Struct def
ty::Adt(adt_def, _) => {
- let substs = Substs::bound_vars_for_item(tcx, adt_def.did);
+ let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did);
let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
let sized_constraint = adt_def.sized_constraint(tcx)
.iter()
fn wf_clause_for_fn_ptr<'tcx>(
tcx: ty::TyCtxt<'_, '_, 'tcx>,
arity_and_output: usize,
- variadic: bool,
+ c_variadic: bool,
unsafety: hir::Unsafety,
abi: abi::Abi
) -> Clauses<'tcx> {
- let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
+ let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, c_variadic, unsafety, abi);
let wf_clause = ProgramClause {
goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
wf_clause_for_fn_ptr(
self.infcx.tcx,
fn_ptr.inputs_and_output.len(),
- fn_ptr.variadic,
+ fn_ptr.c_variadic,
fn_ptr.unsafety,
fn_ptr.abi
)
use rustc::traits::query::{CanonicalTyGoal, NoSolution};
use rustc::traits::{TraitEngine, Normalized, ObligationCause, TraitEngineExt};
use rustc::ty::query::Providers;
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
use rustc::util::nodemap::FxHashSet;
use rustc_data_structures::sync::Lrc;
if def.is_phantom_data() {
// The first generic parameter here is guaranteed to be a type because it's
// `PhantomData`.
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
assert_eq!(substs.len(), 1);
let result = DtorckConstraint {
outlives: vec![],
//! Utilities for creating generic types with bound vars in place of parameter values.
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::InternalSubsts;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc_target::spec::abi;
crate fn fn_ptr(
tcx: ty::TyCtxt<'_, '_, 'tcx>,
arity_and_output: usize,
- variadic: bool,
+ c_variadic: bool,
unsafety: hir::Unsafety,
abi: abi::Abi
) -> Ty<'tcx> {
let fn_sig = ty::Binder::bind(ty::FnSig {
inputs_and_output,
- variadic,
+ c_variadic,
unsafety,
abi,
});
}
crate fn fn_def(tcx: ty::TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> Ty<'tcx> {
- tcx.mk_ty(ty::FnDef(def_id, Substs::bound_vars_for_item(tcx, def_id)))
+ tcx.mk_ty(ty::FnDef(def_id, InternalSubsts::bound_vars_for_item(tcx, def_id)))
}
crate fn closure(tcx: ty::TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> Ty<'tcx> {
tcx.mk_closure(def_id, ty::ClosureSubsts {
- substs: Substs::bound_vars_for_item(tcx, def_id),
+ substs: InternalSubsts::bound_vars_for_item(tcx, def_id),
})
}
crate fn generator(tcx: ty::TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> Ty<'tcx> {
tcx.mk_generator(def_id, ty::GeneratorSubsts {
- substs: Substs::bound_vars_for_item(tcx, def_id),
+ substs: InternalSubsts::bound_vars_for_item(tcx, def_id),
}, hir::GeneratorMovability::Movable)
}
};
use rustc::ty::query::Providers;
use rustc::ty::{self, List, TyCtxt};
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, InternalSubsts};
use syntax::ast;
use std::iter;
// }
// ```
- let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+ let bound_vars = InternalSubsts::bound_vars_for_item(tcx, def_id);
// `Self: Trait<P1..Pn>`
let trait_pred = ty::TraitPredicate {
// }
// ```
- let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+ let bound_vars = InternalSubsts::bound_vars_for_item(tcx, def_id);
let trait_ref = tcx.impl_trait_ref(def_id)
.expect("not an impl")
// }
// ```
- let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+ let bound_vars = InternalSubsts::bound_vars_for_item(tcx, def_id);
// `Ty<...>`
let ty = tcx.type_of(def_id).subst(tcx, bound_vars);
_ => bug!("not an trait container"),
};
- let trait_bound_vars = Substs::bound_vars_for_item(tcx, trait_id);
+ let trait_bound_vars = InternalSubsts::bound_vars_for_item(tcx, trait_id);
let trait_ref = ty::TraitRef {
def_id: trait_id,
substs: trait_bound_vars,
_ => bug!("not an impl container"),
};
- let impl_bound_vars = Substs::bound_vars_for_item(tcx, impl_id);
+ let impl_bound_vars = InternalSubsts::bound_vars_for_item(tcx, impl_id);
// `A0 as Trait<A1..An>`
let trait_ref = tcx.impl_trait_ref(impl_id)
}
impl<'a, 'tcx> ClauseDumper<'a, 'tcx> {
- fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
- let def_id = self.tcx.hir().local_def_id(node_id);
+ fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) {
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(hir_id);
for attr in attrs {
let mut clauses = None;
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
- self.process_attrs(item.id, &item.attrs);
+ self.process_attrs(item.hir_id, &item.attrs);
intravisit::walk_item(self, item);
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
- self.process_attrs(trait_item.id, &trait_item.attrs);
+ self.process_attrs(trait_item.hir_id, &trait_item.attrs);
intravisit::walk_trait_item(self, trait_item);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
- self.process_attrs(impl_item.id, &impl_item.attrs);
+ self.process_attrs(impl_item.hir_id, &impl_item.attrs);
intravisit::walk_impl_item(self, impl_item);
}
fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
- self.process_attrs(s.id, &s.attrs);
+ self.process_attrs(s.hir_id, &s.attrs);
intravisit::walk_struct_field(self, s);
}
}
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::{GenericParamDef, GenericParamDefKind};
-use rustc::ty::subst::{Kind, Subst, Substs};
+use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
use rustc::ty::wf::object_region_bounds;
use rustc_data_structures::sync::Lrc;
use rustc_target::spec::abi;
-use crate::require_c_abi_if_variadic;
+use crate::require_c_abi_if_c_variadic;
use smallvec::SmallVec;
use syntax::ast;
use syntax::feature_gate::{GateIssue, emit_feature_err};
span: Span,
def_id: DefId,
item_segment: &hir::PathSegment)
- -> &'tcx Substs<'tcx>
+ -> SubstsRef<'tcx>
{
let (substs, assoc_bindings, _) = item_segment.with_generic_args(|generic_args| {
self.create_substs_for_ast_path(
args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs>, bool),
provided_kind: impl Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>,
inferred_kind: impl Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>,
- ) -> &'tcx Substs<'tcx> {
+ ) -> SubstsRef<'tcx> {
// Collect the segments of the path; we need to substitute arguments
// for parameters throughout the entire path (wherever there are
// generic parameters).
generic_args: &hir::GenericArgs,
infer_types: bool,
self_ty: Option<Ty<'tcx>>)
- -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>)
+ -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>)
{
// If the type is parameterized by this region, then replace this
// region with the current anon region binding (in other words,
// specify type to assert that error was already reported in Err case:
let predicate: Result<_, ErrorReported> =
self.ast_type_binding_to_poly_projection_predicate(
- trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
+ trait_ref.hir_ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
// okay to ignore Err because of ErrorReported (see above)
Some((predicate.ok()?, binding.span))
}));
trait_def_id: DefId,
self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment,
- ) -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>) {
+ ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>) {
debug!("create_substs_for_ast_trait_ref(trait_segment={:?})",
trait_segment);
fn ast_type_binding_to_poly_projection_predicate(
&self,
- ref_id: ast::NodeId,
+ hir_ref_id: hir::HirId,
trait_ref: ty::PolyTraitRef<'tcx>,
binding: &ConvertedBinding<'tcx>,
speculative: bool,
binding.item_name, binding.span)
}?;
- let hir_ref_id = self.tcx().hir().node_to_hir_id(ref_id);
let (assoc_ident, def_scope) =
tcx.adjust_ident(binding.item_name, candidate.def_id(), hir_ref_id);
let assoc_ty = tcx.associated_items(candidate.def_id()).find(|i| {
// `Self` in impl (we know the concrete type).
assert_eq!(opt_self_ty, None);
self.prohibit_generics(&path.segments);
- tcx.at(span).type_of(def_id)
+ // Try to evaluate any array length constants
+ self.normalize_ty(span, tcx.at(span).type_of(def_id))
}
Def::SelfTy(Some(_), None) => {
// `Self` in trait.
tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)))
}
hir::TyKind::BareFn(ref bf) => {
- require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
+ require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl))
}
hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, def, segment, false).0
}
hir::TyKind::Array(ref ty, ref length) => {
- let length_def_id = tcx.hir().local_def_id(length.id);
- let substs = Substs::identity_for_item(tcx, length_def_id);
+ let length_def_id = tcx.hir().local_def_id_from_hir_id(length.hir_id);
+ let substs = InternalSubsts::identity_for_item(tcx, length_def_id);
let length = ty::LazyConst::Unevaluated(length_def_id, substs);
let length = tcx.mk_lazy_const(length);
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
hir::TyKind::Err => {
tcx.types.err
}
+ hir::TyKind::CVarArgs(lt) => {
+ let va_list_did = match tcx.lang_items().va_list() {
+ Some(did) => did,
+ None => span_bug!(ast_ty.span,
+ "`va_list` lang item required for variadics"),
+ };
+ let region = self.ast_region_to_region(<, None);
+ tcx.type_of(va_list_did).subst(tcx, &[region.into()])
+ }
};
self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
let generics = tcx.generics_of(def_id);
debug!("impl_trait_ty_to_ty: generics={:?}", generics);
- let substs = Substs::for_item(tcx, def_id, |param, _| {
+ let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
// Our own parameters are the resolved lifetimes.
match param.kind {
let bare_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
input_tys,
output_ty,
- decl.variadic,
+ decl.c_variadic,
unsafety,
abi
));
self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span);
common_type
}
- PatKind::Binding(ba, var_id, _, _, ref sub) => {
+ PatKind::Binding(ba, _, var_id, _, ref sub) => {
let bm = if ba == hir::BindingAnnotation::Unannotated {
def_bm
} else {
.pat_binding_modes_mut()
.insert(pat.hir_id, bm);
debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
- let local_ty = self.local_ty(pat.span, pat.id).decl_ty;
+ let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
match bm {
ty::BindByReference(mutbl) => {
// if the binding is like
// if there are multiple arms, make sure they all agree on
// what the type of the binding `x` ought to be
- if var_id != pat.id {
+ if var_id != pat.hir_id {
let vt = self.local_ty(pat.span, var_id).decl_ty;
self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span);
}
.0;
let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
+ let inputs = if fn_sig.c_variadic {
+ if fn_sig.inputs().len() > 1 {
+ &fn_sig.inputs()[..fn_sig.inputs().len() - 1]
+ } else {
+ span_bug!(call_expr.span,
+ "C-variadic functions are only valid with one or more fixed arguments");
+ }
+ } else {
+ &fn_sig.inputs()[..]
+ };
// Call the generic checker.
let expected_arg_tys = self.expected_inputs_for_expected_output(
call_expr.span,
expected,
fn_sig.output(),
- fn_sig.inputs(),
+ inputs,
);
self.check_argument_types(
call_expr.span,
call_expr.span,
- fn_sig.inputs(),
+ inputs,
&expected_arg_tys[..],
arg_exprs,
- fn_sig.variadic,
+ fn_sig.c_variadic,
TupleArgumentsFlag::DontTupleArguments,
def_span,
);
fn_sig.inputs(),
&expected_arg_tys,
arg_exprs,
- fn_sig.variadic,
+ fn_sig.c_variadic,
TupleArgumentsFlag::TupleArguments,
None,
);
use rustc::session::Session;
use rustc::traits;
use rustc::ty::{self, Ty, TypeFoldable, TypeAndMut};
+use rustc::ty::subst::SubstsRef;
use rustc::ty::adjustment::AllowTwoPhase;
use rustc::ty::cast::{CastKind, CastTy};
-use rustc::ty::subst::Substs;
use rustc::middle::lang_items;
use syntax::ast;
use syntax_pos::Span;
/// The unsize info of this projection
OfProjection(&'tcx ty::ProjectionTy<'tcx>),
/// The unsize info of this opaque ty
- OfOpaque(DefId, &'tcx Substs<'tcx>),
+ OfOpaque(DefId, SubstsRef<'tcx>),
/// The unsize info of this parameter
OfParam(&'tcx ty::ParamTy),
}
use rustc::traits::error_reporting::ArgKind;
use rustc::ty::{self, Ty, GenericParamDefKind};
use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::InternalSubsts;
use std::cmp;
use std::iter;
use rustc_target::spec::abi::Abi;
// types of upvars. These will be unified during the upvar
// inference phase (`upvar.rs`).
let base_substs =
- Substs::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id));
+ InternalSubsts::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id));
let substs = base_substs.extend_to(self.tcx,expr_def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
self.tcx.mk_fn_sig(
iter::once(self.tcx.intern_tup(sig.inputs())),
sig.output(),
- sig.variadic,
+ sig.c_variadic,
sig.unsafety,
sig.abi,
)
// Watch out for some surprises and just ignore the
// expectation if things don't see to match up with what we
// expect.
- if expected_sig.sig.variadic != decl.variadic {
+ if expected_sig.sig.c_variadic != decl.c_variadic {
return self.sig_of_closure_no_expectation(expr_def_id, decl, body);
} else if expected_sig.sig.inputs_and_output.len() != decl.inputs.len() + 1 {
return self.sig_of_closure_with_mismatched_number_of_arguments(
let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig(
expected_sig.sig.inputs().iter().cloned(),
expected_sig.sig.output(),
- decl.variadic,
+ decl.c_variadic,
hir::Unsafety::Normal,
Abi::RustCall,
));
let result = ty::Binder::bind(self.tcx.mk_fn_sig(
supplied_arguments,
supplied_return,
- decl.variadic,
+ decl.c_variadic,
hir::Unsafety::Normal,
Abi::RustCall,
));
let result = ty::Binder::bind(self.tcx.mk_fn_sig(
supplied_arguments,
self.tcx.types.err,
- decl.variadic,
+ decl.c_variadic,
hir::Unsafety::Normal,
Abi::RustCall,
));
debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty);
// Special-case that coercion alone cannot handle:
- // Two function item types of differing IDs or Substs.
+ // Two function item types of differing IDs or InternalSubsts.
if let (&ty::FnDef(..), &ty::FnDef(..)) = (&prev_ty.sty, &new_ty.sty) {
// Don't reify if the function types have a LUB, i.e., they
// are the same function and their parameters have a LUB.
use rustc::ty::util::ExplicitSelf;
use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
use rustc::ty::error::{ExpectedFound, TypeError};
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, InternalSubsts, SubstsRef};
use rustc::util::common::ErrorReported;
use errors::Applicability;
// a fresh FulfillmentCtxt, and invoke select_all_or_error.
// Create mapping from impl to placeholder.
- let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
+ let impl_to_skol_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
// Create mapping from trait to placeholder.
let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
trait_m: &ty::AssociatedItem,
trait_generics: &ty::Generics,
impl_generics: &ty::Generics,
- trait_to_skol_substs: &Substs<'tcx>)
+ trait_to_skol_substs: SubstsRef<'tcx>)
-> Result<(), ErrorReported> {
let trait_params = trait_generics.own_counts().lifetimes;
let impl_params = impl_generics.own_counts().lifetimes;
use rustc::infer::{self, InferOk, SuppressRegionErrors};
use rustc::middle::region;
use rustc::traits::{ObligationCause, TraitEngine, TraitEngineExt};
-use rustc::ty::subst::{Subst, Substs, UnpackedKind};
+use rustc::ty::subst::{Subst, SubstsRef, UnpackedKind};
use rustc::ty::{self, Ty, TyCtxt};
use crate::util::common::ErrorReported;
drop_impl_did: DefId,
dtor_predicates: &ty::GenericPredicates<'tcx>,
self_type_did: DefId,
- self_to_impl_substs: &Substs<'tcx>,
+ self_to_impl_substs: SubstsRef<'tcx>,
) -> Result<(), ErrorReported> {
let mut result = Ok(());
"va_start" | "va_end" => {
match mk_va_list_ty() {
Some(va_list_ty) => (0, vec![va_list_ty], tcx.mk_unit()),
- None => bug!("va_list lang_item must be defined to use va_list intrinsics")
+ None => bug!("`va_list` language item needed for C-variadic intrinsics")
}
}
};
(0, vec![tcx.mk_imm_ref(tcx.mk_region(env_region), va_list_ty)], ret_ty)
}
- None => bug!("va_list lang_item must be defined to use va_list intrinsics")
+ None => bug!("`va_list` language item needed for C-variadic intrinsics")
}
}
"va_arg" => {
match mk_va_list_ty() {
Some(va_list_ty) => (1, vec![va_list_ty], param(0)),
- None => bug!("va_list lang_item must be defined to use va_list intrinsics")
+ None => bug!("`va_list` language item needed for C-variadic intrinsics")
}
}
use crate::check::{FnCtxt, PlaceOp, callee, Needs};
use crate::hir::GenericArg;
use crate::hir::def_id::DefId;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Subst, SubstsRef};
use rustc::traits;
use rustc::ty::{self, Ty, GenericParamDefKind};
-use rustc::ty::subst::Subst;
use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref};
use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
fn fresh_receiver_substs(&mut self,
self_ty: Ty<'tcx>,
pick: &probe::Pick<'tcx>)
- -> &'tcx Substs<'tcx> {
+ -> SubstsRef<'tcx> {
match pick.kind {
probe::InherentImplPick => {
let impl_def_id = pick.item.container.id();
&mut self,
pick: &probe::Pick<'tcx>,
seg: &hir::PathSegment,
- parent_substs: &Substs<'tcx>,
- ) -> &'tcx Substs<'tcx> {
+ parent_substs: SubstsRef<'tcx>,
+ ) -> SubstsRef<'tcx> {
// Determine the values for the generic parameters of the method.
// If they were not explicitly supplied, just construct fresh
// variables.
// until we unify the `Self` type.
fn instantiate_method_sig(&mut self,
pick: &probe::Pick<'tcx>,
- all_substs: &'tcx Substs<'tcx>)
+ all_substs: SubstsRef<'tcx>)
-> (ty::FnSig<'tcx>, ty::InstantiatedPredicates<'tcx>) {
debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
pick,
fn add_obligations(&mut self,
fty: Ty<'tcx>,
- all_substs: &Substs<'tcx>,
+ all_substs: SubstsRef<'tcx>,
method_predicates: &ty::InstantiatedPredicates<'tcx>) {
debug!("add_obligations: fty={:?} all_substs={:?} method_predicates={:?}",
fty,
use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
use rustc::traits;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
use rustc::ty::GenericParamDefKind;
use rustc::ty::subst::Subst;
pub struct MethodCallee<'tcx> {
/// Impl method ID, for inherent methods, or trait method ID, otherwise.
pub def_id: DefId,
- pub substs: &'tcx Substs<'tcx>,
+ pub substs: SubstsRef<'tcx>,
/// Instantiated method signature, i.e., it has been
/// substituted, normalized, and has had late-bound
trait_def_id);
// Construct a trait-reference `self_ty : Trait<input_tys>`
- let substs = Substs::for_item(self.tcx, trait_def_id, |param, _| {
+ let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type {..} => {
use rustc::hir;
use rustc::lint;
use rustc::session::config::nightly_options;
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, InternalSubsts, SubstsRef};
use rustc::traits::{self, ObligationCause};
use rustc::traits::query::{CanonicalTyGoal};
use rustc::traits::query::method_autoderef::{CandidateStep, MethodAutoderefStepsResult};
#[derive(Debug)]
enum CandidateKind<'tcx> {
- InherentImplCandidate(&'tcx Substs<'tcx>,
+ InherentImplCandidate(SubstsRef<'tcx>,
// Normalize obligations
Vec<traits::PredicateObligation<'tcx>>),
ObjectCandidate,
fn xform_self_ty(&self,
item: &ty::AssociatedItem,
impl_ty: Ty<'tcx>,
- substs: &Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> (Ty<'tcx>, Option<Ty<'tcx>>) {
if item.kind == ty::AssociatedKind::Method && self.mode == Mode::MethodCall {
let sig = self.xform_method_sig(item.def_id, substs);
fn xform_method_sig(&self,
method: DefId,
- substs: &Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> ty::FnSig<'tcx>
{
let fn_sig = self.tcx.fn_sig(method);
if generics.params.is_empty() {
xform_fn_sig.subst(self.tcx, substs)
} else {
- let substs = Substs::for_item(self.tcx, method, |param, _| {
+ let substs = InternalSubsts::for_item(self.tcx, method, |param, _| {
let i = param.index as usize;
if i < substs.len() {
substs[i]
}
/// Gets the type of an impl and generate substitutions with placeholders.
- fn impl_ty_and_substs(&self, impl_def_id: DefId) -> (Ty<'tcx>, &'tcx Substs<'tcx>) {
+ fn impl_ty_and_substs(&self, impl_def_id: DefId) -> (Ty<'tcx>, SubstsRef<'tcx>) {
(self.tcx.type_of(impl_def_id), self.fresh_item_substs(impl_def_id))
}
- fn fresh_item_substs(&self, def_id: DefId) -> &'tcx Substs<'tcx> {
- Substs::for_item(self.tcx, def_id, |param, _| {
+ fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx> {
+ InternalSubsts::for_item(self.tcx, def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => self.tcx.types.re_erased.into(),
GenericParamDefKind::Type {..} => {
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::query::Providers;
-use rustc::ty::subst::{UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts};
+use rustc::ty::subst::{UnpackedKind, Subst, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts};
use rustc::ty::util::{Representability, IntTypeExt, Discr};
use rustc::ty::layout::VariantIdx;
use syntax_pos::{self, BytePos, Span, MultiSpan};
use std::ops::{self, Deref};
use std::slice;
-use crate::require_c_abi_if_variadic;
-use crate::session::{CompileIncomplete, Session};
+use crate::require_c_abi_if_c_variadic;
+use crate::session::Session;
use crate::session::config::EntryFnType;
use crate::TypeAndSubsts;
use crate::lint;
use crate::util::captures::Captures;
use crate::util::common::{ErrorReported, indenter};
-use crate::util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, HirIdMap, NodeMap};
+use crate::util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, HirIdMap};
pub use self::Expectation::*;
use self::autoderef::Autoderef;
tables: MaybeInProgressTables<'a, 'tcx>,
- locals: RefCell<NodeMap<LocalTy<'tcx>>>,
+ locals: RefCell<HirIdMap<LocalTy<'tcx>>>,
fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx });
}
-pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> {
+pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
tcx.typeck_item_bodies(LOCAL_CRATE)
}
fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
- -> Result<(), CompileIncomplete>
+ -> Result<(), ErrorReported>
{
debug_assert!(crate_num == LOCAL_CRATE);
Ok(tcx.sess.track_errors(|| {
}
impl<'a, 'gcx, 'tcx> GatherLocalsVisitor<'a, 'gcx, 'tcx> {
- fn assign(&mut self, span: Span, nid: ast::NodeId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
+ fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
match ty_opt {
None => {
// infer the variable's type
},
None => None,
};
- self.assign(local.span, local.id, local_ty);
+ self.assign(local.span, local.hir_id, local_ty);
debug!("Local variable {:?} is assigned type {}",
local.pat,
self.fcx.ty_to_string(
- self.fcx.locals.borrow().get(&local.id).unwrap().clone().decl_ty));
+ self.fcx.locals.borrow().get(&local.hir_id).unwrap().clone().decl_ty));
intravisit::walk_local(self, local);
}
// Add pattern bindings.
fn visit_pat(&mut self, p: &'gcx hir::Pat) {
if let PatKind::Binding(_, _, _, ident, _) = p.node {
- let var_ty = self.assign(p.span, p.id, None);
+ let var_ty = self.assign(p.span, p.hir_id, None);
if !self.fcx.tcx.features().unsized_locals {
self.fcx.require_type_is_sized(var_ty, p.span,
debug!("Pattern binding {} is assigned to {} with type {:?}",
ident,
self.fcx.ty_to_string(
- self.fcx.locals.borrow().get(&p.id).unwrap().clone().decl_ty),
+ self.fcx.locals.borrow().get(&p.hir_id).unwrap().clone().decl_ty),
var_ty);
}
intravisit::walk_pat(self, p);
fn_sig = fcx.tcx.mk_fn_sig(
fn_sig.inputs().iter().cloned(),
revealed_ret_ty,
- fn_sig.variadic,
+ fn_sig.c_variadic,
fn_sig.unsafety,
fn_sig.abi
);
fn check_opaque<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
span: Span,
) {
if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) {
hir::ItemKind::Existential(..) => {
let def_id = tcx.hir().local_def_id(it.id);
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
check_opaque(tcx, def_id, substs, it.span);
}
hir::ItemKind::Ty(..) => {
}
if let hir::ForeignItemKind::Fn(ref fn_decl, _, _) = item.node {
- require_c_abi_if_variadic(tcx, fn_decl, m.abi, item.span);
+ require_c_abi_if_c_variadic(tcx, fn_decl, m.abi, item.span);
}
}
}
// Check existing impl methods to see if they are both present in trait
// and compatible with trait signature
for impl_item in impl_items() {
- let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.id));
+ let ty_impl_item = tcx.associated_item(
+ tcx.hir().local_def_id_from_hir_id(impl_item.hir_id));
let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id)
.find(|ac| Namespace::from(&impl_item.node) == Namespace::from(ac.kind) &&
tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id))
// For each field, figure out if it's known to be a ZST and align(1)
let field_infos = adt.non_enum_variant().fields.iter().map(|field| {
- let ty = field.ty(tcx, Substs::identity_for_item(tcx, field.did));
+ let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did));
let param_env = tcx.param_env(field.did);
let layout = tcx.layout_of(param_env.and(ty));
// We are currently checking the type this field came from, so it must be local
for v in vs {
if let Some(ref e) = v.node.disr_expr {
- tcx.typeck_tables_of(tcx.hir().local_def_id(e.id));
+ tcx.typeck_tables_of(tcx.hir().local_def_id_from_hir_id(e.hir_id));
}
}
format!("{:?}", self_ptr)
}
- pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> LocalTy<'tcx> {
+ pub fn local_ty(&self, span: Span, nid: hir::HirId) -> LocalTy<'tcx> {
self.locals.borrow().get(&nid).cloned().unwrap_or_else(||
span_bug!(span, "no type for local variable {}",
- self.tcx.hir().node_to_string(nid))
+ self.tcx.hir().hir_to_string(nid))
)
}
if !method_generics.params.is_empty() {
let user_type_annotation = self.infcx.probe(|_| {
let user_substs = UserSubsts {
- substs: Substs::for_item(self.tcx, method.def_id, |param, _| {
+ substs: InternalSubsts::for_item(self.tcx, method.def_id, |param, _| {
let i = param.index as usize;
if i < method_generics.parent_count {
self.infcx.var_for_def(DUMMY_SP, param)
}
}
- pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
+ pub fn write_substs(&self, node_id: hir::HirId, substs: SubstsRef<'tcx>) {
if !substs.is_noop() {
debug!("write_substs({:?}, {:?}) in fcx {}",
node_id,
&self,
hir_id: hir::HirId,
def_id: DefId,
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
user_self_ty: Option<UserSelfTy<'tcx>>,
) {
debug!(
/// types as well. This function combines the two.
fn instantiate_type_scheme<T>(&self,
span: Span,
- substs: &Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
value: &T)
-> T
where T : TypeFoldable<'tcx>
/// As `instantiate_type_scheme`, but for the bounds found in a
/// generic type scheme.
- fn instantiate_bounds(&self, span: Span, def_id: DefId, substs: &Substs<'tcx>)
+ fn instantiate_bounds(&self, span: Span, def_id: DefId, substs: SubstsRef<'tcx>)
-> ty::InstantiatedPredicates<'tcx> {
let bounds = self.tcx.predicates_of(def_id);
let result = bounds.instantiate(self.tcx, substs);
}
/// Registers obligations that all types appearing in `substs` are well-formed.
- pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr) {
+ pub fn add_wf_bounds(&self, substs: SubstsRef<'tcx>, expr: &hir::Expr) {
for ty in substs.types() {
self.register_wf_obligation(ty, expr.span, traits::MiscObligation);
}
pub fn field_ty(&self,
span: Span,
field: &'tcx ty::FieldDef,
- substs: &Substs<'tcx>)
+ substs: SubstsRef<'tcx>)
-> Ty<'tcx>
{
self.normalize_associated_types_in(span, &field.ty(self.tcx, substs))
&method.sig.inputs()[1..]
);
self.check_argument_types(sp, expr_sp, &method.sig.inputs()[1..], &expected_arg_tys[..],
- args_no_rcvr, method.sig.variadic, tuple_arguments,
+ args_no_rcvr, method.sig.c_variadic, tuple_arguments,
self.tcx.hir().span_if_local(method.def_id));
method.sig.output()
}
fn_inputs: &[Ty<'tcx>],
mut expected_arg_tys: &[Ty<'tcx>],
args: &'gcx [hir::Expr],
- variadic: bool,
+ c_variadic: bool,
tuple_arguments: TupleArgumentsFlag,
def_span: Option<Span>) {
let tcx = self.tcx;
let param_count_error = |expected_count: usize,
arg_count: usize,
error_code: &str,
- variadic: bool,
+ c_variadic: bool,
sugg_unit: bool| {
let mut err = tcx.sess.struct_span_err_with_code(sp,
&format!("this function takes {}{} but {} {} supplied",
- if variadic {"at least "} else {""},
+ if c_variadic { "at least " } else { "" },
potentially_plural_count(expected_count, "parameter"),
potentially_plural_count(arg_count, "parameter"),
if arg_count == 1 {"was"} else {"were"}),
Applicability::MachineApplicable);
} else {
err.span_label(sp, format!("expected {}{}",
- if variadic {"at least "} else {""},
+ if c_variadic { "at least " } else { "" },
potentially_plural_count(expected_count, "parameter")));
}
err.emit();
}
} else if expected_arg_count == supplied_arg_count {
fn_inputs.to_vec()
- } else if variadic {
+ } else if c_variadic {
if supplied_arg_count >= expected_arg_count {
fn_inputs.to_vec()
} else {
self.select_obligations_where_possible(false);
}
- // For variadic functions, we don't have a declared type for all of
+ // For C-variadic functions, we don't have a declared type for all of
// the arguments hence we only do our usual type checking with
// the arguments who's types we do know.
- let t = if variadic {
+ let t = if c_variadic {
expected_arg_count
} else if tuple_arguments == TupleArguments {
args.len()
// We also need to make sure we at least write the ty of the other
// arguments which we skipped above.
- if variadic {
+ if c_variadic {
fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) {
use crate::structured_errors::{VariadicError, StructuredDiagnostic};
VariadicError::new(s, span, t, cast_ty).diagnostic().emit();
tcx.mk_array(element_ty, args.len() as u64)
}
ExprKind::Repeat(ref element, ref count) => {
- let count_def_id = tcx.hir().local_def_id(count.id);
+ let count_def_id = tcx.hir().local_def_id_from_hir_id(count.hir_id);
let param_env = ty::ParamEnv::empty();
- let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
+ let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
let instance = ty::Instance::resolve(
tcx.global_tcx(),
param_env,
// See #44848.
let ref_bindings = local.pat.contains_explicit_ref_binding();
- let local_ty = self.local_ty(init.span, local.id).revealed_ty;
+ let local_ty = self.local_ty(init.span, local.hir_id).revealed_ty;
if let Some(m) = ref_bindings {
// Somewhat subtle: if we have a `ref` binding in the pattern,
// we want to avoid introducing coercions for the RHS. This is
}
pub fn check_decl_local(&self, local: &'gcx hir::Local) {
- let t = self.local_ty(local.span, local.id).decl_ty;
+ let t = self.local_ty(local.span, local.hir_id).decl_ty;
self.write_ty(local.hir_id, t);
if let Some(ref init) = local.init {
match def {
Def::Local(nid) | Def::Upvar(nid, ..) => {
- let ty = self.local_ty(span, nid).decl_ty;
+ let hid = self.tcx.hir().node_to_hir_id(nid);
+ let ty = self.local_ty(span, hid).decl_ty;
let ty = self.normalize_associated_types_in(span, &ty);
self.write_ty(hir_id, ty);
return (ty, def);
use rustc::infer::outlives::env::OutlivesEnvironment;
use rustc::infer::{self, RegionObligation, SuppressRegionErrors};
use rustc::ty::adjustment;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty};
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
fn substs_wf_in_scope(
&mut self,
origin: infer::ParameterOrigin,
- substs: &Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
expr_span: Span,
expr_region: ty::Region<'tcx>,
) {
use crate::hir::def_id::DefId;
use rustc::traits::{self, ObligationCauseCode};
use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable, ToPredicate};
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc::middle::lang_items;
use rustc::infer::opaque_types::may_define_existential_type;
check_item_fn(tcx, item);
}
hir::ItemKind::Static(ref ty, ..) => {
- check_item_type(tcx, item.id, ty.span, false);
+ check_item_type(tcx, item.hir_id, ty.span, false);
}
hir::ItemKind::Const(ref ty, ..) => {
- check_item_type(tcx, item.id, ty.span, false);
+ check_item_type(tcx, item.hir_id, ty.span, false);
}
hir::ItemKind::ForeignMod(ref module) => for it in module.items.iter() {
if let hir::ForeignItemKind::Static(ref ty, ..) = it.node {
- check_item_type(tcx, it.id, ty.span, true);
+ check_item_type(tcx, it.hir_id, ty.span, true);
}
},
hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
hir::TraitItemKind::Method(ref sig, _) => Some(sig),
_ => None
};
- check_associated_item(tcx, trait_item.id, trait_item.span, method_sig);
+ check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig);
}
pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
hir::ImplItemKind::Method(ref sig, _) => Some(sig),
_ => None
};
- check_associated_item(tcx, impl_item.id, impl_item.span, method_sig);
+ check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig);
}
fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- item_id: ast::NodeId,
+ item_id: hir::HirId,
span: Span,
sig_if_method: Option<&hir::MethodSig>) {
debug!("check_associated_item: {:?}", item_id);
let code = ObligationCauseCode::MiscObligation;
for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
- let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
+ let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id_from_hir_id(item_id));
let (mut implied_bounds, self_ty) = match item.container {
ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item)
-> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
- for_id(tcx, item.id, item.span)
+ for_id(tcx, item.hir_id, item.span)
}
-fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span)
+fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: hir::HirId, span: Span)
-> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
- let def_id = tcx.hir().local_def_id(id);
- let hir_id = tcx.hir().node_to_hir_id(id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(id);
CheckWfFcxBuilder {
inherited: Inherited::build(tcx, def_id),
- id: hir_id,
+ id,
span,
param_env: tcx.param_env(def_id),
}
fn check_item_type<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- item_id: ast::NodeId,
+ item_id: hir::HirId,
ty_span: Span,
allow_foreign_ty: bool,
) {
debug!("check_item_type: {:?}", item_id);
for_id(tcx, item_id, ty_span).with_fcx(|fcx, gcx| {
- let ty = gcx.type_of(gcx.hir().local_def_id(item_id));
+ let ty = gcx.type_of(gcx.hir().local_def_id_from_hir_id(item_id));
let item_ty = fcx.normalize_associated_types_in(ty_span, &ty);
let mut forbid_unsized = true;
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
//
// First we build the defaulted substitution.
- let substs = Substs::for_item(fcx.tcx, def_id, |param, _| {
+ let substs = InternalSubsts::for_item(fcx.tcx, def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
// All regions are identity.
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
debug!("visit_trait_item: {:?}", trait_item);
- let def_id = self.tcx.hir().local_def_id(trait_item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(trait_item.hir_id);
self.tcx.ensure().check_trait_item_well_formed(def_id);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
debug!("visit_impl_item: {:?}", impl_item);
- let def_id = self.tcx.hir().local_def_id(impl_item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(impl_item.hir_id);
self.tcx.ensure().check_impl_item_well_formed(def_id);
}
}
fn visit_local(&mut self, l: &'gcx hir::Local) {
intravisit::walk_local(self, l);
- let var_ty = self.fcx.local_ty(l.span, l.id).decl_ty;
+ let var_ty = self.fcx.local_ty(l.span, l.hir_id).decl_ty;
let var_ty = self.resolve(&var_ty, &l.span);
self.write_ty_to_tables(l.hir_id, var_ty);
}
return;
}
if let hir::ItemKind::Use(ref path, _) = item.node {
- self.check_import(item.id, path.span);
+ self.check_import(item.hir_id, path.span);
}
}
}
impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
- fn check_import(&self, id: ast::NodeId, span: Span) {
- let def_id = self.tcx.hir().local_def_id(id);
+ fn check_import(&self, id: hir::HirId, span: Span) {
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(id);
if !self.tcx.maybe_unused_trait_import(def_id) {
return;
}
- let import_def_id = self.tcx.hir().local_def_id(id);
- if self.used_trait_imports.contains(&import_def_id) {
+ if self.used_trait_imports.contains(&def_id) {
return;
}
} else {
"unused import".to_owned()
};
- self.tcx.lint_node(lint::builtin::UNUSED_IMPORTS, id, span, &msg);
+ self.tcx.lint_hir(lint::builtin::UNUSED_IMPORTS, id, span, &msg);
}
}
});
for extern_crate in &crates_to_lint {
- let id = tcx.hir().as_local_node_id(extern_crate.def_id).unwrap();
- let item = tcx.hir().expect_item(id);
+ let id = tcx.hir().as_local_hir_id(extern_crate.def_id).unwrap();
+ let item = tcx.hir().expect_item_by_hir_id(id);
// If the crate is fully unused, we suggest removing it altogether.
// We do this in any edition.
.map(|attr| attr.span)
.fold(span, |acc, attr_span| acc.to(attr_span));
- tcx.struct_span_lint_node(lint, id, span, msg)
+ tcx.struct_span_lint_hir(lint, id, span, msg)
.span_suggestion_short(
span_with_attrs,
"remove it",
None => format!("use {};", item.ident.name),
};
let replacement = visibility_qualified(&item.vis, base_replacement);
- tcx.struct_span_lint_node(lint, id, extern_crate.span, msg)
+ tcx.struct_span_lint_hir(lint, id, extern_crate.span, msg)
.span_suggestion_short(
extern_crate.span,
&help,
for &item2 in &impl_items2[..] {
if (name, namespace) == name_and_namespace(item2) {
- let node_id = self.tcx.hir().as_local_node_id(impl1);
- let mut err = if used_to_be_allowed && node_id.is_some() {
- self.tcx.struct_span_lint_node(
+ let hir_id = self.tcx.hir().as_local_hir_id(impl1);
+ let mut err = if used_to_be_allowed && hir_id.is_some() {
+ self.tcx.struct_span_lint_hir(
lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
- node_id.unwrap(),
+ hir_id.unwrap(),
self.tcx.span_of_impl(item1).unwrap(),
&format!("duplicate definitions with name `{}` (E0592)", name)
)
use crate::middle::weak_lang_items;
use rustc::mir::mono::Linkage;
use rustc::ty::query::Providers;
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::ty::util::Discr;
use rustc::ty::util::IntTypeExt;
use rustc::ty::subst::UnpackedKind;
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
- convert_trait_item(self.tcx, trait_item.id);
+ convert_trait_item(self.tcx, trait_item.hir_id);
intravisit::walk_trait_item(self, trait_item);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
- convert_impl_item(self.tcx, impl_item.id);
+ convert_impl_item(self.tcx, impl_item.hir_id);
intravisit::walk_impl_item(self, impl_item);
}
}
}
}
-fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast::NodeId) {
- let trait_item = tcx.hir().expect_trait_item(trait_item_id);
- let def_id = tcx.hir().local_def_id(trait_item.id);
+fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: hir::HirId) {
+ let trait_item = tcx.hir().expect_trait_item_by_hir_id(trait_item_id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(trait_item.hir_id);
tcx.generics_of(def_id);
match trait_item.node {
tcx.predicates_of(def_id);
}
-fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::NodeId) {
- let def_id = tcx.hir().local_def_id(impl_item_id);
+fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: hir::HirId) {
+ let def_id = tcx.hir().local_def_id_from_hir_id(impl_item_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
- if let hir::ImplItemKind::Method(..) = tcx.hir().expect_impl_item(impl_item_id).node {
+ if let hir::ImplItemKind::Method(..) = tcx.hir().expect_impl_item_by_hir_id(impl_item_id).node {
tcx.fn_sig(def_id);
}
}
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
prev_discr = Some(
if let Some(ref e) = variant.node.disr_expr {
- let expr_did = tcx.hir().local_def_id(e.id);
+ let expr_did = tcx.hir().local_def_id_from_hir_id(e.hir_id);
def.eval_explicit_discr(tcx, expr_did)
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
Some(discr)
let did = tcx.hir().local_def_id(v.node.data.id());
let discr = if let Some(ref e) = v.node.disr_expr {
distance_from_explicit = 0;
- ty::VariantDiscr::Explicit(tcx.hir().local_def_id(e.id))
+ ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id))
} else {
ty::VariantDiscr::Relative(distance_from_explicit)
};
fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
use rustc::hir::*;
- let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
+ let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let icx = ItemCtxt::new(tcx, def_id);
- match tcx.hir().get(node_id) {
+ match tcx.hir().get_by_hir_id(hir_id) {
Node::TraitItem(item) => match item.node {
TraitItemKind::Method(..) => {
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id, substs)
}
TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
Node::ImplItem(item) => match item.node {
ImplItemKind::Method(..) => {
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id, substs)
}
ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
ImplItemKind::Existential(_) => {
if tcx
- .impl_trait_ref(tcx.hir().get_parent_did(node_id))
+ .impl_trait_ref(tcx.hir().get_parent_did_by_hir_id(hir_id))
.is_none()
{
report_assoc_ty_on_inherent_impl(tcx, item.span);
}
ImplItemKind::Type(ref ty) => {
if tcx
- .impl_trait_ref(tcx.hir().get_parent_did(node_id))
+ .impl_trait_ref(tcx.hir().get_parent_did_by_hir_id(hir_id))
.is_none()
{
report_assoc_ty_on_inherent_impl(tcx, item.span);
| ItemKind::Ty(ref t, _)
| ItemKind::Impl(.., ref t, _) => icx.to_ty(t),
ItemKind::Fn(..) => {
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id, substs)
}
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
let def = tcx.adt_def(def_id);
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_adt(def, substs)
}
ItemKind::Existential(hir::ExistTy {
Node::ForeignItem(foreign_item) => match foreign_item.node {
ForeignItemKind::Fn(..) => {
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id, substs)
}
ForeignItemKind::Static(ref t, _) => icx.to_ty(t),
..
}) => match *def {
VariantData::Unit(..) | VariantData::Struct(..) => {
- tcx.type_of(tcx.hir().get_parent_did(node_id))
+ tcx.type_of(tcx.hir().get_parent_did_by_hir_id(hir_id))
}
VariantData::Tuple(..) => {
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id, substs)
}
},
..
}) => {
if gen.is_some() {
- let hir_id = tcx.hir().node_to_hir_id(node_id);
return tcx.typeck_tables_of(def_id).node_type(hir_id);
}
let substs = ty::ClosureSubsts {
- substs: Substs::identity_for_item(tcx, def_id),
+ substs: InternalSubsts::identity_for_item(tcx, def_id),
};
tcx.mk_closure(def_id, substs)
}
- Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(node_id)) {
+ Node::AnonConst(_) => match tcx.hir().get_by_hir_id(
+ tcx.hir().get_parent_node_by_hir_id(hir_id))
+ {
Node::Ty(&hir::Ty {
node: hir::TyKind::Array(_, ref constant),
..
| Node::Expr(&hir::Expr {
node: ExprKind::Repeat(_, ref constant),
..
- }) if constant.id == node_id =>
+ }) if constant.hir_id == hir_id =>
{
tcx.types.usize
}
..
},
..
- }) if e.id == node_id =>
+ }) if e.hir_id == hir_id =>
{
- tcx.adt_def(tcx.hir().get_parent_did(node_id))
+ tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id))
.repr
.discr_type()
.to_ty(tcx)
}
}
fn visit_impl_item(&mut self, it: &'tcx ImplItem) {
- let def_id = self.tcx.hir().local_def_id(it.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
// the existential type itself or its children are not within its reveal scope
if def_id != self.def_id {
self.check(def_id);
}
}
fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
- let def_id = self.tcx.hir().local_def_id(it.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
self.check(def_id);
intravisit::walk_trait_item(self, it);
}
Node::ImplItem(item) => match item.node {
ImplItemKind::Existential(ref bounds) => {
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
let opaque_ty = tcx.mk_opaque(def_id, substs);
// Collect the bounds, i.e., the `A+B+'c` in `impl A+B+'c`.
impl_trait_fn,
ref generics,
}) => {
- let substs = Substs::identity_for_item(tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
let opaque_ty = tcx.mk_opaque(def_id, substs);
// Collect the bounds, i.e., the `A+B+'c` in `impl A+B+'c`.
};
let assoc_ty =
- tcx.mk_projection(tcx.hir().local_def_id(trait_item.id), self_trait_ref.substs);
+ tcx.mk_projection(tcx.hir().local_def_id_from_hir_id(trait_item.hir_id),
+ self_trait_ref.substs);
let bounds = compute_bounds(
&ItemCtxt::new(tcx, def_id),
use rustc::lint;
use rustc::middle;
use rustc::session;
-use rustc::session::CompileIncomplete;
+use rustc::util::common::ErrorReported;
use rustc::session::config::{EntryFnType, nightly_options};
use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::query::Providers;
use rustc::util;
use std::iter;
pub struct TypeAndSubsts<'tcx> {
- substs: &'tcx Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
ty: Ty<'tcx>,
}
}
}
-fn require_c_abi_if_variadic(tcx: TyCtxt<'_, '_, '_>,
- decl: &hir::FnDecl,
- abi: Abi,
- span: Span) {
- if decl.variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
+fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_, '_, '_>,
+ decl: &hir::FnDecl,
+ abi: Abi,
+ span: Span) {
+ if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
let mut err = struct_span_err!(tcx.sess, span, E0045,
- "variadic function must have C or cdecl calling convention");
- err.span_label(span, "variadics require C or cdecl calling convention").emit();
+ "C-variadic function must have C or cdecl calling convention");
+ err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
}
}
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> Result<(), CompileIncomplete>
+ -> Result<(), ErrorReported>
{
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::TypeChecking));
tcx.sess.track_errors(|| {
time(tcx.sess, "type collecting", ||
collect::collect_item_types(tcx));
-
})?;
if tcx.features().rustc_attrs {
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::TypeChecking));
- tcx.sess.compile_status()
+ if tcx.sess.err_count() == 0 {
+ Ok(())
+ } else {
+ Err(ErrorReported)
+ }
}
/// A quasi-deprecated helper used in rustdoc and save-analysis to get
// In case there are any projections etc, find the "environment"
// def-id that will be used to determine the traits/predicates in
// scope. This is derived from the enclosing item-like thing.
- let env_node_id = tcx.hir().get_parent(hir_trait.ref_id);
- let env_def_id = tcx.hir().local_def_id(env_node_id);
+ let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
+ let env_def_id = tcx.hir().local_def_id_from_hir_id(env_hir_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
let mut projections = Vec::new();
let (principal, _) = astconv::AstConv::instantiate_poly_trait_ref_inner(
//! We walk the set of items and, for each member, generate new constraints.
use hir::def_id::DefId;
-use rustc::ty::subst::{Substs, UnpackedKind};
+use rustc::ty::subst::{UnpackedKind, SubstsRef};
use rustc::ty::{self, Ty, TyCtxt};
-use syntax::ast;
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
match item.node {
hir::ItemKind::Struct(ref struct_def, _) |
hir::ItemKind::Union(ref struct_def, _) => {
- self.visit_node_helper(item.id);
+ self.visit_node_helper(item.hir_id);
if let hir::VariantData::Tuple(..) = *struct_def {
- self.visit_node_helper(struct_def.id());
+ self.visit_node_helper(struct_def.hir_id());
}
}
hir::ItemKind::Enum(ref enum_def, _) => {
- self.visit_node_helper(item.id);
+ self.visit_node_helper(item.hir_id);
for variant in &enum_def.variants {
if let hir::VariantData::Tuple(..) = variant.node.data {
- self.visit_node_helper(variant.node.data.id());
+ self.visit_node_helper(variant.node.data.hir_id());
}
}
}
hir::ItemKind::Fn(..) => {
- self.visit_node_helper(item.id);
+ self.visit_node_helper(item.hir_id);
}
hir::ItemKind::ForeignMod(ref foreign_mod) => {
for foreign_item in &foreign_mod.items {
if let hir::ForeignItemKind::Fn(..) = foreign_item.node {
- self.visit_node_helper(foreign_item.id);
+ self.visit_node_helper(foreign_item.hir_id);
}
}
}
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
if let hir::TraitItemKind::Method(..) = trait_item.node {
- self.visit_node_helper(trait_item.id);
+ self.visit_node_helper(trait_item.hir_id);
}
}
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
if let hir::ImplItemKind::Method(..) = impl_item.node {
- self.visit_node_helper(impl_item.id);
+ self.visit_node_helper(impl_item.hir_id);
}
}
}
impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
- fn visit_node_helper(&mut self, id: ast::NodeId) {
+ fn visit_node_helper(&mut self, id: hir::HirId) {
let tcx = self.terms_cx.tcx;
- let def_id = tcx.hir().local_def_id(id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(id);
self.build_constraints_for_item(def_id);
}
return;
}
- let id = tcx.hir().as_local_node_id(def_id).unwrap();
+ let id = tcx.hir().as_local_hir_id(def_id).unwrap();
let inferred_start = self.terms_cx.inferred_starts[&id];
let current_item = &CurrentItem { inferred_start };
match tcx.type_of(def_id).sty {
fn add_constraints_from_invariant_substs(&mut self,
current: &CurrentItem,
- substs: &Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_invariant_substs: substs={:?} variance={:?}",
substs,
fn add_constraints_from_substs(&mut self,
current: &CurrentItem,
def_id: DefId,
- substs: &Substs<'tcx>,
+ substs: SubstsRef<'tcx>,
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
def_id,
return;
}
- let (local, remote) = if let Some(id) = self.tcx().hir().as_local_node_id(def_id) {
+ let (local, remote) = if let Some(id) = self.tcx().hir().as_local_hir_id(def_id) {
(Some(self.terms_cx.inferred_starts[&id]), None)
} else {
(None, Some(self.tcx().variances_of(def_id)))
let solutions = &self.solutions;
self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
- let def_id = tcx.hir().local_def_id(id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(id);
let generics = tcx.generics_of(def_id);
let mut variances = solutions[start..start+generics.count()].to_vec();
use arena::TypedArena;
use rustc::ty::{self, TyCtxt};
use std::fmt;
-use syntax::ast;
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use crate::util::nodemap::NodeMap;
+use crate::util::nodemap::HirIdMap;
use self::VarianceTerm::*;
// For marker types, UnsafeCell, and other lang items where
// variance is hardcoded, records the item-id and the hardcoded
// variance.
- pub lang_items: Vec<(ast::NodeId, Vec<ty::Variance>)>,
+ pub lang_items: Vec<(hir::HirId, Vec<ty::Variance>)>,
// Maps from the node id of an item to the first inferred index
// used for its type & region parameters.
- pub inferred_starts: NodeMap<InferredIndex>,
+ pub inferred_starts: HirIdMap<InferredIndex>,
// Maps from an InferredIndex to the term for that variable.
pub inferred_terms: Vec<VarianceTermPtr<'a>>,
terms_cx
}
-fn lang_items(tcx: TyCtxt<'_, '_, '_>) -> Vec<(ast::NodeId, Vec<ty::Variance>)> {
+fn lang_items(tcx: TyCtxt<'_, '_, '_>) -> Vec<(hir::HirId, Vec<ty::Variance>)> {
let lang_items = tcx.lang_items();
let all = vec![
(lang_items.phantom_data(), vec![ty::Covariant]),
all.into_iter() // iterating over (Option<DefId>, Variance)
.filter(|&(ref d,_)| d.is_some())
.map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance)
- .filter_map(|(d, v)| tcx.hir().as_local_node_id(d).map(|n| (n, v))) // (NodeId, Variance)
+ .filter_map(|(d, v)| tcx.hir().as_local_hir_id(d).map(|n| (n, v))) // (HirId, Variance)
.collect()
}
impl<'a, 'tcx> TermsContext<'a, 'tcx> {
- fn add_inferreds_for_item(&mut self, id: ast::NodeId) {
+ fn add_inferreds_for_item(&mut self, id: hir::HirId) {
let tcx = self.tcx;
- let def_id = tcx.hir().local_def_id(id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(id);
let count = tcx.generics_of(def_id).count();
if count == 0 {
match item.node {
hir::ItemKind::Struct(ref struct_def, _) |
hir::ItemKind::Union(ref struct_def, _) => {
- self.add_inferreds_for_item(item.id);
+ self.add_inferreds_for_item(item.hir_id);
if let hir::VariantData::Tuple(..) = *struct_def {
- self.add_inferreds_for_item(struct_def.id());
+ self.add_inferreds_for_item(struct_def.hir_id());
}
}
hir::ItemKind::Enum(ref enum_def, _) => {
- self.add_inferreds_for_item(item.id);
+ self.add_inferreds_for_item(item.hir_id);
for variant in &enum_def.variants {
if let hir::VariantData::Tuple(..) = variant.node.data {
- self.add_inferreds_for_item(variant.node.data.id());
+ self.add_inferreds_for_item(variant.node.data.hir_id());
}
}
}
hir::ItemKind::Fn(..) => {
- self.add_inferreds_for_item(item.id);
+ self.add_inferreds_for_item(item.hir_id);
}
hir::ItemKind::ForeignMod(ref foreign_mod) => {
for foreign_item in &foreign_mod.items {
if let hir::ForeignItemKind::Fn(..) = foreign_item.node {
- self.add_inferreds_for_item(foreign_item.id);
+ self.add_inferreds_for_item(foreign_item.hir_id);
}
}
}
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
if let hir::TraitItemKind::Method(..) = trait_item.node {
- self.add_inferreds_for_item(trait_item.id);
+ self.add_inferreds_for_item(trait_item.hir_id);
}
}
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
if let hir::ImplItemKind::Method(..) = impl_item.node {
- self.add_inferreds_for_item(impl_item.id);
+ self.add_inferreds_for_item(impl_item.hir_id);
}
}
}
if result.is_auto() {
let trait_ = hir::TraitRef {
path: get_path_for_type(self.cx.tcx, trait_def_id, hir::def::Def::Trait),
- ref_id: ast::DUMMY_NODE_ID,
hir_ref_id: hir::DUMMY_HIR_ID,
};
path: get_path_for_type(infcx.tcx,
trait_def_id,
hir::def::Def::Trait),
- ref_id: ast::DUMMY_NODE_ID,
hir_ref_id: hir::DUMMY_HIR_ID,
};
let provided_trait_methods =
use rustc::hir::{self, GenericArg, HirVec};
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
use rustc::ty::fold::TypeFolder;
use rustc::ty::layout::VariantIdx;
}
fn external_generic_args(cx: &DocContext<'_, '_, '_>, trait_did: Option<DefId>, has_self: bool,
- bindings: Vec<TypeBinding>, substs: &Substs<'_>) -> GenericArgs {
+ bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> GenericArgs {
let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect();
let types = substs.types().skip(has_self as usize).collect::<Vec<_>>();
// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
// from Fn<(A, B,), C> to Fn(A, B) -> C
fn external_path(cx: &DocContext<'_, '_, '_>, name: &str, trait_did: Option<DefId>, has_self: bool,
- bindings: Vec<TypeBinding>, substs: &Substs<'_>) -> Path {
+ bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> Path {
Path {
global: false,
def: Def::Err,
}
}
-impl<'tcx> Clean<Option<Vec<GenericBound>>> for Substs<'tcx> {
+impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
fn clean(&self, cx: &DocContext<'_, '_, '_>) -> Option<Vec<GenericBound>> {
let mut v = Vec::new();
v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
pub struct FnDecl {
pub inputs: Arguments,
pub output: FunctionRetTy,
- pub variadic: bool,
pub attrs: Attributes,
}
FnDecl {
inputs: (&self.0.inputs[..], self.1).clean(cx),
output: self.0.output.clean(cx),
- variadic: self.0.variadic,
attrs: Attributes::default()
}
}
FnDecl {
output: Return(sig.skip_binder().output().clean(cx)),
attrs: Attributes::default(),
- variadic: sig.skip_binder().variadic,
inputs: Arguments {
values: sig.skip_binder().inputs().iter().map(|t| {
Argument {
AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
}
};
+ let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
Item {
name: Some(self.ident.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: local_did,
visibility: None,
- stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
- deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
+ stability: get_stability(cx, local_did),
+ deprecation: get_deprecation(cx, local_did),
inner,
}
}
generics: Generics::default(),
}, true),
};
+ let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
Item {
name: Some(self.ident.name.clean(cx)),
source: self.span.clean(cx),
attrs: self.attrs.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: local_did,
visibility: self.vis.clean(cx),
- stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
- deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
+ stability: get_stability(cx, local_did),
+ deprecation: get_deprecation(cx, local_did),
inner,
}
}
Slice(Box<Type>),
Array(Box<Type>, String),
Never,
+ CVarArgs,
Unique(Box<Type>),
RawPointer(Mutability, Box<Type>),
BorrowedRef {
Reference,
Fn,
Never,
+ CVarArgs,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
Reference => "reference",
Fn => "fn",
Never => "never",
+ CVarArgs => "...",
}
}
match self.node {
TyKind::Never => Never,
+ TyKind::CVarArgs(_) => CVarArgs,
TyKind::Ptr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
TyKind::Rptr(ref l, ref m) => {
let lifetime = if l.is_elided() {
}
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
TyKind::Array(ref ty, ref length) => {
- let def_id = cx.tcx.hir().local_def_id(length.id);
+ let def_id = cx.tcx.hir().local_def_id_from_hir_id(length.hir_id);
let param_env = cx.tcx.param_env(def_id);
- let substs = Substs::identity_for_item(cx.tcx, def_id);
+ let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
let cid = GlobalId {
instance: ty::Instance::new(def_id, substs),
promoted: None
ty::Foreign(did) => {
inline::record_extern_fqn(cx, did, TypeKind::Foreign);
let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
- None, false, vec![], Substs::empty());
+ None, false, vec![], InternalSubsts::empty());
ResolvedPath {
path: path,
typarams: None,
Reference => None,
Fn => None,
Never => None,
+ CVarArgs => tcx.lang_items().va_list(),
};
if let Some(did) = did {
if !did.is_local() {
if matches.opt_strs("passes") == ["list"] {
println!("Available passes for running rustdoc:");
for pass in passes::PASSES {
- println!("{:>20} - {}", pass.name(), pass.description());
+ println!("{:>20} - {}", pass.name, pass.description);
}
println!("\nDefault passes for rustdoc:");
for &name in passes::DEFAULT_PASSES {
use rustc_lint;
-use rustc_driver::{self, driver, target_features, abort_on_err};
+use rustc_driver::{driver, abort_on_err};
use rustc::session::{self, config};
use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CrateNum, LOCAL_CRATE};
use rustc::hir::def::Def;
use rustc::lint::{self, LintPass};
use rustc::session::config::ErrorOutputType;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
+use rustc_interface::util;
use rustc_resolve as resolve;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::CStore;
debugging_options.ui_testing);
let mut sess = session::build_session_(
- sessopts, cpath, diagnostic_handler, source_map,
+ sessopts, cpath, diagnostic_handler, source_map, Default::default(),
);
lint::builtin::HardwiredLints.get_lints()
lint::Allow);
});
- let codegen_backend = rustc_driver::get_codegen_backend(&sess);
+ let codegen_backend = util::get_codegen_backend(&sess);
let cstore = Rc::new(CStore::new(codegen_backend.metadata_loader()));
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
- target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
+ util::add_configuration(&mut cfg, &sess, &*codegen_backend);
sess.parse_sess.config = cfg;
let control = &driver::CompileController::basic();
let mut arenas = AllArenas::new();
let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
- let output_filenames = driver::build_output_filenames(&input,
+ let output_filenames = util::build_output_filenames(&input,
&None,
&None,
&[],
&sess);
let resolver = RefCell::new(resolver);
- abort_on_err(driver::phase_3_run_analysis_passes(&*codegen_backend,
- control,
- &sess,
- &*cstore,
- hir_map,
- resolutions,
- &mut arenas,
- &name,
- &output_filenames,
- |tcx, _, result| {
+ driver::phase_3_run_analysis_passes(&*codegen_backend,
+ control,
+ &sess,
+ &*cstore,
+ hir_map,
+ resolutions,
+ &mut arenas,
+ &name,
+ &output_filenames,
+ |tcx, _, result| {
if result.is_err() {
sess.fatal("Compilation failed, aborting rustdoc");
}
passes::defaults(default_passes).iter().map(|p| p.to_string()).collect();
passes.extend(manual_passes);
+ info!("Executing passes");
+
for pass in &passes {
- // the "unknown pass" error will be reported when late passes are run
- if let Some(pass) = passes::find_pass(pass).and_then(|p| p.early_fn()) {
- krate = pass(krate, &ctxt);
+ match passes::find_pass(pass).map(|p| p.pass) {
+ Some(pass) => krate = pass(krate, &ctxt),
+ None => error!("unknown pass {}, skipping", *pass),
}
}
ctxt.sess().abort_if_errors();
(krate, ctxt.renderinfo.into_inner(), render_options, passes)
- }), &sess)
+ })
})
}
primitive_link(f, PrimitiveType::Array, &format!("; {}]", n))
}
clean::Never => primitive_link(f, PrimitiveType::Never, "!"),
+ clean::CVarArgs => primitive_link(f, PrimitiveType::CVarArgs, "..."),
clean::RawPointer(m, ref t) => {
match **t {
clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {
impl fmt::Display for clean::FnDecl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- if self.variadic {
- if f.alternate() {
- write!(f, "({args:#}, ...){arrow:#}", args = self.inputs, arrow = self.output)
- } else {
- write!(f, "({args}, ...){arrow}", args = self.inputs, arrow = self.output)
- }
+ if f.alternate() {
+ write!(f, "({args:#}){arrow:#}", args = self.inputs, arrow = self.output)
} else {
- if f.alternate() {
- write!(f, "({args:#}){arrow:#}", args = self.inputs, arrow = self.output)
- } else {
- write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output)
- }
+ write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output)
}
}
}
}
}
- let mut args_plain = format!("({})", args_plain);
-
- if decl.variadic {
- args.push_str(",<br> ...");
- args_plain.push_str(", ...");
- }
+ let args_plain = format!("({})", args_plain);
let output = if let hir::IsAsync::Async = asyncness {
Cow::Owned(decl.sugared_async_return_type())
extern crate rustc_metadata;
extern crate rustc_target;
extern crate rustc_typeck;
+extern crate rustc_interface;
extern crate serialize;
extern crate syntax;
extern crate syntax_pos;
krate.version = crate_version;
- info!("Executing passes");
-
- for pass in &passes {
- // determine if we know about this pass
- let pass = match passes::find_pass(pass) {
- Some(pass) => if let Some(pass) = pass.late_fn() {
- pass
- } else {
- // not a late pass, but still valid so don't report the error
- continue
- }
- None => {
- error!("unknown pass {}, skipping", *pass);
-
- continue
- },
- };
-
- // run it
- krate = pass(krate);
- }
-
tx.send(f(Output {
krate: krate,
renderinfo: renderinfo,
use crate::html::markdown::{self, RustCodeBlock};
use crate::passes::Pass;
-pub const CHECK_CODE_BLOCK_SYNTAX: Pass =
- Pass::early("check-code-block-syntax", check_code_block_syntax,
- "validates syntax inside Rust code blocks");
+pub const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
+ name: "check-code-block-syntax",
+ pass: check_code_block_syntax,
+ description: "validates syntax inside Rust code blocks",
+};
pub fn check_code_block_syntax(krate: clean::Crate, cx: &DocContext<'_, '_, '_>) -> clean::Crate {
SyntaxChecker { cx }.fold_crate(krate)
use crate::clean::{self, DocFragment, Item};
+use crate::core::DocContext;
use crate::fold;
use crate::fold::{DocFolder};
use crate::passes::Pass;
use std::mem::replace;
-pub const COLLAPSE_DOCS: Pass =
- Pass::late("collapse-docs", collapse_docs,
- "concatenates all document attributes into one document attribute");
+pub const COLLAPSE_DOCS: Pass = Pass {
+ name: "collapse-docs",
+ pass: collapse_docs,
+ description: "concatenates all document attributes into one document attribute",
+};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum DocFragmentKind {
}
}
-pub fn collapse_docs(krate: clean::Crate) -> clean::Crate {
+pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
Collapser.fold_crate(krate)
}
use super::span_of_attrs;
-pub const COLLECT_INTRA_DOC_LINKS: Pass =
- Pass::early("collect-intra-doc-links", collect_intra_doc_links,
- "reads a crate's documentation to resolve intra-doc-links");
+pub const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
+ name: "collect-intra-doc-links",
+ pass: collect_intra_doc_links,
+ description: "reads a crate's documentation to resolve intra-doc-links",
+};
pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_, '_, '_>) -> Crate {
if !UnstableFeatures::from_environment().is_nightly_build() {
) {
let sp = span_of_attrs(attrs);
- let mut diag = cx.tcx.struct_span_lint_node(
+ let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
- NodeId::from_u32(0),
+ hir::CRATE_HIR_ID,
sp,
&format!("`[{}]` cannot be resolved, ignoring it...", path_str),
);
use rustc::util::nodemap::FxHashSet;
use rustc::hir::def_id::DefId;
-pub const COLLECT_TRAIT_IMPLS: Pass =
- Pass::early("collect-trait-impls", collect_trait_impls,
- "retrieves trait impls for items in the crate");
+pub const COLLECT_TRAIT_IMPLS: Pass = Pass {
+ name: "collect-trait-impls",
+ pass: collect_trait_impls,
+ description: "retrieves trait impls for items in the crate",
+};
pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_, '_, '_>) -> Crate {
let mut synth = SyntheticImplCollector::new(cx);
//! Contains information about "passes", used to modify crate information during the documentation
//! process.
+use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::lint as lint;
use rustc::middle::privacy::AccessLevels;
use rustc::util::nodemap::DefIdSet;
use std::mem;
-use std::fmt;
-use syntax::ast::NodeId;
use syntax_pos::{DUMMY_SP, Span};
use std::ops::Range;
mod check_code_block_syntax;
pub use self::check_code_block_syntax::CHECK_CODE_BLOCK_SYNTAX;
-/// Represents a single pass.
+/// A single pass over the cleaned documentation.
+///
+/// Runs in the compiler context, so it has access to types and traits and the like.
#[derive(Copy, Clone)]
-pub enum Pass {
- /// An "early pass" is run in the compiler context, and can gather information about types and
- /// traits and the like.
- EarlyPass {
- name: &'static str,
- pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate,
- description: &'static str,
- },
- /// A "late pass" is run between crate cleaning and page generation.
- LatePass {
- name: &'static str,
- pass: fn(clean::Crate) -> clean::Crate,
- description: &'static str,
- },
-}
-
-impl fmt::Debug for Pass {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let mut dbg = match *self {
- Pass::EarlyPass { .. } => f.debug_struct("EarlyPass"),
- Pass::LatePass { .. } => f.debug_struct("LatePass"),
- };
-
- dbg.field("name", &self.name())
- .field("pass", &"...")
- .field("description", &self.description())
- .finish()
- }
-}
-
-impl Pass {
- /// Constructs a new early pass.
- pub const fn early(name: &'static str,
- pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate,
- description: &'static str) -> Pass {
- Pass::EarlyPass { name, pass, description }
- }
-
- /// Constructs a new late pass.
- pub const fn late(name: &'static str,
- pass: fn(clean::Crate) -> clean::Crate,
- description: &'static str) -> Pass {
- Pass::LatePass { name, pass, description }
- }
-
- /// Returns the name of this pass.
- pub fn name(self) -> &'static str {
- match self {
- Pass::EarlyPass { name, .. } |
- Pass::LatePass { name, .. } => name,
- }
- }
-
- /// Returns the description of this pass.
- pub fn description(self) -> &'static str {
- match self {
- Pass::EarlyPass { description, .. } |
- Pass::LatePass { description, .. } => description,
- }
- }
-
- /// If this pass is an early pass, returns the pointer to its function.
- pub fn early_fn(self) -> Option<fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate> {
- match self {
- Pass::EarlyPass { pass, .. } => Some(pass),
- _ => None,
- }
- }
-
- /// If this pass is a late pass, returns the pointer to its function.
- pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
- match self {
- Pass::LatePass { pass, .. } => Some(pass),
- _ => None,
- }
- }
+pub struct Pass {
+ pub name: &'static str,
+ pub pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate,
+ pub description: &'static str,
}
/// The full list of passes.
];
/// The list of passes run by default.
-pub const DEFAULT_PASSES: &'static [&'static str] = &[
+pub const DEFAULT_PASSES: &[&str] = &[
"collect-trait-impls",
+ "collapse-docs",
+ "unindent-comments",
"check-private-items-doc-tests",
"strip-hidden",
"strip-private",
"collect-intra-doc-links",
"check-code-block-syntax",
- "collapse-docs",
- "unindent-comments",
"propagate-doc-cfg",
];
/// The list of default passes run with `--document-private-items` is passed to rustdoc.
-pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[
+pub const DEFAULT_PRIVATE_PASSES: &[&str] = &[
"collect-trait-impls",
+ "collapse-docs",
+ "unindent-comments",
"check-private-items-doc-tests",
"strip-priv-imports",
"collect-intra-doc-links",
"check-code-block-syntax",
- "collapse-docs",
- "unindent-comments",
"propagate-doc-cfg",
];
}
/// If the given name matches a known pass, returns its information.
-pub fn find_pass(pass_name: &str) -> Option<Pass> {
- PASSES.iter().find(|p| p.name() == pass_name).cloned()
+pub fn find_pass(pass_name: &str) -> Option<&'static Pass> {
+ PASSES.iter().find(|p| p.name == pass_name)
}
struct Stripper<'a> {
if find_testable_code(&dox, &mut tests, ErrorCodes::No).is_ok() {
if check_missing_code == true && tests.found_tests == 0 {
- let mut diag = cx.tcx.struct_span_lint_node(
+ let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::MISSING_DOC_CODE_EXAMPLES,
- NodeId::from_u32(0),
+ hir::CRATE_HIR_ID,
span_of_attrs(&item.attrs),
"Missing code example in this documentation");
diag.emit();
} else if check_missing_code == false &&
tests.found_tests > 0 &&
!cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) {
- let mut diag = cx.tcx.struct_span_lint_node(
+ let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::PRIVATE_DOC_TESTS,
- NodeId::from_u32(0),
+ hir::CRATE_HIR_ID,
span_of_attrs(&item.attrs),
"Documentation test in private item");
diag.emit();
.span_to_snippet(span_of_attrs(attrs))
.ok()?;
- let starting_line = markdown[..md_range.start].lines().count() - 1;
- let ending_line = markdown[..md_range.end].lines().count() - 1;
+ let starting_line = markdown[..md_range.start].matches('\n').count();
+ let ending_line = starting_line + markdown[md_range.start..md_range.end].matches('\n').count();
- // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we only
- // we can treat CRLF and LF line endings the same way.
+ // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we treat
+ // CRLF and LF line endings the same way.
let mut src_lines = snippet.split_terminator('\n');
let md_lines = markdown.split_terminator('\n');
use crate::fold::DocFolder;
use crate::passes::{look_for_tests, Pass};
-
-pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass =
- Pass::early("check-private-items-doc-tests", check_private_items_doc_tests,
- "check private items doc tests");
+pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
+ name: "check-private-items-doc-tests",
+ pass: check_private_items_doc_tests,
+ description: "check private items doc tests",
+};
struct PrivateItemDocTestLinter<'a, 'tcx: 'a, 'rcx: 'a> {
cx: &'a DocContext<'a, 'tcx, 'rcx>,
use crate::clean::{Crate, Item};
use crate::clean::cfg::Cfg;
+use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::passes::Pass;
-pub const PROPAGATE_DOC_CFG: Pass =
- Pass::late("propagate-doc-cfg", propagate_doc_cfg,
- "propagates `#[doc(cfg(...))]` to child items");
+pub const PROPAGATE_DOC_CFG: Pass = Pass {
+ name: "propagate-doc-cfg",
+ pass: propagate_doc_cfg,
+ description: "propagates `#[doc(cfg(...))]` to child items",
+};
-pub fn propagate_doc_cfg(cr: Crate) -> Crate {
+pub fn propagate_doc_cfg(cr: Crate, _: &DocContext<'_, '_, '_>) -> Crate {
CfgPropagator { parent_cfg: None }.fold_crate(cr)
}
use crate::fold::{DocFolder, StripItem};
use crate::passes::{ImplStripper, Pass};
-pub const STRIP_HIDDEN: Pass =
- Pass::early("strip-hidden", strip_hidden,
- "strips all doc(hidden) items from the output");
+pub const STRIP_HIDDEN: Pass = Pass {
+ name: "strip-hidden",
+ pass: strip_hidden,
+ description: "strips all doc(hidden) items from the output",
+};
/// Strip items marked `#[doc(hidden)]`
pub fn strip_hidden(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
use crate::core::DocContext;
use crate::passes::{ImportStripper, Pass};
-pub const STRIP_PRIV_IMPORTS: Pass = Pass::early("strip-priv-imports", strip_priv_imports,
- "strips all private import statements (`use`, `extern crate`) from a crate");
+pub const STRIP_PRIV_IMPORTS: Pass = Pass {
+ name: "strip-priv-imports",
+ pass: strip_priv_imports,
+ description: "strips all private import statements (`use`, `extern crate`) from a crate",
+};
pub fn strip_priv_imports(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
ImportStripper.fold_crate(krate)
use crate::core::DocContext;
use crate::passes::{ImplStripper, ImportStripper, Stripper, Pass};
-pub const STRIP_PRIVATE: Pass =
- Pass::early("strip-private", strip_private,
- "strips all private items from a crate which cannot be seen externally, \
- implies strip-priv-imports");
+pub const STRIP_PRIVATE: Pass = Pass {
+ name: "strip-private",
+ pass: strip_private,
+ description: "strips all private items from a crate which cannot be seen externally, \
+ implies strip-priv-imports",
+};
/// Strip private items from the point of view of a crate or externally from a
/// crate, specified by the `xcrate` flag.
use std::usize;
use crate::clean::{self, DocFragment, Item};
+use crate::core::DocContext;
use crate::fold::{self, DocFolder};
use crate::passes::Pass;
-pub const UNINDENT_COMMENTS: Pass =
- Pass::late("unindent-comments", unindent_comments,
- "removes excess indentation on comments in order for markdown to like it");
+pub const UNINDENT_COMMENTS: Pass = Pass {
+ name: "unindent-comments",
+ pass: unindent_comments,
+ description: "removes excess indentation on comments in order for markdown to like it",
+};
-pub fn unindent_comments(krate: clean::Crate) -> clean::Crate {
+pub fn unindent_comments(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
CommentCleaner.fold_crate(krate)
}
use errors::emitter::ColorConfig;
use rustc_data_structures::sync::Lrc;
use rustc_lint;
-use rustc_driver::{self, driver, target_features, Compilation};
+use rustc_driver::{self, driver, Compilation};
use rustc_driver::driver::phase_2_configure_and_expand;
use rustc_metadata::cstore::CStore;
+use rustc_interface::util;
use rustc::hir;
use rustc::hir::intravisit;
use rustc::session::{self, CompileIncomplete, config};
Some(source_map.clone()));
let mut sess = session::build_session_(
- sessopts, Some(options.input), handler, source_map.clone(),
+ sessopts, Some(options.input), handler, source_map.clone(), Default::default(),
);
- let codegen_backend = rustc_driver::get_codegen_backend(&sess);
+ let codegen_backend = util::get_codegen_backend(&sess);
let cstore = CStore::new(codegen_backend.metadata_loader());
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess,
config::parse_cfgspecs(options.cfgs.clone()));
- target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
+ util::add_configuration(&mut cfg, &sess, &*codegen_backend);
sess.parse_sess.config = cfg;
let krate =
let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
let mut sess = session::build_session_(
- sessopts, None, diagnostic_handler, source_map,
+ sessopts, None, diagnostic_handler, source_map, Default::default(),
);
- let codegen_backend = rustc_driver::get_codegen_backend(&sess);
+ let codegen_backend = util::get_codegen_backend(&sess);
let cstore = CStore::new(codegen_backend.metadata_loader());
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut control = driver::CompileController::basic();
let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
- target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
+ util::add_configuration(&mut cfg, &sess, &*codegen_backend);
sess.parse_sess.config = cfg;
let out = Some(outdir.lock().unwrap().path().join("rust_out"));
license = "MIT/Apache-2.0"
repository = "https://github.com/rust-lang/rust.git"
description = "The Rust Standard Library"
+edition = "2018"
[lib]
name = "std"
use core::sync::atomic::{AtomicPtr, Ordering};
use core::{mem, ptr};
use core::ptr::NonNull;
-use sys_common::util::dumb_print;
+
+use crate::sys_common::util::dumb_print;
#[stable(feature = "alloc_module", since = "1.28.0")]
#[doc(inline)]
unsafe { mem::transmute(hook) }
};
hook(layout);
- unsafe { ::sys::abort_internal(); }
+ unsafe { crate::sys::abort_internal(); }
}
#[cfg(not(test))]
#![deny(warnings)]
-extern crate cc;
-
use std::env;
fn main() {
#![cfg(test)]
-extern crate test;
-
-use self::test::Bencher;
+use test::Bencher;
#[bench]
fn new_drop(b: &mut Bencher) {
use self::Entry::*;
use self::VacantEntryState::*;
-use intrinsics::unlikely;
-use collections::CollectionAllocErr;
-use cell::Cell;
-use borrow::Borrow;
-use cmp::max;
-use fmt::{self, Debug};
+use crate::intrinsics::unlikely;
+use crate::collections::CollectionAllocErr;
+use crate::cell::Cell;
+use crate::borrow::Borrow;
+use crate::cmp::max;
+use crate::fmt::{self, Debug};
#[allow(deprecated)]
-use hash::{Hash, Hasher, BuildHasher, SipHasher13};
-use iter::{FromIterator, FusedIterator};
-use mem::{self, replace};
-use ops::{Deref, DerefMut, Index};
-use sys;
+use crate::hash::{Hash, Hasher, BuildHasher, SipHasher13};
+use crate::iter::{FromIterator, FusedIterator};
+use crate::mem::{self, replace};
+use crate::ops::{Deref, DerefMut, Index};
+use crate::sys;
use super::table::{self, Bucket, EmptyBucket, Fallibility, FullBucket, FullBucketMut, RawTable,
SafeHash};
use super::HashMap;
use super::Entry::{Occupied, Vacant};
use super::RandomState;
- use cell::RefCell;
+ use crate::cell::RefCell;
use rand::{thread_rng, Rng};
use realstd::collections::CollectionAllocErr::*;
use realstd::mem::size_of;
-use borrow::Borrow;
-use fmt;
-use hash::{Hash, BuildHasher};
-use iter::{Chain, FromIterator, FusedIterator};
-use ops::{BitOr, BitAnd, BitXor, Sub};
+use crate::borrow::Borrow;
+use crate::fmt;
+use crate::hash::{Hash, BuildHasher};
+use crate::iter::{Chain, FromIterator, FusedIterator};
+use crate::ops::{BitOr, BitAnd, BitXor, Sub};
use super::Recover;
use super::map::{self, HashMap, Keys, RandomState};
#[test]
fn test_replace() {
- use hash;
+ use crate::hash;
#[derive(Debug)]
struct Foo(&'static str, i32);
-use alloc::{Global, Alloc, Layout, LayoutErr, handle_alloc_error};
-use collections::CollectionAllocErr;
-use hash::{BuildHasher, Hash, Hasher};
-use marker;
-use mem::{size_of, needs_drop};
-use mem;
-use ops::{Deref, DerefMut};
-use ptr::{self, Unique, NonNull};
-use hint;
+use crate::alloc::{Global, Alloc, Layout, LayoutErr, handle_alloc_error};
+use crate::collections::CollectionAllocErr;
+use crate::hash::{BuildHasher, Hash, Hasher};
+use crate::marker;
+use crate::mem::{self, size_of, needs_drop};
+use crate::ops::{Deref, DerefMut};
+use crate::ptr::{self, Unique, NonNull};
+use crate::hint;
use self::BucketState::*;
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(reason = "moved to `std::ops::Bound`", since = "1.26.0")]
#[doc(hidden)]
-pub use ops::Bound;
+pub use crate::ops::Bound;
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::collections::{BinaryHeap, BTreeMap, BTreeSet};
#[stable(feature = "rust1", since = "1.0.0")]
#![stable(feature = "env", since = "1.0.0")]
-use error::Error;
-use ffi::{OsStr, OsString};
-use fmt;
-use io;
-use path::{Path, PathBuf};
-use sys;
-use sys::os as os_imp;
+use crate::error::Error;
+use crate::ffi::{OsStr, OsString};
+use crate::fmt;
+use crate::io;
+use crate::path::{Path, PathBuf};
+use crate::sys;
+use crate::sys::os as os_imp;
/// Returns the current working directory as a [`PathBuf`].
///
/// Constants associated with the current target
#[stable(feature = "env", since = "1.0.0")]
pub mod consts {
- use sys::env::os;
+ use crate::sys::env::os;
/// A string describing the architecture of the CPU that is currently
/// in use.
mod tests {
use super::*;
- use path::Path;
+ use crate::path::Path;
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[test]
#[cfg(windows)]
fn split_paths_windows() {
- use path::PathBuf;
+ use crate::path::PathBuf;
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
split_paths(unparsed).collect::<Vec<_>>() ==
#[test]
#[cfg(unix)]
fn split_paths_unix() {
- use path::PathBuf;
+ use crate::path::PathBuf;
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
split_paths(unparsed).collect::<Vec<_>>() ==
#[test]
#[cfg(unix)]
fn join_paths_unix() {
- use ffi::OsStr;
+ use crate::ffi::OsStr;
fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() ==
#[test]
#[cfg(windows)]
fn join_paths_windows() {
- use ffi::OsStr;
+ use crate::ffi::OsStr;
fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() ==
// coherence challenge (e.g., specialization, neg impls, etc) we can
// reconsider what crate these items belong in.
-use alloc::{AllocErr, LayoutErr, CannotReallocInPlace};
-use any::TypeId;
-use borrow::Cow;
-use cell;
-use char;
use core::array;
-use fmt::{self, Debug, Display};
-use mem::transmute;
-use num;
-use str;
-use string;
+
+use crate::alloc::{AllocErr, LayoutErr, CannotReallocInPlace};
+use crate::any::TypeId;
+use crate::borrow::Cow;
+use crate::cell;
+use crate::char;
+use crate::fmt::{self, Debug, Display};
+use crate::mem::transmute;
+use crate::num;
+use crate::str;
+use crate::string;
/// `Error` is a trait representing the basic expectations for error values,
/// i.e., values of type `E` in [`Result<T, E>`]. Errors must describe
#[cfg(test)]
mod tests {
use super::Error;
- use fmt;
+ use crate::fmt;
#[derive(Debug, PartialEq)]
struct A;
#![allow(missing_docs)]
#[cfg(not(test))]
-use intrinsics;
+use crate::intrinsics;
#[cfg(not(test))]
-use sys::cmath;
+use crate::sys::cmath;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
#[inline]
pub fn log2(self) -> f32 {
#[cfg(target_os = "android")]
- return ::sys::android::log2f32(self);
+ return crate::sys::android::log2f32(self);
#[cfg(not(target_os = "android"))]
return unsafe { intrinsics::log2f32(self) };
}
#[inline]
pub fn acosh(self) -> f32 {
match self {
- x if x < 1.0 => ::f32::NAN,
+ x if x < 1.0 => crate::f32::NAN,
x => (x + ((x * x) - 1.0).sqrt()).ln(),
}
}
#[cfg(test)]
mod tests {
- use f32;
- use f32::*;
- use num::*;
- use num::FpCategory as Fp;
+ use crate::f32;
+ use crate::f32::*;
+ use crate::num::*;
+ use crate::num::FpCategory as Fp;
#[test]
fn test_num_f32() {
#![allow(missing_docs)]
#[cfg(not(test))]
-use intrinsics;
+use crate::intrinsics;
#[cfg(not(test))]
-use sys::cmath;
+use crate::sys::cmath;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
pub fn log2(self) -> f64 {
self.log_wrapper(|n| {
#[cfg(target_os = "android")]
- return ::sys::android::log2f64(n);
+ return crate::sys::android::log2f64(n);
#[cfg(not(target_os = "android"))]
return unsafe { intrinsics::log2f64(n) };
})
#[cfg(test)]
mod tests {
- use f64;
- use f64::*;
- use num::*;
- use num::FpCategory as Fp;
+ use crate::f64;
+ use crate::f64::*;
+ use crate::num::*;
+ use crate::num::FpCategory as Fp;
#[test]
fn test_num_f64() {
-use ascii;
-use borrow::{Cow, Borrow};
-use cmp::Ordering;
-use error::Error;
-use fmt::{self, Write};
-use io;
-use mem;
-use memchr;
-use ops;
-use os::raw::c_char;
-use ptr;
-use rc::Rc;
-use slice;
-use str::{self, Utf8Error};
-use sync::Arc;
-use sys;
+use crate::ascii;
+use crate::borrow::{Cow, Borrow};
+use crate::cmp::Ordering;
+use crate::error::Error;
+use crate::fmt::{self, Write};
+use crate::io;
+use crate::mem;
+use crate::memchr;
+use crate::ops;
+use crate::os::raw::c_char;
+use crate::ptr;
+use crate::rc::Rc;
+use crate::slice;
+use crate::str::{self, Utf8Error};
+use crate::sync::Arc;
+use crate::sys;
/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
/// middle.
#[cfg(test)]
mod tests {
use super::*;
- use os::raw::c_char;
- use borrow::Cow::{Borrowed, Owned};
- use hash::{Hash, Hasher};
- use collections::hash_map::DefaultHasher;
- use rc::Rc;
- use sync::Arc;
+ use crate::os::raw::c_char;
+ use crate::borrow::Cow::{Borrowed, Owned};
+ use crate::hash::{Hash, Hasher};
+ use crate::collections::hash_map::DefaultHasher;
+ use crate::rc::Rc;
+ use crate::sync::Arc;
#[test]
fn c_to_rust() {
-use borrow::{Borrow, Cow};
-use fmt;
-use ops;
-use cmp;
-use hash::{Hash, Hasher};
-use rc::Rc;
-use sync::Arc;
+use crate::borrow::{Borrow, Cow};
+use crate::fmt;
+use crate::ops;
+use crate::cmp;
+use crate::hash::{Hash, Hasher};
+use crate::rc::Rc;
+use crate::sync::Arc;
-use sys::os_str::{Buf, Slice};
-use sys_common::{AsInner, IntoInner, FromInner};
+use crate::sys::os_str::{Buf, Slice};
+use crate::sys_common::{AsInner, IntoInner, FromInner};
/// A type that can represent owned, mutable platform-native strings, but is
/// cheaply inter-convertible with Rust strings.
#[cfg(test)]
mod tests {
use super::*;
- use sys_common::{AsInner, IntoInner};
+ use crate::sys_common::{AsInner, IntoInner};
- use rc::Rc;
- use sync::Arc;
+ use crate::rc::Rc;
+ use crate::sync::Arc;
#[test]
fn test_os_string_with_capacity() {
#![stable(feature = "rust1", since = "1.0.0")]
-use fmt;
-use ffi::OsString;
-use io::{self, SeekFrom, Seek, Read, Initializer, Write};
-use path::{Path, PathBuf};
-use sys::fs as fs_imp;
-use sys_common::{AsInnerMut, FromInner, AsInner, IntoInner};
-use time::SystemTime;
+use crate::fmt;
+use crate::ffi::OsString;
+use crate::io::{self, SeekFrom, Seek, Read, Initializer, Write};
+use crate::path::{Path, PathBuf};
+use crate::sys::fs as fs_imp;
+use crate::sys_common::{AsInnerMut, FromInner, AsInner, IntoInner};
+use crate::time::SystemTime;
/// A reference to an open file on the filesystem.
///
#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
- use io::prelude::*;
+ use crate::io::prelude::*;
+
+ use crate::fs::{self, File, OpenOptions};
+ use crate::io::{ErrorKind, SeekFrom};
+ use crate::path::Path;
+ use crate::str;
+ use crate::sys_common::io::test::{TempDir, tmpdir};
+ use crate::thread;
- use fs::{self, File, OpenOptions};
- use io::{ErrorKind, SeekFrom};
- use path::Path;
use rand::{rngs::StdRng, FromEntropy, RngCore};
- use str;
- use sys_common::io::test::{TempDir, tmpdir};
- use thread;
#[cfg(windows)]
- use os::windows::fs::{symlink_dir, symlink_file};
+ use crate::os::windows::fs::{symlink_dir, symlink_file};
#[cfg(windows)]
- use sys::fs::symlink_junction;
+ use crate::sys::fs::symlink_junction;
#[cfg(unix)]
- use os::unix::fs::symlink as symlink_dir;
+ use crate::os::unix::fs::symlink as symlink_dir;
#[cfg(unix)]
- use os::unix::fs::symlink as symlink_file;
+ use crate::os::unix::fs::symlink as symlink_file;
#[cfg(unix)]
- use os::unix::fs::symlink as symlink_junction;
+ use crate::os::unix::fs::symlink as symlink_junction;
macro_rules! check { ($e:expr) => (
match $e {
#[test]
#[cfg(unix)]
fn file_test_io_read_write_at() {
- use os::unix::fs::FileExt;
+ use crate::os::unix::fs::FileExt;
let tmpdir = tmpdir();
let filename = tmpdir.join("file_rt_io_file_test_read_write_at.txt");
#[test]
#[cfg(unix)]
fn set_get_unix_permissions() {
- use os::unix::fs::PermissionsExt;
+ use crate::os::unix::fs::PermissionsExt;
let tmpdir = tmpdir();
let filename = &tmpdir.join("set_get_unix_permissions");
#[test]
#[cfg(windows)]
fn file_test_io_seek_read_write() {
- use os::windows::fs::FileExt;
+ use crate::os::windows::fs::FileExt;
let tmpdir = tmpdir();
let filename = tmpdir.join("file_rt_io_file_test_seek_read_write.txt");
#[test]
fn open_flavors() {
- use fs::OpenOptions as OO;
+ use crate::fs::OpenOptions as OO;
fn c<T: Clone>(t: &T) -> T { t.clone() }
let tmpdir = tmpdir();
//! Buffering wrappers for I/O traits
-use io::prelude::*;
+use crate::io::prelude::*;
-use cmp;
-use error;
-use fmt;
-use io::{self, Initializer, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom, IoVec, IoVecMut};
-use memchr;
+use crate::cmp;
+use crate::error;
+use crate::fmt;
+use crate::io::{self, Initializer, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom, IoVec, IoVecMut};
+use crate::memchr;
/// The `BufReader` struct adds buffering to any reader.
///
#[cfg(test)]
mod tests {
- use io::prelude::*;
- use io::{self, BufReader, BufWriter, LineWriter, SeekFrom};
- use sync::atomic::{AtomicUsize, Ordering};
- use thread;
- use test;
+ use crate::io::prelude::*;
+ use crate::io::{self, BufReader, BufWriter, LineWriter, SeekFrom};
+ use crate::sync::atomic::{AtomicUsize, Ordering};
+ use crate::thread;
/// A dummy reader intended at testing short-reads propagation.
pub struct ShortReader {
-use io::prelude::*;
+use crate::io::prelude::*;
+
+use crate::cmp;
+use crate::io::{self, Initializer, SeekFrom, Error, ErrorKind, IoVec, IoVecMut};
use core::convert::TryInto;
-use cmp;
-use io::{self, Initializer, SeekFrom, Error, ErrorKind, IoVec, IoVecMut};
/// A `Cursor` wraps an in-memory buffer and provides it with a
/// [`Seek`] implementation.
#[cfg(test)]
mod tests {
- use io::prelude::*;
- use io::{Cursor, SeekFrom, IoVec, IoVecMut};
+ use crate::io::prelude::*;
+ use crate::io::{Cursor, SeekFrom, IoVec, IoVecMut};
#[test]
fn test_vec_writer() {
-use error;
-use fmt;
-use result;
-use sys;
-use convert::From;
+use crate::error;
+use crate::fmt;
+use crate::result;
+use crate::sys;
+use crate::convert::From;
/// A specialized [`Result`](../result/enum.Result.html) type for I/O
/// operations.
#[cfg(test)]
mod test {
use super::{Error, ErrorKind, Repr, Custom};
- use error;
- use fmt;
- use sys::os::error_string;
- use sys::decode_error_kind;
+ use crate::error;
+ use crate::fmt;
+ use crate::sys::os::error_string;
+ use crate::sys::decode_error_kind;
#[test]
fn test_debug_error() {
-use cmp;
-use io::{self, SeekFrom, Read, Initializer, Write, Seek, BufRead, Error, ErrorKind, IoVecMut,
+use crate::cmp;
+use crate::io::{self, SeekFrom, Read, Initializer, Write, Seek, BufRead, Error, ErrorKind, IoVecMut,
IoVec};
-use fmt;
-use mem;
+use crate::fmt;
+use crate::mem;
// =============================================================================
// Forwarding implementations
#[cfg(test)]
mod tests {
- use io::prelude::*;
- use test;
+ use crate::io::prelude::*;
#[bench]
fn bench_read_slice(b: &mut test::Bencher) {
-use cell::Cell;
-use ptr;
-use sync::Arc;
-use sys_common;
-use sys_common::mutex::Mutex;
+use crate::cell::Cell;
+use crate::ptr;
+use crate::sync::Arc;
+use crate::sys_common;
+use crate::sys_common::mutex::Mutex;
pub struct Lazy<T> {
// We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly!
#![stable(feature = "rust1", since = "1.0.0")]
-use cmp;
-use fmt;
-use slice;
-use str;
-use memchr;
-use ops::{Deref, DerefMut};
-use ptr;
-use sys;
+use crate::cmp;
+use crate::fmt;
+use crate::slice;
+use crate::str;
+use crate::memchr;
+use crate::ops::{Deref, DerefMut};
+use crate::ptr;
+use crate::sys;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::buffered::{BufReader, BufWriter, LineWriter};
mod util;
mod stdio;
-const DEFAULT_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
struct Guard<'a> { buf: &'a mut Vec<u8>, len: usize }
///
/// If successful, this function will return the total number of bytes read.
///
- /// An empty buffer returned indicates that the stream has reached EOF.
+ /// If this function returns `Ok(0)`, the stream has reached EOF.
///
/// # Errors
///
#[cfg(test)]
mod tests {
- use io::prelude::*;
- use io;
+ use crate::io::prelude::*;
+ use crate::io;
use super::Cursor;
- use test;
use super::repeat;
#[test]
-use io::prelude::*;
+use crate::io::prelude::*;
-use cell::RefCell;
-use fmt;
-use io::lazy::Lazy;
-use io::{self, Initializer, BufReader, LineWriter};
-use sync::{Arc, Mutex, MutexGuard};
-use sys::stdio;
-use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
-use thread::LocalKey;
+use crate::cell::RefCell;
+use crate::fmt;
+use crate::io::lazy::Lazy;
+use crate::io::{self, Initializer, BufReader, LineWriter};
+use crate::sync::{Arc, Mutex, MutexGuard};
+use crate::sys::stdio;
+use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
+use crate::thread::LocalKey;
/// Stdout used by print! and println! macros
thread_local! {
issue = "0")]
#[doc(hidden)]
pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
- use panicking::LOCAL_STDERR;
- use mem;
+ use crate::panicking::LOCAL_STDERR;
+ use crate::mem;
LOCAL_STDERR.with(move |slot| {
mem::replace(&mut *slot.borrow_mut(), sink)
}).and_then(|mut s| {
issue = "0")]
#[doc(hidden)]
pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
- use mem;
+ use crate::mem;
LOCAL_STDOUT.with(move |slot| {
mem::replace(&mut *slot.borrow_mut(), sink)
}).and_then(|mut s| {
issue = "0")]
#[doc(hidden)]
pub fn _eprint(args: fmt::Arguments) {
- use panicking::LOCAL_STDERR;
+ use crate::panicking::LOCAL_STDERR;
print_to(args, &LOCAL_STDERR, stderr, "stderr");
}
#[cfg(test)]
mod tests {
- use panic::{UnwindSafe, RefUnwindSafe};
- use thread;
+ use crate::panic::{UnwindSafe, RefUnwindSafe};
+ use crate::thread;
use super::*;
#[test]
#![allow(missing_copy_implementations)]
-use fmt;
-use io::{self, Read, Initializer, Write, ErrorKind, BufRead, IoVec, IoVecMut};
-use mem;
+use crate::fmt;
+use crate::io::{self, Read, Initializer, Write, ErrorKind, BufRead, IoVec, IoVecMut};
+use crate::mem;
/// Copies the entire contents of a reader into a writer.
///
#[cfg(test)]
mod tests {
- use io::prelude::*;
- use io::{copy, sink, empty, repeat};
+ use crate::io::prelude::*;
+ use crate::io::{copy, sink, empty, repeat};
#[test]
fn copy_copies() {
//! [`sync`]: sync/index.html
//! [`thread`]: thread/index.html
//! [`use std::env`]: env/index.html
-//! [`use`]: ../book/ch07-02-modules-and-use-to-control-scope-and-privacy.html#the-use-keyword-to-bring-paths-into-a-scope
+//! [`use`]: ../book/ch07-02-defining-modules-to-control-scope-and-privacy.html
//! [crates.io]: https://crates.io
//! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
//! [files]: fs/struct.File.html
#![deny(intra_doc_link_resolution_failure)]
#![deny(missing_debug_implementations)]
+#![deny(rust_2018_idioms)]
+#![allow(explicit_outlives_requirements)]
+#![allow(elided_lifetimes_in_paths)]
+
// Tell the compiler to link to either panic_abort or panic_unwind
#![needs_panic_runtime]
// Access to Bencher, etc.
#[cfg(test)] extern crate test;
-#[cfg(test)] extern crate rand;
// Re-export a few macros from core
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::{unreachable, unimplemented, write, writeln, try};
+pub use core::{unreachable, unimplemented, write, writeln, r#try};
#[allow(unused_imports)] // macros from `alloc` are not used on all platforms
#[macro_use]
extern crate alloc as alloc_crate;
#[doc(masked)]
+#[allow(unused_extern_crates)]
extern crate libc;
-extern crate rustc_demangle;
// We always need an unwinder currently for backtraces
#[doc(masked)]
#[allow(unused_extern_crates)]
extern crate unwind;
-#[cfg(feature = "backtrace")]
-extern crate backtrace_sys;
-
// During testing, this crate is not actually the "real" std library, but rather
// it links to the real std library, which was compiled from this same source
// code. So any lang items std defines are conditionally excluded (or else they
// testing gives test-std access to real-std lang items and globals. See #2912
#[cfg(test)] extern crate std as realstd;
-#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
-extern crate fortanix_sgx_abi;
-
// The standard macros that are not built-in to the compiler.
#[macro_use]
mod macros;
#[cfg_attr(stage0, allow_internal_unstable)]
#[cfg_attr(not(stage0), allow_internal_unstable(gen_future, generators))]
#[allow_internal_unsafe]
-macro_rules! await {
+macro_rules! r#await {
($e:expr) => { {
let mut pinned = $e;
loop {
/// ```
#[inline]
pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
- ::sys::memchr::memchr(needle, haystack)
+ crate::sys::memchr::memchr(needle, haystack)
}
/// A safe interface to `memrchr`.
/// ```
#[inline]
pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
- ::sys::memchr::memrchr(needle, haystack)
+ crate::sys::memchr::memrchr(needle, haystack)
}
#[cfg(test)]
-use fmt;
-use hash;
-use io;
-use mem;
-use net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
-use option;
-use sys::net::netc as c;
-use sys_common::{FromInner, AsInner, IntoInner};
-use sys_common::net::LookupHost;
-use vec;
-use iter;
-use slice;
-use convert::TryInto;
+use crate::fmt;
+use crate::hash;
+use crate::io;
+use crate::mem;
+use crate::net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
+use crate::option;
+use crate::sys::net::netc as c;
+use crate::sys_common::{FromInner, AsInner, IntoInner};
+use crate::sys_common::net::LookupHost;
+use crate::vec;
+use crate::iter;
+use crate::slice;
+use crate::convert::TryInto;
/// An internet socket address, either IPv4 or IPv6.
///
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use net::*;
- use net::test::{tsa, sa6, sa4};
+ use crate::net::*;
+ use crate::net::test::{tsa, sa6, sa4};
#[test]
fn to_socket_addr_ipaddr_u16() {
be to be stable",
issue = "27709")]
-use cmp::Ordering;
-use fmt;
-use hash;
-use sys::net::netc as c;
-use sys_common::{AsInner, FromInner};
+use crate::cmp::Ordering;
+use crate::fmt;
+use crate::hash;
+use crate::sys::net::netc as c;
+use crate::sys_common::{AsInner, FromInner};
/// An IP address, either IPv4 or IPv6.
///
// Tests for this module
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use net::*;
- use net::Ipv6MulticastScope::*;
- use net::test::{tsa, sa6, sa4};
+ use crate::net::*;
+ use crate::net::Ipv6MulticastScope::*;
+ use crate::net::test::{tsa, sa6, sa4};
#[test]
fn test_from_str_ipv4() {
#![stable(feature = "rust1", since = "1.0.0")]
-use io::{self, Error, ErrorKind};
+use crate::io::{self, Error, ErrorKind};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
//! This module is "publicly exported" through the `FromStr` implementations
//! below.
-use error::Error;
-use fmt;
-use net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
-use str::FromStr;
+use crate::error::Error;
+use crate::fmt;
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+use crate::str::FromStr;
struct Parser<'a> {
// parsing as ASCII, so can use byte array
-use io::prelude::*;
+use crate::io::prelude::*;
-use fmt;
-use io::{self, Initializer, IoVec, IoVecMut};
-use net::{ToSocketAddrs, SocketAddr, Shutdown};
-use sys_common::net as net_imp;
-use sys_common::{AsInner, FromInner, IntoInner};
-use time::Duration;
+use crate::fmt;
+use crate::io::{self, Initializer, IoVec, IoVecMut};
+use crate::net::{ToSocketAddrs, SocketAddr, Shutdown};
+use crate::sys_common::net as net_imp;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::time::Duration;
/// A TCP stream between a local and a remote socket.
///
#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
- use io::{ErrorKind, IoVec, IoVecMut};
- use io::prelude::*;
- use net::*;
- use net::test::{next_test_ip4, next_test_ip6};
- use sync::mpsc::channel;
- use sys_common::AsInner;
- use time::{Instant, Duration};
- use thread;
+ use crate::io::{ErrorKind, IoVec, IoVecMut};
+ use crate::io::prelude::*;
+ use crate::net::*;
+ use crate::net::test::{next_test_ip4, next_test_ip6};
+ use crate::sync::mpsc::channel;
+ use crate::sys_common::AsInner;
+ use crate::time::{Instant, Duration};
+ use crate::thread;
fn each_ip(f: &mut dyn FnMut(SocketAddr)) {
f(next_test_ip4());
#![allow(warnings)] // not used on emscripten
-use env;
-use net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr, ToSocketAddrs};
-use sync::atomic::{AtomicUsize, Ordering};
+use crate::env;
+use crate::net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr, ToSocketAddrs};
+use crate::sync::atomic::{AtomicUsize, Ordering};
static PORT: AtomicUsize = AtomicUsize::new(0);
-use fmt;
-use io::{self, Error, ErrorKind};
-use net::{ToSocketAddrs, SocketAddr, Ipv4Addr, Ipv6Addr};
-use sys_common::net as net_imp;
-use sys_common::{AsInner, FromInner, IntoInner};
-use time::Duration;
+use crate::fmt;
+use crate::io::{self, Error, ErrorKind};
+use crate::net::{ToSocketAddrs, SocketAddr, Ipv4Addr, Ipv6Addr};
+use crate::sys_common::net as net_imp;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::time::Duration;
/// A UDP socket.
///
#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
- use io::ErrorKind;
- use net::*;
- use net::test::{next_test_ip4, next_test_ip6};
- use sync::mpsc::channel;
- use sys_common::AsInner;
- use time::{Instant, Duration};
- use thread;
+ use crate::io::ErrorKind;
+ use crate::net::*;
+ use crate::net::test::{next_test_ip4, next_test_ip6};
+ use crate::sync::mpsc::channel;
+ use crate::sys_common::AsInner;
+ use crate::time::{Instant, Duration};
+ use crate::thread;
fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) {
f(next_test_ip4(), next_test_ip4());
#[stable(feature = "nonzero", since = "1.28.0")]
pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
-#[cfg(test)] use fmt;
-#[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};
+#[cfg(test)] use crate::fmt;
+#[cfg(test)] use crate::ops::{Add, Sub, Mul, Div, Rem};
/// Helper function for testing numeric operations
#[cfg(test)]
#[cfg(test)]
mod tests {
- use u8;
- use u16;
- use u32;
- use u64;
- use usize;
- use ops::Mul;
+ use crate::u8;
+ use crate::u16;
+ use crate::u32;
+ use crate::u64;
+ use crate::usize;
+ use crate::ops::Mul;
#[test]
fn test_saturating_add_uint() {
- use usize::MAX;
+ use crate::usize::MAX;
assert_eq!(3_usize.saturating_add(5_usize), 8_usize);
assert_eq!(3_usize.saturating_add(MAX-1), MAX);
assert_eq!(MAX.saturating_add(MAX), MAX);
#[test]
fn test_saturating_sub_uint() {
- use usize::MAX;
+ use crate::usize::MAX;
assert_eq!(5_usize.saturating_sub(3_usize), 2_usize);
assert_eq!(3_usize.saturating_sub(5_usize), 0_usize);
assert_eq!(0_usize.saturating_sub(1_usize), 0_usize);
#[test]
fn test_saturating_add_int() {
- use isize::{MIN,MAX};
+ use crate::isize::{MIN,MAX};
assert_eq!(3i32.saturating_add(5), 8);
assert_eq!(3isize.saturating_add(MAX-1), MAX);
assert_eq!(MAX.saturating_add(MAX), MAX);
#[test]
fn test_saturating_sub_int() {
- use isize::{MIN,MAX};
+ use crate::isize::{MIN,MAX};
assert_eq!(3i32.saturating_sub(5), -2);
assert_eq!(MIN.saturating_sub(1), MIN);
assert_eq!((-2isize).saturating_sub(MAX), MIN);
assert_eq!(u64_val.to_string(), "0");
}
- fn from_str<T: ::str::FromStr>(t: &str) -> Option<T> {
- ::str::FromStr::from_str(t).ok()
+ fn from_str<T: crate::str::FromStr>(t: &str) -> Option<T> {
+ crate::str::FromStr::from_str(t).ok()
}
#[test]
#[cfg(test)]
mod bench {
- extern crate test;
- use self::test::Bencher;
+ use test::Bencher;
#[bench]
fn bench_pow_function(b: &mut Bencher) {
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::android::raw;
+use crate::os::android::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_long;
+use crate::os::raw::c_long;
#[stable(feature = "pthread_t", since = "1.8.0")]
pub type pthread_t = c_long;
#[cfg(any(target_arch = "arm", target_arch = "x86"))]
mod arch {
- use os::raw::{c_uint, c_uchar, c_ulonglong, c_longlong, c_ulong};
- use os::unix::raw::{uid_t, gid_t};
+ use crate::os::raw::{c_uint, c_uchar, c_ulonglong, c_longlong, c_ulong};
+ use crate::os::unix::raw::{uid_t, gid_t};
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type dev_t = u64;
#[cfg(target_arch = "aarch64")]
mod arch {
- use os::raw::{c_uchar, c_ulong};
- use os::unix::raw::{uid_t, gid_t};
+ use crate::os::raw::{c_uchar, c_ulong};
+ use crate::os::unix::raw::{uid_t, gid_t};
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type dev_t = u64;
#[cfg(target_arch = "x86_64")]
mod arch {
- use os::raw::{c_uint, c_long, c_ulong};
- use os::unix::raw::{uid_t, gid_t};
+ use crate::os::raw::{c_uint, c_long, c_ulong};
+ use crate::os::unix::raw::{uid_t, gid_t};
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type dev_t = u64;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::bitrig::raw;
+use crate::os::bitrig::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_long;
-use os::unix::raw::{uid_t, gid_t};
+use crate::os::raw::c_long;
+use crate::os::unix::raw::{uid_t, gid_t};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::dragonfly::raw;
+use crate::os::dragonfly::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_long;
+use crate::os::raw::c_long;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::emscripten::raw;
+use crate::os::emscripten::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::{c_long, c_short, c_uint, c_ulong};
+use crate::os::raw::{c_long, c_short, c_uint, c_ulong};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
///
/// [ABI documentation]: https://docs.rs/fortanix-sgx-abi/
pub mod usercalls {
- pub use sys::abi::usercalls::*;
+ pub use crate::sys::abi::usercalls::*;
/// Primitives for allocating memory in userspace as well as copying data
/// to and from user memory.
pub mod alloc {
- pub use sys::abi::usercalls::alloc::*;
+ pub use crate::sys::abi::usercalls::alloc::*;
}
/// Lowest-level interfaces to usercalls and usercall ABI type definitions.
pub mod raw {
- pub use sys::abi::usercalls::raw::{do_usercall, Usercalls as UsercallNrs};
- pub use sys::abi::usercalls::raw::{accept_stream, alloc, async_queues, bind_stream, close,
- connect_stream, exit, flush, free, insecure_time,
+ pub use crate::sys::abi::usercalls::raw::{do_usercall, Usercalls as UsercallNrs};
+ pub use crate::sys::abi::usercalls::raw::{accept_stream, alloc, async_queues, bind_stream,
+ close, connect_stream, exit, flush, free, insecure_time,
launch_thread, read, read_alloc, send, wait, write};
// fortanix-sgx-abi re-exports
- pub use sys::abi::usercalls::raw::{ByteBuffer, FifoDescriptor, Return, Usercall};
- pub use sys::abi::usercalls::raw::Error;
- pub use sys::abi::usercalls::raw::{EV_RETURNQ_NOT_EMPTY, EV_UNPARK, EV_USERCALLQ_NOT_FULL,
- FD_STDERR, FD_STDIN, FD_STDOUT, RESULT_SUCCESS,
- USERCALL_USER_DEFINED, WAIT_INDEFINITE, WAIT_NO};
- pub use sys::abi::usercalls::raw::{Fd, Result, Tcs};
+ pub use crate::sys::abi::usercalls::raw::{ByteBuffer, FifoDescriptor, Return, Usercall};
+ pub use crate::sys::abi::usercalls::raw::Error;
+ pub use crate::sys::abi::usercalls::raw::{EV_RETURNQ_NOT_EMPTY, EV_UNPARK,
+ EV_USERCALLQ_NOT_FULL, FD_STDERR, FD_STDIN, FD_STDOUT,
+ RESULT_SUCCESS, USERCALL_USER_DEFINED, WAIT_INDEFINITE,
+ WAIT_NO};
+ pub use crate::sys::abi::usercalls::raw::{Fd, Result, Tcs};
}
}
/// Functions for querying mapping information for pointers.
pub mod mem {
- pub use sys::abi::mem::*;
+ pub use crate::sys::abi::mem::*;
}
-pub use sys::ext::{io, arch, ffi};
+pub use crate::sys::ext::{io, arch, ffi};
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::freebsd::raw;
+use crate::os::freebsd::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_long;
+use crate::os::raw::c_long;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_ulong;
+use crate::os::raw::c_ulong;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
target_arch = "powerpc",
target_arch = "arm"))]
mod arch {
- use os::raw::{c_long, c_short, c_uint};
+ use crate::os::raw::{c_long, c_short, c_uint};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#[cfg(target_arch = "mips")]
mod arch {
- use os::raw::{c_long, c_ulong};
+ use crate::os::raw::{c_long, c_ulong};
#[cfg(target_env = "musl")]
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64;
#[cfg(target_arch = "aarch64")]
mod arch {
- use os::raw::{c_long, c_int};
+ use crate::os::raw::{c_long, c_int};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#[cfg(target_arch = "x86_64")]
mod arch {
- use os::raw::{c_long, c_int};
+ use crate::os::raw::{c_long, c_int};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::haiku::raw;
+use crate::os::haiku::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
#![allow(deprecated)]
-use os::raw::{c_long};
-use os::unix::raw::{uid_t, gid_t};
+use crate::os::raw::{c_long};
+use crate::os::unix::raw::{uid_t, gid_t};
// Use the direct definition of usize, instead of uintptr_t like in libc
#[stable(feature = "pthread_t", since = "1.8.0")] pub type pthread_t = usize;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::hermit::raw;
+use crate::os::hermit::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::ios::raw;
+use crate::os::ios::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_long;
+use crate::os::raw::c_long;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::linux::raw;
+use crate::os::linux::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
#![allow(deprecated)]
#![allow(missing_debug_implementations)]
-use os::raw::c_ulong;
+use crate::os::raw::c_ulong;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
target_arch = "asmjs",
target_arch = "wasm32"))]
mod arch {
- use os::raw::{c_long, c_short, c_uint};
+ use crate::os::raw::{c_long, c_short, c_uint};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#[cfg(target_arch = "mips")]
mod arch {
- use os::raw::{c_long, c_ulong};
+ use crate::os::raw::{c_long, c_ulong};
#[cfg(target_env = "musl")]
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64;
#[cfg(target_arch = "aarch64")]
mod arch {
- use os::raw::{c_long, c_int};
+ use crate::os::raw::{c_long, c_int};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#[cfg(any(target_arch = "x86_64", target_arch = "powerpc64"))]
mod arch {
- use os::raw::{c_long, c_int};
+ use crate::os::raw::{c_long, c_int};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::macos::raw;
+use crate::os::macos::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_long;
+use crate::os::raw::c_long;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
// cross-platform way in the documentation
#[stable(feature = "rust1", since = "1.0.0")]
- pub use sys::unix_ext as unix;
+ pub use crate::sys::unix_ext as unix;
#[stable(feature = "rust1", since = "1.0.0")]
- pub use sys::windows_ext as windows;
+ pub use crate::sys::windows_ext as windows;
#[doc(cfg(target_os = "linux"))]
pub mod linux;
#[cfg(any(target_os = "redox", unix))]
#[stable(feature = "rust1", since = "1.0.0")]
- pub use sys::ext as unix;
+ pub use crate::sys::ext as unix;
#[cfg(windows)]
#[stable(feature = "rust1", since = "1.0.0")]
- pub use sys::ext as windows;
+ pub use crate::sys::ext as windows;
#[cfg(any(target_os = "linux", target_os = "l4re"))]
pub mod linux;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::netbsd::raw;
+use crate::os::netbsd::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_long;
-use os::unix::raw::{uid_t, gid_t};
+use crate::os::raw::c_long;
+use crate::os::unix::raw::{uid_t, gid_t};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::openbsd::raw;
+use crate::os::openbsd::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_long;
+use crate::os::raw::c_long;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#[cfg(test)]
#[allow(unused_imports)]
mod tests {
- use any::TypeId;
- use libc;
- use mem;
+ use crate::any::TypeId;
+ use crate::mem;
macro_rules! ok {
($($t:ident)*) => {$(
#[test]
fn same() {
- use os::raw;
+ use crate::os::raw;
ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong
c_longlong c_ulonglong c_float c_double);
}
#![stable(feature = "metadata_ext", since = "1.1.0")]
-use libc;
-
-use fs::Metadata;
-use sys_common::AsInner;
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
#[allow(deprecated)]
-use os::solaris::raw;
+use crate::os::solaris::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
definitions")]
#![allow(deprecated)]
-use os::raw::c_long;
-use os::unix::raw::{uid_t, gid_t};
+use crate::os::raw::c_long;
+use crate::os::unix::raw::{uid_t, gid_t};
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
#![stable(feature = "std_panic", since = "1.9.0")]
-use any::Any;
-use cell::UnsafeCell;
-use fmt;
-use future::Future;
-use pin::Pin;
-use ops::{Deref, DerefMut};
-use panicking;
-use ptr::{Unique, NonNull};
-use rc::Rc;
-use sync::{Arc, Mutex, RwLock, atomic};
-use task::{Waker, Poll};
-use thread::Result;
+use crate::any::Any;
+use crate::cell::UnsafeCell;
+use crate::fmt;
+use crate::future::Future;
+use crate::pin::Pin;
+use crate::ops::{Deref, DerefMut};
+use crate::panicking;
+use crate::ptr::{Unique, NonNull};
+use crate::rc::Rc;
+use crate::sync::{Arc, Mutex, RwLock, atomic};
+use crate::task::{Waker, Poll};
+use crate::thread::Result;
#[stable(feature = "panic_hooks", since = "1.10.0")]
-pub use panicking::{take_hook, set_hook};
+pub use crate::panicking::{take_hook, set_hook};
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub use core::panic::{PanicInfo, Location};
#[stable(feature = "catch_unwind", since = "1.9.0")]
pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
unsafe {
- panicking::try(f)
+ panicking::r#try(f)
}
}
//! * Shims around "try"
use core::panic::BoxMeUp;
-
-use io::prelude::*;
-
-use any::Any;
-use cell::RefCell;
use core::panic::{PanicInfo, Location};
-use fmt;
-use intrinsics;
-use mem;
-use ptr;
-use raw;
-use sys::stdio::panic_output;
-use sys_common::rwlock::RWLock;
-use sys_common::thread_info;
-use sys_common::util;
-use thread;
+
+use crate::io::prelude::*;
+
+use crate::any::Any;
+use crate::cell::RefCell;
+use crate::fmt;
+use crate::intrinsics;
+use crate::mem;
+use crate::ptr;
+use crate::raw;
+use crate::sys::stdio::panic_output;
+use crate::sys_common::rwlock::RWLock;
+use crate::sys_common::thread_info;
+use crate::sys_common::util;
+use crate::thread;
thread_local! {
pub static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
fn default_hook(info: &PanicInfo) {
#[cfg(feature = "backtrace")]
- use sys_common::backtrace;
+ use crate::sys_common::backtrace;
// If this is a double panic, make sure that we print a backtrace
// for this panic. Otherwise only print it if logging is enabled.
let thread = thread_info::current_thread();
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
- let write = |err: &mut dyn (::io::Write)| {
+ let write = |err: &mut dyn crate::io::Write| {
let _ = writeln!(err, "thread '{}' panicked at '{}', {}",
name, msg, location);
#[cfg(feature = "backtrace")]
{
- use sync::atomic::{AtomicBool, Ordering};
+ use crate::sync::atomic::{AtomicBool, Ordering};
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
#[doc(hidden)]
#[unstable(feature = "update_panic_count", issue = "0")]
pub fn update_panic_count(amt: isize) -> usize {
- use cell::Cell;
+ use crate::cell::Cell;
thread_local! { static PANIC_COUNT: Cell<usize> = Cell::new(0) }
PANIC_COUNT.with(|c| {
pub use realstd::rt::update_panic_count;
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
-pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
+pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
#[allow(unions_with_drop_fields)]
union Data<F, R> {
f: F,
}
fn fill(&mut self) -> &mut String {
- use fmt::Write;
+ use crate::fmt::Write;
let inner = self.inner;
self.string.get_or_insert_with(|| {
#![stable(feature = "rust1", since = "1.0.0")]
-use borrow::{Borrow, Cow};
-use cmp;
-use error::Error;
-use fmt;
-use fs;
-use hash::{Hash, Hasher};
-use io;
-use iter::{self, FusedIterator};
-use ops::{self, Deref};
-use rc::Rc;
-use str::FromStr;
-use sync::Arc;
-
-use ffi::{OsStr, OsString};
-
-use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
+use crate::borrow::{Borrow, Cow};
+use crate::cmp;
+use crate::error::Error;
+use crate::fmt;
+use crate::fs;
+use crate::hash::{Hash, Hasher};
+use crate::io;
+use crate::iter::{self, FusedIterator};
+use crate::ops::{self, Deref};
+use crate::rc::Rc;
+use crate::str::FromStr;
+use crate::sync::Arc;
+
+use crate::ffi::{OsStr, OsString};
+
+use crate::sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
////////////////////////////////////////////////////////////////////////////////
// GENERAL NOTES
///
/// For example, `/` on Unix and `\` on Windows.
#[stable(feature = "rust1", since = "1.0.0")]
-pub const MAIN_SEPARATOR: char = ::sys::path::MAIN_SEP;
+pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
////////////////////////////////////////////////////////////////////////////////
// Misc helpers
mod tests {
use super::*;
- use rc::Rc;
- use sync::Arc;
+ use crate::rc::Rc;
+ use crate::sync::Arc;
macro_rules! t(
($path:expr, iter: $iter:expr) => (
#[test]
fn into() {
- use borrow::Cow;
+ use crate::borrow::Cow;
let static_path = Path::new("/home/foo");
let static_cow_path: Cow<'static, Path> = static_path.into();
#[test]
fn test_eq_receivers() {
- use borrow::Cow;
+ use crate::borrow::Cow;
let borrowed: &Path = Path::new("foo/bar");
let mut owned: PathBuf = PathBuf::new();
#[test]
pub fn test_compare() {
- use hash::{Hash, Hasher};
- use collections::hash_map::DefaultHasher;
+ use crate::hash::{Hash, Hasher};
+ use crate::collections::hash_map::DefaultHasher;
fn hash<T: Hash>(t: T) -> u64 {
let mut s = DefaultHasher::new();
// Re-exported core operators
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use marker::{Copy, Send, Sized, Sync, Unpin};
+pub use crate::marker::{Copy, Send, Sized, Sync, Unpin};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use ops::{Drop, Fn, FnMut, FnOnce};
+pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
// Re-exported functions
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use mem::drop;
+pub use crate::mem::drop;
// Re-exported types and traits
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use clone::Clone;
+pub use crate::clone::Clone;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
+pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use convert::{AsRef, AsMut, Into, From};
+pub use crate::convert::{AsRef, AsMut, Into, From};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use default::Default;
+pub use crate::default::Default;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use iter::{Iterator, Extend, IntoIterator};
+pub use crate::iter::{Iterator, Extend, IntoIterator};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use iter::{DoubleEndedIterator, ExactSizeIterator};
+pub use crate::iter::{DoubleEndedIterator, ExactSizeIterator};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use option::Option::{self, Some, None};
+pub use crate::option::Option::{self, Some, None};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use result::Result::{self, Ok, Err};
+pub use crate::result::Result::{self, Ok, Err};
// The file so far is equivalent to src/libcore/prelude/v1.rs,
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use boxed::Box;
+pub use crate::boxed::Box;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use borrow::ToOwned;
+pub use crate::borrow::ToOwned;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use slice::SliceConcatExt;
+pub use crate::slice::SliceConcatExt;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use string::{String, ToString};
+pub use crate::string::{String, ToString};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
-pub use vec::Vec;
+pub use crate::vec::Vec;
#![stable(feature = "process", since = "1.0.0")]
-use io::prelude::*;
-
-use ffi::OsStr;
-use fmt;
-use fs;
-use io::{self, Initializer};
-use path::Path;
-use str;
-use sys::pipe::{read2, AnonPipe};
-use sys::process as imp;
-use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
+use crate::io::prelude::*;
+
+use crate::ffi::OsStr;
+use crate::fmt;
+use crate::fs;
+use crate::io::{self, Initializer};
+use crate::path::Path;
+use crate::str;
+use crate::sys::pipe::{read2, AnonPipe};
+use crate::sys::process as imp;
+use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
/// Representation of a running or exited child process.
///
///
/// `ChildStdin` will be converted to `Stdio` using `Stdio::from` under the hood.
///
- /// ```rust
+ /// ```rust,no_run
/// use std::process::{Command, Stdio};
///
/// let reverse = Command::new("rev")
///
/// `ChildStdout` will be converted to `Stdio` using `Stdio::from` under the hood.
///
- /// ```rust
+ /// ```rust,no_run
/// use std::process::{Command, Stdio};
///
/// let hello = Command::new("echo")
/// [platform-specific behavior]: #platform-specific-behavior
#[stable(feature = "rust1", since = "1.0.0")]
pub fn exit(code: i32) -> ! {
- ::sys_common::cleanup();
- ::sys::os::exit(code)
+ crate::sys_common::cleanup();
+ crate::sys::os::exit(code)
}
/// Terminates the process in an abnormal fashion.
/// [panic hook]: ../../std/panic/fn.set_hook.html
#[stable(feature = "process_abort", since = "1.17.0")]
pub fn abort() -> ! {
- unsafe { ::sys::abort_internal() };
+ unsafe { crate::sys::abort_internal() };
}
/// Returns the OS-assigned process identifier associated with this process.
///
#[stable(feature = "getpid", since = "1.26.0")]
pub fn id() -> u32 {
- ::sys::os::getpid()
+ crate::sys::os::getpid()
}
/// A trait for implementing arbitrary return types in the `main` function.
#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
- use io::prelude::*;
+ use crate::io::prelude::*;
- use io::ErrorKind;
- use str;
+ use crate::io::ErrorKind;
+ use crate::str;
use super::{Command, Output, Stdio};
// FIXME(#10380) these tests should not all be ignored on android.
#[cfg(unix)]
#[cfg_attr(target_os = "android", ignore)]
fn signal_reported_right() {
- use os::unix::process::ExitStatusExt;
+ use crate::os::unix::process::ExitStatusExt;
let mut p = Command::new("/bin/sh")
.arg("-c").arg("read a")
#[cfg_attr(target_os = "android", ignore)]
#[cfg(unix)]
fn uid_works() {
- use os::unix::prelude::*;
- use libc;
+ use crate::os::unix::prelude::*;
+
let mut p = Command::new("/bin/sh")
.arg("-c").arg("true")
.uid(unsafe { libc::getuid() })
#[cfg_attr(target_os = "android", ignore)]
#[cfg(unix)]
fn uid_to_root_fails() {
- use os::unix::prelude::*;
- use libc;
+ use crate::os::unix::prelude::*;
// if we're already root, this isn't a valid test. Most of the bots run
// as non-root though (android is an exception).
#[test]
fn test_override_env() {
- use env;
+ use crate::env;
// In some build environments (such as chrooted Nix builds), `env` can
// only be found in the explicitly-provided PATH env variable, not in
#[test]
fn test_capture_env_at_spawn() {
- use env;
+ use crate::env;
let mut cmd = env_cmd();
cmd.env("RUN_TEST_NEW_ENV1", "123");
#[test]
#[cfg(windows)]
fn test_creation_flags() {
- use os::windows::process::CommandExt;
- use sys::c::{BOOL, DWORD, INFINITE};
+ use crate::os::windows::process::CommandExt;
+ use crate::sys::c::{BOOL, DWORD, INFINITE};
#[repr(C, packed)]
struct DEBUG_EVENT {
pub event_code: DWORD,
// Re-export some of our utilities which are expected by other crates.
-pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
+pub use crate::panicking::{begin_panic, begin_panic_fmt, update_panic_count};
// To reduce the generated code of the new `lang_start`, this function is doing
// the real work.
#[cfg(not(test))]
-fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
+fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
argc: isize, argv: *const *const u8) -> isize {
- use panic;
- use sys;
- use sys_common;
- use sys_common::thread_info;
- use thread::Thread;
+ use crate::panic;
+ use crate::sys;
+ use crate::sys_common;
+ use crate::sys_common::thread_info;
+ use crate::thread::Thread;
sys::init();
// Let's run some code!
#[cfg(feature = "backtrace")]
let exit_code = panic::catch_unwind(|| {
- ::sys_common::backtrace::__rust_begin_short_backtrace(move || main())
+ sys_common::backtrace::__rust_begin_short_backtrace(move || main())
});
#[cfg(not(feature = "backtrace"))]
let exit_code = panic::catch_unwind(move || main());
#[cfg(not(test))]
#[lang = "start"]
-fn lang_start<T: ::process::Termination + 'static>
+fn lang_start<T: crate::process::Termination + 'static>
(main: fn() -> T, argc: isize, argv: *const *const u8) -> isize
{
lang_start_internal(&move || main().report(), argc, argv)
-use fmt;
-use sync::{Mutex, Condvar};
+use crate::fmt;
+use crate::sync::{Mutex, Condvar};
/// A barrier enables multiple threads to synchronize the beginning
/// of some computation.
#[cfg(test)]
mod tests {
- use sync::{Arc, Barrier};
- use sync::mpsc::{channel, TryRecvError};
- use thread;
+ use crate::sync::{Arc, Barrier};
+ use crate::sync::mpsc::{channel, TryRecvError};
+ use crate::thread;
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
-use fmt;
-use sync::atomic::{AtomicUsize, Ordering};
-use sync::{mutex, MutexGuard, PoisonError};
-use sys_common::condvar as sys;
-use sys_common::mutex as sys_mutex;
-use sys_common::poison::{self, LockResult};
-use time::{Duration, Instant};
+use crate::fmt;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::{mutex, MutexGuard, PoisonError};
+use crate::sys_common::condvar as sys;
+use crate::sys_common::mutex as sys_mutex;
+use crate::sys_common::poison::{self, LockResult};
+use crate::time::{Duration, Instant};
/// A type indicating whether a timed wait on a condition variable returned
/// due to a time out or not.
#[cfg(test)]
mod tests {
/// #![feature(wait_until)]
- use sync::mpsc::channel;
- use sync::{Condvar, Mutex, Arc};
- use sync::atomic::{AtomicBool, Ordering};
- use thread;
- use time::Duration;
- use u64;
+ use crate::sync::mpsc::channel;
+ use crate::sync::{Condvar, Mutex, Arc};
+ use crate::sync::atomic::{AtomicBool, Ordering};
+ use crate::thread;
+ use crate::time::Duration;
+ use crate::u64;
#[test]
fn smoke() {
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::once::{Once, OnceState, ONCE_INIT};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
+pub use crate::sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
//! Generic support for building blocking abstractions.
-use thread::{self, Thread};
-use sync::atomic::{AtomicBool, Ordering};
-use sync::Arc;
-use mem;
-use time::Instant;
+use crate::thread::{self, Thread};
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::Arc;
+use crate::mem;
+use crate::time::Instant;
struct Inner {
thread: Thread,
-use ops::{Deref, DerefMut};
+use crate::ops::{Deref, DerefMut};
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(align(64))]
// And now that you've seen all the races that I found and attempted to fix,
// here's the code for you to find some more!
-use sync::Arc;
-use error;
-use fmt;
-use mem;
-use cell::UnsafeCell;
-use time::{Duration, Instant};
+use crate::sync::Arc;
+use crate::error;
+use crate::fmt;
+use crate::mem;
+use crate::cell::UnsafeCell;
+use crate::time::{Duration, Instant};
#[unstable(feature = "mpsc_select", issue = "27800")]
pub use self::select::{Select, Handle};
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use env;
use super::*;
- use thread;
- use time::{Duration, Instant};
+ use crate::env;
+ use crate::thread;
+ use crate::time::{Duration, Instant};
pub fn stress_factor() -> usize {
match env::var("RUST_TEST_STRESS") {
#[cfg(all(test, not(target_os = "emscripten")))]
mod sync_tests {
- use env;
- use thread;
use super::*;
- use time::Duration;
+ use crate::env;
+ use crate::thread;
+ use crate::time::Duration;
pub fn stress_factor() -> usize {
match env::var("RUST_TEST_STRESS") {
use core::ptr;
use core::cell::UnsafeCell;
-use boxed::Box;
-use sync::atomic::{AtomicPtr, Ordering};
+
+use crate::boxed::Box;
+use crate::sync::atomic::{AtomicPtr, Ordering};
/// A result of the `pop` function.
pub enum PopResult<T> {
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use sync::mpsc::channel;
use super::{Queue, Data, Empty, Inconsistent};
- use sync::Arc;
- use thread;
+ use crate::sync::mpsc::channel;
+ use crate::sync::Arc;
+ use crate::thread;
#[test]
fn test_full() {
pub use self::SelectionResult::*;
use self::MyUpgrade::*;
-use sync::mpsc::Receiver;
-use sync::mpsc::blocking::{self, SignalToken};
-use cell::UnsafeCell;
-use ptr;
-use sync::atomic::{AtomicUsize, Ordering};
-use time::Instant;
+use crate::sync::mpsc::Receiver;
+use crate::sync::mpsc::blocking::{self, SignalToken};
+use crate::cell::UnsafeCell;
+use crate::ptr;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::time::Instant;
// Various states you can find a port in.
const EMPTY: usize = 0; // initial state: no data, no blocked receiver
#![rustc_deprecated(since = "1.32.0",
reason = "channel selection will be removed in a future release")]
-
-use fmt;
-
use core::cell::{Cell, UnsafeCell};
use core::marker;
use core::ptr;
use core::usize;
-use sync::mpsc::{Receiver, RecvError};
-use sync::mpsc::blocking::{self, SignalToken};
+use crate::fmt;
+use crate::sync::mpsc::{Receiver, RecvError};
+use crate::sync::mpsc::blocking::{self, SignalToken};
/// The "receiver set" of the select interface. This structure is used to manage
/// a set of receivers which are being selected over.
/// This file exists to hack around https://github.com/rust-lang/rust/issues/47238
-use thread;
-use sync::mpsc::*;
+use crate::thread;
+use crate::sync::mpsc::*;
// Don't use the libstd version so we can pull in the right Select structure
// (std::comm points at the wrong one)
use core::intrinsics::abort;
use core::isize;
-use cell::UnsafeCell;
-use ptr;
-use sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
-use sync::mpsc::blocking::{self, SignalToken};
-use sync::mpsc::mpsc_queue as mpsc;
-use sync::mpsc::select::StartResult::*;
-use sync::mpsc::select::StartResult;
-use sync::{Mutex, MutexGuard};
-use thread;
-use time::Instant;
+use crate::cell::UnsafeCell;
+use crate::ptr;
+use crate::sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
+use crate::sync::mpsc::blocking::{self, SignalToken};
+use crate::sync::mpsc::mpsc_queue as mpsc;
+use crate::sync::mpsc::select::StartResult::*;
+use crate::sync::mpsc::select::StartResult;
+use crate::sync::{Mutex, MutexGuard};
+use crate::thread;
+use crate::time::Instant;
const DISCONNECTED: isize = isize::MIN;
const FUDGE: isize = 1024;
// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
-use boxed::Box;
use core::ptr;
use core::cell::UnsafeCell;
-use sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
+use crate::boxed::Box;
+use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
use super::cache_aligned::CacheAligned;
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use sync::Arc;
use super::Queue;
- use thread;
- use sync::mpsc::channel;
+ use crate::sync::Arc;
+ use crate::thread;
+ use crate::sync::mpsc::channel;
#[test]
fn smoke() {
pub use self::SelectionResult::*;
use self::Message::*;
-use cell::UnsafeCell;
use core::cmp;
use core::isize;
-use ptr;
-use thread;
-use time::Instant;
-
-use sync::atomic::{AtomicIsize, AtomicUsize, Ordering, AtomicBool};
-use sync::mpsc::Receiver;
-use sync::mpsc::blocking::{self, SignalToken};
-use sync::mpsc::spsc_queue as spsc;
+
+use crate::cell::UnsafeCell;
+use crate::ptr;
+use crate::thread;
+use crate::time::Instant;
+
+use crate::sync::atomic::{AtomicIsize, AtomicUsize, Ordering, AtomicBool};
+use crate::sync::mpsc::Receiver;
+use crate::sync::mpsc::blocking::{self, SignalToken};
+use crate::sync::mpsc::spsc_queue as spsc;
const DISCONNECTED: isize = isize::MIN;
#[cfg(test)]
use core::mem;
use core::ptr;
-use sync::atomic::{Ordering, AtomicUsize};
-use sync::mpsc::blocking::{self, WaitToken, SignalToken};
-use sync::mpsc::select::StartResult::{self, Installed, Abort};
-use sync::{Mutex, MutexGuard};
-use time::Instant;
+use crate::sync::atomic::{Ordering, AtomicUsize};
+use crate::sync::mpsc::blocking::{self, WaitToken, SignalToken};
+use crate::sync::mpsc::select::StartResult::{self, Installed, Abort};
+use crate::sync::{Mutex, MutexGuard};
+use crate::time::Instant;
const MAX_REFCOUNT: usize = (isize::MAX) as usize;
-use cell::UnsafeCell;
-use fmt;
-use mem;
-use ops::{Deref, DerefMut};
-use ptr;
-use sys_common::mutex as sys;
-use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
+use crate::cell::UnsafeCell;
+use crate::fmt;
+use crate::mem;
+use crate::ops::{Deref, DerefMut};
+use crate::ptr;
+use crate::sys_common::mutex as sys;
+use crate::sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
/// A mutual exclusion primitive useful for protecting shared data
///
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use sync::mpsc::channel;
- use sync::{Arc, Mutex, Condvar};
- use sync::atomic::{AtomicUsize, Ordering};
- use thread;
+ use crate::sync::mpsc::channel;
+ use crate::sync::{Arc, Mutex, Condvar};
+ use crate::sync::atomic::{AtomicUsize, Ordering};
+ use crate::thread;
struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
// You'll find a few more details in the implementation, but that's the gist of
// it!
-use fmt;
-use marker;
-use ptr;
-use sync::atomic::{AtomicUsize, AtomicBool, Ordering};
-use thread::{self, Thread};
+use crate::fmt;
+use crate::marker;
+use crate::ptr;
+use crate::sync::atomic::{AtomicUsize, AtomicBool, Ordering};
+use crate::thread::{self, Thread};
/// A synchronization primitive which can be used to run a one-time global
/// initialization. Useful for one-time initialization for FFI or related
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use panic;
- use sync::mpsc::channel;
- use thread;
+ use crate::panic;
+ use crate::sync::mpsc::channel;
+ use crate::thread;
use super::Once;
#[test]
-use cell::UnsafeCell;
-use fmt;
-use mem;
-use ops::{Deref, DerefMut};
-use ptr;
-use sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
-use sys_common::rwlock as sys;
+use crate::cell::UnsafeCell;
+use crate::fmt;
+use crate::mem;
+use crate::ops::{Deref, DerefMut};
+use crate::ptr;
+use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
+use crate::sys_common::rwlock as sys;
/// A reader-writer lock
///
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use rand::{self, Rng};
- use sync::mpsc::channel;
- use thread;
- use sync::{Arc, RwLock, TryLockError};
- use sync::atomic::{AtomicUsize, Ordering};
+ use crate::sync::mpsc::channel;
+ use crate::thread;
+ use crate::sync::{Arc, RwLock, TryLockError};
+ use crate::sync::atomic::{AtomicUsize, Ordering};
#[derive(Eq, PartialEq, Debug)]
struct NonCopy(i32);
// ignore-license
#[cfg(feature = "bitflags")]
-#[macro_use]
-extern crate bitflags;
+use bitflags::bitflags;
// Minimal implementation of bitflags! in case we can't depend on the bitflags
// crate. Only implements `bits()` and a `from_bits_truncate()` that doesn't
#[test]
#[cfg(target_pointer_width = "32")]
fn auxv_layout_test_32() {
- assert_eq!(::core::mem::size_of::<auxv>(), 8);
- assert_eq!(::core::mem::align_of::<auxv>(), 4);
+ assert_eq!(core::mem::size_of::<auxv>(), 8);
+ assert_eq!(core::mem::align_of::<auxv>(), 4);
unsafe {
- let obj: auxv = ::core::mem::uninitialized();
+ let obj: auxv = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.a_type as *const _ as usize - base, 0);
assert_eq!(&obj.union.a_val as *const _ as usize - base, 4);
#[test]
#[cfg(target_pointer_width = "64")]
fn auxv_layout_test_64() {
- assert_eq!(::core::mem::size_of::<auxv>(), 16);
- assert_eq!(::core::mem::align_of::<auxv>(), 8);
+ assert_eq!(core::mem::size_of::<auxv>(), 16);
+ assert_eq!(core::mem::align_of::<auxv>(), 8);
unsafe {
- let obj: auxv = ::core::mem::uninitialized();
+ let obj: auxv = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.a_type as *const _ as usize - base, 0);
assert_eq!(&obj.union.a_val as *const _ as usize - base, 8);
#[test]
#[cfg(target_pointer_width = "32")]
fn ciovec_layout_test_32() {
- assert_eq!(::core::mem::size_of::<ciovec>(), 8);
- assert_eq!(::core::mem::align_of::<ciovec>(), 4);
+ assert_eq!(core::mem::size_of::<ciovec>(), 8);
+ assert_eq!(core::mem::align_of::<ciovec>(), 4);
unsafe {
- let obj: ciovec = ::core::mem::uninitialized();
+ let obj: ciovec = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
#[test]
#[cfg(target_pointer_width = "64")]
fn ciovec_layout_test_64() {
- assert_eq!(::core::mem::size_of::<ciovec>(), 16);
- assert_eq!(::core::mem::align_of::<ciovec>(), 8);
+ assert_eq!(core::mem::size_of::<ciovec>(), 16);
+ assert_eq!(core::mem::align_of::<ciovec>(), 8);
unsafe {
- let obj: ciovec = ::core::mem::uninitialized();
+ let obj: ciovec = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
}
#[test]
fn dirent_layout_test() {
- assert_eq!(::core::mem::size_of::<dirent>(), 24);
- assert_eq!(::core::mem::align_of::<dirent>(), 8);
+ assert_eq!(core::mem::size_of::<dirent>(), 24);
+ assert_eq!(core::mem::align_of::<dirent>(), 8);
unsafe {
- let obj: dirent = ::core::mem::uninitialized();
+ let obj: dirent = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.d_next as *const _ as usize - base, 0);
assert_eq!(&obj.d_ino as *const _ as usize - base, 8);
}
#[test]
fn event_layout_test() {
- assert_eq!(::core::mem::size_of::<event>(), 32);
- assert_eq!(::core::mem::align_of::<event>(), 8);
+ assert_eq!(core::mem::size_of::<event>(), 32);
+ assert_eq!(core::mem::align_of::<event>(), 8);
unsafe {
- let obj: event = ::core::mem::uninitialized();
+ let obj: event = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.userdata as *const _ as usize - base, 0);
assert_eq!(&obj.error as *const _ as usize - base, 8);
}
#[test]
fn fdstat_layout_test() {
- assert_eq!(::core::mem::size_of::<fdstat>(), 24);
- assert_eq!(::core::mem::align_of::<fdstat>(), 8);
+ assert_eq!(core::mem::size_of::<fdstat>(), 24);
+ assert_eq!(core::mem::align_of::<fdstat>(), 8);
unsafe {
- let obj: fdstat = ::core::mem::uninitialized();
+ let obj: fdstat = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.fs_filetype as *const _ as usize - base, 0);
assert_eq!(&obj.fs_flags as *const _ as usize - base, 2);
}
#[test]
fn filestat_layout_test() {
- assert_eq!(::core::mem::size_of::<filestat>(), 56);
- assert_eq!(::core::mem::align_of::<filestat>(), 8);
+ assert_eq!(core::mem::size_of::<filestat>(), 56);
+ assert_eq!(core::mem::align_of::<filestat>(), 8);
unsafe {
- let obj: filestat = ::core::mem::uninitialized();
+ let obj: filestat = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.st_dev as *const _ as usize - base, 0);
assert_eq!(&obj.st_ino as *const _ as usize - base, 8);
#[test]
#[cfg(target_pointer_width = "32")]
fn iovec_layout_test_32() {
- assert_eq!(::core::mem::size_of::<iovec>(), 8);
- assert_eq!(::core::mem::align_of::<iovec>(), 4);
+ assert_eq!(core::mem::size_of::<iovec>(), 8);
+ assert_eq!(core::mem::align_of::<iovec>(), 4);
unsafe {
- let obj: iovec = ::core::mem::uninitialized();
+ let obj: iovec = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
#[test]
#[cfg(target_pointer_width = "64")]
fn iovec_layout_test_64() {
- assert_eq!(::core::mem::size_of::<iovec>(), 16);
- assert_eq!(::core::mem::align_of::<iovec>(), 8);
+ assert_eq!(core::mem::size_of::<iovec>(), 16);
+ assert_eq!(core::mem::align_of::<iovec>(), 8);
unsafe {
- let obj: iovec = ::core::mem::uninitialized();
+ let obj: iovec = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
}
#[test]
fn lookup_layout_test() {
- assert_eq!(::core::mem::size_of::<lookup>(), 8);
- assert_eq!(::core::mem::align_of::<lookup>(), 4);
+ assert_eq!(core::mem::size_of::<lookup>(), 8);
+ assert_eq!(core::mem::align_of::<lookup>(), 4);
unsafe {
- let obj: lookup = ::core::mem::uninitialized();
+ let obj: lookup = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.fd as *const _ as usize - base, 0);
assert_eq!(&obj.flags as *const _ as usize - base, 4);
#[test]
#[cfg(target_pointer_width = "32")]
fn recv_in_layout_test_32() {
- assert_eq!(::core::mem::size_of::<recv_in>(), 20);
- assert_eq!(::core::mem::align_of::<recv_in>(), 4);
+ assert_eq!(core::mem::size_of::<recv_in>(), 20);
+ assert_eq!(core::mem::align_of::<recv_in>(), 4);
unsafe {
- let obj: recv_in = ::core::mem::uninitialized();
+ let obj: recv_in = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 4);
#[test]
#[cfg(target_pointer_width = "64")]
fn recv_in_layout_test_64() {
- assert_eq!(::core::mem::size_of::<recv_in>(), 40);
- assert_eq!(::core::mem::align_of::<recv_in>(), 8);
+ assert_eq!(core::mem::size_of::<recv_in>(), 40);
+ assert_eq!(core::mem::align_of::<recv_in>(), 8);
unsafe {
- let obj: recv_in = ::core::mem::uninitialized();
+ let obj: recv_in = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 8);
#[test]
#[cfg(target_pointer_width = "32")]
fn recv_out_layout_test_32() {
- assert_eq!(::core::mem::size_of::<recv_out>(), 52);
- assert_eq!(::core::mem::align_of::<recv_out>(), 4);
+ assert_eq!(core::mem::size_of::<recv_out>(), 52);
+ assert_eq!(core::mem::align_of::<recv_out>(), 4);
unsafe {
- let obj: recv_out = ::core::mem::uninitialized();
+ let obj: recv_out = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 4);
#[test]
#[cfg(target_pointer_width = "64")]
fn recv_out_layout_test_64() {
- assert_eq!(::core::mem::size_of::<recv_out>(), 64);
- assert_eq!(::core::mem::align_of::<recv_out>(), 8);
+ assert_eq!(core::mem::size_of::<recv_out>(), 64);
+ assert_eq!(core::mem::align_of::<recv_out>(), 8);
unsafe {
- let obj: recv_out = ::core::mem::uninitialized();
+ let obj: recv_out = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 8);
#[test]
#[cfg(target_pointer_width = "32")]
fn send_in_layout_test_32() {
- assert_eq!(::core::mem::size_of::<send_in>(), 20);
- assert_eq!(::core::mem::align_of::<send_in>(), 4);
+ assert_eq!(core::mem::size_of::<send_in>(), 20);
+ assert_eq!(core::mem::align_of::<send_in>(), 4);
unsafe {
- let obj: send_in = ::core::mem::uninitialized();
+ let obj: send_in = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
assert_eq!(&obj.si_data.1 as *const _ as usize - base, 4);
#[test]
#[cfg(target_pointer_width = "64")]
fn send_in_layout_test_64() {
- assert_eq!(::core::mem::size_of::<send_in>(), 40);
- assert_eq!(::core::mem::align_of::<send_in>(), 8);
+ assert_eq!(core::mem::size_of::<send_in>(), 40);
+ assert_eq!(core::mem::align_of::<send_in>(), 8);
unsafe {
- let obj: send_in = ::core::mem::uninitialized();
+ let obj: send_in = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
assert_eq!(&obj.si_data.1 as *const _ as usize - base, 8);
#[test]
#[cfg(target_pointer_width = "32")]
fn send_out_layout_test_32() {
- assert_eq!(::core::mem::size_of::<send_out>(), 4);
- assert_eq!(::core::mem::align_of::<send_out>(), 4);
+ assert_eq!(core::mem::size_of::<send_out>(), 4);
+ assert_eq!(core::mem::align_of::<send_out>(), 4);
unsafe {
- let obj: send_out = ::core::mem::uninitialized();
+ let obj: send_out = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
}
#[test]
#[cfg(target_pointer_width = "64")]
fn send_out_layout_test_64() {
- assert_eq!(::core::mem::size_of::<send_out>(), 8);
- assert_eq!(::core::mem::align_of::<send_out>(), 8);
+ assert_eq!(core::mem::size_of::<send_out>(), 8);
+ assert_eq!(core::mem::align_of::<send_out>(), 8);
unsafe {
- let obj: send_out = ::core::mem::uninitialized();
+ let obj: send_out = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
}
#[test]
#[cfg(target_pointer_width = "32")]
fn subscription_layout_test_32() {
- assert_eq!(::core::mem::size_of::<subscription>(), 56);
- assert_eq!(::core::mem::align_of::<subscription>(), 8);
+ assert_eq!(core::mem::size_of::<subscription>(), 56);
+ assert_eq!(core::mem::align_of::<subscription>(), 8);
unsafe {
- let obj: subscription = ::core::mem::uninitialized();
+ let obj: subscription = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.userdata as *const _ as usize - base, 0);
assert_eq!(&obj.unused as *const _ as usize - base, 8);
#[test]
#[cfg(target_pointer_width = "64")]
fn subscription_layout_test_64() {
- assert_eq!(::core::mem::size_of::<subscription>(), 56);
- assert_eq!(::core::mem::align_of::<subscription>(), 8);
+ assert_eq!(core::mem::size_of::<subscription>(), 56);
+ assert_eq!(core::mem::align_of::<subscription>(), 8);
unsafe {
- let obj: subscription = ::core::mem::uninitialized();
+ let obj: subscription = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.userdata as *const _ as usize - base, 0);
assert_eq!(&obj.unused as *const _ as usize - base, 8);
#[test]
#[cfg(target_pointer_width = "32")]
fn tcb_layout_test_32() {
- assert_eq!(::core::mem::size_of::<tcb>(), 4);
- assert_eq!(::core::mem::align_of::<tcb>(), 4);
+ assert_eq!(core::mem::size_of::<tcb>(), 4);
+ assert_eq!(core::mem::align_of::<tcb>(), 4);
unsafe {
- let obj: tcb = ::core::mem::uninitialized();
+ let obj: tcb = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.parent as *const _ as usize - base, 0);
}
#[test]
#[cfg(target_pointer_width = "64")]
fn tcb_layout_test_64() {
- assert_eq!(::core::mem::size_of::<tcb>(), 8);
- assert_eq!(::core::mem::align_of::<tcb>(), 8);
+ assert_eq!(core::mem::size_of::<tcb>(), 8);
+ assert_eq!(core::mem::align_of::<tcb>(), 8);
unsafe {
- let obj: tcb = ::core::mem::uninitialized();
+ let obj: tcb = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.parent as *const _ as usize - base, 0);
}
#[test]
#[cfg(target_pointer_width = "32")]
fn threadattr_layout_test_32() {
- assert_eq!(::core::mem::size_of::<threadattr>(), 16);
- assert_eq!(::core::mem::align_of::<threadattr>(), 4);
+ assert_eq!(core::mem::size_of::<threadattr>(), 16);
+ assert_eq!(core::mem::align_of::<threadattr>(), 4);
unsafe {
- let obj: threadattr = ::core::mem::uninitialized();
+ let obj: threadattr = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
assert_eq!(&obj.stack.0 as *const _ as usize - base, 4);
#[test]
#[cfg(target_pointer_width = "64")]
fn threadattr_layout_test_64() {
- assert_eq!(::core::mem::size_of::<threadattr>(), 32);
- assert_eq!(::core::mem::align_of::<threadattr>(), 8);
+ assert_eq!(core::mem::size_of::<threadattr>(), 32);
+ assert_eq!(core::mem::align_of::<threadattr>(), 8);
unsafe {
- let obj: threadattr = ::core::mem::uninitialized();
+ let obj: threadattr = core::mem::uninitialized();
let base = &obj as *const _ as usize;
assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
assert_eq!(&obj.stack.0 as *const _ as usize - base, 8);
-pub use sys::cloudabi::shims::args::*;
+pub use crate::sys::cloudabi::shims::args::*;
#[allow(dead_code)]
pub fn init(_: isize, _: *const *const u8) {}
-use error::Error;
-use ffi::CStr;
-use intrinsics;
-use io;
-use libc;
-use sys_common::backtrace::Frame;
+use crate::error::Error;
+use crate::ffi::CStr;
+use crate::fmt;
+use crate::intrinsics;
+use crate::io;
+use crate::sys_common::backtrace::Frame;
+
use unwind as uw;
pub struct BacktraceContext;
}
}
-impl ::fmt::Display for UnwindError {
- fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+impl fmt::Display for UnwindError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {:?}", self.description(), self.0)
}
}
-use cell::UnsafeCell;
-use mem;
-use sync::atomic::{AtomicU32, Ordering};
-use sys::cloudabi::abi;
-use sys::mutex::{self, Mutex};
-use sys::time::checked_dur2intervals;
-use time::Duration;
+use crate::cell::UnsafeCell;
+use crate::mem;
+use crate::sync::atomic::{AtomicU32, Ordering};
+use crate::sys::cloudabi::abi;
+use crate::sys::mutex::{self, Mutex};
+use crate::sys::time::checked_dur2intervals;
+use crate::time::Duration;
extern "C" {
#[thread_local]
-use libc;
-use mem;
+use crate::io::ErrorKind;
+use crate::mem;
#[path = "../unix/alloc.rs"]
pub mod alloc;
#[allow(dead_code)]
pub fn init() {}
-pub fn decode_error_kind(errno: i32) -> ::io::ErrorKind {
+pub fn decode_error_kind(errno: i32) -> ErrorKind {
match errno {
- x if x == abi::errno::ACCES as i32 => ::io::ErrorKind::PermissionDenied,
- x if x == abi::errno::ADDRINUSE as i32 => ::io::ErrorKind::AddrInUse,
- x if x == abi::errno::ADDRNOTAVAIL as i32 => ::io::ErrorKind::AddrNotAvailable,
- x if x == abi::errno::AGAIN as i32 => ::io::ErrorKind::WouldBlock,
- x if x == abi::errno::CONNABORTED as i32 => ::io::ErrorKind::ConnectionAborted,
- x if x == abi::errno::CONNREFUSED as i32 => ::io::ErrorKind::ConnectionRefused,
- x if x == abi::errno::CONNRESET as i32 => ::io::ErrorKind::ConnectionReset,
- x if x == abi::errno::EXIST as i32 => ::io::ErrorKind::AlreadyExists,
- x if x == abi::errno::INTR as i32 => ::io::ErrorKind::Interrupted,
- x if x == abi::errno::INVAL as i32 => ::io::ErrorKind::InvalidInput,
- x if x == abi::errno::NOENT as i32 => ::io::ErrorKind::NotFound,
- x if x == abi::errno::NOTCONN as i32 => ::io::ErrorKind::NotConnected,
- x if x == abi::errno::PERM as i32 => ::io::ErrorKind::PermissionDenied,
- x if x == abi::errno::PIPE as i32 => ::io::ErrorKind::BrokenPipe,
- x if x == abi::errno::TIMEDOUT as i32 => ::io::ErrorKind::TimedOut,
- _ => ::io::ErrorKind::Other,
+ x if x == abi::errno::ACCES as i32 => ErrorKind::PermissionDenied,
+ x if x == abi::errno::ADDRINUSE as i32 => ErrorKind::AddrInUse,
+ x if x == abi::errno::ADDRNOTAVAIL as i32 => ErrorKind::AddrNotAvailable,
+ x if x == abi::errno::AGAIN as i32 => ErrorKind::WouldBlock,
+ x if x == abi::errno::CONNABORTED as i32 => ErrorKind::ConnectionAborted,
+ x if x == abi::errno::CONNREFUSED as i32 => ErrorKind::ConnectionRefused,
+ x if x == abi::errno::CONNRESET as i32 => ErrorKind::ConnectionReset,
+ x if x == abi::errno::EXIST as i32 => ErrorKind::AlreadyExists,
+ x if x == abi::errno::INTR as i32 => ErrorKind::Interrupted,
+ x if x == abi::errno::INVAL as i32 => ErrorKind::InvalidInput,
+ x if x == abi::errno::NOENT as i32 => ErrorKind::NotFound,
+ x if x == abi::errno::NOTCONN as i32 => ErrorKind::NotConnected,
+ x if x == abi::errno::PERM as i32 => ErrorKind::PermissionDenied,
+ x if x == abi::errno::PIPE as i32 => ErrorKind::BrokenPipe,
+ x if x == abi::errno::TIMEDOUT as i32 => ErrorKind::TimedOut,
+ _ => ErrorKind::Other,
}
}
pub unsafe fn abort_internal() -> ! {
- ::core::intrinsics::abort();
+ core::intrinsics::abort();
}
pub use libc::strlen;
-use cell::UnsafeCell;
-use mem;
-use sync::atomic::{AtomicU32, Ordering};
-use sys::cloudabi::abi;
-use sys::rwlock::{self, RWLock};
+use crate::cell::UnsafeCell;
+use crate::mem;
+use crate::sync::atomic::{AtomicU32, Ordering};
+use crate::sys::cloudabi::abi;
+use crate::sys::rwlock::{self, RWLock};
extern "C" {
#[thread_local]
-use ffi::CStr;
-use libc::{self, c_int};
-use str;
+use crate::ffi::CStr;
+use crate::str;
-pub use sys::cloudabi::shims::os::*;
+use libc::c_int;
+
+pub use crate::sys::cloudabi::shims::os::*;
pub fn errno() -> i32 {
extern "C" {
-use cell::UnsafeCell;
-use mem;
-use sync::atomic::{AtomicU32, Ordering};
-use sys::cloudabi::abi;
+use crate::cell::UnsafeCell;
+use crate::mem;
+use crate::sync::atomic::{AtomicU32, Ordering};
+use crate::sys::cloudabi::abi;
extern "C" {
#[thread_local]
-use ffi::OsString;
+use crate::ffi::OsString;
pub struct Args(());
-use ffi::OsString;
-use fmt;
-use hash::{Hash, Hasher};
-use io::{self, SeekFrom};
-use path::{Path, PathBuf};
-use sys::time::SystemTime;
-use sys::{unsupported, Void};
+use crate::ffi::OsString;
+use crate::fmt;
+use crate::hash::{Hash, Hasher};
+use crate::io::{self, SeekFrom};
+use crate::path::{Path, PathBuf};
+use crate::sys::time::SystemTime;
+use crate::sys::{unsupported, Void};
pub struct File(Void);
-use io;
+use crate::io;
pub mod args;
pub mod env;
-use fmt;
-use io::{self, IoVec, IoVecMut};
-use net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
-use time::Duration;
-use sys::{unsupported, Void};
-use convert::TryFrom;
-
+use crate::fmt;
+use crate::io::{self, IoVec, IoVecMut};
+use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use crate::time::Duration;
+use crate::sys::{unsupported, Void};
+use crate::convert::TryFrom;
+
+#[allow(unused_extern_crates)]
pub extern crate libc as netc;
pub struct TcpStream(Void);
-use error::Error as StdError;
-use ffi::{OsStr, OsString};
-use fmt;
-use io;
-use iter;
-use path::{self, PathBuf};
-use sys::{unsupported, Void};
+use crate::error::Error as StdError;
+use crate::ffi::{OsStr, OsString};
+use crate::fmt;
+use crate::io;
+use crate::iter;
+use crate::path::{self, PathBuf};
+use crate::sys::{unsupported, Void};
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
-use io;
-use sys::Void;
+use crate::io;
+use crate::sys::Void;
pub struct AnonPipe(Void);
-use ffi::OsStr;
-use fmt;
-use io;
-use sys::fs::File;
-use sys::pipe::AnonPipe;
-use sys::{unsupported, Void};
-use sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::ffi::OsStr;
+use crate::fmt;
+use crate::io;
+use crate::sys::fs::File;
+use crate::sys::pipe::AnonPipe;
+use crate::sys::{unsupported, Void};
+use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
////////////////////////////////////////////////////////////////////////////////
// Command
-use io;
-use sys::cloudabi::abi;
+use crate::io;
+use crate::sys::cloudabi::abi;
pub struct Stdin(());
pub struct Stdout(());
err.raw_os_error() == Some(abi::errno::BADF as i32)
}
-pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
pub fn panic_output() -> Option<impl io::Write> {
Stderr::new().ok()
-use boxed::FnBox;
-use cmp;
-use ffi::CStr;
-use io;
-use libc;
-use mem;
-use ptr;
-use sys::cloudabi::abi;
-use sys::time::checked_dur2intervals;
-use sys_common::thread::*;
-use time::Duration;
+use crate::boxed::FnBox;
+use crate::cmp;
+use crate::ffi::CStr;
+use crate::io;
+use crate::mem;
+use crate::ptr;
+use crate::sys::cloudabi::abi;
+use crate::sys::time::checked_dur2intervals;
+use crate::sys_common::thread::*;
+use crate::time::Duration;
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
-use mem;
-use sys::cloudabi::abi;
-use time::Duration;
+use crate::mem;
+use crate::sys::cloudabi::abi;
+use crate::time::Duration;
const NSEC_PER_SEC: abi::timestamp = 1_000_000_000;
pub mod unix_ext {}
} else {
// On other platforms like Windows document the bare bones of unix
- use os::linux as platform;
+ use crate::os::linux as platform;
#[path = "unix/ext/mod.rs"]
pub mod unix_ext;
}
#![allow(dead_code)] // runtime init functions not used during testing
-use ffi::OsString;
-use marker::PhantomData;
-use vec;
+use crate::ffi::OsString;
+use crate::marker::PhantomData;
+use crate::vec;
/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }
}
mod imp {
- use os::unix::prelude::*;
- use mem;
- use ffi::{CStr, OsString};
- use marker::PhantomData;
- use libc;
+ use crate::os::unix::prelude::*;
+ use crate::mem;
+ use crate::ffi::{CStr, OsString};
+ use crate::marker::PhantomData;
use super::Args;
- use sys_common::mutex::Mutex;
+ use crate::sys_common::mutex::Mutex;
static mut GLOBAL_ARGS_PTR: usize = 0;
static LOCK: Mutex = Mutex::new();
mod printing;
pub mod gnu {
- use io;
- use fs;
+ use crate::io;
+ use crate::fs;
+ use crate::vec::Vec;
+ use crate::ffi::OsStr;
+ use crate::os::unix::ffi::OsStrExt;
+ use crate::io::Read;
use libc::c_char;
- use vec::Vec;
- use ffi::OsStr;
- use os::unix::ffi::OsStrExt;
- use io::Read;
pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
let mut exefile = fs::File::open("sys:exe")?;
-pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
+pub use crate::sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
-use error::Error;
-use io;
-use libc;
-use sys::backtrace::BacktraceContext;
-use sys_common::backtrace::Frame;
+use crate::error::Error;
+use crate::fmt;
+use crate::io;
+use crate::sys::backtrace::BacktraceContext;
+use crate::sys_common::backtrace::Frame;
use unwind as uw;
}
}
-impl ::fmt::Display for UnwindError {
- fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+impl fmt::Display for UnwindError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {:?}", self.description(), self.0)
}
}
-use cell::UnsafeCell;
-use intrinsics::{atomic_cxchg, atomic_load, atomic_xadd, atomic_xchg};
-use ptr;
-use time::Duration;
+use crate::cell::UnsafeCell;
+use crate::intrinsics::{atomic_cxchg, atomic_load, atomic_xadd, atomic_xchg};
+use crate::ptr;
+use crate::time::Duration;
-use sys::mutex::{mutex_unlock, Mutex};
-use sys::syscall::{futex, TimeSpec, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
+use crate::sys::mutex::{mutex_unlock, Mutex};
+use crate::sys::syscall::{futex, TimeSpec, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
pub struct Condvar {
lock: UnsafeCell<*mut i32>,
atomic_xadd(seq, 1);
- let _ = futex(seq, FUTEX_REQUEUE, 1, ::usize::MAX, *lock);
+ let _ = futex(seq, FUTEX_REQUEUE, 1, crate::usize::MAX, *lock);
}
}
#![stable(feature = "rust1", since = "1.0.0")]
-use ffi::{OsStr, OsString};
-use mem;
-use sys::os_str::Buf;
-use sys_common::{FromInner, IntoInner, AsInner};
+use crate::ffi::{OsStr, OsString};
+use crate::mem;
+use crate::sys::os_str::Buf;
+use crate::sys_common::{FromInner, IntoInner, AsInner};
/// Redox-specific extensions to [`OsString`].
///
#![stable(feature = "rust1", since = "1.0.0")]
-use fs::{self, Permissions, OpenOptions};
-use io;
-use path::Path;
-use sys;
-use sys_common::{FromInner, AsInner, AsInnerMut};
+use crate::fs::{self, Permissions, OpenOptions};
+use crate::io;
+use crate::path::Path;
+use crate::sys;
+use crate::sys_common::{FromInner, AsInner, AsInnerMut};
/// Redox-specific extensions to [`fs::Permissions`].
///
#![stable(feature = "rust1", since = "1.0.0")]
-use fs;
-use net;
-use sys;
-use io;
-use sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::fs;
+use crate::net;
+use crate::sys;
+use crate::io;
+use crate::sys_common::{self, AsInner, FromInner, IntoInner};
/// Raw file descriptors.
#[stable(feature = "rust1", since = "1.0.0")]
//! Unix-specific networking functionality
-use fmt;
-use io::{self, Error, ErrorKind, Initializer};
-use net::Shutdown;
-use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
-use path::Path;
-use time::Duration;
-use sys::{cvt, fd::FileDesc, syscall};
+use crate::fmt;
+use crate::io::{self, Error, ErrorKind, Initializer};
+use crate::net::Shutdown;
+use crate::os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
+use crate::path::Path;
+use crate::time::Duration;
+use crate::sys::{cvt, fd::FileDesc, syscall};
/// An address associated with a Unix socket.
///
#![stable(feature = "rust1", since = "1.0.0")]
-use io;
-use os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
-use process;
-use sys;
-use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
+use crate::io;
+use crate::os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
+use crate::process;
+use crate::sys;
+use crate::sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
/// Redox-specific extensions to the [`process::Command`] builder,
///
#![stable(feature = "thread_extensions", since = "1.9.0")]
-use sys_common::{AsInner, IntoInner};
-use thread::JoinHandle;
+use crate::sys_common::{AsInner, IntoInner};
+use crate::thread::JoinHandle;
#[stable(feature = "thread_extensions", since = "1.9.0")]
#[allow(deprecated)]
#![cfg(target_thread_local)]
#![unstable(feature = "thread_local_internals", issue = "0")]
-use cell::{Cell, UnsafeCell};
-use mem;
-use ptr;
+use crate::cell::{Cell, UnsafeCell};
+use crate::mem;
+use crate::ptr;
pub struct Key<T> {
dtor_running: Cell<bool>,
}
-unsafe impl<T> ::marker::Sync for Key<T> { }
+unsafe impl<T> Sync for Key<T> { }
impl<T> Key<T> {
pub const fn new() -> Key<T> {
// *should* be the case that this loop always terminates because we
// provide the guarantee that a TLS key cannot be set after it is
// flagged for destruction.
- use sys_common::thread_local as os;
+ use crate::sys_common::thread_local as os;
static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors));
type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
#![unstable(reason = "not public", issue = "0", feature = "fd")]
-use io::{self, Read};
-use mem;
-use sys::{cvt, syscall};
-use sys_common::AsInner;
+use crate::io::{self, Read};
+use crate::mem;
+use crate::sys::{cvt, syscall};
+use crate::sys_common::AsInner;
pub struct FileDesc {
fd: usize,
-use os::unix::prelude::*;
-
-use ffi::{OsString, OsStr};
-use fmt;
-use io::{self, Error, ErrorKind, SeekFrom};
-use path::{Path, PathBuf};
-use sync::Arc;
-use sys::fd::FileDesc;
-use sys::time::SystemTime;
-use sys::{cvt, syscall};
-use sys_common::{AsInner, FromInner};
+use crate::os::unix::prelude::*;
+
+use crate::ffi::{OsString, OsStr};
+use crate::fmt;
+use crate::io::{self, Error, ErrorKind, SeekFrom};
+use crate::path::{Path, PathBuf};
+use crate::sync::Arc;
+use crate::sys::fd::FileDesc;
+use crate::sys::time::SystemTime;
+use crate::sys::{cvt, syscall};
+use crate::sys_common::{AsInner, FromInner};
pub struct File(FileDesc);
}
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
- use fs::{File, set_permissions};
+ use crate::fs::{File, set_permissions};
if !from.is_file() {
return Err(Error::new(ErrorKind::InvalidInput,
"the source path is not an existing regular file"))
#![allow(dead_code, missing_docs, nonstandard_style)]
-use ::io::{ErrorKind};
+use crate::io::ErrorKind;
pub use libc::strlen;
pub use self::rand::hashmap_random_keys;
}
}
-pub fn cvt(result: Result<usize, syscall::Error>) -> ::io::Result<usize> {
- result.map_err(|err| ::io::Error::from_raw_os_error(err.errno))
+pub fn cvt(result: Result<usize, syscall::Error>) -> crate::io::Result<usize> {
+ result.map_err(|err| crate::io::Error::from_raw_os_error(err.errno))
}
#[doc(hidden)]
impl_is_minus_one! { i8 i16 i32 i64 isize }
-pub fn cvt_libc<T: IsMinusOne>(t: T) -> ::io::Result<T> {
+pub fn cvt_libc<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
if t.is_minus_one() {
- Err(::io::Error::last_os_error())
+ Err(crate::io::Error::last_os_error())
} else {
Ok(t)
}
/// On Redox, use an illegal instruction to abort
pub unsafe fn abort_internal() -> ! {
- ::core::intrinsics::abort();
+ core::intrinsics::abort();
}
-use cell::UnsafeCell;
-use intrinsics::{atomic_cxchg, atomic_xchg};
-use ptr;
+use crate::cell::UnsafeCell;
+use crate::intrinsics::{atomic_cxchg, atomic_xchg};
+use crate::ptr;
-use sys::syscall::{futex, getpid, FUTEX_WAIT, FUTEX_WAKE};
+use crate::sys::syscall::{futex, getpid, FUTEX_WAIT, FUTEX_WAKE};
pub unsafe fn mutex_try_lock(m: *mut i32) -> bool {
atomic_cxchg(m, 0, 1).0 == 0
-use string::String;
-use vec::Vec;
+use crate::string::String;
+use crate::vec::Vec;
#[derive(Clone, Debug)]
pub struct DnsAnswer {
pub use self::answer::DnsAnswer;
pub use self::query::DnsQuery;
-use slice;
-use u16;
-use string::String;
-use vec::Vec;
+use crate::slice;
+use crate::u16;
+use crate::string::String;
+use crate::vec::Vec;
mod answer;
mod query;
-use string::String;
+use crate::string::String;
#[derive(Clone, Debug)]
pub struct DnsQuery {
-use fs::File;
-use io::{Error, Read, self};
-use iter::Iterator;
-use net::{Ipv4Addr, SocketAddr, SocketAddrV4};
-use str::FromStr;
-use string::{String, ToString};
-use sys::syscall::EINVAL;
-use time::{self, Duration};
-use vec::{IntoIter, Vec};
-use convert::{TryFrom, TryInto};
+use crate::fs::File;
+use crate::io::{Error, Read, self};
+use crate::iter::Iterator;
+use crate::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
+use crate::str::FromStr;
+use crate::string::{String, ToString};
+use crate::sys::syscall::EINVAL;
+use crate::time::{self, Duration};
+use crate::vec::{IntoIter, Vec};
+use crate::convert::{TryFrom, TryInto};
use self::dns::{Dns, DnsQuery};
-use cmp;
-use io::{self, Error, ErrorKind, Result, IoVec, IoVecMut};
-use mem;
-use net::{SocketAddr, Shutdown};
-use path::Path;
-use sys::fs::{File, OpenOptions};
-use sys::syscall::TimeSpec;
-use sys_common::{AsInner, FromInner, IntoInner};
-use time::Duration;
+use crate::cmp;
+use crate::io::{self, Error, ErrorKind, Result, IoVec, IoVecMut};
+use crate::mem;
+use crate::net::{SocketAddr, Shutdown};
+use crate::path::Path;
+use crate::sys::fs::{File, OpenOptions};
+use crate::sys::syscall::TimeSpec;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::time::Duration;
use super::{path_to_peer_addr, path_to_local_addr};
-use cell::UnsafeCell;
-use cmp;
-use io::{self, Error, ErrorKind, Result};
-use mem;
-use net::{SocketAddr, Ipv4Addr, Ipv6Addr};
-use path::Path;
-use sys::fs::{File, OpenOptions};
-use sys::syscall::TimeSpec;
-use sys_common::{AsInner, FromInner, IntoInner};
-use time::Duration;
+use crate::cell::UnsafeCell;
+use crate::cmp;
+use crate::io::{self, Error, ErrorKind, Result};
+use crate::mem;
+use crate::net::{SocketAddr, Ipv4Addr, Ipv6Addr};
+use crate::path::Path;
+use crate::sys::fs::{File, OpenOptions};
+use crate::sys::syscall::TimeSpec;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::time::Duration;
use super::{path_to_peer_addr, path_to_local_addr};
#![allow(unused_imports)] // lots of cfg code here
-use libc::{self, c_char};
-
-use os::unix::prelude::*;
-
-use error::Error as StdError;
-use ffi::{CStr, CString, OsStr, OsString};
-use fmt;
-use io::{self, Read, Write};
-use iter;
-use marker::PhantomData;
-use mem;
-use memchr;
-use path::{self, PathBuf};
-use ptr;
-use slice;
-use str;
-use sys_common::mutex::Mutex;
-use sys::{cvt, cvt_libc, fd, syscall};
-use vec;
+use libc::c_char;
+
+use crate::os::unix::prelude::*;
+
+use crate::error::Error as StdError;
+use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::fmt;
+use crate::io::{self, Read, Write};
+use crate::iter;
+use crate::marker::PhantomData;
+use crate::mem;
+use crate::memchr;
+use crate::path::{self, PathBuf};
+use crate::ptr;
+use crate::slice;
+use crate::str;
+use crate::sys_common::mutex::Mutex;
+use crate::sys::{cvt, cvt_libc, fd, syscall};
+use crate::vec;
extern {
#[link_name = "__errno_location"]
}
pub fn current_exe() -> io::Result<PathBuf> {
- use fs::File;
+ use crate::fs::File;
let mut file = File::open("sys:exe")?;
}
pub fn temp_dir() -> PathBuf {
- ::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| {
+ crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| {
PathBuf::from("/tmp")
})
}
pub fn home_dir() -> Option<PathBuf> {
- return ::env::var_os("HOME").map(PathBuf::from);
+ return crate::env::var_os("HOME").map(PathBuf::from);
}
pub fn exit(code: i32) -> ! {
/// The underlying OsString/OsStr implementation on Unix systems: just
/// a `Vec<u8>`/`[u8]`.
-use borrow::Cow;
-use fmt;
-use str;
-use mem;
-use rc::Rc;
-use sync::Arc;
-use sys_common::{AsInner, IntoInner};
-use sys_common::bytestring::debug_fmt_bytestring;
+use crate::borrow::Cow;
+use crate::fmt;
+use crate::str;
+use crate::mem;
+use crate::rc::Rc;
+use crate::sync::Arc;
+use crate::sys_common::{AsInner, IntoInner};
+use crate::sys_common::bytestring::debug_fmt_bytestring;
+
use core::str::lossy::Utf8Lossy;
#[derive(Clone, Hash)]
-use ffi::OsStr;
-use path::Prefix;
+use crate::ffi::OsStr;
+use crate::path::Prefix;
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
-use io;
-use sys::{cvt, syscall};
-use sys::fd::FileDesc;
+use crate::io;
+use crate::sys::{cvt, syscall};
+use crate::sys::fd::FileDesc;
////////////////////////////////////////////////////////////////////////////////
// Anonymous pipes
-use env::{split_paths};
-use ffi::{CStr, OsStr};
-use fmt;
-use fs::File;
-use io::{self, prelude::*, BufReader, Error, ErrorKind, SeekFrom};
+use crate::env::{self, split_paths};
+use crate::ffi::{CStr, OsStr};
+use crate::fmt;
+use crate::fs::File;
+use crate::io::{self, prelude::*, BufReader, Error, ErrorKind, SeekFrom};
+use crate::os::unix::ffi::OsStrExt;
+use crate::path::{Path, PathBuf};
+use crate::ptr;
+use crate::sys::ext::fs::MetadataExt;
+use crate::sys::ext::io::AsRawFd;
+use crate::sys::fd::FileDesc;
+use crate::sys::fs::{File as SysFile, OpenOptions};
+use crate::sys::os::{ENV_LOCK, environ};
+use crate::sys::pipe::{self, AnonPipe};
+use crate::sys::{cvt, syscall};
+use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+
use libc::{EXIT_SUCCESS, EXIT_FAILURE};
-use os::unix::ffi::OsStrExt;
-use path::{Path, PathBuf};
-use ptr;
-use sys::ext::fs::MetadataExt;
-use sys::ext::io::AsRawFd;
-use sys::fd::FileDesc;
-use sys::fs::{File as SysFile, OpenOptions};
-use sys::os::{ENV_LOCK, environ};
-use sys::pipe::{self, AnonPipe};
-use sys::{cvt, syscall};
-use sys_common::process::{CommandEnv, DefaultEnvKey};
////////////////////////////////////////////////////////////////////////////////
// Command
let program = if self.program.contains(':') || self.program.contains('/') {
Some(PathBuf::from(&self.program))
- } else if let Ok(path_env) = ::env::var("PATH") {
+ } else if let Ok(path_env) = env::var("PATH") {
let mut program = None;
for mut path in split_paths(&path_env) {
path.push(&self.program);
-use io;
-use sys::{cvt, syscall};
-use sys::fd::FileDesc;
+use crate::io;
+use crate::sys::{cvt, syscall};
+use crate::sys::fd::FileDesc;
pub struct Stdin(());
pub struct Stdout(());
}
pub fn is_ebadf(err: &io::Error) -> bool {
- err.raw_os_error() == Some(::sys::syscall::EBADF as i32)
+ err.raw_os_error() == Some(crate::sys::syscall::EBADF as i32)
}
-pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
pub fn panic_output() -> Option<impl io::Write> {
Stderr::new().ok()
-use boxed::FnBox;
-use ffi::CStr;
-use io;
-use mem;
-use sys_common::thread::start_thread;
-use sys::{cvt, syscall};
-use time::Duration;
+use crate::boxed::FnBox;
+use crate::ffi::CStr;
+use crate::io;
+use crate::mem;
+use crate::sys_common::thread::start_thread;
+use crate::sys::{cvt, syscall};
+use crate::time::Duration;
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
#![allow(dead_code)] // not used on all platforms
-use collections::BTreeMap;
-use ptr;
-use sync::atomic::{AtomicUsize, Ordering};
+use crate::collections::BTreeMap;
+use crate::ptr;
+use crate::sync::atomic::{AtomicUsize, Ordering};
pub type Key = usize;
-use cmp::Ordering;
-use fmt;
-use sys::{cvt, syscall};
-use time::Duration;
-use convert::TryInto;
+use crate::cmp::Ordering;
+use crate::fmt;
+use crate::sys::{cvt, syscall};
+use crate::time::Duration;
+use crate::convert::TryInto;
+
use core::hash::{Hash, Hasher};
const NSEC_PER_SEC: u64 = 1_000_000_000;
use core::sync::atomic::{AtomicUsize, Ordering};
-use io::Write;
+use crate::io::Write;
// runtime features
mod reloc;
},
// We need to wait until the initialization is done.
BUSY => while RELOC_STATE.load(Ordering::Acquire) == BUSY {
- ::core::arch::x86_64::_mm_pause()
+ core::arch::x86_64::_mm_pause()
},
// Initialization is done.
DONE => {},
use super::usercalls::{alloc::UserRef, self};
-use cmp;
-use io::{self, Write};
-use mem;
+use crate::cmp;
+use crate::io::{self, Write};
+use crate::mem;
extern "C" {
fn take_debug_panic_buf_ptr() -> *mut u8;
-use slice::from_raw_parts;
+use crate::slice::from_raw_parts;
use super::mem;
const R_X86_64_RELATIVE: u32 = 8;
-use sync::atomic::{AtomicUsize, Ordering};
-use ptr;
-use mem;
-use cell::Cell;
-use num::NonZeroUsize;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::ptr;
+use crate::mem;
+use crate::cell::Cell;
+use crate::num::NonZeroUsize;
use self::sync_bitset::*;
#[cfg(target_pointer_width="64")]
}
mod sync_bitset {
- use sync::atomic::{AtomicUsize, Ordering};
- use iter::{Enumerate, Peekable};
- use slice::Iter;
+ use crate::sync::atomic::{AtomicUsize, Ordering};
+ use crate::iter::{Enumerate, Peekable};
+ use crate::slice::Iter;
use super::{TLS_KEYS_BITSET_SIZE, USIZE_BITS};
/// A bitset that can be used synchronously.
#![allow(unused)]
-use ptr::{self, NonNull};
-use mem;
-use cell::UnsafeCell;
-use slice;
-use ops::{Deref, DerefMut, Index, IndexMut, CoerceUnsized};
-use slice::SliceIndex;
+use crate::ptr::{self, NonNull};
+use crate::mem;
+use crate::cell::UnsafeCell;
+use crate::slice;
+use crate::ops::{Deref, DerefMut, Index, IndexMut, CoerceUnsized};
+use crate::slice::SliceIndex;
use fortanix_sgx_abi::*;
use super::super::mem::is_user_range;
-use io::{Error as IoError, Result as IoResult};
-use time::Duration;
+use crate::io::{Error as IoError, Result as IoResult};
+use crate::time::Duration;
pub(crate) mod alloc;
#[macro_use]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
unsafe {
- let userbuf = ByteBuffer { data: ::ptr::null_mut(), len: 0 };
+ let userbuf = ByteBuffer { data: crate::ptr::null_mut(), len: 0 };
let mut userbuf = alloc::User::new_from_enclave(&userbuf);
raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?;
Ok(userbuf.copy_user_buffer())
#[unstable(feature = "sgx_platform", issue = "56975")]
pub use fortanix_sgx_abi::*;
-use ptr::NonNull;
-use num::NonZeroU64;
+use crate::ptr::NonNull;
+use crate::num::NonZeroU64;
#[repr(C)]
struct UsercallReturn(u64, u64);
type Register = u64;
trait RegisterArgument {
- fn from_register(Register) -> Self;
+ fn from_register(_: Register) -> Self;
fn into_register(self) -> Register;
}
-extern crate dlmalloc;
-
-use alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::{GlobalAlloc, Layout, System};
use super::waitqueue::SpinMutex;
-use ffi::OsString;
use super::abi::usercalls::{alloc, raw::ByteBuffer};
-use sync::atomic::{AtomicUsize, Ordering};
-use sys::os_str::Buf;
-use sys_common::FromInner;
-use slice;
+use crate::ffi::OsString;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sys::os_str::Buf;
+use crate::sys_common::FromInner;
+use crate::slice;
static ARGS: AtomicUsize = AtomicUsize::new(0);
type ArgsStore = Vec<OsString>;
-use io;
-use error::Error;
-use libc;
-use sys_common::backtrace::Frame;
+use crate::io;
+use crate::error::Error;
+use crate::fmt;
+use crate::sys_common::backtrace::Frame;
+use crate::sys::sgx::abi::mem::image_base;
+
use unwind as uw;
-use sys::sgx::abi::mem::image_base;
pub struct BacktraceContext;
}
}
-impl ::fmt::Display for UnwindError {
- fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+impl fmt::Display for UnwindError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {:?}", self.description(), self.0)
}
}
-use sys::mutex::Mutex;
-use time::Duration;
+use crate::sys::mutex::Mutex;
+use crate::time::Duration;
use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex};
//! Software Developer's Manual, Volume 3, Chapter 40.
#![unstable(feature = "sgx_platform", issue = "56975")]
-use mem::MaybeUninit;
+use crate::mem::MaybeUninit;
/// Wrapper struct to force 16-byte alignment.
#[repr(align(16))]
#![unstable(feature = "sgx_platform", issue = "56975")]
-use ffi::{OsStr, OsString};
-use mem;
-use sys::os_str::Buf;
-use sys_common::{FromInner, IntoInner, AsInner};
+use crate::ffi::{OsStr, OsString};
+use crate::mem;
+use crate::sys::os_str::Buf;
+use crate::sys_common::{FromInner, IntoInner, AsInner};
/// SGX-specific extensions to [`OsString`].
///
//! description of [`TryIntoRawFd`](trait.TryIntoRawFd.html) for more details.
#![unstable(feature = "sgx_platform", issue = "56975")]
-pub use sys::abi::usercalls::raw::Fd as RawFd;
-use net;
-use sys::{self, AsInner, FromInner, IntoInner, TryIntoInner};
+pub use crate::sys::abi::usercalls::raw::Fd as RawFd;
+use crate::net;
+use crate::sys::{self, AsInner, FromInner, IntoInner, TryIntoInner};
/// A trait to extract the raw SGX file descriptor from an underlying
/// object.
use fortanix_sgx_abi::Fd;
-use io;
-use mem;
-use sys::{AsInner, FromInner, IntoInner};
+use crate::io;
+use crate::mem;
+use crate::sys::{AsInner, FromInner, IntoInner};
use super::abi::usercalls;
#[derive(Debug)]
-use ffi::OsString;
-use fmt;
-use hash::{Hash, Hasher};
-use io::{self, SeekFrom};
-use path::{Path, PathBuf};
-use sys::time::SystemTime;
-use sys::{unsupported, Void};
+use crate::ffi::OsString;
+use crate::fmt;
+use crate::hash::{Hash, Hasher};
+use crate::io::{self, SeekFrom};
+use crate::path::{Path, PathBuf};
+use crate::sys::time::SystemTime;
+use crate::sys::{unsupported, Void};
pub struct File(Void);
//! This module contains the facade (aka platform-specific) implementations of
//! OS level functionality for Fortanix SGX.
-use os::raw::c_char;
-use sync::atomic::{AtomicBool, Ordering};
+use crate::io::ErrorKind;
+use crate::os::raw::c_char;
+use crate::sync::atomic::{AtomicBool, Ordering};
pub mod abi;
mod waitqueue;
/// This function is used to implement functionality that simply doesn't exist.
/// Programs relying on this functionality will need to deal with the error.
-pub fn unsupported<T>() -> ::io::Result<T> {
+pub fn unsupported<T>() -> crate::io::Result<T> {
Err(unsupported_err())
}
-pub fn unsupported_err() -> ::io::Error {
- ::io::Error::new(::io::ErrorKind::Other,
+pub fn unsupported_err() -> crate::io::Error {
+ crate::io::Error::new(ErrorKind::Other,
"operation not supported on SGX yet")
}
/// returned, the program might very well be able to function normally. This is
/// what happens when `SGX_INEFFECTIVE_ERROR` is set to `true`. If it is
/// `false`, the behavior is the same as `unsupported`.
-pub fn sgx_ineffective<T>(v: T) -> ::io::Result<T> {
+pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> {
static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false);
if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) {
- Err(::io::Error::new(::io::ErrorKind::Other,
+ Err(crate::io::Error::new(ErrorKind::Other,
"operation can't be trusted to have any effect on SGX"))
} else {
Ok(v)
}
}
-pub fn decode_error_kind(code: i32) -> ::io::ErrorKind {
+pub fn decode_error_kind(code: i32) -> ErrorKind {
use fortanix_sgx_abi::Error;
// FIXME: not sure how to make sure all variants of Error are covered
if code == Error::NotFound as _ {
- ::io::ErrorKind::NotFound
+ ErrorKind::NotFound
} else if code == Error::PermissionDenied as _ {
- ::io::ErrorKind::PermissionDenied
+ ErrorKind::PermissionDenied
} else if code == Error::ConnectionRefused as _ {
- ::io::ErrorKind::ConnectionRefused
+ ErrorKind::ConnectionRefused
} else if code == Error::ConnectionReset as _ {
- ::io::ErrorKind::ConnectionReset
+ ErrorKind::ConnectionReset
} else if code == Error::ConnectionAborted as _ {
- ::io::ErrorKind::ConnectionAborted
+ ErrorKind::ConnectionAborted
} else if code == Error::NotConnected as _ {
- ::io::ErrorKind::NotConnected
+ ErrorKind::NotConnected
} else if code == Error::AddrInUse as _ {
- ::io::ErrorKind::AddrInUse
+ ErrorKind::AddrInUse
} else if code == Error::AddrNotAvailable as _ {
- ::io::ErrorKind::AddrNotAvailable
+ ErrorKind::AddrNotAvailable
} else if code == Error::BrokenPipe as _ {
- ::io::ErrorKind::BrokenPipe
+ ErrorKind::BrokenPipe
} else if code == Error::AlreadyExists as _ {
- ::io::ErrorKind::AlreadyExists
+ ErrorKind::AlreadyExists
} else if code == Error::WouldBlock as _ {
- ::io::ErrorKind::WouldBlock
+ ErrorKind::WouldBlock
} else if code == Error::InvalidInput as _ {
- ::io::ErrorKind::InvalidInput
+ ErrorKind::InvalidInput
} else if code == Error::InvalidData as _ {
- ::io::ErrorKind::InvalidData
+ ErrorKind::InvalidData
} else if code == Error::TimedOut as _ {
- ::io::ErrorKind::TimedOut
+ ErrorKind::TimedOut
} else if code == Error::WriteZero as _ {
- ::io::ErrorKind::WriteZero
+ ErrorKind::WriteZero
} else if code == Error::Interrupted as _ {
- ::io::ErrorKind::Interrupted
+ ErrorKind::Interrupted
} else if code == Error::Other as _ {
- ::io::ErrorKind::Other
+ ErrorKind::Other
} else if code == Error::UnexpectedEof as _ {
- ::io::ErrorKind::UnexpectedEof
+ ErrorKind::UnexpectedEof
} else {
- ::io::ErrorKind::Other
+ ErrorKind::Other
}
}
pub fn hashmap_random_keys() -> (u64, u64) {
fn rdrand64() -> u64 {
unsafe {
- let mut ret: u64 = ::mem::uninitialized();
+ let mut ret: u64 = crate::mem::uninitialized();
for _ in 0..10 {
- if ::arch::x86_64::_rdrand64_step(&mut ret) == 1 {
+ if crate::arch::x86_64::_rdrand64_step(&mut ret) == 1 {
return ret;
}
}
(rdrand64(), rdrand64())
}
-pub use sys_common::{AsInner, FromInner, IntoInner};
+pub use crate::sys_common::{AsInner, FromInner, IntoInner};
pub trait TryIntoInner<Inner>: Sized {
fn try_into_inner(self) -> Result<Inner, Self>;
-use fmt;
-use io::{self, IoVec, IoVecMut};
-use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr, ToSocketAddrs};
-use time::Duration;
-use sys::{unsupported, Void, sgx_ineffective, AsInner, FromInner, IntoInner, TryIntoInner};
-use sys::fd::FileDesc;
-use convert::TryFrom;
-use error;
-use sync::Arc;
+use crate::fmt;
+use crate::io::{self, IoVec, IoVecMut};
+use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr, ToSocketAddrs};
+use crate::time::Duration;
+use crate::sys::{unsupported, Void, sgx_ineffective, AsInner, FromInner, IntoInner, TryIntoInner};
+use crate::sys::fd::FileDesc;
+use crate::convert::TryFrom;
+use crate::error;
+use crate::sync::Arc;
use super::abi::usercalls;
use fortanix_sgx_abi::{Error, RESULT_SUCCESS};
-use error::Error as StdError;
-use ffi::{OsString, OsStr};
-use fmt;
-use io;
-use path::{self, PathBuf};
-use str;
-use sys::{unsupported, Void, sgx_ineffective, decode_error_kind};
-use collections::HashMap;
-use vec;
-use sync::Mutex;
-use sync::atomic::{AtomicUsize, Ordering};
-use sync::Once;
+use crate::error::Error as StdError;
+use crate::ffi::{OsString, OsStr};
+use crate::fmt;
+use crate::io;
+use crate::path::{self, PathBuf};
+use crate::str;
+use crate::sys::{unsupported, Void, sgx_ineffective, decode_error_kind};
+use crate::collections::HashMap;
+use crate::vec;
+use crate::sync::Mutex;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::Once;
pub fn errno() -> i32 {
RESULT_SUCCESS
/// The underlying OsString/OsStr implementation on Unix systems: just
/// a `Vec<u8>`/`[u8]`.
-use borrow::Cow;
-use fmt;
-use str;
-use mem;
-use rc::Rc;
-use sync::Arc;
-use sys_common::{AsInner, IntoInner};
-use sys_common::bytestring::debug_fmt_bytestring;
+use crate::borrow::Cow;
+use crate::fmt;
+use crate::str;
+use crate::mem;
+use crate::rc::Rc;
+use crate::sync::Arc;
+use crate::sys_common::{AsInner, IntoInner};
+use crate::sys_common::bytestring::debug_fmt_bytestring;
+
use core::str::lossy::Utf8Lossy;
#[derive(Clone, Hash)]
-use path::Prefix;
-use ffi::OsStr;
+use crate::path::Prefix;
+use crate::ffi::OsStr;
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
-use io;
-use sys::Void;
+use crate::io;
+use crate::sys::Void;
pub struct AnonPipe(Void);
-use ffi::OsStr;
-use fmt;
-use io;
-use sys::fs::File;
-use sys::pipe::AnonPipe;
-use sys::{unsupported, Void};
-use sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::ffi::OsStr;
+use crate::fmt;
+use crate::io;
+use crate::sys::fs::File;
+use crate::sys::pipe::AnonPipe;
+use crate::sys::{unsupported, Void};
+use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
////////////////////////////////////////////////////////////////////////////////
// Command
-use alloc::{self, Layout};
-use num::NonZeroUsize;
-use slice;
-use str;
+use crate::alloc::{self, Layout};
+use crate::num::NonZeroUsize;
+use crate::slice;
+use crate::str;
use super::waitqueue::{
try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
};
-use mem;
+use crate::mem;
pub struct RWLock {
readers: SpinMutex<WaitVariable<Option<NonZeroUsize>>>,
#[no_mangle]
// NB. used by both libunwind and libpanic_abort
pub unsafe extern "C" fn __rust_abort() {
- ::sys::abort_internal();
+ crate::sys::abort_internal();
}
#[no_mangle]
use super::*;
use core::array::FixedSizeArray;
- use mem::MaybeUninit;
- use {mem, ptr};
+ use crate::mem::MaybeUninit;
+ use crate::{mem, ptr};
// The below test verifies that the bytes of initialized RWLock are the ones
// we use in libunwind.
use fortanix_sgx_abi as abi;
-use io;
-use sys::fd::FileDesc;
+use crate::io;
+use crate::sys::fd::FileDesc;
pub struct Stdin(());
pub struct Stdout(());
}
}
-pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
pub fn is_ebadf(err: &io::Error) -> bool {
// FIXME: Rust normally maps Unix EBADF to `Other`
-use boxed::FnBox;
-use ffi::CStr;
-use io;
-use time::Duration;
+use crate::boxed::FnBox;
+use crate::ffi::CStr;
+use crate::io;
+use crate::time::Duration;
use super::abi::usercalls;
pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
mod task_queue {
- use sync::{Mutex, MutexGuard, Once};
- use sync::mpsc;
- use boxed::FnBox;
+ use crate::sync::{Mutex, MutexGuard, Once};
+ use crate::sync::mpsc;
+ use crate::boxed::FnBox;
pub type JoinHandle = mpsc::Receiver<()>;
-use time::Duration;
+use crate::time::Duration;
use super::abi::usercalls;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
/// recorded in the enclave. The wakeup event state is protected by a spinlock.
/// The queue and associated wait state are stored in a `WaitVariable`.
-use ops::{Deref, DerefMut};
-use num::NonZeroUsize;
+use crate::ops::{Deref, DerefMut};
+use crate::num::NonZeroUsize;
use fortanix_sgx_abi::{Tcs, EV_UNPARK, WAIT_INDEFINITE};
use super::abi::usercalls;
/// A doubly-linked list where callers are in charge of memory allocation
/// of the nodes in the list.
mod unsafe_list {
- use ptr::NonNull;
- use mem;
+ use crate::ptr::NonNull;
+ use crate::mem;
pub struct UnsafeListEntry<T> {
next: NonNull<UnsafeListEntry<T>>,
#[cfg(test)]
mod tests {
use super::*;
- use cell::Cell;
+ use crate::cell::Cell;
unsafe fn assert_empty<T>(list: &mut UnsafeList<T>) {
assert!(list.pop().is_none(), "assertion failed: list is not empty");
/// Trivial spinlock-based implementation of `sync::Mutex`.
// FIXME: Perhaps use Intel TSX to avoid locking?
mod spin_mutex {
- use cell::UnsafeCell;
- use sync::atomic::{AtomicBool, Ordering, spin_loop_hint};
- use ops::{Deref, DerefMut};
+ use crate::cell::UnsafeCell;
+ use crate::sync::atomic::{AtomicBool, Ordering, spin_loop_hint};
+ use crate::ops::{Deref, DerefMut};
#[derive(Default)]
pub struct SpinMutex<T> {
#![allow(deprecated)]
use super::*;
- use sync::Arc;
- use thread;
+ use crate::sync::Arc;
+ use crate::thread;
#[test]
fn sleep() {
#[cfg(test)]
mod tests {
use super::*;
- use sync::Arc;
- use thread;
+ use crate::sync::Arc;
+ use crate::thread;
#[test]
fn queue() {
-use ptr;
-use libc;
-use sys_common::alloc::{MIN_ALIGN, realloc_fallback};
-use alloc::{GlobalAlloc, Layout, System};
+use crate::ptr;
+use crate::sys_common::alloc::{MIN_ALIGN, realloc_fallback};
+use crate::alloc::{GlobalAlloc, Layout, System};
#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
use libc::{ftruncate, pread, pwrite};
-use io;
+use crate::io;
use super::{cvt, cvt_r};
// The `log2` and `log2f` functions apparently appeared in android-18, or at
#[cfg(not(test))]
pub fn log2f32(f: f32) -> f32 {
- f.ln() * ::f32::consts::LOG2_E
+ f.ln() * crate::f32::consts::LOG2_E
}
#[cfg(not(test))]
pub fn log2f64(f: f64) -> f64 {
- f.ln() * ::f64::consts::LOG2_E
+ f.ln() * crate::f64::consts::LOG2_E
}
// Back in the day [1] the `signal` function was just an inline wrapper
pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
-> io::Result<ssize_t>
{
- use convert::TryInto;
+ use crate::convert::TryInto;
weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t);
pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
if let Ok(o) = offset.try_into() {
pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
-> io::Result<ssize_t>
{
- use convert::TryInto;
+ use crate::convert::TryInto;
weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t);
pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
if let Ok(o) = offset.try_into() {
#![allow(dead_code)] // runtime init functions not used during testing
-use ffi::OsString;
-use marker::PhantomData;
-use vec;
+use crate::ffi::OsString;
+use crate::marker::PhantomData;
+use crate::vec;
/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }
target_os = "fuchsia",
target_os = "hermit"))]
mod imp {
- use os::unix::prelude::*;
- use ptr;
- use ffi::{CStr, OsString};
- use marker::PhantomData;
- use libc;
+ use crate::os::unix::prelude::*;
+ use crate::ptr;
+ use crate::ffi::{CStr, OsString};
+ use crate::marker::PhantomData;
use super::Args;
- use sys_common::mutex::Mutex;
+ use crate::sys_common::mutex::Mutex;
static mut ARGC: isize = 0;
static mut ARGV: *const *const u8 = ptr::null();
#[cfg(any(target_os = "macos",
target_os = "ios"))]
mod imp {
- use ffi::CStr;
- use marker::PhantomData;
- use libc;
+ use crate::ffi::CStr;
+ use crate::marker::PhantomData;
use super::Args;
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
#[cfg(target_os = "macos")]
pub fn args() -> Args {
- use os::unix::prelude::*;
+ use crate::os::unix::prelude::*;
extern {
// These functions are in crt_externs.h.
fn _NSGetArgc() -> *mut libc::c_int;
// res
#[cfg(target_os = "ios")]
pub fn args() -> Args {
- use ffi::OsString;
- use mem;
- use str;
+ use crate::ffi::OsString;
+ use crate::mem;
+ use crate::str;
extern {
fn sel_registerName(name: *const libc::c_uchar) -> Sel;
#[cfg(not(target_os = "emscripten"))]
pub mod gnu {
- use io;
- use fs;
+ use crate::io;
+ use crate::fs;
+
use libc::c_char;
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
- use env;
- use os::unix::ffi::OsStrExt;
+ use crate::env;
+ use crate::os::unix::ffi::OsStrExt;
let filename = env::current_exe()?;
let file = fs::File::open(&filename)?;
-use io;
-use intrinsics;
-use ffi::CStr;
-use libc;
-use sys::backtrace::BacktraceContext;
-use sys_common::backtrace::Frame;
+use crate::io;
+use crate::intrinsics;
+use crate::ffi::CStr;
+use crate::sys::backtrace::BacktraceContext;
+use crate::sys_common::backtrace::Frame;
pub fn resolve_symname<F>(frame: Frame,
callback: F,
mod dladdr;
-use sys::backtrace::BacktraceContext;
-use sys_common::backtrace::Frame;
-use io;
+use crate::sys::backtrace::BacktraceContext;
+use crate::sys_common::backtrace::Frame;
+use crate::io;
#[cfg(target_os = "emscripten")]
pub use self::dladdr::resolve_symname;
}
#[cfg(not(target_os = "emscripten"))]
-pub use sys_common::gnu::libbacktrace::foreach_symbol_fileline;
+pub use crate::sys_common::gnu::libbacktrace::foreach_symbol_fileline;
#[cfg(not(target_os = "emscripten"))]
pub fn resolve_symname<F>(frame: Frame, callback: F, bc: &BacktraceContext) -> io::Result<()>
where
F: FnOnce(Option<&str>) -> io::Result<()>
{
- ::sys_common::gnu::libbacktrace::resolve_symname(frame, |symname| {
+ crate::sys_common::gnu::libbacktrace::resolve_symname(frame, |symname| {
if symname.is_some() {
callback(symname)
} else {
/// simple to use it should be used only on iOS devices as the only viable
/// option.
-use io;
-use libc;
-use sys::backtrace::BacktraceContext;
-use sys_common::backtrace::Frame;
+use crate::io;
+use crate::ptr;
+use crate::sys::backtrace::BacktraceContext;
+use crate::sys_common::backtrace::Frame;
#[inline(never)] // if we know this is a function call, we can skip it when
// tracing
{
const FRAME_LEN: usize = 100;
assert!(FRAME_LEN >= frames.len());
- let mut raw_frames = [::ptr::null_mut(); FRAME_LEN];
+ let mut raw_frames = [ptr::null_mut(); FRAME_LEN];
let nb_frames = unsafe {
backtrace(raw_frames.as_mut_ptr(), raw_frames.len() as libc::c_int)
} as usize;
-use error::Error;
-use io;
-use libc;
-use sys::backtrace::BacktraceContext;
-use sys_common::backtrace::Frame;
+use crate::error::Error;
+use crate::fmt;
+use crate::io;
+use crate::sys::backtrace::BacktraceContext;
+use crate::sys_common::backtrace::Frame;
use unwind as uw;
}
}
-impl ::fmt::Display for UnwindError {
- fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+impl fmt::Display for UnwindError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {:?}", self.description(), self.0)
}
}
-use cell::UnsafeCell;
-use libc;
-use sys::mutex::{self, Mutex};
-use time::Duration;
+use crate::cell::UnsafeCell;
+use crate::sys::mutex::{self, Mutex};
+use crate::time::Duration;
pub struct Condvar { inner: UnsafeCell<libc::pthread_cond_t> }
target_os = "android",
target_os = "hermit")))]
pub unsafe fn init(&mut self) {
- use mem;
+ use crate::mem;
let mut attr: libc::pthread_condattr_t = mem::uninitialized();
let r = libc::pthread_condattr_init(&mut attr);
assert_eq!(r, 0);
target_os = "android",
target_os = "hermit")))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
- use mem;
+ use crate::mem;
let mut now: libc::timespec = mem::zeroed();
let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);
// https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "android", target_os = "hermit"))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
- use ptr;
- use time::Instant;
+ use crate::ptr;
+ use crate::time::Instant;
// 1000 years
let max_dur = Duration::from_secs(1000 * 365 * 86400);
#![stable(feature = "rust1", since = "1.0.0")]
-use ffi::{OsStr, OsString};
-use mem;
-use sys::os_str::Buf;
-use sys_common::{FromInner, IntoInner, AsInner};
+use crate::ffi::{OsStr, OsString};
+use crate::mem;
+use crate::sys::os_str::Buf;
+use crate::sys_common::{FromInner, IntoInner, AsInner};
/// Unix-specific extensions to [`OsString`].
///
#![stable(feature = "rust1", since = "1.0.0")]
-use fs::{self, Permissions, OpenOptions};
-use io;
-use libc;
-use path::Path;
-use sys;
-use sys_common::{FromInner, AsInner, AsInnerMut};
-use sys::platform::fs::MetadataExt as UnixMetadataExt;
+use crate::fs::{self, Permissions, OpenOptions};
+use crate::io;
+use crate::path::Path;
+use crate::sys;
+use crate::sys_common::{FromInner, AsInner, AsInnerMut};
+use crate::sys::platform::fs::MetadataExt as UnixMetadataExt;
/// Unix-specific extensions to [`File`].
///
#![stable(feature = "rust1", since = "1.0.0")]
-use fs;
-use os::raw;
-use sys;
-use io;
-use sys_common::{AsInner, FromInner, IntoInner};
-use libc;
+use crate::fs;
+use crate::os::raw;
+use crate::sys;
+use crate::io;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
/// Raw file descriptors.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct sockaddr_un;
}
-use ascii;
-use ffi::OsStr;
-use fmt;
-use io::{self, Initializer, IoVec, IoVecMut};
-use mem;
-use net::{self, Shutdown};
-use os::unix::ffi::OsStrExt;
-use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
-use path::Path;
-use time::Duration;
-use sys::{self, cvt};
-use sys::net::Socket;
-use sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::ascii;
+use crate::ffi::OsStr;
+use crate::fmt;
+use crate::io::{self, Initializer, IoVec, IoVecMut};
+use crate::mem;
+use crate::net::{self, Shutdown};
+use crate::os::unix::ffi::OsStrExt;
+use crate::os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
+use crate::path::Path;
+use crate::time::Duration;
+use crate::sys::{self, cvt};
+use crate::sys::net::Socket;
+use crate::sys_common::{self, AsInner, FromInner, IntoInner};
#[cfg(any(target_os = "linux", target_os = "android",
target_os = "dragonfly", target_os = "freebsd",
#[cfg(all(test, not(target_os = "emscripten")))]
mod test {
- use thread;
- use io::{self, ErrorKind};
- use io::prelude::*;
- use time::Duration;
- use sys_common::io::test::tmpdir;
+ use crate::thread;
+ use crate::io::{self, ErrorKind};
+ use crate::io::prelude::*;
+ use crate::time::Duration;
+ use crate::sys_common::io::test::tmpdir;
use super::*;
#![stable(feature = "rust1", since = "1.0.0")]
-use io;
-use os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
-use process;
-use sys;
-use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
+use crate::io;
+use crate::os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
+use crate::process;
+use crate::sys;
+use crate::sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
/// Unix-specific extensions to the [`process::Command`] builder.
///
/// Returns the OS-assigned process identifier associated with this process's parent.
#[stable(feature = "unix_ppid", since = "1.27.0")]
pub fn parent_id() -> u32 {
- ::sys::os::getppid()
+ crate::sys::os::getppid()
}
#[doc(inline)]
#[stable(feature = "pthread_t", since = "1.8.0")]
-pub use sys::platform::raw::pthread_t;
+pub use crate::sys::platform::raw::pthread_t;
#[doc(inline)]
#[stable(feature = "raw_ext", since = "1.1.0")]
-pub use sys::platform::raw::{dev_t, ino_t, mode_t, nlink_t, off_t, blksize_t};
+pub use crate::sys::platform::raw::{dev_t, ino_t, mode_t, nlink_t, off_t, blksize_t};
#[doc(inline)]
#[stable(feature = "raw_ext", since = "1.1.0")]
-pub use sys::platform::raw::{blkcnt_t, time_t};
+pub use crate::sys::platform::raw::{blkcnt_t, time_t};
#![stable(feature = "thread_extensions", since = "1.9.0")]
#[allow(deprecated)]
-use os::unix::raw::pthread_t;
-use sys_common::{AsInner, IntoInner};
-use thread::JoinHandle;
+use crate::os::unix::raw::pthread_t;
+use crate::sys_common::{AsInner, IntoInner};
+use crate::thread::JoinHandle;
#[stable(feature = "thread_extensions", since = "1.9.0")]
#[allow(deprecated)]
// Due to rust-lang/rust#18804, make sure this is not generic!
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit"))]
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
- use libc;
- use mem;
- use sys_common::thread_local::register_dtor_fallback;
+ use crate::mem;
+ use crate::sys_common::thread_local::register_dtor_fallback;
extern {
#[linkage = "extern_weak"]
// _tlv_atexit.
#[cfg(target_os = "macos")]
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
- use cell::Cell;
- use ptr;
+ use crate::cell::Cell;
+ use crate::ptr;
#[thread_local]
static REGISTERED: Cell<bool> = Cell::new(false);
#![unstable(reason = "not public", issue = "0", feature = "fd")]
-use cmp;
-use io::{self, Read, Initializer, IoVec, IoVecMut};
-use libc::{self, c_int, c_void, ssize_t};
-use mem;
-use sync::atomic::{AtomicBool, Ordering};
-use sys::cvt;
-use sys_common::AsInner;
+use crate::cmp;
+use crate::io::{self, Read, Initializer, IoVec, IoVecMut};
+use crate::mem;
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sys::cvt;
+use crate::sys_common::AsInner;
+
+use libc::{c_int, c_void, ssize_t};
#[derive(Debug)]
pub struct FileDesc {
unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: usize, offset: i64)
-> io::Result<isize>
{
- use convert::TryInto;
+ use crate::convert::TryInto;
use libc::pread64;
// pread64 on emscripten actually takes a 32 bit offset
if let Ok(o) = offset.try_into() {
unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: usize, offset: i64)
-> io::Result<isize>
{
- use convert::TryInto;
+ use crate::convert::TryInto;
use libc::pwrite64;
// pwrite64 on emscripten actually takes a 32 bit offset
if let Ok(o) = offset.try_into() {
-use os::unix::prelude::*;
-
-use ffi::{CString, CStr, OsString, OsStr};
-use fmt;
-use io::{self, Error, ErrorKind, SeekFrom};
-use libc::{self, c_int, mode_t};
-use mem;
-use path::{Path, PathBuf};
-use ptr;
-use sync::Arc;
-use sys::fd::FileDesc;
-use sys::time::SystemTime;
-use sys::{cvt, cvt_r};
-use sys_common::{AsInner, FromInner};
+use crate::os::unix::prelude::*;
+
+use crate::ffi::{CString, CStr, OsString, OsStr};
+use crate::fmt;
+use crate::io::{self, Error, ErrorKind, SeekFrom};
+use crate::mem;
+use crate::path::{Path, PathBuf};
+use crate::ptr;
+use crate::sync::Arc;
+use crate::sys::fd::FileDesc;
+use crate::sys::time::SystemTime;
+use crate::sys::{cvt, cvt_r};
+use crate::sys_common::{AsInner, FromInner};
+
+use libc::{c_int, mode_t};
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "l4re"))]
use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64};
#[cfg(any(target_os = "solaris", target_os = "fuchsia"))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
+ use crate::slice;
+
unsafe {
loop {
// Although readdir_r(3) would be a correct function to use here because
let ret = DirEntry {
entry: *entry_ptr,
- name: ::slice::from_raw_parts(name as *const u8,
- namelen as usize).to_owned().into_boxed_slice(),
+ name: slice::from_raw_parts(name as *const u8,
+ namelen as usize).to_owned().into_boxed_slice(),
dir: self.clone()
};
if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
target_os = "dragonfly",
target_os = "bitrig"))]
fn name_bytes(&self) -> &[u8] {
+ use crate::slice;
unsafe {
- ::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8,
- self.entry.d_namlen as usize)
+ slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8,
+ self.entry.d_namlen as usize)
}
}
#[cfg(any(target_os = "android",
// that we support, so we only do this on Linux currently.
#[cfg(target_os = "linux")]
fn ensure_cloexec(fd: &FileDesc) -> io::Result<()> {
- use sync::atomic::{AtomicUsize, Ordering};
+ use crate::sync::atomic::{AtomicUsize, Ordering};
const OPEN_CLOEXEC_UNKNOWN: usize = 0;
const OPEN_CLOEXEC_SUPPORTED: usize = 1;
pub fn truncate(&self, size: u64) -> io::Result<()> {
#[cfg(target_os = "android")]
- return ::sys::android::ftruncate64(self.0.raw(), size);
+ return crate::sys::android::ftruncate64(self.0.raw(), size);
#[cfg(not(target_os = "android"))]
return cvt_r(|| unsafe {
#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
- use fs::File;
+ use crate::fs::File;
if !from.is_file() {
return Err(Error::new(ErrorKind::InvalidInput,
"the source path is not an existing regular file"))
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
- use cmp;
- use fs::File;
- use sync::atomic::{AtomicBool, Ordering};
+ use crate::cmp;
+ use crate::fs::File;
+ use crate::sync::atomic::{AtomicBool, Ordering};
// Kernel prior to 4.5 don't have copy_file_range
// We store the availability in a global to avoid unnecessary syscalls
-use marker::PhantomData;
+use crate::marker::PhantomData;
+use crate::slice;
+
use libc::{iovec, c_void};
-use slice;
#[repr(transparent)]
pub struct IoVec<'a> {
pub mod net {
#![allow(warnings)]
- use fmt;
- use io::{self, IoVec, IoVecMut};
- use libc;
- use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
- use sys_common::{AsInner, FromInner, IntoInner};
- use sys::fd::FileDesc;
- use time::Duration;
- use convert::TryFrom;
-
+ use crate::fmt;
+ use crate::io::{self, IoVec, IoVecMut};
+ use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
+ use crate::sys_common::{AsInner, FromInner, IntoInner};
+ use crate::sys::fd::FileDesc;
+ use crate::time::Duration;
+ use crate::convert::TryFrom;
+
+ #[allow(unused_extern_crates)]
pub extern crate libc as netc;
pub struct Socket(FileDesc);
// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
- use libc;
-
let p = unsafe {
libc::memchr(
haystack.as_ptr() as *const libc::c_void,
#[cfg(target_os = "linux")]
fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
- use libc;
-
// GNU's memrchr() will - unlike memchr() - error if haystack is empty.
if haystack.is_empty() {return None}
let p = unsafe {
#[cfg(not(target_os = "linux"))]
fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
- ::core::slice::memchr::memrchr(needle, haystack)
+ core::slice::memchr::memrchr(needle, haystack)
}
memrchr_specific(needle, haystack)
#![allow(missing_docs, nonstandard_style)]
-use io::ErrorKind;
-use libc;
-
-#[cfg(any(rustdoc, target_os = "linux"))] pub use os::linux as platform;
-
-#[cfg(all(not(rustdoc), target_os = "android"))] pub use os::android as platform;
-#[cfg(all(not(rustdoc), target_os = "bitrig"))] pub use os::bitrig as platform;
-#[cfg(all(not(rustdoc), target_os = "dragonfly"))] pub use os::dragonfly as platform;
-#[cfg(all(not(rustdoc), target_os = "freebsd"))] pub use os::freebsd as platform;
-#[cfg(all(not(rustdoc), target_os = "haiku"))] pub use os::haiku as platform;
-#[cfg(all(not(rustdoc), target_os = "ios"))] pub use os::ios as platform;
-#[cfg(all(not(rustdoc), target_os = "macos"))] pub use os::macos as platform;
-#[cfg(all(not(rustdoc), target_os = "netbsd"))] pub use os::netbsd as platform;
-#[cfg(all(not(rustdoc), target_os = "openbsd"))] pub use os::openbsd as platform;
-#[cfg(all(not(rustdoc), target_os = "solaris"))] pub use os::solaris as platform;
-#[cfg(all(not(rustdoc), target_os = "emscripten"))] pub use os::emscripten as platform;
-#[cfg(all(not(rustdoc), target_os = "fuchsia"))] pub use os::fuchsia as platform;
-#[cfg(all(not(rustdoc), target_os = "l4re"))] pub use os::linux as platform;
-#[cfg(all(not(rustdoc), target_os = "hermit"))] pub use os::hermit as platform;
+use crate::io::ErrorKind;
+
+#[cfg(any(rustdoc, target_os = "linux"))] pub use crate::os::linux as platform;
+
+#[cfg(all(not(rustdoc), target_os = "android"))] pub use crate::os::android as platform;
+#[cfg(all(not(rustdoc), target_os = "bitrig"))] pub use crate::os::bitrig as platform;
+#[cfg(all(not(rustdoc), target_os = "dragonfly"))] pub use crate::os::dragonfly as platform;
+#[cfg(all(not(rustdoc), target_os = "freebsd"))] pub use crate::os::freebsd as platform;
+#[cfg(all(not(rustdoc), target_os = "haiku"))] pub use crate::os::haiku as platform;
+#[cfg(all(not(rustdoc), target_os = "ios"))] pub use crate::os::ios as platform;
+#[cfg(all(not(rustdoc), target_os = "macos"))] pub use crate::os::macos as platform;
+#[cfg(all(not(rustdoc), target_os = "netbsd"))] pub use crate::os::netbsd as platform;
+#[cfg(all(not(rustdoc), target_os = "openbsd"))] pub use crate::os::openbsd as platform;
+#[cfg(all(not(rustdoc), target_os = "solaris"))] pub use crate::os::solaris as platform;
+#[cfg(all(not(rustdoc), target_os = "emscripten"))] pub use crate::os::emscripten as platform;
+#[cfg(all(not(rustdoc), target_os = "fuchsia"))] pub use crate::os::fuchsia as platform;
+#[cfg(all(not(rustdoc), target_os = "l4re"))] pub use crate::os::linux as platform;
+#[cfg(all(not(rustdoc), target_os = "hermit"))] pub use crate::os::hermit as platform;
pub use self::rand::hashmap_random_keys;
pub use libc::strlen;
}
#[cfg(target_os = "android")]
-pub use sys::android::signal;
+pub use crate::sys::android::signal;
#[cfg(not(target_os = "android"))]
pub use libc::signal;
impl_is_minus_one! { i8 i16 i32 i64 isize }
-pub fn cvt<T: IsMinusOne>(t: T) -> ::io::Result<T> {
+pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
if t.is_minus_one() {
- Err(::io::Error::last_os_error())
+ Err(crate::io::Error::last_os_error())
} else {
Ok(t)
}
}
-pub fn cvt_r<T, F>(mut f: F) -> ::io::Result<T>
+pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
where T: IsMinusOne,
F: FnMut() -> T
{
// instruction" that intrinsics::abort would cause, as intrinsics::abort is
// implemented as an illegal instruction.
pub unsafe fn abort_internal() -> ! {
- ::libc::abort()
+ libc::abort()
}
-use cell::UnsafeCell;
-use libc;
-use mem;
+use crate::cell::UnsafeCell;
+use crate::mem;
pub struct Mutex { inner: UnsafeCell<libc::pthread_mutex_t> }
#[inline]
#[cfg(target_os = "dragonfly")]
pub unsafe fn destroy(&self) {
- use libc;
let r = libc::pthread_mutex_destroy(self.inner.get());
// On DragonFly pthread_mutex_destroy() returns EINVAL if called on a
// mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER.
-use ffi::CStr;
-use io::{self, IoVec, IoVecMut};
-use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK};
-use mem;
-use net::{SocketAddr, Shutdown};
-use str;
-use sys::fd::FileDesc;
-use sys_common::{AsInner, FromInner, IntoInner};
-use sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
-use time::{Duration, Instant};
-use cmp;
-
-pub use sys::{cvt, cvt_r};
+use crate::ffi::CStr;
+use crate::io::{self, IoVec, IoVecMut};
+use crate::mem;
+use crate::net::{SocketAddr, Shutdown};
+use crate::str;
+use crate::sys::fd::FileDesc;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
+use crate::time::{Duration, Instant};
+use crate::cmp;
+
+use libc::{c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK};
+
+pub use crate::sys::{cvt, cvt_r};
+
+#[allow(unused_extern_crates)]
pub extern crate libc as netc;
pub type wrlen_t = size_t;
// believe it's thread-safe).
#[cfg(target_env = "gnu")]
fn on_resolver_failure() {
- use sys;
+ use crate::sys;
// If the version fails to parse, we treat it the same as "not glibc".
if let Some(version) = sys::os::glibc_version() {
#![allow(unused_imports)] // lots of cfg code here
-use os::unix::prelude::*;
-
-use error::Error as StdError;
-use ffi::{CString, CStr, OsString, OsStr};
-use fmt;
-use io;
-use iter;
-use libc::{self, c_int, c_char, c_void};
-use marker::PhantomData;
-use mem;
-use memchr;
-use path::{self, PathBuf};
-use ptr;
-use slice;
-use str;
-use sys_common::mutex::{Mutex, MutexGuard};
-use sys::cvt;
-use sys::fd;
-use vec;
+use crate::os::unix::prelude::*;
+
+use crate::error::Error as StdError;
+use crate::ffi::{CString, CStr, OsString, OsStr};
+use crate::fmt;
+use crate::io;
+use crate::iter;
+use crate::marker::PhantomData;
+use crate::mem;
+use crate::memchr;
+use crate::path::{self, PathBuf};
+use crate::ptr;
+use crate::slice;
+use crate::str;
+use crate::sys_common::mutex::{Mutex, MutexGuard};
+use crate::sys::cvt;
+use crate::sys::fd;
+use crate::vec;
+
+use libc::{c_int, c_char, c_void};
const TMPBUF_SZ: usize = 128;
libc::KERN_PROC_PATHNAME as c_int,
-1 as c_int];
let mut sz = 0;
- cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+ cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as libc::c_uint,
ptr::null_mut(), &mut sz, ptr::null_mut(), 0))?;
if sz == 0 {
return Err(io::Error::last_os_error())
}
let mut v: Vec<u8> = Vec::with_capacity(sz);
- cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+ cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as libc::c_uint,
v.as_mut_ptr() as *mut libc::c_void, &mut sz,
ptr::null_mut(), 0))?;
if sz == 0 {
unsafe {
let mib = [libc::CTL_KERN, libc::KERN_PROC_ARGS, -1, libc::KERN_PROC_PATHNAME];
let mut path_len: usize = 0;
- cvt(libc::sysctl(mib.as_ptr(), mib.len() as ::libc::c_uint,
+ cvt(libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint,
ptr::null_mut(), &mut path_len,
ptr::null(), 0))?;
if path_len <= 1 {
"KERN_PROC_PATHNAME sysctl returned zero-length string"))
}
let mut path: Vec<u8> = Vec::with_capacity(path_len);
- cvt(libc::sysctl(mib.as_ptr(), mib.len() as ::libc::c_uint,
+ cvt(libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint,
path.as_ptr() as *mut libc::c_void, &mut path_len,
ptr::null(), 0))?;
path.set_len(path_len - 1); // chop off NUL
fn procfs() -> io::Result<PathBuf> {
let curproc_exe = path::Path::new("/proc/curproc/exe");
if curproc_exe.is_file() {
- return ::fs::read_link(curproc_exe);
+ return crate::fs::read_link(curproc_exe);
}
Err(io::Error::new(io::ErrorKind::Other,
"/proc/curproc/exe doesn't point to regular file."))
}
let argv0 = CStr::from_ptr(argv[0]).to_bytes();
if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') {
- ::fs::canonicalize(OsStr::from_bytes(argv0))
+ crate::fs::canonicalize(OsStr::from_bytes(argv0))
} else {
Ok(PathBuf::from(OsStr::from_bytes(argv0)))
}
#[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))]
pub fn current_exe() -> io::Result<PathBuf> {
- match ::fs::read_link("/proc/self/exe") {
+ match crate::fs::read_link("/proc/self/exe") {
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
Err(io::Error::new(
io::ErrorKind::Other,
let result = _get_next_image_info(0, &mut cookie, &mut info,
mem::size_of::<image_info>() as i32);
if result != 0 {
- use io::ErrorKind;
+ use crate::io::ErrorKind;
Err(io::Error::new(ErrorKind::Other, "Error getting executable path"))
} else {
let name = CStr::from_ptr(info.name.as_ptr()).to_bytes();
#[cfg(any(target_os = "fuchsia", target_os = "l4re", target_os = "hermit"))]
pub fn current_exe() -> io::Result<PathBuf> {
- use io::ErrorKind;
+ use crate::io::ErrorKind;
Err(io::Error::new(ErrorKind::Other, "Not yet implemented!"))
}
}
pub fn temp_dir() -> PathBuf {
- ::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| {
+ crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| {
if cfg!(target_os = "android") {
PathBuf::from("/data/local/tmp")
} else {
}
pub fn home_dir() -> Option<PathBuf> {
- return ::env::var_os("HOME").or_else(|| unsafe {
+ return crate::env::var_os("HOME").or_else(|| unsafe {
fallback()
}).map(PathBuf::from);
/// The underlying OsString/OsStr implementation on Unix systems: just
/// a `Vec<u8>`/`[u8]`.
-use borrow::Cow;
-use fmt;
-use str;
-use mem;
-use rc::Rc;
-use sync::Arc;
-use sys_common::{AsInner, IntoInner};
-use sys_common::bytestring::debug_fmt_bytestring;
+use crate::borrow::Cow;
+use crate::fmt;
+use crate::str;
+use crate::mem;
+use crate::rc::Rc;
+use crate::sync::Arc;
+use crate::sys_common::{AsInner, IntoInner};
+use crate::sys_common::bytestring::debug_fmt_bytestring;
+
use core::str::lossy::Utf8Lossy;
#[derive(Clone, Hash)]
-use path::Prefix;
-use ffi::OsStr;
+use crate::path::Prefix;
+use crate::ffi::OsStr;
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
-use io;
-use libc::{self, c_int};
-use mem;
-use sync::atomic::{AtomicBool, Ordering};
-use sys::fd::FileDesc;
-use sys::{cvt, cvt_r};
+use crate::io;
+use crate::mem;
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sys::fd::FileDesc;
+use crate::sys::{cvt, cvt_r};
+
+use libc::c_int;
////////////////////////////////////////////////////////////////////////////////
// Anonymous pipes
-use os::unix::prelude::*;
-
-use ffi::{OsString, OsStr, CString, CStr};
-use fmt;
-use io;
-use libc::{self, c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE};
-use ptr;
-use sys::fd::FileDesc;
-use sys::fs::{File, OpenOptions};
-use sys::pipe::{self, AnonPipe};
-use sys_common::process::{CommandEnv, DefaultEnvKey};
-use collections::BTreeMap;
+use crate::os::unix::prelude::*;
+
+use crate::ffi::{OsString, OsStr, CString, CStr};
+use crate::fmt;
+use crate::io;
+use crate::ptr;
+use crate::sys::fd::FileDesc;
+use crate::sys::fs::{File, OpenOptions};
+use crate::sys::pipe::{self, AnonPipe};
+use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::collections::BTreeMap;
+
+use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE};
////////////////////////////////////////////////////////////////////////////////
// Command
mod tests {
use super::*;
- use ffi::OsStr;
- use mem;
- use ptr;
- use libc;
- use sys::cvt;
+ use crate::ffi::OsStr;
+ use crate::mem;
+ use crate::ptr;
+ use crate::sys::cvt;
macro_rules! t {
($e:expr) => {
#[cfg(target_os = "android")]
unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
- use slice;
+ use crate::slice;
let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>());
let bit = (signum - 1) as usize;
-use io;
-use libc::{self, size_t};
-use mem;
-use ptr;
+use crate::io;
+use crate::mem;
+use crate::ptr;
-use sys::process::zircon::{Handle, zx_handle_t};
-use sys::process::process_common::*;
+use crate::sys::process::zircon::{Handle, zx_handle_t};
+use crate::sys::process::process_common::*;
+
+use libc::size_t;
////////////////////////////////////////////////////////////////////////////////
// Command
unsafe fn do_exec(&mut self, stdio: ChildPipes, maybe_envp: Option<&CStringArray>)
-> io::Result<zx_handle_t> {
- use sys::process::zircon::*;
+ use crate::sys::process::zircon::*;
let envp = match maybe_envp {
Some(envp) => envp.as_ptr(),
}
pub fn kill(&mut self) -> io::Result<()> {
- use sys::process::zircon::*;
+ use crate::sys::process::zircon::*;
unsafe { zx_cvt(zx_task_kill(self.handle.raw()))?; }
}
pub fn wait(&mut self) -> io::Result<ExitStatus> {
- use default::Default;
- use sys::process::zircon::*;
+ use crate::default::Default;
+ use crate::sys::process::zircon::*;
let mut proc_info: zx_info_process_t = Default::default();
let mut actual: size_t = 0;
}
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
- use default::Default;
- use sys::process::zircon::*;
+ use crate::default::Default;
+ use crate::sys::process::zircon::*;
let mut proc_info: zx_info_process_t = Default::default();
let mut actual: size_t = 0;
-use io::{self, Error, ErrorKind};
-use libc::{self, c_int, gid_t, pid_t, uid_t};
-use ptr;
-use sys::cvt;
-use sys::process::process_common::*;
-use sys;
+use crate::io::{self, Error, ErrorKind};
+use crate::ptr;
+use crate::sys::cvt;
+use crate::sys::process::process_common::*;
+use crate::sys;
+
+use libc::{c_int, gid_t, pid_t, uid_t};
////////////////////////////////////////////////////////////////////////////////
// Command
stdio: ChildPipes,
maybe_envp: Option<&CStringArray>
) -> io::Error {
- use sys::{self, cvt_r};
+ use crate::sys::{self, cvt_r};
macro_rules! t {
($e:expr) => (match $e {
// emscripten has no signal support.
#[cfg(not(any(target_os = "emscripten")))]
{
- use mem;
+ use crate::mem;
// Reset signal handling so the child process starts in a
// standardized state. libstd ignores SIGPIPE, and signal-handling
// libraries often set a mask. Child processes inherit ignored
fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
-> io::Result<Option<Process>>
{
- use mem;
- use sys;
+ use crate::mem;
+ use crate::sys;
if self.get_gid().is_some() ||
self.get_uid().is_some() ||
}
pub fn wait(&mut self) -> io::Result<ExitStatus> {
- use sys::cvt_r;
+ use crate::sys::cvt_r;
if let Some(status) = self.status {
return Ok(status)
}
#![allow(non_camel_case_types, unused)]
-use convert::TryInto;
-use io;
-use os::raw::c_char;
-use u64;
+use crate::convert::TryInto;
+use crate::io;
+use crate::os::raw::c_char;
+use crate::u64;
use libc::{c_int, c_void, size_t};
-use mem;
-use slice;
+use crate::mem;
+use crate::slice;
pub fn hashmap_random_keys() -> (u64, u64) {
let mut v = (0, 0);
not(target_os = "freebsd"),
not(target_os = "fuchsia")))]
mod imp {
- use fs::File;
- use io::Read;
- #[cfg(any(target_os = "linux", target_os = "android"))]
- use libc;
+ use crate::fs::File;
+ use crate::io::Read;
#[cfg(any(target_os = "linux", target_os = "android"))]
fn getrandom(buf: &mut [u8]) -> libc::c_long {
#[cfg(any(target_os = "linux", target_os = "android"))]
fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
- use sync::atomic::{AtomicBool, Ordering};
- use sys::os::errno;
+ use crate::sync::atomic::{AtomicBool, Ordering};
+ use crate::sys::os::errno;
static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
if GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed) {
#[cfg(target_os = "openbsd")]
mod imp {
- use libc;
- use sys::os::errno;
+ use crate::sys::os::errno;
pub fn fill_bytes(v: &mut [u8]) {
// getentropy(2) permits a maximum buffer size of 256 bytes
#[cfg(target_os = "ios")]
mod imp {
- use io;
+ use crate::io;
+ use crate::ptr;
use libc::{c_int, size_t};
- use ptr;
enum SecRandom {}
#[cfg(target_os = "freebsd")]
mod imp {
- use libc;
- use ptr;
+ use crate::ptr;
pub fn fill_bytes(v: &mut [u8]) {
let mib = [libc::CTL_KERN, libc::KERN_ARND];
-use libc;
-use cell::UnsafeCell;
-use sync::atomic::{AtomicUsize, Ordering};
+use crate::cell::UnsafeCell;
+use crate::sync::atomic::{AtomicUsize, Ordering};
pub struct RWLock {
inner: UnsafeCell<libc::pthread_rwlock_t>,
#![cfg_attr(test, allow(dead_code))]
-use libc;
use self::imp::{make_handler, drop_handler};
pub use self::imp::cleanup;
target_os = "openbsd"))]
mod imp {
use super::Handler;
- use mem;
- use ptr;
+ use crate::mem;
+ use crate::ptr;
+
use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
use libc::{sigaction, SIGBUS, SIG_DFL,
SA_SIGINFO, SA_ONSTACK, sighandler_t};
- use libc;
use libc::{mmap, munmap};
use libc::{SIGSEGV, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON};
use libc::MAP_FAILED;
- use sys_common::thread_info;
+ use crate::sys_common::thread_info;
#[cfg(any(target_os = "linux", target_os = "android"))]
unsafe extern fn signal_handler(signum: libc::c_int,
info: *mut libc::siginfo_t,
_data: *mut libc::c_void) {
- use sys_common::util::report_overflow;
+ use crate::sys_common::util::report_overflow;
let guard = thread_info::stack_guard().unwrap_or(0..0);
let addr = siginfo_si_addr(info);
all(target_os = "netbsd", not(target_vendor = "rumprun")),
target_os = "openbsd")))]
mod imp {
- use ptr;
+ use crate::ptr;
pub unsafe fn init() {
}
-use io;
-use libc;
-use sys::fd::FileDesc;
+use crate::io;
+use crate::sys::fd::FileDesc;
pub struct Stdin(());
pub struct Stdout(());
err.raw_os_error() == Some(libc::EBADF as i32)
}
-pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
pub fn panic_output() -> Option<impl io::Write> {
Stderr::new().ok()
-use boxed::FnBox;
-use cmp;
-use ffi::CStr;
-use io;
-use libc;
-use mem;
-use ptr;
-use sys::os;
-use time::Duration;
-
-use sys_common::thread::*;
+use crate::boxed::FnBox;
+use crate::cmp;
+use crate::ffi::CStr;
+use crate::io;
+use crate::mem;
+use crate::ptr;
+use crate::sys::os;
+use crate::time::Duration;
+
+use crate::sys_common::thread::*;
#[cfg(not(target_os = "l4re"))]
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
#[cfg(target_os = "netbsd")]
pub fn set_name(name: &CStr) {
- use ffi::CString;
+ use crate::ffi::CString;
let cname = CString::new(&b"%s"[..]).unwrap();
unsafe {
libc::pthread_setname_np(libc::pthread_self(), cname.as_ptr(),
not(target_os = "solaris")))]
#[cfg_attr(test, allow(dead_code))]
pub mod guard {
- use ops::Range;
+ use crate::ops::Range;
pub type Guard = Range<usize>;
pub unsafe fn current() -> Option<Guard> { None }
pub unsafe fn init() -> Option<Guard> { None }
target_os = "solaris"))]
#[cfg_attr(test, allow(dead_code))]
pub mod guard {
- use libc;
use libc::{mmap, mprotect};
use libc::{PROT_NONE, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED};
- use ops::Range;
- use sys::os;
+
+ use crate::ops::Range;
+ use crate::sys::os;
// This is initialized in init() and only read from after
static mut PAGE_SIZE: usize = 0;
#[cfg(target_os = "solaris")]
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
- let mut current_stack: libc::stack_t = ::mem::zeroed();
+ let mut current_stack: libc::stack_t = crate::mem::zeroed();
assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
Some(current_stack.ss_sp)
}
#[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
- let mut current_stack: libc::stack_t = ::mem::zeroed();
+ let mut current_stack: libc::stack_t = crate::mem::zeroed();
assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(),
&mut current_stack), 0);
target_os = "linux", target_os = "netbsd", target_os = "l4re"))]
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
let mut ret = None;
- let mut attr: libc::pthread_attr_t = ::mem::zeroed();
+ let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
#[cfg(target_os = "freebsd")]
let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
#[cfg(not(target_os = "freebsd"))]
let e = libc::pthread_getattr_np(libc::pthread_self(), &mut attr);
if e == 0 {
- let mut stackaddr = ::ptr::null_mut();
+ let mut stackaddr = crate::ptr::null_mut();
let mut stacksize = 0;
assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr,
&mut stacksize), 0);
target_os = "linux", target_os = "netbsd", target_os = "l4re"))]
pub unsafe fn current() -> Option<Guard> {
let mut ret = None;
- let mut attr: libc::pthread_attr_t = ::mem::zeroed();
+ let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
#[cfg(target_os = "freebsd")]
let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
if guardsize == 0 {
panic!("there is no guard page");
}
- let mut stackaddr = ::ptr::null_mut();
+ let mut stackaddr = crate::ptr::null_mut();
let mut size = 0;
assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr,
&mut size), 0);
#![allow(dead_code)] // not used on all platforms
-use mem;
-use libc;
+use crate::mem;
pub type Key = libc::pthread_key_t;
-use cmp::Ordering;
-use libc;
-use time::Duration;
+use crate::cmp::Ordering;
+use crate::time::Duration;
+
use core::hash::{Hash, Hasher};
pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
-use convert::TryInto;
+use crate::convert::TryInto;
const NSEC_PER_SEC: u64 = 1_000_000_000;
#[cfg(any(target_os = "macos", target_os = "ios"))]
mod inner {
- use fmt;
- use libc;
- use sync::Once;
- use sys::cvt;
- use sys_common::mul_div_u64;
- use time::Duration;
+ use crate::fmt;
+ use crate::sync::Once;
+ use crate::sys::cvt;
+ use crate::sys_common::mul_div_u64;
+ use crate::time::Duration;
use super::NSEC_PER_SEC;
use super::Timespec;
impl SystemTime {
pub fn now() -> SystemTime {
- use ptr;
+ use crate::ptr;
let mut s = libc::timeval {
tv_sec: 0,
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
mod inner {
- use fmt;
- use libc;
- use sys::cvt;
- use time::Duration;
+ use crate::fmt;
+ use crate::sys::cvt;
+ use crate::time::Duration;
use super::Timespec;
//! symbol, but that caused Debian to detect an unnecessarily strict versioned
//! dependency on libc6 (#23628).
-use libc;
-
-use ffi::CStr;
-use marker;
-use mem;
-use sync::atomic::{AtomicUsize, Ordering};
+use crate::ffi::CStr;
+use crate::marker;
+use crate::mem;
+use crate::sync::atomic::{AtomicUsize, Ordering};
macro_rules! weak {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
- static $name: ::sys::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
- ::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
+ static $name: crate::sys::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
+ crate::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
)
}
macro_rules! syscall {
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
unsafe fn $name($($arg_name: $t),*) -> $ret {
- use libc;
use super::os;
weak! { fn $name($($t),*) -> $ret }
//! The crate itself provides a global allocator which on wasm has no
//! synchronization as there are no threads!
-extern crate dlmalloc;
-
-use alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::{GlobalAlloc, Layout, System};
static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
#[cfg(target_feature = "atomics")]
mod lock {
- use arch::wasm32;
- use sync::atomic::{AtomicI32, Ordering::SeqCst};
+ use crate::arch::wasm32;
+ use crate::sync::atomic::{AtomicI32, Ordering::SeqCst};
static LOCKED: AtomicI32 = AtomicI32::new(0);
-use ffi::OsString;
-use marker::PhantomData;
-use vec;
-use sys::ArgsSysCall;
+use crate::ffi::OsString;
+use crate::marker::PhantomData;
+use crate::vec;
+use crate::sys::ArgsSysCall;
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
// On wasm these should always be null, so there's nothing for us to do here
-use io;
-use sys::unsupported;
-use sys_common::backtrace::Frame;
+use crate::io;
+use crate::sys::unsupported;
+use crate::sys_common::backtrace::Frame;
pub struct BacktraceContext;
-use sys::mutex::Mutex;
-use time::Duration;
+use crate::sys::mutex::Mutex;
+use crate::time::Duration;
pub struct Condvar { }
-use arch::wasm32;
-use cmp;
-use mem;
-use sync::atomic::{AtomicUsize, Ordering::SeqCst};
-use sys::mutex::Mutex;
-use time::Duration;
+use crate::arch::wasm32;
+use crate::cmp;
+use crate::mem;
+use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
+use crate::sys::mutex::Mutex;
+use crate::time::Duration;
pub struct Condvar {
cnt: AtomicUsize,
-use ffi::OsString;
-use fmt;
-use hash::{Hash, Hasher};
-use io::{self, SeekFrom};
-use path::{Path, PathBuf};
-use sys::time::SystemTime;
-use sys::{unsupported, Void};
+use crate::ffi::OsString;
+use crate::fmt;
+use crate::hash::{Hash, Hasher};
+use crate::io::{self, SeekFrom};
+use crate::path::{Path, PathBuf};
+use crate::sys::time::SystemTime;
+use crate::sys::{unsupported, Void};
pub struct File(Void);
//! compiling for wasm. That way it's a compile time error for something that's
//! guaranteed to be a runtime error!
-use os::raw::c_char;
-use ptr;
-use sys::os_str::Buf;
-use sys_common::{AsInner, FromInner};
-use ffi::{OsString, OsStr};
-use time::Duration;
+use crate::os::raw::c_char;
+use crate::ptr;
+use crate::sys::os_str::Buf;
+use crate::sys_common::{AsInner, FromInner};
+use crate::ffi::{OsString, OsStr};
+use crate::time::Duration;
pub mod alloc;
pub mod args;
pub fn init() {
}
-pub fn unsupported<T>() -> ::io::Result<T> {
+pub fn unsupported<T>() -> crate::io::Result<T> {
Err(unsupported_err())
}
-pub fn unsupported_err() -> ::io::Error {
- ::io::Error::new(::io::ErrorKind::Other,
+pub fn unsupported_err() -> crate::io::Error {
+ crate::io::Error::new(crate::io::ErrorKind::Other,
"operation not supported on wasm yet")
}
-pub fn decode_error_kind(_code: i32) -> ::io::ErrorKind {
- ::io::ErrorKind::Other
+pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
+ crate::io::ErrorKind::Other
}
// This enum is used as the storage for a bunch of types which can't actually
};
unsafe {
syscall(SysCallIndex::Exit, &mut call_record);
- ::intrinsics::abort();
+ crate::intrinsics::abort();
}
}
}
-use cell::UnsafeCell;
+use crate::cell::UnsafeCell;
pub struct Mutex {
locked: UnsafeCell<bool>,
-use arch::wasm32;
-use cell::UnsafeCell;
-use mem;
-use sync::atomic::{AtomicUsize, AtomicU32, Ordering::SeqCst};
-use sys::thread;
+use crate::arch::wasm32;
+use crate::cell::UnsafeCell;
+use crate::mem;
+use crate::sync::atomic::{AtomicUsize, AtomicU32, Ordering::SeqCst};
+use crate::sys::thread;
pub struct Mutex {
locked: AtomicUsize,
-use fmt;
-use io::{self, IoVec, IoVecMut};
-use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
-use time::Duration;
-use sys::{unsupported, Void};
-use convert::TryFrom;
+use crate::fmt;
+use crate::io::{self, IoVec, IoVecMut};
+use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
+use crate::time::Duration;
+use crate::sys::{unsupported, Void};
+use crate::convert::TryFrom;
pub struct TcpStream(Void);
-use error::Error as StdError;
-use ffi::{OsString, OsStr};
-use fmt;
-use io;
-use path::{self, PathBuf};
-use str;
-use sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall};
+use crate::error::Error as StdError;
+use crate::ffi::{OsString, OsStr};
+use crate::fmt;
+use crate::io;
+use crate::path::{self, PathBuf};
+use crate::str;
+use crate::sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall};
pub fn errno() -> i32 {
0
/// The underlying OsString/OsStr implementation on Unix systems: just
/// a `Vec<u8>`/`[u8]`.
-use borrow::Cow;
-use fmt;
-use str;
-use mem;
-use rc::Rc;
-use sync::Arc;
-use sys_common::{AsInner, IntoInner};
-use sys_common::bytestring::debug_fmt_bytestring;
+use crate::borrow::Cow;
+use crate::fmt;
+use crate::str;
+use crate::mem;
+use crate::rc::Rc;
+use crate::sync::Arc;
+use crate::sys_common::{AsInner, IntoInner};
+use crate::sys_common::bytestring::debug_fmt_bytestring;
+
use core::str::lossy::Utf8Lossy;
#[derive(Clone, Hash)]
-use path::Prefix;
-use ffi::OsStr;
+use crate::path::Prefix;
+use crate::ffi::OsStr;
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
-use io;
-use sys::Void;
+use crate::io;
+use crate::sys::Void;
pub struct AnonPipe(Void);
-use ffi::OsStr;
-use fmt;
-use io;
-use sys::fs::File;
-use sys::pipe::AnonPipe;
-use sys::{unsupported, Void};
-use sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::ffi::OsStr;
+use crate::fmt;
+use crate::io;
+use crate::sys::fs::File;
+use crate::sys::pipe::AnonPipe;
+use crate::sys::{unsupported, Void};
+use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
////////////////////////////////////////////////////////////////////////////////
// Command
-use cell::UnsafeCell;
+use crate::cell::UnsafeCell;
pub struct RWLock {
mode: UnsafeCell<isize>,
-use cell::UnsafeCell;
-use sys::mutex::Mutex;
-use sys::condvar::Condvar;
+use crate::cell::UnsafeCell;
+use crate::sys::mutex::Mutex;
+use crate::sys::condvar::Condvar;
pub struct RWLock {
lock: Mutex,
-use io;
-use sys::{ReadSysCall, WriteSysCall};
+use crate::io;
+use crate::sys::{ReadSysCall, WriteSysCall};
pub struct Stdin;
pub struct Stdout;
-use boxed::FnBox;
-use ffi::CStr;
-use io;
-use sys::{unsupported, Void};
-use time::Duration;
+use crate::boxed::FnBox;
+use crate::ffi::CStr;
+use crate::io;
+use crate::sys::{unsupported, Void};
+use crate::time::Duration;
pub struct Thread(Void);
#[cfg(target_feature = "atomics")]
pub fn sleep(dur: Duration) {
- use arch::wasm32;
- use cmp;
+ use crate::arch::wasm32;
+ use crate::cmp;
// Use an atomic wait to block the current thread artificially with a
// timeout listed. Note that we should never be notified (return value
// you'd like to use them be sure to update that and make sure everyone
// agrees what's what.
pub fn tcb_get() -> *mut u8 {
- use mem;
+ use crate::mem;
assert_eq!(mem::size_of::<*mut u8>(), mem::size_of::<u32>());
unsafe { __wbindgen_tcb_get() as *mut u8 }
}
-use boxed::Box;
-use ptr;
+use crate::boxed::Box;
+use crate::ptr;
pub type Key = usize;
-use sys::thread;
-use sync::atomic::{AtomicUsize, Ordering::SeqCst};
+use crate::sys::thread;
+use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
const MAX_KEYS: usize = 128;
static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
-use time::Duration;
-use sys::{TimeSysCall, TimeClock};
+use crate::time::Duration;
+use crate::sys::{TimeSysCall, TimeClock};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Instant(Duration);
-use alloc::{GlobalAlloc, Layout, System};
-use sys::c;
-use sys_common::alloc::{MIN_ALIGN, realloc_fallback};
+use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::sys::c;
+use crate::sys_common::alloc::{MIN_ALIGN, realloc_fallback};
#[repr(C)]
struct Header(*mut u8);
#![allow(dead_code)] // runtime init functions not used during testing
-use os::windows::prelude::*;
-use sys::windows::os::current_exe;
-use sys::c;
-use ffi::OsString;
-use fmt;
-use vec;
+use crate::os::windows::prelude::*;
+use crate::sys::windows::os::current_exe;
+use crate::sys::c;
+use crate::ffi::OsString;
+use crate::fmt;
+use crate::vec;
+use crate::slice;
+use crate::path::PathBuf;
+
use core::iter;
-use slice;
-use path::PathBuf;
pub unsafe fn init(_argc: isize, _argv: *const *const u8) { }
// "However, if lpCmdLine starts with any amount of whitespace, CommandLineToArgvW
// will consider the first argument to be an empty string. Excess whitespace at the
// end of lpCmdLine is ignored."
- 0...SPACE => {
+ 0..=SPACE => {
ret_val.push(OsString::new());
&cmd_line[1..]
},
#[cfg(test)]
mod tests {
- use sys::windows::args::*;
- use ffi::OsString;
+ use crate::sys::windows::args::*;
+ use crate::ffi::OsString;
fn chk(string: &str, parts: &[&str]) {
let mut wide: Vec<u16> = OsString::from(string).encode_wide().collect();
-use io;
-use sys::c;
+use crate::io;
+use crate::sys::c;
+use crate::path::PathBuf;
+use crate::fs::{OpenOptions, File};
+use crate::sys::ext::fs::OpenOptionsExt;
+use crate::sys::handle::Handle;
+
use libc::c_char;
-use path::PathBuf;
-use fs::{OpenOptions, File};
-use sys::ext::fs::OpenOptionsExt;
-use sys::handle::Handle;
use super::super::{fill_utf16_buf, os2path, to_u16s, wide_char_to_multi_byte};
fn query_full_process_image_name() -> io::Result<PathBuf> {
#![allow(deprecated)] // dynamic_lib
-use io;
+use crate::io;
+use crate::mem;
+use crate::ptr;
+use crate::sys::c;
+use crate::sys::dynamic_lib::DynamicLibrary;
+use crate::sys_common::backtrace::Frame;
+
use libc::c_void;
-use mem;
-use ptr;
-use sys::c;
-use sys::dynamic_lib::DynamicLibrary;
-use sys_common::backtrace::Frame;
macro_rules! sym {
($lib:expr, $e:expr, $t:ident) => (
#[cfg(target_env = "gnu")]
mod printing {
- pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
+ pub use crate::sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
// dummy functions to mirror those present in msvc version.
- use sys::dynamic_lib::DynamicLibrary;
- use io;
+ use crate::sys::dynamic_lib::DynamicLibrary;
+ use crate::io;
pub struct PrintingFnsEx {}
pub struct PrintingFns64 {}
pub fn load_printing_fns_ex(_: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
-use ffi::CStr;
-use io;
+use crate::ffi::CStr;
+use crate::io;
+use crate::mem;
+use crate::sys::backtrace::BacktraceContext;
+use crate::sys::backtrace::StackWalkVariant;
+use crate::sys::c;
+use crate::sys::dynamic_lib::DynamicLibrary;
+use crate::sys_common::backtrace::Frame;
+
use libc::{c_char, c_ulong};
-use mem;
-use sys::backtrace::BacktraceContext;
-use sys::backtrace::StackWalkVariant;
-use sys::c;
-use sys::dynamic_lib::DynamicLibrary;
-use sys_common::backtrace::Frame;
// Structs holding printing functions and loaders for them
// Two versions depending on whether dbghelp.dll has StackWalkEx or not
{
unsafe {
let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
- line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
+ line.SizeOfStruct = mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
let ret = line_getter(
context.handle,
#![cfg_attr(test, allow(dead_code))]
#![unstable(issue = "0", feature = "windows_c")]
-use os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort, c_char};
+use crate::os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort, c_char};
#[cfg(target_arch = "x86_64")]
-use os::raw::c_ulonglong;
+use crate::os::raw::c_ulonglong;
+use crate::ptr;
+
use libc::{wchar_t, size_t, c_void};
-use ptr;
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
pub use self::EXCEPTION_DISPOSITION::*;
pub type PLARGE_INTEGER = *mut c_longlong;
pub type PSRWLOCK = *mut SRWLOCK;
-pub type SOCKET = ::os::windows::raw::SOCKET;
+pub type SOCKET = crate::os::windows::raw::SOCKET;
pub type socklen_t = c_int;
pub type ADDRESS_FAMILY = USHORT;
pub PathBuffer: WCHAR,
}
-pub type LPPROGRESS_ROUTINE = ::option::Option<unsafe extern "system" fn(
+pub type LPPROGRESS_ROUTINE = crate::option::Option<unsafe extern "system" fn(
TotalFileSize: LARGE_INTEGER,
TotalBytesTransferred: LARGE_INTEGER,
StreamSize: LARGE_INTEGER,
//! manner we pay a semi-large one-time cost up front for detecting whether a
//! function is available but afterwards it's just a load and a jump.
-use ffi::CString;
-use sync::atomic::{AtomicUsize, Ordering};
-use sys::c;
+use crate::ffi::CString;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sys::c;
pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
let mut module: Vec<u16> = module.encode_utf16().collect();
)*) => ($(
#[allow(unused_variables)]
pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
- use sync::atomic::{AtomicUsize, Ordering};
- use mem;
+ use crate::sync::atomic::{AtomicUsize, Ordering};
+ use crate::mem;
type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
static PTR: AtomicUsize = AtomicUsize::new(0);
fn load() -> usize {
- ::sys::compat::store_func(&PTR,
+ crate::sys::compat::store_func(&PTR,
stringify!($module),
stringify!($symbol),
fallback as usize)
-use cell::UnsafeCell;
-use sys::c;
-use sys::mutex::{self, Mutex};
-use sys::os;
-use time::Duration;
+use crate::cell::UnsafeCell;
+use crate::sys::c;
+use crate::sys::mutex::{self, Mutex};
+use crate::sys::os;
+use crate::time::Duration;
pub struct Condvar { inner: UnsafeCell<c::CONDITION_VARIABLE> }
-use os::windows::prelude::*;
+use crate::os::windows::prelude::*;
-use ffi::{CString, OsStr};
-use io;
-use sys::c;
+use crate::ffi::{CString, OsStr};
+use crate::io;
+use crate::sys::c;
pub struct DynamicLibrary {
handle: c::HMODULE,
#![stable(feature = "rust1", since = "1.0.0")]
-use ffi::{OsString, OsStr};
-use sys::os_str::Buf;
-use sys_common::wtf8::Wtf8Buf;
-use sys_common::{FromInner, AsInner};
+use crate::ffi::{OsString, OsStr};
+use crate::sys::os_str::Buf;
+use crate::sys_common::wtf8::Wtf8Buf;
+use crate::sys_common::{FromInner, AsInner};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use sys_common::wtf8::EncodeWide;
+pub use crate::sys_common::wtf8::EncodeWide;
/// Windows-specific extensions to [`OsString`].
///
#![stable(feature = "rust1", since = "1.0.0")]
-use fs::{self, OpenOptions, Metadata};
-use io;
-use path::Path;
-use sys;
-use sys_common::{AsInnerMut, AsInner};
+use crate::fs::{self, OpenOptions, Metadata};
+use crate::io;
+use crate::path::Path;
+use crate::sys;
+use crate::sys_common::{AsInnerMut, AsInner};
/// Windows-specific extensions to [`File`].
///
#![stable(feature = "rust1", since = "1.0.0")]
-use fs;
-use os::windows::raw;
-use net;
-use sys_common::{self, AsInner, FromInner, IntoInner};
-use sys;
-use io;
-use sys::c;
+use crate::fs;
+use crate::os::windows::raw;
+use crate::net;
+use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::sys;
+use crate::sys::c;
+use crate::io;
/// Raw HANDLEs.
#[stable(feature = "rust1", since = "1.0.0")]
#![stable(feature = "process_extensions", since = "1.2.0")]
-use os::windows::io::{FromRawHandle, RawHandle, AsRawHandle, IntoRawHandle};
-use process;
-use sys;
-use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
+use crate::os::windows::io::{FromRawHandle, RawHandle, AsRawHandle, IntoRawHandle};
+use crate::process;
+use crate::sys;
+use crate::sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
#[stable(feature = "process_extensions", since = "1.2.0")]
impl FromRawHandle for process::Stdio {
#![stable(feature = "raw_ext", since = "1.1.0")]
-use os::raw::c_void;
+use crate::os::raw::c_void;
#[stable(feature = "raw_ext", since = "1.1.0")] pub type HANDLE = *mut c_void;
#[cfg(target_pointer_width = "32")]
#![stable(feature = "thread_extensions", since = "1.9.0")]
-use os::windows::io::{RawHandle, AsRawHandle, IntoRawHandle};
-use thread;
-use sys_common::{AsInner, IntoInner};
+use crate::os::windows::io::{RawHandle, AsRawHandle, IntoRawHandle};
+use crate::thread;
+use crate::sys_common::{AsInner, IntoInner};
#[stable(feature = "thread_extensions", since = "1.9.0")]
impl<T> AsRawHandle for thread::JoinHandle<T> {
#![unstable(feature = "thread_local_internals", issue = "0")]
#![cfg(target_thread_local)]
-pub use sys_common::thread_local::register_dtor_fallback as register_dtor;
+pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor;
pub fn requires_move_before_drop() -> bool {
false
-use os::windows::prelude::*;
-
-use ffi::OsString;
-use fmt;
-use io::{self, Error, SeekFrom};
-use mem;
-use path::{Path, PathBuf};
-use ptr;
-use slice;
-use sync::Arc;
-use sys::handle::Handle;
-use sys::time::SystemTime;
-use sys::{c, cvt};
-use sys_common::FromInner;
+use crate::os::windows::prelude::*;
+
+use crate::ffi::OsString;
+use crate::fmt;
+use crate::io::{self, Error, SeekFrom};
+use crate::mem;
+use crate::path::{Path, PathBuf};
+use crate::ptr;
+use crate::slice;
+use crate::sync::Arc;
+use crate::sys::handle::Handle;
+use crate::sys::time::SystemTime;
+use crate::sys::{c, cvt};
+use crate::sys_common::FromInner;
use super::to_u16s;
#![unstable(issue = "0", feature = "windows_handle")]
-use cmp;
-use io::{ErrorKind, Read};
-use io;
-use mem;
-use ops::Deref;
-use ptr;
-use sys::c;
-use sys::cvt;
+use crate::cmp;
+use crate::io::{self, ErrorKind, Read};
+use crate::mem;
+use crate::ops::Deref;
+use crate::ptr;
+use crate::sys::c;
+use crate::sys::cvt;
/// An owned container for `HANDLE` object, closing them on Drop.
///
-use marker::PhantomData;
-use slice;
-use sys::c;
+use crate::marker::PhantomData;
+use crate::slice;
+use crate::sys::c;
#[repr(transparent)]
pub struct IoVec<'a> {
#![allow(missing_docs, nonstandard_style)]
-use ptr;
-use ffi::{OsStr, OsString};
-use io::ErrorKind;
-use os::windows::ffi::{OsStrExt, OsStringExt};
-use path::PathBuf;
-use time::Duration;
+use crate::ptr;
+use crate::ffi::{OsStr, OsString};
+use crate::io::ErrorKind;
+use crate::os::windows::ffi::{OsStrExt, OsStringExt};
+use crate::path::PathBuf;
+use crate::time::Duration;
pub use libc::strlen;
pub use self::rand::hashmap_random_keys;
}
}
-pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> ::io::Result<Vec<u16>> {
- fn inner(s: &OsStr) -> ::io::Result<Vec<u16>> {
+pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
+ fn inner(s: &OsStr) -> crate::io::Result<Vec<u16>> {
let mut maybe_result: Vec<u16> = s.encode_wide().collect();
if maybe_result.iter().any(|&u| u == 0) {
- return Err(::io::Error::new(::io::ErrorKind::InvalidInput,
+ return Err(crate::io::Error::new(ErrorKind::InvalidInput,
"strings passed to WinAPI cannot contain NULs"));
}
maybe_result.push(0);
// Once the syscall has completed (errors bail out early) the second closure is
// yielded the data which has been read from the syscall. The return value
// from this closure is then the return value of the function.
-fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> ::io::Result<T>
+fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T>
where F1: FnMut(*mut u16, c::DWORD) -> c::DWORD,
F2: FnOnce(&[u16]) -> T
{
c::SetLastError(0);
let k = match f1(buf.as_mut_ptr(), n as c::DWORD) {
0 if c::GetLastError() == 0 => 0,
- 0 => return Err(::io::Error::last_os_error()),
+ 0 => return Err(crate::io::Error::last_os_error()),
n => n,
} as usize;
if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER {
flags: u32,
s: &[u16],
no_default_char: bool)
- -> ::io::Result<Vec<i8>> {
+ -> crate::io::Result<Vec<i8>> {
unsafe {
let mut size = c::WideCharToMultiByte(code_page,
flags,
ptr::null(),
ptr::null_mut());
if size == 0 {
- return Err(::io::Error::last_os_error());
+ return Err(crate::io::Error::last_os_error());
}
let mut buf = Vec::with_capacity(size as usize);
if no_default_char { &mut used_default_char }
else { ptr::null_mut() });
if size == 0 {
- return Err(::io::Error::last_os_error());
+ return Err(crate::io::Error::last_os_error());
}
if no_default_char && used_default_char == c::TRUE {
- return Err(::io::Error::new(::io::ErrorKind::InvalidData,
+ return Err(crate::io::Error::new(crate::io::ErrorKind::InvalidData,
"string cannot be converted to requested code page"));
}
impl_is_zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
-pub fn cvt<I: IsZero>(i: I) -> ::io::Result<I> {
+pub fn cvt<I: IsZero>(i: I) -> crate::io::Result<I> {
if i.is_zero() {
- Err(::io::Error::last_os_error())
+ Err(crate::io::Error::last_os_error())
} else {
Ok(i)
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
- ::intrinsics::unreachable();
+ crate::intrinsics::unreachable();
}
- ::intrinsics::abort();
+ crate::intrinsics::abort();
}
//! CriticalSection is used and we keep track of who's holding the mutex to
//! detect recursive locks.
-use cell::UnsafeCell;
-use mem::{self, MaybeUninit};
-use sync::atomic::{AtomicUsize, Ordering};
-use sys::c;
-use sys::compat;
+use crate::cell::UnsafeCell;
+use crate::mem::{self, MaybeUninit};
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sys::c;
+use crate::sys::compat;
pub struct Mutex {
lock: AtomicUsize,
#![unstable(issue = "0", feature = "windows_net")]
-use cmp;
-use io::{self, Read, IoVec, IoVecMut};
+use crate::cmp;
+use crate::io::{self, Read, IoVec, IoVecMut};
+use crate::mem;
+use crate::net::{SocketAddr, Shutdown};
+use crate::ptr;
+use crate::sync::Once;
+use crate::sys::c;
+use crate::sys;
+use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::sys_common::net;
+use crate::time::Duration;
+
use libc::{c_int, c_void, c_ulong, c_long};
-use mem;
-use net::{SocketAddr, Shutdown};
-use ptr;
-use sync::Once;
-use sys::c;
-use sys;
-use sys_common::{self, AsInner, FromInner, IntoInner};
-use sys_common::net;
-use time::Duration;
pub type wrlen_t = i32;
pub mod netc {
- pub use sys::c::*;
- pub use sys::c::SOCKADDR as sockaddr;
- pub use sys::c::SOCKADDR_STORAGE_LH as sockaddr_storage;
- pub use sys::c::ADDRINFOA as addrinfo;
- pub use sys::c::ADDRESS_FAMILY as sa_family_t;
+ pub use crate::sys::c::*;
+ pub use crate::sys::c::SOCKADDR as sockaddr;
+ pub use crate::sys::c::SOCKADDR_STORAGE_LH as sockaddr_storage;
+ pub use crate::sys::c::ADDRINFOA as addrinfo;
+ pub use crate::sys::c::ADDRESS_FAMILY as sa_family_t;
}
pub struct Socket(c::SOCKET);
#![allow(nonstandard_style)]
-use os::windows::prelude::*;
-
-use error::Error as StdError;
-use ffi::{OsString, OsStr};
-use fmt;
-use io;
-use os::windows::ffi::EncodeWide;
-use path::{self, PathBuf};
-use ptr;
-use slice;
-use sys::{c, cvt};
-use sys::handle::Handle;
+use crate::os::windows::prelude::*;
+
+use crate::error::Error as StdError;
+use crate::ffi::{OsString, OsStr};
+use crate::fmt;
+use crate::io;
+use crate::os::windows::ffi::EncodeWide;
+use crate::path::{self, PathBuf};
+use crate::ptr;
+use crate::slice;
+use crate::sys::{c, cvt};
+use crate::sys::handle::Handle;
use super::to_u16s;
}
pub fn home_dir() -> Option<PathBuf> {
- ::env::var_os("HOME").or_else(|| {
- ::env::var_os("USERPROFILE")
+ crate::env::var_os("HOME").or_else(|| {
+ crate::env::var_os("USERPROFILE")
}).map(PathBuf::from).or_else(|| unsafe {
let me = c::GetCurrentProcess();
let mut token = ptr::null_mut();
#[cfg(test)]
mod tests {
- use io::Error;
- use sys::c;
+ use crate::io::Error;
+ use crate::sys::c;
// tests `error_string` above
#[test]
/// The underlying OsString/OsStr implementation on Windows is a
/// wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
-use borrow::Cow;
-use fmt;
-use sys_common::wtf8::{Wtf8, Wtf8Buf};
-use mem;
-use rc::Rc;
-use sync::Arc;
-use sys_common::{AsInner, IntoInner, FromInner};
+use crate::borrow::Cow;
+use crate::fmt;
+use crate::sys_common::wtf8::{Wtf8, Wtf8Buf};
+use crate::mem;
+use crate::rc::Rc;
+use crate::sync::Arc;
+use crate::sys_common::{AsInner, IntoInner, FromInner};
#[derive(Clone, Hash)]
pub struct Buf {
-use path::Prefix;
-use ffi::OsStr;
-use mem;
+use crate::path::Prefix;
+use crate::ffi::OsStr;
+use crate::mem;
fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
unsafe { mem::transmute(s) }
}
pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix> {
- use path::Prefix::*;
+ use crate::path::Prefix::*;
unsafe {
// The unsafety here stems from converting between &OsStr and &[u8]
// and back. This is safe to do because (1) we only look at ASCII
-use os::windows::prelude::*;
+use crate::os::windows::prelude::*;
-use ffi::OsStr;
-use io;
-use mem;
-use path::Path;
-use ptr;
-use slice;
-use sync::atomic::Ordering::SeqCst;
-use sync::atomic::AtomicUsize;
-use sys::c;
-use sys::fs::{File, OpenOptions};
-use sys::handle::Handle;
-use sys::hashmap_random_keys;
+use crate::ffi::OsStr;
+use crate::io;
+use crate::mem;
+use crate::path::Path;
+use crate::ptr;
+use crate::slice;
+use crate::sync::atomic::Ordering::SeqCst;
+use crate::sync::atomic::AtomicUsize;
+use crate::sys::c;
+use crate::sys::fs::{File, OpenOptions};
+use crate::sys::handle::Handle;
+use crate::sys::hashmap_random_keys;
////////////////////////////////////////////////////////////////////////////////
// Anonymous pipes
#![unstable(feature = "process_internals", issue = "0")]
-use collections::BTreeMap;
-use env::split_paths;
-use env;
-use ffi::{OsString, OsStr};
-use fmt;
-use fs;
-use io::{self, Error, ErrorKind};
+use crate::collections::BTreeMap;
+use crate::env::split_paths;
+use crate::env;
+use crate::ffi::{OsString, OsStr};
+use crate::fmt;
+use crate::fs;
+use crate::io::{self, Error, ErrorKind};
+use crate::mem;
+use crate::os::windows::ffi::OsStrExt;
+use crate::path::Path;
+use crate::ptr;
+use crate::sys::mutex::Mutex;
+use crate::sys::c;
+use crate::sys::fs::{OpenOptions, File};
+use crate::sys::handle::Handle;
+use crate::sys::pipe::{self, AnonPipe};
+use crate::sys::stdio;
+use crate::sys::cvt;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::process::{CommandEnv, EnvKey};
+use crate::borrow::Borrow;
+
use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE};
-use mem;
-use os::windows::ffi::OsStrExt;
-use path::Path;
-use ptr;
-use sys::mutex::Mutex;
-use sys::c;
-use sys::fs::{OpenOptions, File};
-use sys::handle::Handle;
-use sys::pipe::{self, AnonPipe};
-use sys::stdio;
-use sys::cvt;
-use sys_common::{AsInner, FromInner, IntoInner};
-use sys_common::process::{CommandEnv, EnvKey};
-use borrow::Borrow;
////////////////////////////////////////////////////////////////////////////////
// Command
#[cfg(test)]
mod tests {
- use ffi::{OsStr, OsString};
+ use crate::ffi::{OsStr, OsString};
use super::make_command_line;
#[test]
-use io;
-use mem;
-use sys::c;
+use crate::io;
+use crate::mem;
+use crate::sys::c;
pub fn hashmap_random_keys() -> (u64, u64) {
let mut v = (0, 0);
-use cell::UnsafeCell;
-use sys::c;
+use crate::cell::UnsafeCell;
+use crate::sys::c;
pub struct RWLock { inner: UnsafeCell<c::SRWLOCK> }
#![cfg_attr(test, allow(dead_code))]
-use sys_common::util::report_overflow;
-use sys::c;
+use crate::sys_common::util::report_overflow;
+use crate::sys::c;
pub struct Handler;
#![unstable(issue = "0", feature = "windows_stdio")]
-use char::decode_utf16;
-use cmp;
-use io;
-use ptr;
-use str;
-use sys::c;
-use sys::cvt;
-use sys::handle::Handle;
+use crate::char::decode_utf16;
+use crate::cmp;
+use crate::io;
+use crate::ptr;
+use crate::str;
+use crate::sys::c;
+use crate::sys::cvt;
+use crate::sys::handle::Handle;
// Don't cache handles but get them fresh for every read/write. This allows us to track changes to
// the value over time (such as if a process calls `SetStdHandle` while it's running). See #40490.
const CTRL_Z: u16 = 0x1A;
const CTRL_Z_MASK: c::ULONG = 1 << CTRL_Z;
let mut input_control = c::CONSOLE_READCONSOLE_CONTROL {
- nLength: ::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG,
+ nLength: crate::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG,
nInitialChars: 0,
dwCtrlWakeupMask: CTRL_Z_MASK,
dwControlKeyState: 0,
-use boxed::FnBox;
-use io;
-use ffi::CStr;
-use mem;
+use crate::boxed::FnBox;
+use crate::io;
+use crate::ffi::CStr;
+use crate::mem;
+use crate::ptr;
+use crate::sys::c;
+use crate::sys::handle::Handle;
+use crate::sys_common::thread::*;
+use crate::time::Duration;
+
use libc::c_void;
-use ptr;
-use sys::c;
-use sys::handle::Handle;
-use sys_common::thread::*;
-use time::Duration;
use super::to_u16s;
-use mem;
-use ptr;
-use sync::atomic::AtomicPtr;
-use sync::atomic::Ordering::SeqCst;
-use sys::c;
+use crate::mem;
+use crate::ptr;
+use crate::sync::atomic::AtomicPtr;
+use crate::sync::atomic::Ordering::SeqCst;
+use crate::sys::c;
pub type Key = c::DWORD;
pub type Dtor = unsafe extern fn(*mut u8);
#[cfg(target_env = "msvc")]
unsafe fn reference_tls_used() {
extern { static _tls_used: u8; }
- ::intrinsics::volatile_load(&_tls_used);
+ crate::intrinsics::volatile_load(&_tls_used);
}
#[cfg(not(target_env = "msvc"))]
unsafe fn reference_tls_used() {}
-use cmp::Ordering;
-use fmt;
-use mem;
-use sys::c;
-use time::Duration;
-use convert::TryInto;
+use crate::cmp::Ordering;
+use crate::fmt;
+use crate::mem;
+use crate::sys::c;
+use crate::time::Duration;
+use crate::convert::TryInto;
+
use core::hash::{Hash, Hasher};
const NANOS_PER_SEC: u64 = 1_000_000_000;
mod perf_counter {
use super::{NANOS_PER_SEC};
- use sync::Once;
- use sys_common::mul_div_u64;
- use sys::c;
- use sys::cvt;
- use time::Duration;
+ use crate::sync::Once;
+ use crate::sys_common::mul_div_u64;
+ use crate::sys::c;
+ use crate::sys::cvt;
+ use crate::time::Duration;
pub struct PerformanceCounterInstant {
ts: c::LARGE_INTEGER
#![allow(dead_code)]
-use alloc::{GlobalAlloc, Layout, System};
-use cmp;
-use ptr;
+use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::cmp;
+use crate::ptr;
// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values.
//!
//! Documentation can be found on the `rt::at_exit` function.
-use boxed::FnBox;
-use ptr;
-use mem;
-use sys_common::mutex::Mutex;
+use crate::boxed::FnBox;
+use crate::ptr;
+use crate::mem;
+use crate::sys_common::mutex::Mutex;
type Queue = Vec<Box<dyn FnBox()>>;
/// Common code for printing the backtrace in the same way across the different
/// supported platforms.
-use env;
-use io::prelude::*;
-use io;
-use path::{self, Path};
-use ptr;
+use crate::env;
+use crate::io::prelude::*;
+use crate::io;
+use crate::path::{self, Path};
+use crate::ptr;
+use crate::str;
+use crate::sync::atomic::{self, Ordering};
+use crate::sys::mutex::Mutex;
+
use rustc_demangle::demangle;
-use str;
-use sync::atomic::{self, Ordering};
-use sys::mutex::Mutex;
-pub use sys::backtrace::{
+pub use crate::sys::backtrace::{
unwind_backtrace,
resolve_symname,
foreach_symbol_fileline,
#![allow(dead_code)]
-use fmt::{Formatter, Result, Write};
+use crate::fmt::{Formatter, Result, Write};
use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter) -> Result {
#[cfg(test)]
mod tests {
use super::*;
- use fmt::{Formatter, Result, Debug};
+ use crate::fmt::{Formatter, Result, Debug};
#[test]
fn smoke() {
-use time::Duration;
-use sys_common::mutex::{self, Mutex};
-use sys::condvar as imp;
+use crate::time::Duration;
+use crate::sys_common::mutex::{self, Mutex};
+use crate::sys::condvar as imp;
/// An OS-based condition variable.
///
-use libc;
-use backtrace_sys::{self, backtrace_state};
+use backtrace_sys::backtrace_state;
-use ffi::CStr;
-use io;
-use mem;
-use ptr;
-use sys::backtrace::BacktraceContext;
-use sys_common::backtrace::Frame;
+use crate::ffi::CStr;
+use crate::io;
+use crate::mem;
+use crate::ptr;
+use crate::sys::backtrace::BacktraceContext;
+use crate::sys_common::backtrace::Frame;
pub fn foreach_symbol_fileline<F>(frame: Frame,
mut f: F,
static mut STATE: *mut backtrace_state = ptr::null_mut();
if !STATE.is_null() { return STATE }
- let filename = match ::sys::backtrace::gnu::get_executable_filename() {
+ let filename = match crate::sys::backtrace::gnu::get_executable_filename() {
Ok((filename, file)) => {
// filename is purposely leaked here since libbacktrace requires
// it to stay allocated permanently, file is also leaked so that
#[cfg(test)]
#[allow(dead_code)] // not used on emscripten
pub mod test {
- use path::{Path, PathBuf};
- use env;
- use rand::{self, RngCore};
- use fs;
+ use crate::path::{Path, PathBuf};
+ use crate::env;
+ use crate::fs;
+ use rand::RngCore;
pub struct TempDir(PathBuf);
#![allow(missing_docs)]
#![allow(missing_debug_implementations)]
-use sync::Once;
-use sys;
+use crate::sync::Once;
+use crate::sys;
macro_rules! rtabort {
- ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*)))
+ ($($t:tt)*) => (crate::sys_common::util::abort(format_args!($($t)*)))
}
macro_rules! rtassert {
target_os = "redox",
all(target_arch = "wasm32", not(target_os = "emscripten")),
all(target_vendor = "fortanix", target_env = "sgx")))] {
- pub use sys::net;
+ pub use crate::sys::net;
} else {
pub mod net;
}
-use sys::mutex as imp;
+use crate::sys::mutex as imp;
/// An OS-based mutual exclusion lock.
///
-use cmp;
-use ffi::CString;
-use fmt;
-use io::{self, Error, ErrorKind, IoVec, IoVecMut};
+use crate::cmp;
+use crate::ffi::CString;
+use crate::fmt;
+use crate::io::{self, Error, ErrorKind, IoVec, IoVecMut};
+use crate::mem;
+use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
+use crate::ptr;
+use crate::sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
+use crate::sys::net::netc as c;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::time::Duration;
+use crate::convert::{TryFrom, TryInto};
+
use libc::{c_int, c_void};
-use mem;
-use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
-use ptr;
-use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
-use sys::net::netc as c;
-use sys_common::{AsInner, FromInner, IntoInner};
-use time::Duration;
-use convert::{TryFrom, TryInto};
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "openbsd", target_os = "netbsd",
target_os = "solaris", target_os = "haiku", target_os = "l4re"))]
-use sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
+use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "openbsd", target_os = "netbsd",
target_os = "solaris", target_os = "haiku", target_os = "l4re")))]
-use sys::net::netc::IPV6_ADD_MEMBERSHIP;
+use crate::sys::net::netc::IPV6_ADD_MEMBERSHIP;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "openbsd", target_os = "netbsd",
target_os = "solaris", target_os = "haiku", target_os = "l4re"))]
-use sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
+use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "openbsd", target_os = "netbsd",
target_os = "solaris", target_os = "haiku", target_os = "l4re")))]
-use sys::net::netc::IPV6_DROP_MEMBERSHIP;
+use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP;
#[cfg(any(target_os = "linux", target_os = "android",
target_os = "dragonfly", target_os = "freebsd",
}
#[cfg(not(target_os = "android"))]
-fn to_ipv6mr_interface(value: u32) -> ::libc::c_uint {
- value as ::libc::c_uint
+fn to_ipv6mr_interface(value: u32) -> libc::c_uint {
+ value as libc::c_uint
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(test)]
mod tests {
use super::*;
- use collections::HashMap;
+ use crate::collections::HashMap;
#[test]
fn no_lookup_host_duplicates() {
-use error::{Error};
-use fmt;
-use sync::atomic::{AtomicBool, Ordering};
-use thread;
+use crate::error::{Error};
+use crate::fmt;
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::thread;
pub struct Flag { failed: AtomicBool }
#![allow(dead_code)]
#![unstable(feature = "process_internals", issue = "0")]
-use ffi::{OsStr, OsString};
-use env;
-use collections::BTreeMap;
-use borrow::Borrow;
+use crate::ffi::{OsStr, OsString};
+use crate::env;
+use crate::collections::BTreeMap;
+use crate::borrow::Borrow;
pub trait EnvKey:
From<OsString> + Into<OsString> +
-use fmt;
-use marker;
-use ops::Deref;
-use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
-use sys::mutex as sys;
-use panic::{UnwindSafe, RefUnwindSafe};
+use crate::fmt;
+use crate::marker;
+use crate::ops::Deref;
+use crate::sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
+use crate::sys::mutex as sys;
+use crate::panic::{UnwindSafe, RefUnwindSafe};
/// A re-entrant mutual exclusion
///
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
- use cell::RefCell;
- use sync::Arc;
- use thread;
+ use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
+ use crate::cell::RefCell;
+ use crate::sync::Arc;
+ use crate::thread;
#[test]
fn smoke() {
-use sys::rwlock as imp;
+use crate::sys::rwlock as imp;
/// An OS-based reader-writer lock.
///
-use boxed::FnBox;
-use env;
-use sync::atomic::{self, Ordering};
-use sys::stack_overflow;
-use sys::thread as imp;
+use crate::boxed::FnBox;
+use crate::env;
+use crate::sync::atomic::{self, Ordering};
+use crate::sys::stack_overflow;
+use crate::sys::thread as imp;
#[allow(dead_code)]
pub unsafe fn start_thread(main: *mut u8) {
#![allow(dead_code)] // stack_guard isn't used right now on all platforms
-use cell::RefCell;
-use sys::thread::guard::Guard;
-use thread::Thread;
+use crate::cell::RefCell;
+use crate::sys::thread::guard::Guard;
+use crate::thread::Thread;
struct ThreadInfo {
stack_guard: Option<Guard>,
#![unstable(feature = "thread_local_internals", issue = "0")]
#![allow(dead_code)] // sys isn't exported yet
-use ptr;
-use sync::atomic::{self, AtomicUsize, Ordering};
-use sys::thread_local as imp;
-use sys_common::mutex::Mutex;
+use crate::ptr;
+use crate::sync::atomic::{self, AtomicUsize, Ordering};
+use crate::sys::thread_local as imp;
+use crate::sys_common::mutex::Mutex;
/// A type for TLS keys that are statically allocated.
///
-use fmt;
-use io::prelude::*;
-use sys::stdio::panic_output;
-use thread;
+use crate::fmt;
+use crate::io::prelude::*;
+use crate::sys::stdio::panic_output;
+use crate::thread;
pub fn dumb_print(args: fmt::Arguments) {
if let Some(mut out) = panic_output() {
// Other platforms should use the appropriate platform-specific mechanism for
// aborting the process. If no platform-specific mechanism is available,
-// ::intrinsics::abort() may be used instead. The above implementations cover
+// crate::intrinsics::abort() may be used instead. The above implementations cover
// all targets currently supported by libstd.
pub fn abort(args: fmt::Arguments) -> ! {
dumb_print(format_args!("fatal runtime error: {}\n", args));
- unsafe { ::sys::abort_internal(); }
+ unsafe { crate::sys::abort_internal(); }
}
#[allow(dead_code)] // stack overflow detection not enabled on all platforms
use core::str::next_code_point;
-use borrow::Cow;
-use char;
-use fmt;
-use hash::{Hash, Hasher};
-use iter::FromIterator;
-use mem;
-use ops;
-use rc::Rc;
-use slice;
-use str;
-use sync::Arc;
-use sys_common::AsInner;
+use crate::borrow::Cow;
+use crate::char;
+use crate::fmt;
+use crate::hash::{Hash, Hasher};
+use crate::iter::FromIterator;
+use crate::mem;
+use crate::ops;
+use crate::rc::Rc;
+use crate::slice;
+use crate::str;
+use crate::sync::Arc;
+use crate::sys_common::AsInner;
const UTF8_REPLACEMENT_CHARACTER: &str = "\u{FFFD}";
impl fmt::Debug for Wtf8 {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn write_str_escaped(f: &mut fmt::Formatter, s: &str) -> fmt::Result {
- use fmt::Write;
+ use crate::fmt::Write;
for c in s.chars().flat_map(|c| c.escape_debug()) {
f.write_char(c)?
}
#[cfg(test)]
mod tests {
- use borrow::Cow;
+ use crate::borrow::Cow;
use super::*;
#[test]
-extern crate rand;
-
use std::env::*;
use std::ffi::{OsString, OsStr};
#![unstable(feature = "thread_local_internals", issue = "0")]
-use cell::UnsafeCell;
-use fmt;
-use hint;
-use mem;
+use crate::cell::UnsafeCell;
+use crate::fmt;
+use crate::hint;
+use crate::mem;
/// A thread local storage key which owns its contents.
///
#[doc(hidden)]
#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
pub mod statik {
- use cell::UnsafeCell;
- use fmt;
+ use crate::cell::UnsafeCell;
+ use crate::fmt;
pub struct Key<T> {
inner: UnsafeCell<Option<T>>,
}
- unsafe impl<T> ::marker::Sync for Key<T> { }
+ unsafe impl<T> Sync for Key<T> { }
impl<T> fmt::Debug for Key<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[doc(hidden)]
#[cfg(target_thread_local)]
pub mod fast {
- use cell::{Cell, UnsafeCell};
- use fmt;
- use mem;
- use ptr;
- use sys::fast_thread_local::{register_dtor, requires_move_before_drop};
+ use crate::cell::{Cell, UnsafeCell};
+ use crate::fmt;
+ use crate::mem;
+ use crate::ptr;
+ use crate::sys::fast_thread_local::{register_dtor, requires_move_before_drop};
pub struct Key<T> {
inner: UnsafeCell<Option<T>>,
#[doc(hidden)]
pub mod os {
- use cell::{Cell, UnsafeCell};
- use fmt;
- use marker;
- use ptr;
- use sys_common::thread_local::StaticKey as OsStaticKey;
+ use crate::cell::{Cell, UnsafeCell};
+ use crate::fmt;
+ use crate::marker;
+ use crate::ptr;
+ use crate::sys_common::thread_local::StaticKey as OsStaticKey;
pub struct Key<T> {
// OS-TLS key that we'll use to key off.
}
}
- unsafe impl<T> ::marker::Sync for Key<T> { }
+ unsafe impl<T> Sync for Key<T> { }
struct Value<T: 'static> {
key: &'static Key<T>,
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use sync::mpsc::{channel, Sender};
- use cell::{Cell, UnsafeCell};
- use thread;
+ use crate::sync::mpsc::{channel, Sender};
+ use crate::cell::{Cell, UnsafeCell};
+ use crate::thread;
struct Foo(Sender<()>);
#[cfg(test)]
mod dynamic_tests {
- use cell::RefCell;
- use collections::HashMap;
+ use crate::cell::RefCell;
+ use crate::collections::HashMap;
#[test]
fn smoke() {
#![stable(feature = "rust1", since = "1.0.0")]
-use any::Any;
-use boxed::FnBox;
-use cell::UnsafeCell;
-use ffi::{CStr, CString};
-use fmt;
-use io;
-use mem;
-use panic;
-use panicking;
-use str;
-use sync::{Mutex, Condvar, Arc};
-use sync::atomic::AtomicUsize;
-use sync::atomic::Ordering::SeqCst;
-use sys::thread as imp;
-use sys_common::mutex;
-use sys_common::thread_info;
-use sys_common::thread;
-use sys_common::{AsInner, IntoInner};
-use time::Duration;
+use crate::any::Any;
+use crate::boxed::FnBox;
+use crate::cell::UnsafeCell;
+use crate::ffi::{CStr, CString};
+use crate::fmt;
+use crate::io;
+use crate::mem;
+use crate::panic;
+use crate::panicking;
+use crate::str;
+use crate::sync::{Mutex, Condvar, Arc};
+use crate::sync::atomic::AtomicUsize;
+use crate::sync::atomic::Ordering::SeqCst;
+use crate::sys::thread as imp;
+use crate::sys_common::mutex;
+use crate::sys_common::thread_info;
+use crate::sys_common::thread;
+use crate::sys_common::{AsInner, IntoInner};
+use crate::time::Duration;
////////////////////////////////////////////////////////////////////////////////
// Thread-local storage
thread_info::set(imp::guard::current(), their_thread);
#[cfg(feature = "backtrace")]
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
- ::sys_common::backtrace::__rust_begin_short_backtrace(f)
+ crate::sys_common::backtrace::__rust_begin_short_backtrace(f)
}));
#[cfg(not(feature = "backtrace"))]
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f));
// If we somehow use up all our bits, panic so that we're not
// covering up subtle bugs of IDs being reused.
- if COUNTER == ::u64::MAX {
+ if COUNTER == crate::u64::MAX {
panic!("failed to generate unique thread ID: bitspace exhausted");
}
///
/// [`Result`]: ../../std/result/enum.Result.html
#[stable(feature = "rust1", since = "1.0.0")]
-pub type Result<T> = ::result::Result<T, Box<dyn Any + Send + 'static>>;
+pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>;
// This packet is used to communicate the return value between the child thread
// and the parent thread. Memory is shared through the `Arc` within and there's
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
- use any::Any;
- use sync::mpsc::{channel, Sender};
- use result;
- use super::{Builder};
- use thread;
- use time::Duration;
- use u32;
+ use super::Builder;
+ use crate::any::Any;
+ use crate::sync::mpsc::{channel, Sender};
+ use crate::result;
+ use crate::thread;
+ use crate::time::Duration;
+ use crate::u32;
// !!! These tests are dangerous. If something is buggy, they will hang, !!!
// !!! instead of exiting cleanly. This might wedge the buildbots. !!!
#![stable(feature = "time", since = "1.3.0")]
-use cmp;
-use error::Error;
-use fmt;
-use ops::{Add, Sub, AddAssign, SubAssign};
-use sys::time;
-use sys_common::FromInner;
-use sys_common::mutex::Mutex;
+use crate::cmp;
+use crate::error::Error;
+use crate::fmt;
+use crate::ops::{Add, Sub, AddAssign, SubAssign};
+use crate::sys::time;
+use crate::sys_common::FromInner;
+use crate::sys_common::mutex::Mutex;
#[stable(feature = "time", since = "1.3.0")]
pub use core::time::Duration;
assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
// A difference of 80 and 800 years cannot fit inside a 32-bit time_t
- if !(cfg!(unix) && ::mem::size_of::<::libc::time_t>() <= 4) {
+ if !(cfg!(unix) && crate::mem::size_of::<libc::time_t>() <= 4) {
let eighty_years = second * 60 * 60 * 24 * 365 * 80;
assert_almost_eq!(a - eighty_years + eighty_years, a);
assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
bitflags = "1.0"
serialize = { path = "../libserialize" }
log = "0.4"
-scoped-tls = "0.1"
+scoped-tls = "1.0"
syntax_pos = { path = "../libsyntax_pos" }
errors = { path = "../librustc_errors", package = "rustc_errors" }
rustc_data_structures = { path = "../librustc_data_structures" }
Mac(Mac),
/// Placeholder for a kind that has failed to be defined.
Err,
+ /// Placeholder for a `va_list`.
+ CVarArgs,
}
impl TyKind {
pub struct FnDecl {
pub inputs: Vec<Arg>,
pub output: FunctionRetTy,
- pub variadic: bool,
+ pub c_variadic: bool,
}
impl FnDecl {
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
pub struct FnHeader {
pub unsafety: Unsafety,
- pub asyncness: IsAsync,
+ pub asyncness: Spanned<IsAsync>,
pub constness: Spanned<Constness>,
pub abi: Abi,
}
fn default() -> FnHeader {
FnHeader {
unsafety: Unsafety::Normal,
- asyncness: IsAsync::NotAsync,
+ asyncness: dummy_spanned(IsAsync::NotAsync),
constness: dummy_spanned(Constness::NotConst),
abi: Abi::Rust,
}
P(ast::FnDecl {
inputs,
output,
- variadic: false
+ c_variadic: false
})
}
ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)),
ast::FnHeader {
unsafety: ast::Unsafety::Normal,
- asyncness: ast::IsAsync::NotAsync,
+ asyncness: dummy_spanned(ast::IsAsync::NotAsync),
constness: dummy_spanned(ast::Constness::NotConst),
abi: Abi::Rust,
},
// #1 is a separator and #2 should be a KleepeOp.
// (N.B. We need to advance the input iterator.)
match parse_kleene_op(input, span) {
- // #2 is `?`, which is not allowed as a Kleene op in 2015 edition.
+ // #2 is `?`, which is not allowed as a Kleene op in 2015 edition,
+ // but is allowed in the 2018 edition.
Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => {
sess.span_diagnostic
.struct_span_err(op2_span, "expected `*` or `+`")
- .note("`?` is not a macro repetition operator")
+ .note("`?` is not a macro repetition operator in the 2015 edition, \
+ but is accepted in the 2018 edition")
.emit();
// Return a dummy
Err(_) => op1_span,
}
} else {
- // `?` is not allowed as a Kleene op in 2015
+ // `?` is not allowed as a Kleene op in 2015,
+ // but is allowed in the 2018 edition
sess.span_diagnostic
.struct_span_err(op1_span, "expected `*` or `+`")
- .note("`?` is not a macro repetition operator")
+ .note("`?` is not a macro repetition operator in the 2015 edition, \
+ but is accepted in the 2018 edition")
.emit();
// Return a dummy
// #1 is a separator followed by #2, a KleeneOp
Ok(Err((tok, span))) => match parse_kleene_op(input, span) {
- // #2 is a `?`, which is not allowed as a Kleene op in 2015 edition.
+ // #2 is a `?`, which is not allowed as a Kleene op in 2015 edition,
+ // but is allowed in the 2018 edition
Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => {
sess.span_diagnostic
.struct_span_err(op2_span, "expected `*` or `+`")
- .note("`?` is not a macro repetition operator")
+ .note("`?` is not a macro repetition operator in the 2015 edition, \
+ but is accepted in the 2018 edition")
.emit();
// Return a dummy
// Allows `#[unwind(..)]`.
//
- // rustc internal for rust runtime
- (active, unwind_attributes, "1.4.0", None, None),
+ // Permits specifying whether a function should permit unwinding or abort on unwind.
+ (active, unwind_attributes, "1.4.0", Some(58760), None),
// Allows the use of `#[naked]` on functions.
(active, naked_functions, "1.9.0", Some(32408), None),
// #[repr(align(X))] on enums
(active, repr_align_enum, "1.34.0", Some(57996), None),
+
+ // Allows the use of C-variadics
+ (active, c_variadic, "1.34.0", Some(44930), None),
);
declare_features! (
match fn_kind {
FnKind::ItemFn(_, header, _, _) => {
// Check for const fn and async fn declarations.
- if header.asyncness.is_async() {
+ if header.asyncness.node.is_async() {
gate_feature_post!(&self, async_await, span, "async fn is unstable");
}
+
+ if fn_decl.c_variadic {
+ gate_feature_post!(&self, c_variadic, span,
+ "C-varaidic functions are unstable");
+ }
// Stability of const fn methods are covered in
// `visit_trait_item` and `visit_impl_item` below; this is
// because default methods don't pass through this point.
if block.is_none() {
self.check_abi(sig.header.abi, ti.span);
}
+ if sig.decl.c_variadic {
+ gate_feature_post!(&self, c_variadic, ti.span,
+ "C-varaidic functions are unstable");
+ }
if sig.header.constness.node == ast::Constness::Const {
gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
}
use rustc_data_structures::sync::Lrc;
use std::ops::DerefMut;
+use std::{panic, process, ptr};
pub trait ExpectOne<A: Array> {
fn expect_one(self, err: &'static str) -> A::Item;
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
-/// method.
+/// method. Abort the program if the closure panics.
//
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
pub fn visit_clobber<T, F>(t: &mut T, f: F) where F: FnOnce(T) -> T {
- unsafe { std::ptr::write(t, f(std::ptr::read(t))); }
+ unsafe {
+ // Safe because `t` is used in a read-only fashion by `read()` before
+ // being overwritten by `write()`.
+ let old_t = ptr::read(t);
+ let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t)))
+ .unwrap_or_else(|_| process::abort());
+ ptr::write(t, new_t);
+ }
}
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
let Ty { id, node, span } = ty.deref_mut();
vis.visit_id(id);
match node {
- TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err | TyKind::Never => {}
+ TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err |
+ TyKind::Never | TyKind::CVarArgs => {}
TyKind::Slice(ty) => vis.visit_ty(ty),
TyKind::Ptr(mt) => vis.visit_mt(mt),
TyKind::Rptr(lt, mt) => {
}
pub fn noop_visit_fn_decl<T: MutVisitor>(decl: &mut P<FnDecl>, vis: &mut T) {
- let FnDecl { inputs, output, variadic: _ } = decl.deref_mut();
+ let FnDecl { inputs, output, c_variadic: _ } = decl.deref_mut();
visit_vec(inputs, |input| vis.visit_arg(input));
match output {
FunctionRetTy::Default(span) => vis.visit_span(span),
pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header;
- vis.visit_asyncness(asyncness);
+ vis.visit_asyncness(&mut asyncness.node);
}
pub fn noop_visit_mod<T: MutVisitor>(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) {
};
self.expect_keyword(keywords::Fn)?;
- let (inputs, variadic) = self.parse_fn_args(false, true)?;
+ let (inputs, c_variadic) = self.parse_fn_args(false, true)?;
let ret_ty = self.parse_ret_ty(false)?;
let decl = P(FnDecl {
inputs,
output: ret_ty,
- variadic,
+ c_variadic,
});
Ok(TyKind::BareFn(P(BareFnTy {
abi,
// definition...
// We don't allow argument names to be left off in edition 2018.
- p.parse_arg_general(p.span.rust_2018(), true)
+ p.parse_arg_general(p.span.rust_2018(), true, false)
})?;
generics.where_clause = self.parse_where_clause()?;
/// Parses an optional return type `[ -> TY ]` in a function declaration.
fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> {
if self.eat(&token::RArrow) {
- Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true)?))
+ Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?))
} else {
Ok(FunctionRetTy::Default(self.span.shrink_to_lo()))
}
/// Parses a type.
pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
- self.parse_ty_common(true, true)
+ self.parse_ty_common(true, true, false)
}
/// Parses a type in restricted contexts where `+` is not permitted.
/// Example 2: `value1 as TYPE + value2`
/// `+` is prohibited to avoid interactions with expression grammar.
fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
- self.parse_ty_common(false, true)
+ self.parse_ty_common(false, true, false)
}
- fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
- -> PResult<'a, P<Ty>> {
+ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool,
+ allow_c_variadic: bool) -> PResult<'a, P<Ty>> {
maybe_whole!(self, NtTy, |x| x);
let lo = self.span;
TyKind::Path(None, path)
}
}
+ } else if self.check(&token::DotDotDot) {
+ if allow_c_variadic {
+ self.eat(&token::DotDotDot);
+ TyKind::CVarArgs
+ } else {
+ return Err(self.fatal(
+ "only foreign functions are allowed to be C-variadic"
+ ));
+ }
} else {
let msg = format!("expected type, found {}", self.this_token_descr());
return Err(self.fatal(&msg));
}
/// This version of parse arg doesn't necessarily require identifier names.
- fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool) -> PResult<'a, Arg> {
+ fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool,
+ allow_c_variadic: bool) -> PResult<'a, Arg> {
maybe_whole!(self, NtArg, |x| x);
if let Ok(Some(_)) = self.parse_self_arg() {
}
self.eat_incorrect_doc_comment("a method argument's type");
- (pat, self.parse_ty()?)
+ (pat, self.parse_ty_common(true, true, allow_c_variadic)?)
} else {
debug!("parse_arg_general ident_to_pat");
let parser_snapshot_before_ty = self.clone();
self.eat_incorrect_doc_comment("a method argument's type");
- let mut ty = self.parse_ty();
+ let mut ty = self.parse_ty_common(true, true, allow_c_variadic);
if ty.is_ok() && self.token != token::Comma &&
self.token != token::CloseDelim(token::Paren) {
// This wasn't actually a type, but a pattern looking like a type,
(pat, ty)
}
Err(mut err) => {
+ // If this is a C-variadic argument and we hit an error, return the
+ // error.
+ if self.token == token::DotDotDot {
+ return Err(err);
+ }
// Recover from attempting to parse the argument as a type without pattern.
err.cancel();
mem::replace(self, parser_snapshot_before_ty);
/// Parses a single function argument.
crate fn parse_arg(&mut self) -> PResult<'a, Arg> {
- self.parse_arg_general(true, false)
+ self.parse_arg_general(true, false, false)
}
/// Parses an argument in a lambda header (e.g., `|arg, arg|`).
}
let span = lo.to(self.prev_span);
let output = if self.eat(&token::RArrow) {
- Some(self.parse_ty_common(false, false)?)
+ Some(self.parse_ty_common(false, false, false)?)
} else {
None
};
)
}
+ fn is_async_fn(&mut self) -> bool {
+ self.token.is_keyword(keywords::Async) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
+ }
+
fn is_do_catch_block(&mut self) -> bool {
self.token.is_keyword(keywords::Do) &&
self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
!self.is_union_item() &&
!self.is_crate_vis() &&
!self.is_existential_type_decl() &&
- !self.is_auto_trait_item() {
+ !self.is_auto_trait_item() &&
+ !self.is_async_fn() {
let pth = self.parse_path(PathStyle::Expr)?;
if !self.eat(&token::Not) {
Ok(where_clause)
}
- fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool)
+ fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool)
-> PResult<'a, (Vec<Arg> , bool)> {
self.expect(&token::OpenDelim(token::Paren))?;
let sp = self.span;
- let mut variadic = false;
+ let mut c_variadic = false;
let (args, recovered): (Vec<Option<Arg>>, bool) =
self.parse_seq_to_before_end(
&token::CloseDelim(token::Paren),
SeqSep::trailing_allowed(token::Comma),
|p| {
- if p.token == token::DotDotDot {
- p.bump();
- variadic = true;
- if allow_variadic {
- if p.token != token::CloseDelim(token::Paren) {
- let span = p.span;
- p.span_err(span,
- "`...` must be last in argument list for variadic function");
- }
- Ok(None)
- } else {
- let span = p.prev_span;
- if p.token == token::CloseDelim(token::Paren) {
- // continue parsing to present any further errors
- p.struct_span_err(
- span,
- "only foreign functions are allowed to be variadic"
- ).emit();
- Ok(Some(dummy_arg(span)))
- } else {
- // this function definition looks beyond recovery, stop parsing
- p.span_err(span,
- "only foreign functions are allowed to be variadic");
- Ok(None)
- }
- }
+ // If the argument is a C-variadic argument we should not
+ // enforce named arguments.
+ let enforce_named_args = if p.token == token::DotDotDot {
+ false
} else {
- match p.parse_arg_general(named_args, false) {
- Ok(arg) => Ok(Some(arg)),
- Err(mut e) => {
- e.emit();
- let lo = p.prev_span;
- // Skip every token until next possible arg or end.
- p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
- // Create a placeholder argument for proper arg count (#34264).
- let span = lo.to(p.prev_span);
- Ok(Some(dummy_arg(span)))
+ named_args
+ };
+ match p.parse_arg_general(enforce_named_args, false,
+ allow_c_variadic) {
+ Ok(arg) => {
+ if let TyKind::CVarArgs = arg.ty.node {
+ c_variadic = true;
+ if p.token != token::CloseDelim(token::Paren) {
+ let span = p.span;
+ p.span_err(span,
+ "`...` must be the last argument of a C-variadic function");
+ Ok(None)
+ } else {
+ Ok(Some(arg))
+ }
+ } else {
+ Ok(Some(arg))
}
+ },
+ Err(mut e) => {
+ e.emit();
+ let lo = p.prev_span;
+ // Skip every token until next possible arg or end.
+ p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
+ // Create a placeholder argument for proper arg count (issue #34264).
+ let span = lo.to(p.prev_span);
+ Ok(Some(dummy_arg(span)))
}
}
}
let args: Vec<_> = args.into_iter().filter_map(|x| x).collect();
- if variadic && args.is_empty() {
+ if c_variadic && args.is_empty() {
self.span_err(sp,
- "variadic function must be declared with at least one named argument");
+ "C-variadic function must be declared with at least one named argument");
}
- Ok((args, variadic))
+ Ok((args, c_variadic))
}
/// Parses the argument list and result type of a function declaration.
- fn parse_fn_decl(&mut self, allow_variadic: bool) -> PResult<'a, P<FnDecl>> {
+ fn parse_fn_decl(&mut self, allow_c_variadic: bool) -> PResult<'a, P<FnDecl>> {
- let (args, variadic) = self.parse_fn_args(true, allow_variadic)?;
+ let (args, c_variadic) = self.parse_fn_args(true, allow_c_variadic)?;
let ret_ty = self.parse_ret_ty(true)?;
Ok(P(FnDecl {
inputs: args,
output: ret_ty,
- variadic,
+ c_variadic,
}))
}
Ok(P(FnDecl {
inputs: fn_inputs,
output: self.parse_ret_ty(true)?,
- variadic: false
+ c_variadic: false
}))
}
Ok(P(FnDecl {
inputs: inputs_captures,
output,
- variadic: false
+ c_variadic: false
}))
}
/// Parses an item-position function declaration.
fn parse_item_fn(&mut self,
unsafety: Unsafety,
- asyncness: IsAsync,
+ asyncness: Spanned<IsAsync>,
constness: Spanned<Constness>,
abi: Abi)
-> PResult<'a, ItemInfo> {
let (ident, mut generics) = self.parse_fn_header()?;
- let decl = self.parse_fn_decl(false)?;
+ let allow_c_variadic = abi == Abi::C && unsafety == Unsafety::Unsafe;
+ let decl = self.parse_fn_decl(allow_c_variadic)?;
generics.where_clause = self.parse_where_clause()?;
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
let header = FnHeader { unsafety, asyncness, constness, abi };
-> PResult<'a, (
Spanned<Constness>,
Unsafety,
- IsAsync,
+ Spanned<IsAsync>,
Abi
)>
{
let const_span = self.prev_span;
let unsafety = self.parse_unsafety();
let asyncness = self.parse_asyncness();
+ let asyncness = respan(self.prev_span, asyncness);
let (constness, unsafety, abi) = if is_const_fn {
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
} else {
let abi = opt_abi.unwrap_or(Abi::C);
let (ident, item_, extra_attrs) =
self.parse_item_fn(Unsafety::Normal,
- IsAsync::NotAsync,
+ respan(fn_span, IsAsync::NotAsync),
respan(fn_span, Constness::NotConst),
abi)?;
let prev_span = self.prev_span;
self.bump();
let (ident, item_, extra_attrs) =
self.parse_item_fn(unsafety,
- IsAsync::NotAsync,
+ respan(const_span, IsAsync::NotAsync),
respan(const_span, Constness::Const),
Abi::Rust)?;
let prev_span = self.prev_span;
// ASYNC FUNCTION ITEM
let unsafety = self.parse_unsafety();
self.expect_keyword(keywords::Async)?;
+ let async_span = self.prev_span;
self.expect_keyword(keywords::Fn)?;
let fn_span = self.prev_span;
let (ident, item_, extra_attrs) =
self.parse_item_fn(unsafety,
- IsAsync::Async {
+ respan(async_span, IsAsync::Async {
closure_id: ast::DUMMY_NODE_ID,
return_impl_trait_id: ast::DUMMY_NODE_ID,
- },
+ }),
respan(fn_span, Constness::NotConst),
Abi::Rust)?;
let prev_span = self.prev_span;
item_,
visibility,
maybe_append(attrs, extra_attrs));
+ if self.span.rust_2015() {
+ self.diagnostic().struct_span_err_with_code(
+ async_span,
+ "`async fn` is not permitted in the 2015 edition",
+ DiagnosticId::Error("E0670".into())
+ ).emit();
+ }
return Ok(Some(item));
}
if self.check_keyword(keywords::Unsafe) &&
let fn_span = self.prev_span;
let (ident, item_, extra_attrs) =
self.parse_item_fn(Unsafety::Normal,
- IsAsync::NotAsync,
+ respan(fn_span, IsAsync::NotAsync),
respan(fn_span, Constness::NotConst),
Abi::Rust)?;
let prev_span = self.prev_span;
let fn_span = self.prev_span;
let (ident, item_, extra_attrs) =
self.parse_item_fn(Unsafety::Unsafe,
- IsAsync::NotAsync,
+ respan(fn_span, IsAsync::NotAsync),
respan(fn_span, Constness::NotConst),
abi)?;
let prev_span = self.prev_span;
lo: Span,
visibility: Visibility
) -> PResult<'a, Option<P<Item>>> {
- if macros_allowed && self.token.is_path_start() {
+ if macros_allowed && self.token.is_path_start() &&
+ !(self.is_async_fn() && self.span.rust_2015()) {
// MACRO INVOCATION ITEM
let prev_span = self.prev_span;
fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
at_end: &mut bool) -> PResult<'a, Option<Mac>>
{
- if self.token.is_path_start() {
+ if self.token.is_path_start() &&
+ !(self.is_async_fn() && self.span.rust_2015()) {
let prev_span = self.prev_span;
let lo = self.span;
let pth = self.parse_path(PathStyle::Mod)?;
ast::TyKind::Mac(ref m) => {
self.print_mac(m)?;
}
+ ast::TyKind::CVarArgs => {
+ self.s.word("...")?;
+ }
}
self.end()
}
-> io::Result<()> {
self.popen()?;
self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?;
- if decl.variadic {
+ if decl.c_variadic {
self.s.word(", ...")?;
}
self.pclose()?;
ast::Constness::Const => self.word_nbsp("const")?
}
- self.print_asyncness(header.asyncness)?;
+ self.print_asyncness(header.asyncness.node)?;
self.print_unsafety(header.unsafety)?;
if header.abi != Abi::Rust {
let decl = ast::FnDecl {
inputs: Vec::new(),
output: ast::FunctionRetTy::Default(syntax_pos::DUMMY_SP),
- variadic: false
+ c_variadic: false
};
let generics = ast::Generics::default();
assert_eq!(
ast::FnHeader {
unsafety: ast::Unsafety::Normal,
constness: source_map::dummy_spanned(ast::Constness::NotConst),
- asyncness: ast::IsAsync::NotAsync,
+ asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync),
abi: Abi::Rust,
},
abba_ident,
#[derive(Copy, Clone)]
pub enum FnKind<'a> {
/// fn foo() or extern "Abi" fn foo()
- ItemFn(Ident, FnHeader, &'a Visibility, &'a Block),
+ ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
/// fn foo(&self)
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) {
walk_fn_ret_ty(self, ret_ty)
}
+ fn visit_fn_header(&mut self, _header: &'ast FnHeader) {
+ // Nothing to do
+ }
}
#[macro_export]
visitor.visit_ty(typ);
visitor.visit_expr(expr);
}
- ItemKind::Fn(ref declaration, header, ref generics, ref body) => {
+ ItemKind::Fn(ref declaration, ref header, ref generics, ref body) => {
visitor.visit_generics(generics);
+ visitor.visit_fn_header(header);
visitor.visit_fn(FnKind::ItemFn(item.ident, header,
&item.vis, body),
declaration,
walk_list!(visitor, visit_lifetime, opt_lifetime);
visitor.visit_ty(&mutable_type.ty)
}
- TyKind::Never => {},
+ TyKind::Never | TyKind::CVarArgs => {}
TyKind::Tup(ref tuple_element_types) => {
walk_list!(visitor, visit_ty, tuple_element_types);
}
where V: Visitor<'a>,
{
match kind {
- FnKind::ItemFn(_, _, _, body) => {
+ FnKind::ItemFn(_, header, _, body) => {
+ visitor.visit_fn_header(header);
walk_fn_decl(visitor, declaration);
visitor.visit_block(body);
}
- FnKind::Method(_, _, _, body) => {
+ FnKind::Method(_, sig, _, body) => {
+ visitor.visit_fn_header(&sig.header);
walk_fn_decl(visitor, declaration);
visitor.visit_block(body);
}
walk_list!(visitor, visit_expr, default);
}
TraitItemKind::Method(ref sig, None) => {
+ visitor.visit_fn_header(&sig.header);
walk_fn_decl(visitor, &sig.decl);
}
TraitItemKind::Method(ref sig, Some(ref body)) => {
);
return false
}
- if header.asyncness.is_async() {
+ if header.asyncness.node.is_async() {
sd.span_err(
i.span,
"async functions cannot be used for tests"
serialize = { path = "../libserialize" }
rustc_data_structures = { path = "../librustc_data_structures" }
arena = { path = "../libarena" }
-scoped-tls = { version = "0.1.1", features = ["nightly"] }
+scoped-tls = "1.0"
unicode-width = "0.1.4"
cfg-if = "0.1.2"
pub list: bool,
pub filter: Option<String>,
pub filter_exact: bool,
+ pub exclude_should_panic: bool,
pub run_ignored: RunIgnored,
pub run_tests: bool,
pub bench_benchmarks: bool,
list: false,
filter: None,
filter_exact: false,
+ exclude_should_panic: false,
run_ignored: RunIgnored::No,
run_tests: false,
bench_benchmarks: false,
let mut opts = getopts::Options::new();
opts.optflag("", "include-ignored", "Run ignored and not ignored tests")
.optflag("", "ignored", "Run only ignored tests")
+ .optflag("", "exclude-should-panic", "Excludes tests marked as should_panic")
.optflag("", "test", "Run tests and not benchmarks")
.optflag("", "bench", "Run benchmarks instead of tests")
.optflag("", "list", "List all tests and benchmarks")
None
};
+ let exclude_should_panic = matches.opt_present("exclude-should-panic");
+ if !allow_unstable && exclude_should_panic {
+ return Some(Err(
+ "The \"exclude-should-panic\" flag is only accepted on the nightly compiler".into(),
+ ));
+ }
+
let include_ignored = matches.opt_present("include-ignored");
if !allow_unstable && include_ignored {
return Some(Err(
list,
filter,
filter_exact: exact,
+ exclude_should_panic,
run_ignored,
run_tests,
bench_benchmarks,
// Skip tests that match any of the skip filters
filtered.retain(|test| !opts.skip.iter().any(|sf| matches_filter(test, sf)));
+ // Excludes #[should_panic] tests
+ if opts.exclude_should_panic {
+ filtered.retain(|test| test.desc.should_panic == ShouldPanic::No);
+ }
+
// maybe unignore tests
match opts.run_ignored {
RunIgnored::Yes => {
assert!(!filtered[1].desc.ignore);
}
+ #[test]
+ pub fn exclude_should_panic_option() {
+ let mut opts = TestOpts::new();
+ opts.run_tests = true;
+ opts.exclude_should_panic = true;
+
+ let mut tests = one_ignored_one_unignored_test();
+ tests.push(TestDescAndFn {
+ desc: TestDesc {
+ name: StaticTestName("3"),
+ ignore: false,
+ should_panic: ShouldPanic::Yes,
+ allow_fail: false,
+ },
+ testfn: DynTestFn(Box::new(move || {})),
+ });
+
+ let filtered = filter_tests(&opts, tests);
+
+ assert_eq!(filtered.len(), 2);
+ assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
+ }
+
#[test]
pub fn exact_filter_match() {
fn tests() -> Vec<TestDescAndFn> {
-Subproject commit 73a75d35b9776d56160fa3200aca4a970ae49b60
+Subproject commit 38ad31bde8ff681d862dc0f96930a5dd9b7a472e
--- /dev/null
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(c_variadic)]
+#![no_std]
+use core::ffi::VaList;
+
+extern "C" {
+ fn foreign_c_variadic_0(_: i32, ...);
+ fn foreign_c_variadic_1(_: VaList, ...);
+}
+
+pub unsafe extern "C" fn use_foreign_c_variadic_0() {
+ // Ensure that we correctly call foreign C-variadic functions.
+ // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0)
+ foreign_c_variadic_0(0);
+ // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42)
+ foreign_c_variadic_0(0, 42i32);
+ // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42, i32 1024)
+ foreign_c_variadic_0(0, 42i32, 1024i32);
+ // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42, i32 1024, i32 0)
+ foreign_c_variadic_0(0, 42i32, 1024i32, 0i32);
+}
+
+// Ensure that we do not remove the `va_list` passed to the foreign function when
+// removing the "spoofed" `VaList` that is used by Rust defined C-variadics.
+pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) {
+ // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap)
+ foreign_c_variadic_1(ap);
+}
+
+pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) {
+ // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 42)
+ foreign_c_variadic_1(ap, 42i32);
+}
+pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) {
+ // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42)
+ foreign_c_variadic_1(ap, 2i32, 42i32);
+}
+
+pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) {
+ // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42, i32 0)
+ foreign_c_variadic_1(ap, 2i32, 42i32, 0i32);
+}
+
+// Ensure that `va_start` and `va_end` are properly injected.
+#[no_mangle]
+pub unsafe extern "C" fn c_variadic(n: i32, mut ap: ...) -> i32 {
+ // CHECK: call void @llvm.va_start
+ let mut sum = 0;
+ for _ in 0..n {
+ sum += ap.arg::<i32>();
+ }
+ sum
+ // CHECK: call void @llvm.va_end
+}
+
+// Ensure that we generate the correct `call` signature when calling a Rust
+// defined C-variadic.
+pub unsafe fn test_c_variadic_call() {
+ // CHECK: call i32 (i32, ...) @c_variadic(i32 0)
+ c_variadic(0);
+ // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42)
+ c_variadic(0, 42i32);
+ // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42, i32 1024)
+ c_variadic(0, 42i32, 1024i32);
+ // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42, i32 1024, i32 0)
+ c_variadic(0, 42i32, 1024i32, 0i32);
+}
unsafe fn compare_c_str(ptr: *const c_char, val: &str) -> bool {
let cstr0 = CStr::from_ptr(ptr);
- let cstr1 = CString::new(val).unwrap();
- &*cstr1 == cstr0
+ match CString::new(val) {
+ Ok(cstr1) => &*cstr1 == cstr0,
+ Err(_) => false,
+ }
}
#[no_mangle]
}
})
}
+
+#[no_mangle]
+pub unsafe extern "C" fn check_varargs_0(_: c_int, mut ap: ...) -> usize {
+ continue_if!(ap.arg::<c_int>() == 42);
+ continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Hello, World!"));
+ 0
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn check_varargs_1(_: c_int, mut ap: ...) -> usize {
+ continue_if!(ap.arg::<c_double>().floor() == 3.14f64.floor());
+ continue_if!(ap.arg::<c_long>() == 12);
+ continue_if!(ap.arg::<c_char>() == 'A' as c_char);
+ continue_if!(ap.arg::<c_longlong>() == 1);
+ 0
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn check_varargs_2(_: c_int, mut ap: ...) -> usize {
+ 0
+}
extern size_t check_list_1(va_list ap);
extern size_t check_list_2(va_list ap);
extern size_t check_list_copy_0(va_list ap);
+extern size_t check_varargs_0(int fixed, ...);
+extern size_t check_varargs_1(int fixed, ...);
+extern size_t check_varargs_2(int fixed, ...);
int test_rust(size_t (*fn)(va_list), ...) {
size_t ret = 0;
assert(test_rust(check_list_2, 3.14, 12l, 'a', 6.28, "Hello", 42, "World") == 0);
assert(test_rust(check_list_copy_0, 6.28, 16, 'A', "Skip Me!", "Correct") == 0);
+
+ assert(check_varargs_0(0, 42, "Hello, World!") == 0);
+
+ assert(check_varargs_1(0, 3.14, 12l, 'A', 0x1LL) == 0);
+
+ assert(check_varargs_2(0, "All", "of", "these", "are", "ignored", ".") == 0);
+
return 0;
}
extern crate rustc_metadata;
extern crate rustc_errors;
extern crate rustc_codegen_utils;
+extern crate rustc_interface;
extern crate syntax;
use rustc::session::{build_session, Session};
use rustc_driver::driver::{self, compile_input, CompileController};
use rustc_metadata::cstore::CStore;
use rustc_errors::registry::Registry;
+use rustc_interface::util;
use syntax::source_map::FileName;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
fn basic_sess(opts: Options) -> (Session, Rc<CStore>, Box<CodegenBackend>) {
let descriptions = Registry::new(&rustc::DIAGNOSTICS);
let sess = build_session(opts, None, descriptions);
- let codegen_backend = rustc_driver::get_codegen_backend(&sess);
+ let codegen_backend = util::get_codegen_backend(&sess);
let cstore = Rc::new(CStore::new(codegen_backend.metadata_loader()));
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
(sess, cstore, codegen_backend)
let decl = P(FnDecl {
inputs: vec![],
output: FunctionRetTy::Default(DUMMY_SP),
- variadic: false,
+ c_variadic: false,
});
iter_exprs(depth - 1, &mut |e| g(
ExprKind::Closure(CaptureBy::Value,
--- /dev/null
+trait FromUnchecked {
+ unsafe fn from_unchecked();
+}
+
+impl FromUnchecked for [u8; 1] {
+ unsafe fn from_unchecked() {
+ let mut array: Self = std::mem::uninitialized();
+ let _ptr = &mut array as *mut [u8] as *mut u8;
+ }
+}
+
+fn main() {
+}
3 | no
| ^^ not found in this scope
-thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:351:13
+thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:352:13
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
---- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ----
thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
-', src/librustdoc/test.rs:372:17
+', src/librustdoc/test.rs:373:17
failures:
|
= note: the link appears in this line:
- [error]
- ^^^^^
+ [error]
+ ^^^^^
= help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
warning: `[error1]` cannot be resolved, ignoring it...
--- /dev/null
+// compile-pass
+
+#![deny(private_doc_tests)]
+
+mod foo {
+ /**
+ Does nothing, returns `()`
+
+ yadda-yadda-yadda
+ */
+ fn foo() {}
+}
--- /dev/null
+// compile-pass
+
+pub trait Foo {
+ /**
+ Does nothing, returns `()`
+
+ yadda-yadda-yadda
+ */
+ fn foo() {}
+}
extern "C" {
- // @has variadic/fn.foo.html //pre 'pub unsafe extern "C" fn foo(x: i32, ...)'
+ // @has variadic/fn.foo.html //pre 'pub unsafe extern "C" fn foo(x: i32, _: ...)'
pub fn foo(x: i32, ...);
}
use rustc_plugin::Registry;
use syntax::ast;
declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
-declare_tool_lint!(pub clippy::TEST_GROUP, Warn, "Warn about other stuff");
+declare_tool_lint!(
+ /// Some docs
+ pub clippy::TEST_GROUP,
+ Warn, "Warn about other stuff"
+);
struct Pass;
--- /dev/null
+// ignore-arm stdcall isn't supported
+// ignore-aarch64 stdcall isn't supported
+
+extern "stdcall" {
+ fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling
+}
+
+extern {
+ fn foo(f: isize, x: u8, ...);
+}
+
+extern "C" fn bar(f: isize, x: u8) {}
+
+fn main() {
+ // errors below are no longer checked because error above aborts
+ // compilation; see variadic-ffi-3.rs for corresponding test.
+ unsafe {
+ foo();
+ foo(1);
+
+ let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
+ let y: extern "C" fn(f: isize, x: u8, ...) = bar;
+
+ foo(1, 2, 3f32);
+ foo(1, 2, true);
+ foo(1, 2, 1i8);
+ foo(1, 2, 1u8);
+ foo(1, 2, 1i16);
+ foo(1, 2, 1u16);
+ }
+}
--- /dev/null
+error[E0045]: C-variadic function must have C or cdecl calling convention
+ --> $DIR/variadic-ffi-1.rs:5:5
+ |
+LL | fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0045`.
--- /dev/null
+// ignore-arm stdcall isn't supported
+
+fn baz(f: extern "stdcall" fn(usize, ...)) {
+ //~^ ERROR: variadic function must have C or cdecl calling convention
+ f(22, 44);
+}
+
+fn main() {}
--- /dev/null
+error[E0045]: C-variadic function must have C or cdecl calling convention
+ --> $DIR/variadic-ffi-2.rs:3:11
+ |
+LL | fn baz(f: extern "stdcall" fn(usize, ...)) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0045`.
--- /dev/null
+extern {
+ fn foo(f: isize, x: u8, ...);
+ //~^ defined here
+ //~| defined here
+}
+
+extern "C" fn bar(f: isize, x: u8) {}
+
+fn main() {
+ unsafe {
+ foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied
+ foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
+
+ let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
+ //~^ ERROR: mismatched types
+ //~| expected type `unsafe extern "C" fn(isize, u8)`
+
+ let y: extern "C" fn(f: isize, x: u8, ...) = bar;
+ //~^ ERROR: mismatched types
+ //~| expected type `for<'r> extern "C" fn(isize, u8, std::ffi::VaList<'r>, ...)`
+
+ foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function
+ foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function
+ foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function
+ foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function
+ foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function
+ foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function
+ }
+}
--- /dev/null
+error[E0060]: this function takes at least 2 parameters but 0 parameters were supplied
+ --> $DIR/variadic-ffi-3.rs:11:9
+ |
+LL | fn foo(f: isize, x: u8, ...);
+ | ----------------------------- defined here
+...
+LL | foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied
+ | ^^^^^ expected at least 2 parameters
+
+error[E0060]: this function takes at least 2 parameters but 1 parameter was supplied
+ --> $DIR/variadic-ffi-3.rs:12:9
+ |
+LL | fn foo(f: isize, x: u8, ...);
+ | ----------------------------- defined here
+...
+LL | foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
+ | ^^^^^^ expected at least 2 parameters
+
+error[E0308]: mismatched types
+ --> $DIR/variadic-ffi-3.rs:14:56
+ |
+LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
+ | ^^^ expected non-variadic fn, found variadic function
+ |
+ = note: expected type `unsafe extern "C" fn(isize, u8)`
+ found type `for<'r> unsafe extern "C" fn(isize, u8, std::ffi::VaList<'r>, ...) {foo}`
+
+error[E0308]: mismatched types
+ --> $DIR/variadic-ffi-3.rs:18:54
+ |
+LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar;
+ | ^^^ expected variadic fn, found non-variadic function
+ |
+ = note: expected type `for<'r> extern "C" fn(isize, u8, std::ffi::VaList<'r>, ...)`
+ found type `extern "C" fn(isize, u8) {bar}`
+
+error[E0617]: can't pass `f32` to variadic function
+ --> $DIR/variadic-ffi-3.rs:22:19
+ |
+LL | foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function
+ | ^^^^ help: cast the value to `c_double`: `3f32 as c_double`
+
+error[E0617]: can't pass `bool` to variadic function
+ --> $DIR/variadic-ffi-3.rs:23:19
+ |
+LL | foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function
+ | ^^^^ help: cast the value to `c_int`: `true as c_int`
+
+error[E0617]: can't pass `i8` to variadic function
+ --> $DIR/variadic-ffi-3.rs:24:19
+ |
+LL | foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function
+ | ^^^ help: cast the value to `c_int`: `1i8 as c_int`
+
+error[E0617]: can't pass `u8` to variadic function
+ --> $DIR/variadic-ffi-3.rs:25:19
+ |
+LL | foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function
+ | ^^^ help: cast the value to `c_uint`: `1u8 as c_uint`
+
+error[E0617]: can't pass `i16` to variadic function
+ --> $DIR/variadic-ffi-3.rs:26:19
+ |
+LL | foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function
+ | ^^^^ help: cast the value to `c_int`: `1i16 as c_int`
+
+error[E0617]: can't pass `u16` to variadic function
+ --> $DIR/variadic-ffi-3.rs:27:19
+ |
+LL | foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function
+ | ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint`
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0060, E0308, E0617.
+For more information about an error, try `rustc --explain E0060`.
--- /dev/null
+#![crate_type="lib"]
+#![no_std]
+#![feature(c_variadic)]
+
+use core::ffi::VaList;
+
+pub unsafe extern "C" fn no_escape0<'a>(_: usize, ap: ...) -> VaList<'a> {
+ ap //~ ERROR: explicit lifetime required
+}
+
+pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> {
+ ap //~ ERROR: explicit lifetime required
+}
+
+pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) {
+ let _ = ap.copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime
+}
+
+pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+ *ap0 = ap1; //~ ERROR: mismatched types
+}
+
+pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+ ap0 = &mut ap1;
+ //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+ //~^^ ERROR: mismatched types
+ //~^^^ ERROR: mismatched types
+ //~^^^^ ERROR: cannot infer an appropriate lifetime
+}
--- /dev/null
+error[E0621]: explicit lifetime required in the type of `ap`
+ --> $DIR/variadic-ffi-4.rs:8:5
+ |
+LL | pub unsafe extern "C" fn no_escape0<'a>(_: usize, ap: ...) -> VaList<'a> {
+ | --- help: add explicit lifetime `'a` to the type of `ap`: `core::ffi::VaList<'a>`
+LL | ap //~ ERROR: explicit lifetime required
+ | ^^ lifetime `'a` required
+
+error[E0621]: explicit lifetime required in the type of `ap`
+ --> $DIR/variadic-ffi-4.rs:12:5
+ |
+LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> {
+ | --- help: add explicit lifetime `'static` to the type of `ap`: `core::ffi::VaList<'static>`
+LL | ap //~ ERROR: explicit lifetime required
+ | ^^ lifetime `'static` required
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+ --> $DIR/variadic-ffi-4.rs:16:28
+ |
+LL | let _ = ap.copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime
+ | ^^
+ |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 16:21...
+ --> $DIR/variadic-ffi-4.rs:16:21
+ |
+LL | let _ = ap.copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime
+ | ^^^^^^^^^^^
+ = note: ...so that the expression is assignable:
+ expected core::ffi::VaList<'_>
+ found core::ffi::VaList<'_>
+note: but, the lifetime must be valid for the method call at 16:13...
+ --> $DIR/variadic-ffi-4.rs:16:13
+ |
+LL | let _ = ap.copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime
+ | ^^^^^^^^^^^^^^^^^^^^
+note: ...so type `core::ffi::VaList<'_>` of expression is valid during the expression
+ --> $DIR/variadic-ffi-4.rs:16:13
+ |
+LL | let _ = ap.copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/variadic-ffi-4.rs:20:12
+ |
+LL | *ap0 = ap1; //~ ERROR: mismatched types
+ | ^^^ lifetime mismatch
+ |
+ = note: expected type `core::ffi::VaList<'_>`
+ found type `core::ffi::VaList<'_>`
+note: the anonymous lifetime #3 defined on the function body at 19:1...
+ --> $DIR/variadic-ffi-4.rs:19:1
+ |
+LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+LL | | *ap0 = ap1; //~ ERROR: mismatched types
+LL | | }
+ | |_^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 19:1
+ --> $DIR/variadic-ffi-4.rs:19:1
+ |
+LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+LL | | *ap0 = ap1; //~ ERROR: mismatched types
+LL | | }
+ | |_^
+
+error[E0490]: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+ --> $DIR/variadic-ffi-4.rs:24:11
+ |
+LL | ap0 = &mut ap1;
+ | ^^^^^^^^
+ |
+note: the type is valid for the anonymous lifetime #1 defined on the function body at 23:1
+ --> $DIR/variadic-ffi-4.rs:23:1
+ |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | | ap0 = &mut ap1;
+LL | | //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+LL | | //~^^ ERROR: mismatched types
+LL | | //~^^^ ERROR: mismatched types
+LL | | //~^^^^ ERROR: cannot infer an appropriate lifetime
+LL | | }
+ | |_^
+note: but the borrow lasts for the anonymous lifetime #3 defined on the function body at 23:1
+ --> $DIR/variadic-ffi-4.rs:23:1
+ |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | | ap0 = &mut ap1;
+LL | | //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+LL | | //~^^ ERROR: mismatched types
+LL | | //~^^^ ERROR: mismatched types
+LL | | //~^^^^ ERROR: cannot infer an appropriate lifetime
+LL | | }
+ | |_^
+
+error[E0308]: mismatched types
+ --> $DIR/variadic-ffi-4.rs:24:11
+ |
+LL | ap0 = &mut ap1;
+ | ^^^^^^^^ lifetime mismatch
+ |
+ = note: expected type `&mut core::ffi::VaList<'_>`
+ found type `&mut core::ffi::VaList<'_>`
+note: the anonymous lifetime #3 defined on the function body at 23:1...
+ --> $DIR/variadic-ffi-4.rs:23:1
+ |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | | ap0 = &mut ap1;
+LL | | //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+LL | | //~^^ ERROR: mismatched types
+LL | | //~^^^ ERROR: mismatched types
+LL | | //~^^^^ ERROR: cannot infer an appropriate lifetime
+LL | | }
+ | |_^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 23:1
+ --> $DIR/variadic-ffi-4.rs:23:1
+ |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | | ap0 = &mut ap1;
+LL | | //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+LL | | //~^^ ERROR: mismatched types
+LL | | //~^^^ ERROR: mismatched types
+LL | | //~^^^^ ERROR: cannot infer an appropriate lifetime
+LL | | }
+ | |_^
+
+error[E0308]: mismatched types
+ --> $DIR/variadic-ffi-4.rs:24:11
+ |
+LL | ap0 = &mut ap1;
+ | ^^^^^^^^ lifetime mismatch
+ |
+ = note: expected type `&mut core::ffi::VaList<'_>`
+ found type `&mut core::ffi::VaList<'_>`
+note: the anonymous lifetime #2 defined on the function body at 23:1...
+ --> $DIR/variadic-ffi-4.rs:23:1
+ |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | | ap0 = &mut ap1;
+LL | | //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+LL | | //~^^ ERROR: mismatched types
+LL | | //~^^^ ERROR: mismatched types
+LL | | //~^^^^ ERROR: cannot infer an appropriate lifetime
+LL | | }
+ | |_^
+note: ...does not necessarily outlive the anonymous lifetime #3 defined on the function body at 23:1
+ --> $DIR/variadic-ffi-4.rs:23:1
+ |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | | ap0 = &mut ap1;
+LL | | //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+LL | | //~^^ ERROR: mismatched types
+LL | | //~^^^ ERROR: mismatched types
+LL | | //~^^^^ ERROR: cannot infer an appropriate lifetime
+LL | | }
+ | |_^
+
+error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+ --> $DIR/variadic-ffi-4.rs:24:11
+ |
+LL | ap0 = &mut ap1;
+ | ^^^^^^^^
+ |
+note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the function body at 23:1...
+ --> $DIR/variadic-ffi-4.rs:23:1
+ |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | | ap0 = &mut ap1;
+LL | | //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+LL | | //~^^ ERROR: mismatched types
+LL | | //~^^^ ERROR: mismatched types
+LL | | //~^^^^ ERROR: cannot infer an appropriate lifetime
+LL | | }
+ | |_^
+note: ...so that the type `core::ffi::VaList<'_>` is not borrowed for too long
+ --> $DIR/variadic-ffi-4.rs:24:11
+ |
+LL | ap0 = &mut ap1;
+ | ^^^^^^^^
+note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 23:1...
+ --> $DIR/variadic-ffi-4.rs:23:1
+ |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | | ap0 = &mut ap1;
+LL | | //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+LL | | //~^^ ERROR: mismatched types
+LL | | //~^^^ ERROR: mismatched types
+LL | | //~^^^^ ERROR: cannot infer an appropriate lifetime
+LL | | }
+ | |_^
+note: ...so that reference does not outlive borrowed content
+ --> $DIR/variadic-ffi-4.rs:24:11
+ |
+LL | ap0 = &mut ap1;
+ | ^^^^^^^^
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0308, E0490, E0495, E0621.
+For more information about an error, try `rustc --explain E0308`.
--- /dev/null
+#![crate_type="lib"]
+#![no_std]
+#![feature(c_variadic)]
+// The tests in this file are similar to that of variadic-ffi-4, but this
+// one enables nll.
+#![feature(nll)]
+
+use core::ffi::VaList;
+
+pub unsafe extern "C" fn no_escape0<'a>(_: usize, ap: ...) -> VaList<'a> {
+ ap //~ ERROR: explicit lifetime required
+}
+
+pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> {
+ ap //~ ERROR: explicit lifetime required
+}
+
+pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) {
+ let _ = ap.copy(|ap| { ap }); //~ ERROR: lifetime may not live long enough
+}
+
+pub unsafe extern "C" fn no_escape3(_: usize, ap0: &mut VaList, mut ap1: ...) {
+ *ap0 = ap1; //~ ERROR: lifetime may not live long enough
+}
+
+pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+ ap0 = &mut ap1;
+ //~^ ERROR: lifetime may not live long enough
+ //~^^ ERROR: lifetime may not live long enough
+ //~^^^ ERROR: `ap1` does not live long enough
+}
--- /dev/null
+error[E0621]: explicit lifetime required in the type of `ap`
+ --> $DIR/variadic-ffi-5.rs:11:5
+ |
+LL | pub unsafe extern "C" fn no_escape0<'a>(_: usize, ap: ...) -> VaList<'a> {
+ | --- help: add explicit lifetime `'a` to the type of `ap`: `core::ffi::VaList<'a>`
+LL | ap //~ ERROR: explicit lifetime required
+ | ^^ lifetime `'a` required
+
+error[E0621]: explicit lifetime required in the type of `ap`
+ --> $DIR/variadic-ffi-5.rs:15:5
+ |
+LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> {
+ | --- help: add explicit lifetime `'static` to the type of `ap`: `core::ffi::VaList<'static>`
+LL | ap //~ ERROR: explicit lifetime required
+ | ^^ lifetime `'static` required
+
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-5.rs:19:28
+ |
+LL | let _ = ap.copy(|ap| { ap }); //~ ERROR: lifetime may not live long enough
+ | --- ^^ returning this value requires that `'1` must outlive `'2`
+ | | |
+ | | return type of closure is core::ffi::VaList<'2>
+ | has type `core::ffi::VaList<'1>`
+
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-5.rs:23:5
+ |
+LL | pub unsafe extern "C" fn no_escape3(_: usize, ap0: &mut VaList, mut ap1: ...) {
+ | --- ------- has type `core::ffi::VaList<'1>`
+ | |
+ | has type `&mut core::ffi::VaList<'2>`
+LL | *ap0 = ap1; //~ ERROR: lifetime may not live long enough
+ | ^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-5.rs:27:5
+ |
+LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+ | ------- ------- has type `core::ffi::VaList<'2>`
+ | |
+ | has type `&mut core::ffi::VaList<'1>`
+LL | ap0 = &mut ap1;
+ | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+
+error: lifetime may not live long enough
+ --> $DIR/variadic-ffi-5.rs:27:5
+ |
+LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+ | ------- ------- has type `core::ffi::VaList<'1>`
+ | |
+ | has type `&mut core::ffi::VaList<'2>`
+LL | ap0 = &mut ap1;
+ | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+
+error[E0597]: `ap1` does not live long enough
+ --> $DIR/variadic-ffi-5.rs:27:11
+ |
+LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+ | - let's call the lifetime of this reference `'1`
+LL | ap0 = &mut ap1;
+ | ------^^^^^^^^
+ | | |
+ | | borrowed value does not live long enough
+ | assignment requires that `ap1` is borrowed for `'1`
+...
+LL | }
+ | - `ap1` dropped here while still borrowed
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0597, E0621.
+For more information about an error, try `rustc --explain E0597`.
--- /dev/null
+#![crate_type="lib"]
+#![feature(c_variadic)]
+
+pub unsafe extern "C" fn use_vararg_lifetime(
+ x: usize,
+ y: ...
+) -> &usize { //~ ERROR missing lifetime specifier
+ &0
+}
+
+pub unsafe extern "C" fn use_normal_arg_lifetime(x: &usize, y: ...) -> &usize { // OK
+ x
+}
--- /dev/null
+error[E0106]: missing lifetime specifier
+ --> $DIR/variadic-ffi-6.rs:7:6
+ |
+LL | ) -> &usize { //~ ERROR missing lifetime specifier
+ | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
+ |
+ = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
--- /dev/null
+// edition:2015
+
+#![feature(futures_api, async_await)]
+
+async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+
+fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition
+
+async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition
+ async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+}
+
+struct Foo {}
+
+impl Foo {
+ async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+}
+
+trait Bar {
+ async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ //~^ ERROR trait fns cannot be declared `async`
+}
+
+fn main() {
+ macro_rules! accept_item { ($x:item) => {} }
+
+ accept_item! {
+ async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ }
+
+ let inside_closure = || {
+ async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ };
+}
--- /dev/null
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:5:1
+ |
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:7:12
+ |
+LL | fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:10:5
+ |
+LL | async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:9:1
+ |
+LL | async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:32:9
+ |
+LL | async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:28:9
+ |
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:16:5
+ |
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^
+
+error[E0706]: trait fns cannot be declared `async`
+ --> $DIR/edition-deny-async-fns-2015.rs:20:5
+ |
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^^^^^^^^^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:20:5
+ |
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0670, E0706.
+For more information about an error, try `rustc --explain E0670`.
-error[E0045]: variadic function must have C or cdecl calling convention
+error[E0045]: C-variadic function must have C or cdecl calling convention
--> $DIR/E0045.rs:1:17
|
LL | extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045
- | ^^^^^^^^^^^^^^^^^^^ variadics require C or cdecl calling convention
+ | ^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention
error: aborting due to previous error
//~^ ERROR can't pass `u16` to variadic function
//~| HELP cast the value to `c_uint`
printf(::std::ptr::null(), printf);
- //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function
- //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)`
+ //~^ ERROR can't pass `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...) {printf}` to variadic function
+ //~| HELP cast the value to `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...)`
}
}
LL | printf(::std::ptr::null(), 0u16);
| ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint`
-error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function
+error[E0617]: can't pass `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...) {printf}` to variadic function
--> $DIR/E0617.rs:24:36
|
LL | printf(::std::ptr::null(), printf);
| ^^^^^^
-help: cast the value to `unsafe extern "C" fn(*const i8, ...)`
+help: cast the value to `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...)`
|
-LL | printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | printf(::std::ptr::null(), printf as for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
--- /dev/null
+#![crate_type="lib"]
+
+pub unsafe extern "C" fn test(_: i32, ap: ...) { }
+//~^ C-varaidic functions are unstable
--- /dev/null
+error[E0658]: C-varaidic functions are unstable (see issue #44930)
+ --> $DIR/feature-gate-c_variadic.rs:3:1
+ |
+LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(c_variadic)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
#![feature(futures_api)]
-async fn foo() {} //~ ERROR async fn is unstable
+async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ //~^ ERROR async fn is unstable
fn main() {
let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/feature-gate-async-await-2015-edition.rs:5:1
+ |
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ | ^^^^^
+
error[E0422]: cannot find struct, variant or union type `async` in this scope
- --> $DIR/feature-gate-async-await-2015-edition.rs:8:13
+ --> $DIR/feature-gate-async-await-2015-edition.rs:9:13
|
LL | let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
| ^^^^^ not found in this scope
error[E0425]: cannot find value `async` in this scope
- --> $DIR/feature-gate-async-await-2015-edition.rs:9:13
+ --> $DIR/feature-gate-async-await-2015-edition.rs:10:13
|
LL | let _ = async || { true }; //~ ERROR cannot find value `async` in this scope
| ^^^^^ not found in this scope
error[E0658]: async fn is unstable (see issue #50547)
--> $DIR/feature-gate-async-await-2015-edition.rs:5:1
|
-LL | async fn foo() {} //~ ERROR async fn is unstable
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
| ^^^^^^^^^^^^^^^^^
|
= help: add #![feature(async_await)] to the crate attributes to enable
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
-Some errors occurred: E0422, E0425, E0658.
+Some errors occurred: E0422, E0425, E0658, E0670.
For more information about an error, try `rustc --explain E0422`.
-error[E0658]: #[unwind] is experimental
+error[E0658]: #[unwind] is experimental (see issue #58760)
--> $DIR/feature-gate-unwind-attributes.rs:11:5
|
LL | #[unwind(allowed)] //~ ERROR #[unwind] is experimental
}
fn f() {
::foo::m!();
- println!(); // OK on 2015 edition (at least for now)
+ println!(); //~ ERROR cannot find macro `print!` in this scope
}
}
LL | Vec::new(); //~ ERROR failed to resolve
| ^^^ use of undeclared type or module `Vec`
+error: cannot find macro `print!` in this scope
+ --> $DIR/no_implicit_prelude.rs:16:9
+ |
+LL | println!(); //~ ERROR cannot find macro `print!` in this scope
+ | ^^^^^^^^^^^
+ |
+ = help: have you added the `#[macro_use]` on the module/import?
+ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
error[E0599]: no method named `clone` found for type `()` in the current scope
--> $DIR/no_implicit_prelude.rs:12:12
|
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
`use std::clone::Clone;`
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
Some errors occurred: E0433, E0599.
For more information about an error, try `rustc --explain E0433`.
--- /dev/null
+// edition:2018
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden when using `async` and `await`.
+
+#![feature(await_macro, async_await, futures_api, generators)]
+
+async fn recursive_async_function() -> () { //~ ERROR
+ await!(recursive_async_function());
+}
+
+fn main() {}
--- /dev/null
+error[E0720]: opaque type expands to a recursive type
+ --> $DIR/recursive-async-impl-trait-type.rs:7:40
+ |
+LL | async fn recursive_async_function() -> () { //~ ERROR
+ | ^^ expands to self-referential type
+ |
+ = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-async-impl-trait-type.rs:7:43: 9:2 {impl std::future::Future, ()}]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.
// Test that impl trait does not allow creating recursive types that are
// otherwise forbidden.
-#![feature(await_macro, async_await, futures_api, generators)]
+#![feature(futures_api, generators)]
fn option(i: i32) -> impl Sized { //~ ERROR
if i < 0 {
}
}
-async fn recursive_async_function() -> () { //~ ERROR
- await!(recursive_async_function());
-}
-
fn use_fn_ptr() -> impl Sized { // OK, error already reported
fn_ptr()
}
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]`
error[E0720]: opaque type expands to a recursive type
- --> $DIR/recursive-impl-trait-type.rs:65:40
- |
-LL | async fn recursive_async_function() -> () { //~ ERROR
- | ^^ expands to self-referential type
- |
- = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-impl-trait-type.rs:65:43: 67:2 {impl std::future::Future, ()}]>`
-
-error[E0720]: opaque type expands to a recursive type
- --> $DIR/recursive-impl-trait-type.rs:73:26
+ --> $DIR/recursive-impl-trait-type.rs:69:26
|
LL | fn mutual_recursion() -> impl Sync { //~ ERROR
| ^^^^^^^^^ expands to self-referential type
= note: type resolves to itself
error[E0720]: opaque type expands to a recursive type
- --> $DIR/recursive-impl-trait-type.rs:77:28
+ --> $DIR/recursive-impl-trait-type.rs:73:28
|
LL | fn mutual_recursion_b() -> impl Sized { //~ ERROR
| ^^^^^^^^^^ expands to self-referential type
|
= note: type resolves to itself
-error: aborting due to 15 previous errors
+error: aborting due to 14 previous errors
For more information about this error, try `rustc --explain E0720`.
extern "C" fn foo(x: u8, ...);
-//~^ ERROR only foreign functions are allowed to be variadic
+//~^ ERROR only foreign functions are allowed to be C-variadic
//~| ERROR expected one of `->`, `where`, or `{`, found `;`
-error: only foreign functions are allowed to be variadic
+error: only foreign functions are allowed to be C-variadic
--> $DIR/invalid-variadic-function.rs:1:26
|
LL | extern "C" fn foo(x: u8, ...);
LL | const B: i32 = A;
| ^
= note: ...which again requires const checking if rvalue is promotable to static `A`, completing the cycle
+ = note: cycle used when running analysis passes on this crate
error: aborting due to previous error
LL | ($(a)?) => {} //~ERROR expected `*` or `+`
| ^
|
- = note: `?` is not a macro repetition operator
+ = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition
error: expected `*` or `+`
--> $DIR/macro-at-most-once-rep-2015-ques-rep.rs:10:11
LL | ($(a),?) => {} //~ERROR expected `*` or `+`
| ^
|
- = note: `?` is not a macro repetition operator
+ = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition
error: aborting due to 2 previous errors
LL | Nope(i32 {}) //~ ERROR: found `{`
| ^ expected one of 7 possible tokens here
-error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `::`, `<`, `?`, `[`, `_`, `crate`, `dyn`, `extern`, `fn`, `for`, `impl`, `pub`, `unsafe`, `}`, or lifetime, found `{`
+error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `...`, `::`, `<`, `?`, `[`, `_`, `crate`, `dyn`, `extern`, `fn`, `for`, `impl`, `pub`, `unsafe`, `}`, or lifetime, found `{`
--> $DIR/recover-enum2.rs:27:22
|
LL | Nope(i32 {}) //~ ERROR: found `{`
- | ^ expected one of 23 possible tokens here
+ | ^ expected one of 24 possible tokens here
error: expected expression, found reserved identifier `_`
--> $DIR/recover-enum2.rs:32:22
fn foo(x: isize, ...) {
- //~^ ERROR: only foreign functions are allowed to be variadic
+ //~^ ERROR: only foreign functions are allowed to be C-variadic
}
fn main() {}
-error: only foreign functions are allowed to be variadic
+error: only foreign functions are allowed to be C-variadic
--> $DIR/variadic-ffi-3.rs:1:18
|
LL | fn foo(x: isize, ...) {
extern "C" fn foo(x: isize, ...) {
- //~^ ERROR: only foreign functions are allowed to be variadic
+ //~^ ERROR: only foreign functions are allowed to be C-variadic
}
fn main() {}
-error: only foreign functions are allowed to be variadic
+error: only foreign functions are allowed to be C-variadic
--> $DIR/variadic-ffi-4.rs:1:29
|
LL | extern "C" fn foo(x: isize, ...) {
// Issue #876
-#![no_implicit_prelude]
use std::vec::Vec;
fn last<T>(v: Vec<&T> ) -> std::option::Option<T> {
- panic!();
+ ::std::panic!();
}
fn main() {
error[E0308]: mismatched types
- --> $DIR/tag-that-dare-not-speak-its-name.rs:12:20
+ --> $DIR/tag-that-dare-not-speak-its-name.rs:11:20
|
LL | let x : char = last(y);
| ^^^^^^^ expected char, found enum `std::option::Option`
+++ /dev/null
-// ignore-arm stdcall isn't supported
-
-fn baz(f: extern "stdcall" fn(usize, ...)) {
- //~^ ERROR: variadic function must have C or cdecl calling convention
- f(22, 44);
-}
-
-fn main() {}
+++ /dev/null
-error[E0045]: variadic function must have C or cdecl calling convention
- --> $DIR/variadic-ffi-2.rs:3:11
- |
-LL | fn baz(f: extern "stdcall" fn(usize, ...)) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variadics require C or cdecl calling convention
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0045`.
+++ /dev/null
-extern {
- fn foo(f: isize, x: u8, ...);
- //~^ defined here
- //~| defined here
-}
-
-extern "C" fn bar(f: isize, x: u8) {}
-
-fn main() {
- unsafe {
- foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied
- foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
-
- let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
- //~^ ERROR: mismatched types
- //~| expected type `unsafe extern "C" fn(isize, u8)`
- //~| found type `unsafe extern "C" fn(isize, u8, ...) {foo}`
-
- let y: extern "C" fn(f: isize, x: u8, ...) = bar;
- //~^ ERROR: mismatched types
- //~| expected type `extern "C" fn(isize, u8, ...)`
- //~| found type `extern "C" fn(isize, u8) {bar}`
-
- foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function
- foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function
- foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function
- foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function
- foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function
- foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function
- }
-}
+++ /dev/null
-error[E0060]: this function takes at least 2 parameters but 0 parameters were supplied
- --> $DIR/variadic-ffi-3.rs:11:9
- |
-LL | fn foo(f: isize, x: u8, ...);
- | ----------------------------- defined here
-...
-LL | foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied
- | ^^^^^ expected at least 2 parameters
-
-error[E0060]: this function takes at least 2 parameters but 1 parameter was supplied
- --> $DIR/variadic-ffi-3.rs:12:9
- |
-LL | fn foo(f: isize, x: u8, ...);
- | ----------------------------- defined here
-...
-LL | foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
- | ^^^^^^ expected at least 2 parameters
-
-error[E0308]: mismatched types
- --> $DIR/variadic-ffi-3.rs:14:56
- |
-LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
- | ^^^ expected non-variadic fn, found variadic function
- |
- = note: expected type `unsafe extern "C" fn(isize, u8)`
- found type `unsafe extern "C" fn(isize, u8, ...) {foo}`
-
-error[E0308]: mismatched types
- --> $DIR/variadic-ffi-3.rs:19:54
- |
-LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar;
- | ^^^ expected variadic fn, found non-variadic function
- |
- = note: expected type `extern "C" fn(isize, u8, ...)`
- found type `extern "C" fn(isize, u8) {bar}`
-
-error[E0617]: can't pass `f32` to variadic function
- --> $DIR/variadic-ffi-3.rs:24:19
- |
-LL | foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function
- | ^^^^ help: cast the value to `c_double`: `3f32 as c_double`
-
-error[E0617]: can't pass `bool` to variadic function
- --> $DIR/variadic-ffi-3.rs:25:19
- |
-LL | foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function
- | ^^^^ help: cast the value to `c_int`: `true as c_int`
-
-error[E0617]: can't pass `i8` to variadic function
- --> $DIR/variadic-ffi-3.rs:26:19
- |
-LL | foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function
- | ^^^ help: cast the value to `c_int`: `1i8 as c_int`
-
-error[E0617]: can't pass `u8` to variadic function
- --> $DIR/variadic-ffi-3.rs:27:19
- |
-LL | foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function
- | ^^^ help: cast the value to `c_uint`: `1u8 as c_uint`
-
-error[E0617]: can't pass `i16` to variadic function
- --> $DIR/variadic-ffi-3.rs:28:19
- |
-LL | foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function
- | ^^^^ help: cast the value to `c_int`: `1i16 as c_int`
-
-error[E0617]: can't pass `u16` to variadic function
- --> $DIR/variadic-ffi-3.rs:29:19
- |
-LL | foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function
- | ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint`
-
-error: aborting due to 10 previous errors
-
-Some errors occurred: E0060, E0308, E0617.
-For more information about an error, try `rustc --explain E0060`.
+++ /dev/null
-// ignore-arm stdcall isn't supported
-// ignore-aarch64 stdcall isn't supported
-
-extern "stdcall" {
- fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling
-}
-
-extern {
- fn foo(f: isize, x: u8, ...);
-}
-
-extern "C" fn bar(f: isize, x: u8) {}
-
-fn main() {
- // errors below are no longer checked because error above aborts
- // compilation; see variadic-ffi-3.rs for corresponding test.
- unsafe {
- foo();
- foo(1);
-
- let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
- let y: extern "C" fn(f: isize, x: u8, ...) = bar;
-
- foo(1, 2, 3f32);
- foo(1, 2, true);
- foo(1, 2, 1i8);
- foo(1, 2, 1u8);
- foo(1, 2, 1i16);
- foo(1, 2, 1u16);
- }
-}
+++ /dev/null
-error[E0045]: variadic function must have C or cdecl calling convention
- --> $DIR/variadic-ffi.rs:5:5
- |
-LL | fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variadics require C or cdecl calling convention
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0045`.
!lang_features.contains_key(name)
}).collect();
+ // Library features
let unstable_lib_feature_names = collect_unstable_feature_names(&lib_features);
let unstable_book_lib_features_section_file_names =
collect_unstable_book_lib_features_section_file_names(path);
- // Check for Unstable Book sections that don't have a corresponding unstable feature
- for feature_name in &unstable_book_lib_features_section_file_names -
- &unstable_lib_feature_names {
- tidy_error!(bad,
- "The Unstable Book has a 'library feature' section '{}' which doesn't \
- correspond to an unstable library feature",
- feature_name)
- }
-
// Language features
-
let unstable_lang_feature_names = collect_unstable_feature_names(&lang_features);
let unstable_book_lang_features_section_file_names =
collect_unstable_book_lang_features_section_file_names(path);
+ // Check for Unstable Book sections that don't have a corresponding unstable feature
+ for feature_name in &unstable_book_lib_features_section_file_names -
+ &unstable_lib_feature_names {
+ if !unstable_lang_feature_names.contains(&feature_name) {
+ tidy_error!(bad,
+ "The Unstable Book has a 'library feature' section '{}' which doesn't \
+ correspond to an unstable library feature",
+ feature_name);
+ }
+ }
+
// Check for Unstable Book sections that don't have a corresponding unstable feature.
for feature_name in &unstable_book_lang_features_section_file_names -
&unstable_lang_feature_names {