diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml index 94553608a2f4..ca088ba31fdf 100644 --- a/.github/workflows/post-merge.yml +++ b/.github/workflows/post-merge.yml @@ -25,12 +25,19 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | + # Give GitHub some time to propagate the information that the PR was merged + sleep 60 + # Get closest bors merge commit PARENT_COMMIT=`git rev-list --author='bors ' -n1 --first-parent HEAD^1` echo "Parent: ${PARENT_COMMIT}" # Find PR for the current commit HEAD_PR=`gh pr list --search "${{ github.sha }}" --state merged --json number --jq '.[0].number'` + if [ -z "${HEAD_PR}" ]; then + echo "PR for commit SHA ${{ github.sha }} not found, exiting" + exit 1 + fi echo "HEAD: ${{ github.sha }} (#${HEAD_PR})" cd src/ci/citool diff --git a/Cargo.lock b/Cargo.lock index 361d237b3af8..fa0fa33ea75a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,12 +158,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" -dependencies = [ - "backtrace", -] +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "ar_archive_writer" @@ -188,9 +185,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "askama" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a4e46abb203e00ef226442d452769233142bbfdd79c3941e84c8e61c4112543" +checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7" dependencies = [ "askama_derive", "itoa", @@ -201,9 +198,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54398906821fd32c728135f7b351f0c7494ab95ae421d41b6f5a020e158f28a6" +checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac" dependencies = [ "askama_parser", "basic-toml", @@ -213,7 +210,7 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "serde_derive", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -225,7 +222,7 @@ dependencies = [ "memchr", "serde", "serde_derive", - "winnow 0.7.6", + "winnow 0.7.9", ] [[package]] @@ -281,9 +278,9 @@ checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "blake3" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389a099b34312839e16420d499a9cad9650541715937ffbdd40d36f49e77eeb3" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" dependencies = [ "arrayref", "arrayvec", @@ -452,9 +449,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -496,9 +493,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", "clap_derive", @@ -516,9 +513,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", @@ -535,7 +532,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -561,13 +558,13 @@ dependencies = [ "if_chain", "itertools", "parking_lot", - "pulldown-cmark 0.11.3", + "pulldown-cmark", "quote", "regex", "rustc_tools_util 0.4.2", "serde", "serde_json", - "syn 2.0.100", + "syn 2.0.101", "tempfile", "termize", "tokio", @@ -653,16 +650,16 @@ dependencies = [ [[package]] name = "color-eyre" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +checksum = "e6e1761c0e16f8883bbbb8ce5990867f4f06bf11a0253da6495a04ce4b6ef0ec" dependencies = [ "backtrace", "color-spantrace", "eyre", "indenter", "once_cell", - "owo-colors", + "owo-colors 4.2.0", "tracing-error", ] @@ -684,17 +681,17 @@ dependencies = [ "nom", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] name = "color-spantrace" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +checksum = "2ddd8d5bfda1e11a501d0a7303f3bfed9aa632ebdb859be40d0fd70478ed70d5" dependencies = [ "once_cell", - "owo-colors", + "owo-colors 4.2.0", "tracing-core", "tracing-error", ] @@ -780,6 +777,7 @@ name = "coverage-dump" version = "0.1.0" dependencies = [ "anyhow", + "itertools", "leb128", "md-5", "miniz_oxide 0.7.4", @@ -910,7 +908,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -921,7 +919,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -943,13 +941,13 @@ dependencies = [ [[package]] name = "derive-where" -version = "1.2.7" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +checksum = "e73f2692d4bd3cac41dca28934a39894200c9fabf49586d77d0e5954af1d7902" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -970,7 +968,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -980,7 +978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -992,7 +990,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1082,7 +1080,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1361,7 +1359,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1434,9 +1432,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -1502,9 +1500,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" dependencies = [ "allocator-api2", "equivalent", @@ -1761,7 +1759,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1919,9 +1917,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.6" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f33145a5cbea837164362c7bd596106eb7c5198f97d1ba6f6ebb3223952e488" +checksum = "d07d8d955d798e7a4d6f9c58cd1f1916e790b42b092758a9ef6e16fef9f1b3fd" dependencies = [ "jiff-static", "log", @@ -1932,13 +1930,13 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.6" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ce13c40ec6956157a3635d97a1ee2df323b263f09ea14165131289cb0f5c19" +checksum = "f244cfe006d98d26f859c7abd1318d85327e1882dc9cef80f62daeeb0adcf300" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -2071,14 +2069,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] name = "libm" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72" [[package]] name = "libredox" @@ -2202,7 +2200,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -2307,7 +2305,7 @@ dependencies = [ "libffi", "libloading", "measureme", - "rand 0.9.0", + "rand 0.9.1", "regex", "rustc_version", "smallvec", @@ -2466,6 +2464,25 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags", +] + +[[package]] +name = "objc2-io-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a" +dependencies = [ + "libc", + "objc2-core-foundation", +] + [[package]] name = "object" version = "0.32.2" @@ -2525,9 +2542,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.107" +version = "0.9.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" dependencies = [ "cc", "libc", @@ -2550,7 +2567,6 @@ dependencies = [ "humansize", "humantime", "log", - "serde", "serde_json", "sysinfo", "tabled", @@ -2577,6 +2593,12 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "owo-colors" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564" + [[package]] name = "pad" version = "0.1.6" @@ -2681,7 +2703,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -2798,7 +2820,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abec3fb083c10660b3854367697da94c674e9e82aa7511014dc958beeb7215e9" dependencies = [ - "owo-colors", + "owo-colors 3.5.0", "pad", ] @@ -2810,33 +2832,22 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" +checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" dependencies = [ "cc", ] -[[package]] -name = "pulldown-cmark" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" -dependencies = [ - "bitflags", - "memchr", - "unicase", -] - [[package]] name = "pulldown-cmark" version = "0.11.3" @@ -2895,13 +2906,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy", ] [[package]] @@ -2930,7 +2940,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -2973,9 +2983,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ "bitflags", ] @@ -2986,7 +2996,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", "thiserror 1.0.69", ] @@ -2997,7 +3007,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", "thiserror 2.0.12", ] @@ -3179,7 +3189,7 @@ name = "rustc_abi" version = "0.0.0" dependencies = [ "bitflags", - "rand 0.9.0", + "rand 0.9.1", "rand_xoshiro", "rustc_data_structures", "rustc_hashes", @@ -3583,13 +3593,13 @@ dependencies = [ "rustc_query_system", "rustc_resolve", "rustc_session", - "rustc_smir", "rustc_span", "rustc_target", "rustc_trait_selection", "rustc_ty_utils", "serde_json", "shlex", + "stable_mir", "tracing", "windows 0.59.0", ] @@ -3693,7 +3703,7 @@ dependencies = [ "fluent-syntax", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "unic-langid", ] @@ -3805,7 +3815,7 @@ dependencies = [ name = "rustc_incremental" version = "0.0.0" dependencies = [ - "rand 0.9.0", + "rand 0.9.1", "rustc_ast", "rustc_data_structures", "rustc_errors", @@ -3839,7 +3849,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3985,7 +3995,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure", ] @@ -4015,6 +4025,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", + "tempfile", "tracing", ] @@ -4314,7 +4325,7 @@ version = "0.0.0" dependencies = [ "bitflags", "itertools", - "pulldown-cmark 0.11.3", + "pulldown-cmark", "rustc_arena", "rustc_ast", "rustc_ast_pretty", @@ -4371,7 +4382,7 @@ dependencies = [ "bitflags", "getopts", "libc", - "rand 0.9.0", + "rand 0.9.1", "rustc_abi", "rustc_ast", "rustc_data_structures", @@ -4481,7 +4492,6 @@ dependencies = [ "itertools", "rustc_abi", "rustc_ast", - "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4575,7 +4585,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure", ] @@ -4599,7 +4609,6 @@ dependencies = [ "indexmap", "itertools", "minifier", - "pulldown-cmark 0.9.6", "pulldown-cmark-escape", "regex", "rustdoc-json-types", @@ -4666,7 +4675,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -4700,9 +4709,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ "bitflags", "errno", @@ -4803,7 +4812,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -4840,9 +4849,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -4961,9 +4970,9 @@ dependencies = [ [[package]] name = "stacker" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9" +checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b" dependencies = [ "cc", "cfg-if", @@ -5049,9 +5058,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -5060,24 +5069,25 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] name = "sysinfo" -version = "0.31.4" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" +checksum = "b897c8ea620e181c7955369a31be5f48d9a9121cb59fd33ecef9ff2a34323422" dependencies = [ - "core-foundation-sys", "libc", - "windows 0.57.0", + "objc2-core-foundation", + "objc2-io-kit", + "windows 0.61.1", ] [[package]] @@ -5161,7 +5171,7 @@ version = "0.1.0" dependencies = [ "indicatif", "num", - "rand 0.9.0", + "rand 0.9.1", "rand_chacha 0.9.0", "rayon", ] @@ -5198,7 +5208,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -5209,7 +5219,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -5335,9 +5345,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" dependencies = [ "serde", ] @@ -5375,7 +5385,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -5546,7 +5556,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b" dependencies = [ "proc-macro-hack", "quote", - "syn 2.0.100", + "syn 2.0.101", "unic-langid-impl", ] @@ -5762,7 +5772,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "wasm-bindgen-shared", ] @@ -5784,7 +5794,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5952,16 +5962,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" -dependencies = [ - "windows-core 0.57.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.59.0" @@ -5972,6 +5972,19 @@ dependencies = [ "windows-targets 0.53.0", ] +[[package]] +name = "windows" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" +dependencies = [ + "windows-collections", + "windows-core 0.61.0", + "windows-future", + "windows-link", + "windows-numerics", +] + [[package]] name = "windows-bindgen" version = "0.61.0" @@ -5984,15 +5997,12 @@ dependencies = [ ] [[package]] -name = "windows-core" -version = "0.57.0" +name = "windows-collections" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-implement 0.57.0", - "windows-interface 0.57.0", - "windows-result 0.1.2", - "windows-targets 0.52.6", + "windows-core 0.61.0", ] [[package]] @@ -6002,8 +6012,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" dependencies = [ "windows-implement 0.59.0", - "windows-interface 0.59.1", - "windows-result 0.3.2", + "windows-interface", + "windows-result", "windows-strings 0.3.1", "windows-targets 0.53.0", ] @@ -6015,21 +6025,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" dependencies = [ "windows-implement 0.60.0", - "windows-interface 0.59.1", + "windows-interface", "windows-link", - "windows-result 0.3.2", + "windows-result", "windows-strings 0.4.0", ] [[package]] -name = "windows-implement" -version = "0.57.0" +name = "windows-future" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", + "windows-core 0.61.0", + "windows-link", ] [[package]] @@ -6040,7 +6049,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6051,18 +6060,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", -] - -[[package]] -name = "windows-interface" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6073,7 +6071,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6083,12 +6081,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" [[package]] -name = "windows-result" -version = "0.1.2" +name = "windows-numerics" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-targets 0.52.6", + "windows-core 0.61.0", + "windows-link", ] [[package]] @@ -6341,9 +6340,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.6" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3" dependencies = [ "memchr", ] @@ -6464,28 +6463,28 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6505,7 +6504,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure", ] @@ -6528,5 +6527,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] diff --git a/RELEASES.md b/RELEASES.md index 0948eb85192e..1a77c33b9957 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,169 @@ +Version 1.87.0 (2025-05-15) +========================== + + + +Language +-------- +- [Stabilize `asm_goto` feature](https://github.com/rust-lang/rust/pull/133870) +- [Allow parsing open beginning ranges (`..EXPR`) after unary operators `!`, `~`, `-`, and `*`}](https://github.com/rust-lang/rust/pull/134900). +- [Don't require method impls for methods with `Self: Sized` bounds in `impl`s for unsized types](https://github.com/rust-lang/rust/pull/135480) +- [Stabilize `feature(precise_capturing_in_traits)` allowing `use<...>` bounds on return position `impl Trait` in `trait`s](https://github.com/rust-lang/rust/pull/138128) + + + +Compiler +-------- +- [x86: make SSE2 required for i686 targets and use it to pass SIMD types](https://github.com/rust-lang/rust/pull/135408) + + + +Platform Support +---------------- +- [Remove `i586-pc-windows-msvc` target](https://github.com/rust-lang/rust/pull/137957) + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + +[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html + + + +Libraries +--------- +- [Stabilize the anonymous pipe API](https://github.com/rust-lang/rust/issues/127154) +- [Add support for unbounded left/right shift operations](https://github.com/rust-lang/rust/issues/129375) +- [Print pointer metadata in `Debug` impl of raw pointers](https://github.com/rust-lang/rust/pull/135080) +- [`Vec::with_capacity` guarantees it allocates with the amount requested, even if `Vec::capacity` returns a different number.](https://github.com/rust-lang/rust/pull/135933) +- Most `std::arch` intrinsics which don't take pointer arguments can now be called from safe code if the caller has the appropriate target features already enabled (https://github.com/rust-lang/stdarch/pull/1714, https://github.com/rust-lang/stdarch/pull/1716, https://github.com/rust-lang/stdarch/pull/1717) +- [Undeprecate `env::home_dir`](https://github.com/rust-lang/rust/pull/137327) +- [Denote `ControlFlow` as `#[must_use]`](https://github.com/rust-lang/rust/pull/137449) +- [Macros such as `assert_eq!` and `vec!` now support `const {...}` expressions](https://github.com/rust-lang/rust/pull/138162) + + + +Stabilized APIs +--------------- + +- [`Vec::extract_if`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.extract_if) +- [`vec::ExtractIf`](https://doc.rust-lang.org/nightly/std/vec/struct.ExtractIf.html) +- [`LinkedList::extract_if`](https://doc.rust-lang.org/nightly/std/collections/struct.LinkedList.html#method.extract_if) +- [`linked_list::ExtractIf`](https://doc.rust-lang.org/nightly/std/collections/linked_list/struct.ExtractIf.html) +- [`<[T]>::split_off`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off) +- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_mut) +- [`<[T]>::split_off_first`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first) +- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first_mut) +- [`<[T]>::split_off_last`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last) +- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last_mut) +- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within) +- [`os_str::Display`](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.Display.html) +- [`OsString::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.display) +- [`OsStr::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsStr.html#method.display) +- [`io::pipe`](https://doc.rust-lang.org/nightly/std/io/fn.pipe.html) +- [`io::PipeReader`](https://doc.rust-lang.org/nightly/std/io/struct.PipeReader.html) +- [`io::PipeWriter`](https://doc.rust-lang.org/nightly/std/io/struct.PipeWriter.html) +- [`impl From for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle) +- [`impl From for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle) +- [`impl From for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html) +- [`impl From for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio) +- [`impl From for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd) +- [`impl From for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd) +- [`Box>::write`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.write) +- [`impl TryFrom> for String`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String) + +These APIs are now stable in const contexts: + +- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned) +- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned) +- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned-1) +- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned-1) +- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.offset_from_unsigned) +- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned) +- [`::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.cast_signed) +- [`NonZero::::cast_signed`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_signed-5). +- [`::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.cast_signed). +- [`NonZero::::cast_unsigned`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_unsigned-5). +- [`::is_multiple_of`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.is_multiple_of) +- [`::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shl) +- [`::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shr) +- [`::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shl) +- [`::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shr) +- [`::from_utf8`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8) +- [`::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_mut) +- [`::from_utf8_unchecked`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked) +- [`::from_utf8_unchecked_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked_mut) +- [`core::str::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/str/fn.from_utf8_mut.html) +- [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.copy_from_slice) +- [`SocketAddr::set_ip`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_ip) +- [`SocketAddr::set_port`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_port), +- [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_ip) +- [`SocketAddrV4::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_port), +- [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_ip) +- [`SocketAddrV6::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_port) +- [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_flowinfo) +- [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_scope_id) +- [`char::is_digit`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_digit) +- [`char::is_whitespace`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_whitespace) +- [`::midpoint`](https://doc.rust-lang.org/std/primitive.isize.html#method.midpoint) +- [`<[[T; N]]>::as_flattened`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_flattened) +- [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_flattened_mut) +- [`String::into_bytes`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.into_bytes) +- [`String::as_str`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_str) +- [`String::capacity`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.capacity) +- [`String::as_bytes`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_bytes) +- [`String::len`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.len) +- [`String::is_empty`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.is_empty) +- [`String::as_mut_str`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_str) +- [`String::as_mut_vec`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_vec) +- [`Vec::as_ptr`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_ptr) +- [`Vec::as_slice`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_slice) +- [`Vec::capacity`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.capacity) +- [`Vec::len`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.len) +- [`Vec::is_empty`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.is_empty) +- [`Vec::as_mut_slice`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_mut_slice) +- [`Vec::as_mut_ptr`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_mut_ptr) + + + +Cargo +----- +- [Add terminal integration via ANSI OSC 9;4 sequences](https://github.com/rust-lang/cargo/pull/14615/) +- [chore: bump openssl to v3](https://github.com/rust-lang/cargo/pull/15232/) +- [feat(package): add --exclude-lockfile flag](https://github.com/rust-lang/cargo/pull/15234/) + + + +Compatibility Notes +------------------- +- [Rust now raises an error for macro invocations inside the `#![crate_name]` attribute](https://github.com/rust-lang/rust/pull/127581) +- [Unstable fields are now always considered to be inhabited](https://github.com/rust-lang/rust/pull/133889) +- [Macro arguments of unary operators followed by open beginning ranges may now be matched differently](https://github.com/rust-lang/rust/pull/134900) +- [Make `Debug` impl of raw pointers print metadata if present](https://github.com/rust-lang/rust/pull/135080) +- [Warn against function pointers using unsupported ABI strings in dependencies](https://github.com/rust-lang/rust/pull/135767) +- [Associated types on `dyn` types are no longer deduplicated](https://github.com/rust-lang/rust/pull/136458) +- [Forbid attributes on `..` inside of struct patterns (`let Struct { #[attribute] .. }) =`](https://github.com/rust-lang/rust/pull/136490) +- [Make `ptr_cast_add_auto_to_object` lint into hard error](https://github.com/rust-lang/rust/pull/136764) +- Many `std::arch` intrinsics are now safe to call in some contexts, there may now be new `unused_unsafe` warnings in existing codebases. +- [Limit `width` and `precision` formatting options to 16 bits on all targets](https://github.com/rust-lang/rust/pull/136932) +- [Turn order dependent trait objects future incompat warning into a hard error](https://github.com/rust-lang/rust/pull/136968) +- [Denote `ControlFlow` as `#[must_use]`](https://github.com/rust-lang/rust/pull/137449) +- [Windows: The standard library no longer links `advapi32`, except on win7.](https://github.com/rust-lang/rust/pull/138233) Code such as C libraries that were relying on this assumption may need to explicitly link advapi32. +- [Proc macros can no longer observe expanded `cfg(true)` attributes.](https://github.com/rust-lang/rust/pull/138844) +- [Start changing the internal representation of pasted tokens](https://github.com/rust-lang/rust/pull/124141). Certain invalid declarative macros that were previously accepted in obscure circumstances are now correctly rejected by the compiler. Use of a `tt` fragment specifier can often fix these macros. +- [Don't allow flattened format_args in const.](https://github.com/rust-lang/rust/pull/139624) + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +- [Update to LLVM 20](https://github.com/rust-lang/rust/pull/135763) + + Version 1.86.0 (2025-04-03) ========================== diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 8e1a3cd14354..9f3aed9216c2 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -492,9 +492,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut generic_args = ThinVec::new(); for (idx, arg) in args.iter().cloned().enumerate() { if legacy_args_idx.contains(&idx) { - let parent_def_id = self.current_hir_id_owner.def_id; let node_id = self.next_node_id(); - self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, f.span); + self.create_def(node_id, None, DefKind::AnonConst, f.span); let mut visitor = WillCreateDefIdsVisitor {}; let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) { AstP(Expr { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c009abd729da..f48a571b86a7 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1310,7 +1310,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // create a fake body so that the entire rest of the compiler doesn't have to deal with // this as a special case. return self.lower_fn_body(decl, contract, |this| { - if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)) { + if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)) + || this.tcx.is_sdylib_interface_build() + { let span = this.lower_span(span); let empty_block = hir::Block { hir_id: this.next_id(), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9f9d1f9a5565..8597820073a5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -500,12 +500,12 @@ enum GenericArgsMode { impl<'a, 'hir> LoweringContext<'a, 'hir> { fn create_def( &mut self, - parent: LocalDefId, node_id: ast::NodeId, name: Option, def_kind: DefKind, span: Span, ) -> LocalDefId { + let parent = self.current_hir_id_owner.def_id; debug_assert_ne!(node_id, ast::DUMMY_NODE_ID); assert!( self.opt_local_def_id(node_id).is_none(), @@ -515,7 +515,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.tcx.hir_def_key(self.local_def_id(node_id)), ); - let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id(); + let def_id = self + .tcx + .at(span) + .create_def(parent, name, def_kind, None, &mut self.resolver.disambiguator) + .def_id(); debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); self.resolver.node_id_to_def_id.insert(node_id, def_id); @@ -787,7 +791,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, kind, .. } => { // Late resolution delegates to us the creation of the `LocalDefId`. let _def_id = self.create_def( - self.current_hir_id_owner.def_id, param, Some(kw::UnderscoreLifetime), DefKind::LifetimeParam, @@ -2113,8 +2116,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::ConstArgKind::Path(qpath) } else { // Construct an AnonConst where the expr is the "ty"'s path. - - let parent_def_id = self.current_hir_id_owner.def_id; let node_id = self.next_node_id(); let span = self.lower_span(span); @@ -2122,7 +2123,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // We're lowering a const argument that was originally thought to be a type argument, // so the def collector didn't create the def ahead of time. That's why we have to do // it here. - let def_id = self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, span); + let def_id = self.create_def(node_id, None, DefKind::AnonConst, span); let hir_id = self.lower_node_id(node_id); let path_expr = Expr { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 4a6929ef0117..58dea472f1d3 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -522,14 +522,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, base_type: Span, ) -> &'hir hir::ConstArg<'hir> { - let parent_def_id = self.current_hir_id_owner.def_id; let node_id = self.next_node_id(); // Add a definition for the in-band const def. // We're generating a range end that didn't exist in the AST, // so the def collector didn't create the def ahead of time. That's why we have to do // it here. - let def_id = self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, span); + let def_id = self.create_def(node_id, None, DefKind::AnonConst, span); let hir_id = self.lower_node_id(node_id); let unstable_span = self.mark_span_with_reason( diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 1feb3e9bf9b4..cbf4f2f5eb2b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -82,6 +82,10 @@ struct AstValidator<'a> { /// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe. extern_mod_safety: Option, + lint_node_id: NodeId, + + is_sdylib_interface: bool, + lint_buffer: &'a mut LintBuffer, } @@ -826,7 +830,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_attribute(&mut self, attr: &Attribute) { - validate_attr::check_attr(&self.sess.psess, attr); + validate_attr::check_attr(&self.sess.psess, attr, self.lint_node_id); } fn visit_ty(&mut self, ty: &'a Ty) { @@ -839,6 +843,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.has_proc_macro_decls = true; } + let previous_lint_node_id = mem::replace(&mut self.lint_node_id, item.id); + if let Some(ident) = item.kind.ident() && attr::contains_name(&item.attrs, sym::no_mangle) { @@ -948,7 +954,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_defaultness(item.span, *defaultness); let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)); - if body.is_none() && !is_intrinsic { + if body.is_none() && !is_intrinsic && !self.is_sdylib_interface { self.dcx().emit_err(errors::FnWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), @@ -1128,6 +1134,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } _ => visit::walk_item(self, item), } + + self.lint_node_id = previous_lint_node_id; } fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { @@ -1435,7 +1443,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); } AssocItemKind::Fn(box Fn { body, .. }) => { - if body.is_none() { + if body.is_none() && !self.is_sdylib_interface { self.dcx().emit_err(errors::AssocFnWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), @@ -1683,6 +1691,7 @@ pub fn check_crate( sess: &Session, features: &Features, krate: &Crate, + is_sdylib_interface: bool, lints: &mut LintBuffer, ) -> bool { let mut validator = AstValidator { @@ -1694,6 +1703,8 @@ pub fn check_crate( outer_impl_trait_span: None, disallow_tilde_const: Some(TildeConstReason::Item), extern_mod_safety: None, + lint_node_id: CRATE_NODE_ID, + is_sdylib_interface, lint_buffer: lints, }; visit::walk_crate(&mut validator, krate); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index e312f15f05b0..915613a39137 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -514,6 +514,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(contracts_internals, "contract internal machinery is for internal use only"); gate_all!(where_clause_attrs, "attributes in `where` clause are unstable"); gate_all!(super_let, "`super let` is experimental"); + gate_all!(frontmatter, "frontmatters are experimental"); if !visitor.features.never_patterns() { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs index 142c80b8e39e..8a0dbadf18cd 100644 --- a/compiler/rustc_ast_pretty/src/pp.rs +++ b/compiler/rustc_ast_pretty/src/pp.rs @@ -244,9 +244,6 @@ struct BufEntry { // forgotten will trigger a panic in `drop`. (Closing a box more than once // isn't possible because `BoxMarker` doesn't implement `Copy` or `Clone`.) // -// FIXME(nnethercote): the panic in `drop` is currently disabled because a few -// places fail to close their boxes. It can be enabled once they are fixed. -// // Note: it would be better to make open/close mismatching impossible and avoid // the need for this marker type altogether by having functions like // `with_ibox` that open a box, call a closure, and then close the box. That @@ -261,8 +258,7 @@ impl !Copy for BoxMarker {} impl Drop for BoxMarker { fn drop(&mut self) { - // FIXME(nnethercote): enable once the bad cases are fixed - //panic!("BoxMarker not ended with `Printer::end()`"); + panic!("BoxMarker not ended with `Printer::end()`"); } } diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs index 551506f2aef8..a05e2bd6a5d7 100644 --- a/compiler/rustc_ast_pretty/src/pprust/mod.rs +++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs @@ -7,7 +7,9 @@ use std::borrow::Cow; use rustc_ast as ast; use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; -pub use state::{AnnNode, Comments, PpAnn, PrintState, State, print_crate}; +pub use state::{ + AnnNode, Comments, PpAnn, PrintState, State, print_crate, print_crate_as_interface, +}; /// Print the token kind precisely, without converting `$crate` into its respective crate name. pub fn token_kind_to_string(tok: &TokenKind) -> Cow<'static, str> { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 28d5eb87c27c..0990c9b27eb0 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -221,6 +221,7 @@ pub struct State<'a> { pub s: pp::Printer, comments: Option>, ann: &'a (dyn PpAnn + 'a), + is_sdylib_interface: bool, } const INDENT_UNIT: isize = 4; @@ -237,9 +238,36 @@ pub fn print_crate<'a>( edition: Edition, g: &AttrIdGenerator, ) -> String { - let mut s = - State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann }; + let mut s = State { + s: pp::Printer::new(), + comments: Some(Comments::new(sm, filename, input)), + ann, + is_sdylib_interface: false, + }; + print_crate_inner(&mut s, krate, is_expanded, edition, g); + s.s.eof() +} + +pub fn print_crate_as_interface( + krate: &ast::Crate, + edition: Edition, + g: &AttrIdGenerator, +) -> String { + let mut s = + State { s: pp::Printer::new(), comments: None, ann: &NoAnn, is_sdylib_interface: true }; + + print_crate_inner(&mut s, krate, false, edition, g); + s.s.eof() +} + +fn print_crate_inner<'a>( + s: &mut State<'a>, + krate: &ast::Crate, + is_expanded: bool, + edition: Edition, + g: &AttrIdGenerator, +) { // We need to print shebang before anything else // otherwise the resulting code will not compile // and shebang will be useless. @@ -282,8 +310,7 @@ pub fn print_crate<'a>( s.print_item(item); } s.print_remaining_comments(); - s.ann.post(&mut s, AnnNode::Crate(krate)); - s.s.eof() + s.ann.post(s, AnnNode::Crate(krate)); } /// Should two consecutive tokens be printed with a space between them? @@ -1111,7 +1138,7 @@ impl<'a> PrintState<'a> for State<'a> { impl<'a> State<'a> { pub fn new() -> State<'a> { - State { s: pp::Printer::new(), comments: None, ann: &NoAnn } + State { s: pp::Printer::new(), comments: None, ann: &NoAnn, is_sdylib_interface: false } } fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G) diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 38cadc77b777..c9a7e2aebd01 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -13,7 +13,7 @@ use rustc_ast::{ use crate::pp::Breaks::Inconsistent; use crate::pprust::state::fixup::FixupContext; -use crate::pprust::state::{AnnNode, BoxMarker, INDENT_UNIT, PrintState, State}; +use crate::pprust::state::{AnnNode, INDENT_UNIT, PrintState, State}; impl<'a> State<'a> { fn print_else(&mut self, els: Option<&ast::Expr>) { @@ -485,12 +485,12 @@ impl<'a> State<'a> { self.print_block_with_attrs(body, attrs, cb, ib); } ast::ExprKind::Loop(blk, opt_label, _) => { + let cb = self.cbox(0); + let ib = self.ibox(0); if let Some(label) = opt_label { self.print_ident(label.ident); self.word_space(":"); } - let cb = self.cbox(0); - let ib = self.ibox(0); self.word_nbsp("loop"); self.print_block_with_attrs(blk, attrs, cb, ib); } @@ -542,15 +542,6 @@ impl<'a> State<'a> { self.print_fn_params_and_ret(fn_decl, true); self.space(); self.print_expr(body, FixupContext::default()); - // FIXME(nnethercote): Bogus. Reduce visibility of `ended` once it's fixed. - let fake_ib = BoxMarker; - self.end(fake_ib); - - // A box will be closed by print_expr, but we didn't want an overall - // wrapper so we closed the corresponding opening. so create an - // empty box to satisfy the close. - // FIXME(nnethercote): Bogus. - let _ib = self.ibox(0); } ast::ExprKind::Block(blk, opt_label) => { if let Some(label) = opt_label { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 1e02ac8fd5d1..70cf2f2a4598 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -160,6 +160,10 @@ impl<'a> State<'a> { /// Pretty-prints an item. pub(crate) fn print_item(&mut self, item: &ast::Item) { + if self.is_sdylib_interface && item.span.is_dummy() { + // Do not print prelude for interface files. + return; + } self.hardbreak_if_not_bol(); self.maybe_print_comment(item.span.lo()); self.print_outer_attributes(&item.attrs); @@ -682,6 +686,13 @@ impl<'a> State<'a> { self.print_contract(contract); } if let Some((body, (cb, ib))) = body_cb_ib { + if self.is_sdylib_interface { + self.word(";"); + self.end(ib); // end inner head-block + self.end(cb); // end outer head-block + return; + } + self.nbsp(); self.print_block_with_attrs(body, attrs, cb, ib); } else { diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index d37ede86cfd2..c1d95d07f4c6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -53,7 +53,7 @@ fn parse_unstable<'a>( for param in list.mixed() { let param_span = param.span(); - if let Some(ident) = param.meta_item().and_then(|i| i.word_without_args()) { + if let Some(ident) = param.meta_item().and_then(|i| i.path_without_args().word()) { res.push(ident.name); } else { cx.emit_err(session_diagnostics::ExpectsFeatures { diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 7d1417446b21..fb3d5f57d4fa 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -1,5 +1,4 @@ use rustc_attr_data_structures::{AttributeKind, DeprecatedSince, Deprecation}; -use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol, sym}; use super::SingleAttributeParser; @@ -13,16 +12,13 @@ pub(crate) struct DeprecationParser; fn get( cx: &AcceptContext<'_>, - ident: Ident, + name: Symbol, param_span: Span, arg: &ArgParser<'_>, item: &Option, ) -> Option { if item.is_some() { - cx.emit_err(session_diagnostics::MultipleItem { - span: param_span, - item: ident.to_string(), - }); + cx.emit_err(session_diagnostics::MultipleItem { span: param_span, item: name.to_string() }); return None; } if let Some(v) = arg.name_value() { @@ -83,16 +79,16 @@ impl SingleAttributeParser for DeprecationParser { return None; }; - let (ident, arg) = param.word_or_empty(); + let ident_name = param.path_without_args().word_sym(); - match ident.name { - sym::since => { - since = Some(get(cx, ident, param_span, arg, &since)?); + match ident_name { + Some(name @ sym::since) => { + since = Some(get(cx, name, param_span, param.args(), &since)?); } - sym::note => { - note = Some(get(cx, ident, param_span, arg, ¬e)?); + Some(name @ sym::note) => { + note = Some(get(cx, name, param_span, param.args(), ¬e)?); } - sym::suggestion => { + Some(name @ sym::suggestion) => { if !features.deprecated_suggestion() { cx.emit_err(session_diagnostics::DeprecatedItemSuggestion { span: param_span, @@ -101,12 +97,12 @@ impl SingleAttributeParser for DeprecationParser { }); } - suggestion = Some(get(cx, ident, param_span, arg, &suggestion)?); + suggestion = Some(get(cx, name, param_span, param.args(), &suggestion)?); } _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param_span, - item: ident.to_string(), + item: param.path_without_args().to_string(), expected: if features.deprecated_suggestion() { &["since", "note", "suggestion"] } else { diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 26ca637faec6..43dfb85a7c41 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -96,58 +96,75 @@ fn parse_repr(cx: &AcceptContext<'_>, param: &MetaItemParser<'_>) -> Option { - cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident.span }); + let args = param.args(); + + match (name, args) { + (Some(sym::align), ArgParser::NoArgs) => { + cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident_span }); None } - (sym::align, ArgParser::List(l)) => parse_repr_align(cx, l, param.span(), AlignKind::Align), + (Some(sym::align), ArgParser::List(l)) => { + parse_repr_align(cx, l, param.span(), AlignKind::Align) + } - (sym::packed, ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)), - (sym::packed, ArgParser::List(l)) => { + (Some(sym::packed), ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)), + (Some(sym::packed), ArgParser::List(l)) => { parse_repr_align(cx, l, param.span(), AlignKind::Packed) } - (sym::align | sym::packed, ArgParser::NameValue(l)) => { + (Some(name @ sym::align | name @ sym::packed), ArgParser::NameValue(l)) => { cx.emit_err(session_diagnostics::IncorrectReprFormatGeneric { span: param.span(), // FIXME(jdonszelmann) can just be a string in the diag type - repr_arg: &ident.to_string(), + repr_arg: name, cause: IncorrectReprFormatGenericCause::from_lit_kind( param.span(), &l.value_as_lit().kind, - ident.name.as_str(), + name, ), }); None } - (sym::Rust, ArgParser::NoArgs) => Some(ReprRust), - (sym::C, ArgParser::NoArgs) => Some(ReprC), - (sym::simd, ArgParser::NoArgs) => Some(ReprSimd), - (sym::transparent, ArgParser::NoArgs) => Some(ReprTransparent), - (i @ int_pat!(), ArgParser::NoArgs) => { + (Some(sym::Rust), ArgParser::NoArgs) => Some(ReprRust), + (Some(sym::C), ArgParser::NoArgs) => Some(ReprC), + (Some(sym::simd), ArgParser::NoArgs) => Some(ReprSimd), + (Some(sym::transparent), ArgParser::NoArgs) => Some(ReprTransparent), + (Some(name @ int_pat!()), ArgParser::NoArgs) => { // int_pat!() should make sure it always parses - Some(ReprInt(int_type_of_word(i).unwrap())) + Some(ReprInt(int_type_of_word(name).unwrap())) } ( - sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), + Some( + name @ sym::Rust + | name @ sym::C + | name @ sym::simd + | name @ sym::transparent + | name @ int_pat!(), + ), ArgParser::NameValue(_), ) => { - cx.emit_err(session_diagnostics::InvalidReprHintNoValue { - span: param.span(), - name: ident.to_string(), - }); + cx.emit_err(session_diagnostics::InvalidReprHintNoValue { span: param.span(), name }); None } - (sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), ArgParser::List(_)) => { - cx.emit_err(session_diagnostics::InvalidReprHintNoParen { - span: param.span(), - name: ident.to_string(), - }); + ( + Some( + name @ sym::Rust + | name @ sym::C + | name @ sym::simd + | name @ sym::transparent + | name @ int_pat!(), + ), + ArgParser::List(_), + ) => { + cx.emit_err(session_diagnostics::InvalidReprHintNoParen { span: param.span(), name }); None } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index bdad6b50186d..cd1f21d92e7e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -242,9 +242,9 @@ pub(crate) fn parse_stability( return None; }; - match param.word_or_empty_without_args().name { - sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, - sym::since => insert_value_into_option_or_error(cx, ¶m, &mut since)?, + match param.path_without_args().word_sym() { + Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, + Some(sym::since) => insert_value_into_option_or_error(cx, ¶m, &mut since)?, _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param_span, @@ -310,11 +310,10 @@ pub(crate) fn parse_unstability( return None; }; - let (word, args) = param.word_or_empty(); - match word.name { - sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, - sym::reason => insert_value_into_option_or_error(cx, ¶m, &mut reason)?, - sym::issue => { + match param.path_without_args().word_sym() { + Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, + Some(sym::reason) => insert_value_into_option_or_error(cx, ¶m, &mut reason)?, + Some(sym::issue) => { insert_value_into_option_or_error(cx, ¶m, &mut issue)?; // These unwraps are safe because `insert_value_into_option_or_error` ensures the meta item @@ -328,7 +327,7 @@ pub(crate) fn parse_unstability( session_diagnostics::InvalidIssueString { span: param.span(), cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind( - args.name_value().unwrap().value_span, + param.args().name_value().unwrap().value_span, err.kind(), ), }, @@ -338,13 +337,15 @@ pub(crate) fn parse_unstability( }, }; } - sym::soft => { - if !args.no_args() { + Some(sym::soft) => { + if !param.args().no_args() { cx.emit_err(session_diagnostics::SoftNoArgs { span: param.span() }); } is_soft = true; } - sym::implied_by => insert_value_into_option_or_error(cx, ¶m, &mut implied_by)?, + Some(sym::implied_by) => { + insert_value_into_option_or_error(cx, ¶m, &mut implied_by)? + } _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param.span(), diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 40aa39711d3e..077d953cfa31 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -78,8 +78,8 @@ impl<'a> PathParser<'a> { (self.len() == 1).then(|| **self.segments().next().as_ref().unwrap()) } - pub fn word_or_empty(&self) -> Ident { - self.word().unwrap_or_else(Ident::empty) + pub fn word_sym(&self) -> Option { + self.word().map(|ident| ident.name) } /// Asserts that this MetaItem is some specific word. @@ -284,11 +284,6 @@ impl<'a> MetaItemParser<'a> { Some(self.word()?.0) } - /// Like [`word`](Self::word), but returns an empty symbol instead of None - pub fn word_or_empty_without_args(&self) -> Ident { - self.word_or_empty().0 - } - /// Asserts that this MetaItem starts with a word, or single segment path. /// /// Some examples: @@ -300,12 +295,6 @@ impl<'a> MetaItemParser<'a> { Some((path.word()?, args)) } - /// Like [`word`](Self::word), but returns an empty symbol instead of None - pub fn word_or_empty(&self) -> (Ident, &ArgParser<'a>) { - let (path, args) = self.deconstruct(); - (path.word().unwrap_or(Ident::empty()), args) - } - /// Asserts that this MetaItem starts with some specific word. /// /// See [`word`](Self::word) for examples of what a word is. diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 9d34b807ac2f..2c434175b4b6 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -204,7 +204,7 @@ pub(crate) struct InvalidReprHintNoParen { #[primary_span] pub span: Span, - pub name: String, + pub name: Symbol, } #[derive(Diagnostic)] @@ -213,7 +213,7 @@ pub(crate) struct InvalidReprHintNoValue { #[primary_span] pub span: Span, - pub name: String, + pub name: Symbol, } /// Error code: E0565 @@ -295,21 +295,21 @@ pub(crate) struct IncorrectReprFormatExpectInteger { #[derive(Diagnostic)] #[diag(attr_parsing_incorrect_repr_format_generic, code = E0693)] -pub(crate) struct IncorrectReprFormatGeneric<'a> { +pub(crate) struct IncorrectReprFormatGeneric { #[primary_span] pub span: Span, - pub repr_arg: &'a str, + pub repr_arg: Symbol, #[subdiagnostic] - pub cause: Option>, + pub cause: Option, } #[derive(Subdiagnostic)] -pub(crate) enum IncorrectReprFormatGenericCause<'a> { +pub(crate) enum IncorrectReprFormatGenericCause { #[suggestion( attr_parsing_suggestion, - code = "{name}({int})", + code = "{name}({value})", applicability = "machine-applicable" )] Int { @@ -317,15 +317,15 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> { span: Span, #[skip_arg] - name: &'a str, + name: Symbol, #[skip_arg] - int: u128, + value: u128, }, #[suggestion( attr_parsing_suggestion, - code = "{name}({symbol})", + code = "{name}({value})", applicability = "machine-applicable" )] Symbol { @@ -333,20 +333,20 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> { span: Span, #[skip_arg] - name: &'a str, + name: Symbol, #[skip_arg] - symbol: Symbol, + value: Symbol, }, } -impl<'a> IncorrectReprFormatGenericCause<'a> { - pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option { - match kind { - ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { - Some(Self::Int { span, name, int: int.get() }) +impl IncorrectReprFormatGenericCause { + pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: Symbol) -> Option { + match *kind { + ast::LitKind::Int(value, ast::LitIntType::Unsuffixed) => { + Some(Self::Int { span, name, value: value.get() }) } - ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }), + ast::LitKind::Str(value, _) => Some(Self::Symbol { span, name, value }), _ => None, } } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 0f8acadb978c..3b7d31b1b13b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2954,12 +2954,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } - let name = if borrow_span.in_external_macro(self.infcx.tcx.sess.source_map()) { - // Don't name local variables in external macros. - "value".to_string() - } else { - format!("`{name}`") - }; + let name = format!("`{name}`"); let mut err = self.path_does_not_live_long_enough(borrow_span, &name); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index f9f63ae92a84..5e3f3ffa2ea8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -317,6 +317,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { opt: DescribePlaceOpt, ) -> Option { let local = place.local; + if self.body.local_decls[local] + .source_info + .span + .in_external_macro(self.infcx.tcx.sess.source_map()) + { + return None; + } + let mut autoderef_index = None; let mut buf = String::new(); let mut ok = self.append_local_to_string(local, &mut buf); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 44af1b765399..3e075d420a3a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -47,7 +47,7 @@ use rustc_mir_dataflow::impls::{ use rustc_mir_dataflow::move_paths::{ InitIndex, InitLocation, LookupResult, MoveData, MovePathIndex, }; -use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results}; +use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor, visit_results}; use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT}; use rustc_span::{ErrorGuaranteed, Span, Symbol}; use smallvec::SmallVec; @@ -127,6 +127,14 @@ fn mir_borrowck( Ok(tcx.arena.alloc(opaque_types)) } else { let mut root_cx = BorrowCheckRootCtxt::new(tcx, def); + // We need to manually borrowck all nested bodies from the HIR as + // we do not generate MIR for dead code. Not doing so causes us to + // never check closures in dead code. + let nested_bodies = tcx.nested_bodies_within(def); + for def_id in nested_bodies { + root_cx.get_or_insert_nested(def_id); + } + let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } = do_mir_borrowck(&mut root_cx, def, None).0; debug_assert!(closure_requirements.is_none()); @@ -461,11 +469,13 @@ fn do_mir_borrowck<'tcx>( // Compute and report region errors, if any. mbcx.report_region_errors(nll_errors); - let mut flow_results = get_flow_results(tcx, body, &move_data, &borrow_set, ®ioncx); + let (mut flow_analysis, flow_entry_states) = + get_flow_results(tcx, body, &move_data, &borrow_set, ®ioncx); visit_results( body, traversal::reverse_postorder(body).map(|(bb, _)| bb), - &mut flow_results, + &mut flow_analysis, + &flow_entry_states, &mut mbcx, ); @@ -525,7 +535,7 @@ fn get_flow_results<'a, 'tcx>( move_data: &'a MoveData<'tcx>, borrow_set: &'a BorrowSet<'tcx>, regioncx: &RegionInferenceContext<'tcx>, -) -> Results<'tcx, Borrowck<'a, 'tcx>> { +) -> (Borrowck<'a, 'tcx>, Results) { // We compute these three analyses individually, but them combine them into // a single results so that `mbcx` can visit them all together. let borrows = Borrows::new(tcx, body, regioncx, borrow_set).iterate_to_fixpoint( @@ -550,14 +560,14 @@ fn get_flow_results<'a, 'tcx>( ever_inits: ever_inits.analysis, }; - assert_eq!(borrows.entry_states.len(), uninits.entry_states.len()); - assert_eq!(borrows.entry_states.len(), ever_inits.entry_states.len()); - let entry_states: EntryStates<'_, Borrowck<'_, '_>> = - itertools::izip!(borrows.entry_states, uninits.entry_states, ever_inits.entry_states) + assert_eq!(borrows.results.len(), uninits.results.len()); + assert_eq!(borrows.results.len(), ever_inits.results.len()); + let results: Results<_> = + itertools::izip!(borrows.results, uninits.results, ever_inits.results) .map(|(borrows, uninits, ever_inits)| BorrowckDomain { borrows, uninits, ever_inits }) .collect(); - Results { analysis, entry_states } + (analysis, results) } pub(crate) struct BorrowckInferCtxt<'tcx> { @@ -705,7 +715,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> { fn visit_after_early_statement_effect( &mut self, - _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, + _analysis: &mut Borrowck<'a, 'tcx>, state: &BorrowckDomain, stmt: &Statement<'tcx>, location: Location, @@ -781,7 +791,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, fn visit_after_early_terminator_effect( &mut self, - _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, + _analysis: &mut Borrowck<'a, 'tcx>, state: &BorrowckDomain, term: &Terminator<'tcx>, loc: Location, @@ -901,7 +911,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, fn visit_after_primary_terminator_effect( &mut self, - _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, + _analysis: &mut Borrowck<'a, 'tcx>, state: &BorrowckDomain, term: &Terminator<'tcx>, loc: Location, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 550c57338d30..25cbd579ea1c 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -267,13 +267,13 @@ impl<'tcx> InferCtxt<'tcx> { return Ty::new_error(self.tcx, e); } - if let Err(guar) = check_opaque_type_parameter_valid( + if let Err(err) = check_opaque_type_parameter_valid( self, opaque_type_key, instantiated_ty.span, DefiningScopeKind::MirBorrowck, ) { - return Ty::new_error(self.tcx, guar); + return Ty::new_error(self.tcx, err.report(self)); } let definition_ty = instantiated_ty diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs index b2ed8a358279..8e04791461b2 100644 --- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs +++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs @@ -7,6 +7,8 @@ use rustc_middle::ty::RegionVid; use crate::RegionInferenceContext; use crate::constraints::ConstraintSccIndex; +use crate::region_infer::ConstraintSccs; +use crate::universal_regions::UniversalRegions; pub(crate) struct ReverseSccGraph { graph: VecGraph, @@ -19,6 +21,29 @@ pub(crate) struct ReverseSccGraph { } impl ReverseSccGraph { + pub(super) fn compute( + constraint_sccs: &ConstraintSccs, + universal_regions: &UniversalRegions<'_>, + ) -> Self { + let graph = constraint_sccs.reverse(); + let mut paired_scc_regions = universal_regions + .universal_regions_iter() + .map(|region| (constraint_sccs.scc(region), region)) + .collect::>(); + paired_scc_regions.sort(); + let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect(); + + let mut scc_regions = FxIndexMap::default(); + let mut start = 0; + for chunk in paired_scc_regions.chunk_by(|&(scc1, _), &(scc2, _)| scc1 == scc2) { + let (scc, _) = chunk[0]; + + scc_regions.insert(scc, start..start + chunk.len()); + start += chunk.len(); + } + ReverseSccGraph { graph, scc_regions, universal_regions } + } + /// Find all universal regions that are required to outlive the given SCC. pub(super) fn upper_bounds(&self, scc0: ConstraintSccIndex) -> impl Iterator { let mut duplicates = FxIndexSet::default(); @@ -40,23 +65,7 @@ impl RegionInferenceContext<'_> { return; } - let graph = self.constraint_sccs.reverse(); - let mut paired_scc_regions = self - .universal_regions() - .universal_regions_iter() - .map(|region| (self.constraint_sccs.scc(region), region)) - .collect::>(); - paired_scc_regions.sort(); - let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect(); - - let mut scc_regions = FxIndexMap::default(); - let mut start = 0; - for chunk in paired_scc_regions.chunk_by(|&(scc1, _), &(scc2, _)| scc1 == scc2) { - let (scc, _) = chunk[0]; - scc_regions.insert(scc, start..start + chunk.len()); - start += chunk.len(); - } - - self.rev_scc_graph = Some(ReverseSccGraph { graph, scc_regions, universal_regions }); + self.rev_scc_graph = + Some(ReverseSccGraph::compute(&self.constraint_sccs, self.universal_regions())); } } diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs index 13daa5c72214..66b526fa02a5 100644 --- a/compiler/rustc_borrowck/src/root_cx.rs +++ b/compiler/rustc_borrowck/src/root_cx.rs @@ -62,7 +62,10 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> { self.tainted_by_errors = Some(guar); } - fn get_or_insert_nested(&mut self, def_id: LocalDefId) -> &PropagatedBorrowCheckResults<'tcx> { + pub(super) fn get_or_insert_nested( + &mut self, + def_id: LocalDefId, + ) -> &PropagatedBorrowCheckResults<'tcx> { debug_assert_eq!( self.tcx.typeck_root_def_id(def_id.to_def_id()), self.root_def_id.to_def_id() diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 536a27763d29..92732aba29ba 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -41,8 +41,8 @@ type NormalizedInputsAndOutput<'tcx> = Vec>; pub(crate) struct CreateResult<'tcx> { pub(crate) universal_region_relations: Frozen>, - pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>, - pub(crate) known_type_outlives_obligations: Vec>, + pub(crate) region_bound_pairs: Frozen>, + pub(crate) known_type_outlives_obligations: Frozen>>, pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, } @@ -333,8 +333,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { outlives: self.outlives.freeze(), inverse_outlives: self.inverse_outlives.freeze(), }), - known_type_outlives_obligations, - region_bound_pairs: self.region_bound_pairs, + known_type_outlives_obligations: Frozen::freeze(known_type_outlives_obligations), + region_bound_pairs: Frozen::freeze(self.region_bound_pairs), normalized_inputs_and_output, } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 99a544279b96..8c5122571209 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -151,8 +151,8 @@ pub(crate) fn type_check<'a, 'tcx>( body, promoted, user_type_annotations: &body.user_type_annotations, - region_bound_pairs, - known_type_outlives_obligations, + region_bound_pairs: ®ion_bound_pairs, + known_type_outlives_obligations: &known_type_outlives_obligations, reported_errors: Default::default(), universal_regions: &universal_region_relations.universal_regions, location_table, @@ -216,8 +216,8 @@ struct TypeChecker<'a, 'tcx> { /// User type annotations are shared between the main MIR and the MIR of /// all of the promoted items. user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>, - region_bound_pairs: RegionBoundPairs<'tcx>, - known_type_outlives_obligations: Vec>, + region_bound_pairs: &'a RegionBoundPairs<'tcx>, + known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>], reported_errors: FxIndexSet<(Ty<'tcx>, Span)>, universal_regions: &'a UniversalRegions<'tcx>, location_table: &'a PoloniusLocationTable, @@ -412,9 +412,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { constraint_conversion::ConstraintConversion::new( self.infcx, self.universal_regions, - &self.region_bound_pairs, + self.region_bound_pairs, self.infcx.param_env, - &self.known_type_outlives_obligations, + self.known_type_outlives_obligations, locations, locations.span(self.body), category, @@ -2506,9 +2506,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { constraint_conversion::ConstraintConversion::new( self.infcx, self.universal_regions, - &self.region_bound_pairs, + self.region_bound_pairs, self.infcx.param_env, - &self.known_type_outlives_obligations, + self.known_type_outlives_obligations, locations, self.body.span, // irrelevant; will be overridden. ConstraintCategory::Boring, // same as above. diff --git a/compiler/rustc_borrowck/src/type_check/opaque_types.rs b/compiler/rustc_borrowck/src/type_check/opaque_types.rs index d41cbf757d7f..341c50c37f6d 100644 --- a/compiler/rustc_borrowck/src/type_check/opaque_types.rs +++ b/compiler/rustc_borrowck/src/type_check/opaque_types.rs @@ -266,10 +266,6 @@ impl<'tcx, OP> TypeVisitor> for ConstrainOpaqueTypeRegionVisitor<'t where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { - t.super_visit_with(self); - } - fn visit_region(&mut self, r: ty::Region<'tcx>) { match r.kind() { // ignore bound regions, keep visiting diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 12654001a1e2..39f9d5f90051 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -1,3 +1,5 @@ +use std::ops::Range; + use parse::Position::ArgumentNamed; use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; @@ -335,7 +337,7 @@ fn make_format_args( return ExpandResult::Ready(Err(guar)); } - let to_span = |inner_span: parse::InnerSpan| { + let to_span = |inner_span: Range| { is_source_literal.then(|| { fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end }) }) @@ -407,7 +409,7 @@ fn make_format_args( let mut placeholder_index = 0; for piece in &pieces { - match *piece { + match piece.clone() { parse::Piece::Lit(s) => { unfinished_literal.push_str(s); } @@ -417,7 +419,8 @@ fn make_format_args( unfinished_literal.clear(); } - let span = parser.arg_places.get(placeholder_index).and_then(|&s| to_span(s)); + let span = + parser.arg_places.get(placeholder_index).and_then(|s| to_span(s.clone())); placeholder_index += 1; let position_span = to_span(position_span); @@ -609,7 +612,7 @@ fn make_format_args( fn invalid_placeholder_type_error( ecx: &ExtCtxt<'_>, ty: &str, - ty_span: Option, + ty_span: Option>, fmt_span: Span, ) { let sp = ty_span.map(|sp| fmt_span.from_inner(InnerSpan::new(sp.start, sp.end))); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index d3f47ad72633..e866b8962551 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1282,7 +1282,7 @@ fn codegen_regular_intrinsic_call<'tcx>( intrinsic.name, ); } - return Err(Instance::new(instance.def_id(), instance.args)); + return Err(Instance::new_raw(instance.def_id(), instance.args)); } } diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs index e5221c7da319..faeb2643ecb8 100644 --- a/compiler/rustc_codegen_gcc/src/back/lto.rs +++ b/compiler/rustc_codegen_gcc/src/back/lto.rs @@ -44,7 +44,11 @@ use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level}; pub fn crate_type_allows_lto(crate_type: CrateType) -> bool { match crate_type { - CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true, + CrateType::Executable + | CrateType::Dylib + | CrateType::Staticlib + | CrateType::Cdylib + | CrateType::Sdylib => true, CrateType::Rlib | CrateType::ProcMacro => false, } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index d22f4229e237..2ed5ec4381ed 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -399,7 +399,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } // Fall back to default body - _ => return Err(Instance::new(instance.def_id(), instance.args)), + _ => return Err(Instance::new_raw(instance.def_id(), instance.args)), }; if !fn_abi.ret.is_ignore() { diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 39b3a23e0b1b..cb329323f5d7 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -42,7 +42,8 @@ fn crate_type_allows_lto(crate_type: CrateType) -> bool { | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib - | CrateType::ProcMacro => true, + | CrateType::ProcMacro + | CrateType::Sdylib => true, CrateType::Rlib => false, } } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index bf81eb648f8a..cbac55c71531 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -364,7 +364,12 @@ impl<'ll> CodegenCx<'ll, '_> { if !def_id.is_local() { let needs_dll_storage_attr = self.use_dll_storage_attrs - && !self.tcx.is_foreign_item(def_id) + // If the symbol is a foreign item, then don't automatically apply DLLImport, as + // we'll rely on the #[link] attribute instead. BUT, if this is an internal symbol + // then it may be generated by the compiler in some crate, so we do need to apply + // DLLImport when linking with the MSVC linker. + && (!self.tcx.is_foreign_item(def_id) + || (self.sess().target.is_like_msvc && fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL))) // Local definitions can never be imported, so we must not apply // the DLLImport annotation. && !dso_local diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs index 68f60f169b5b..fe3a7a1580b5 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs @@ -157,7 +157,7 @@ fn make_dummy_instance<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> ty: let def_id = local_def_id.to_def_id(); // Make a dummy instance that fills in all generics with placeholders. - ty::Instance::new( + ty::Instance::new_raw( def_id, ty::GenericArgs::for_item(tcx, def_id, |param, _| { if let ty::GenericParamDefKind::Lifetime = param.kind { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 4ffe551df09b..8f0948b8183b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -95,7 +95,11 @@ pub(crate) fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { // in the `.debug_gdb_scripts` section. For that reason, we make sure that the // section is only emitted for leaf crates. let embed_visualizers = cx.tcx.crate_types().iter().any(|&crate_type| match crate_type { - CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::Staticlib => { + CrateType::Executable + | CrateType::Dylib + | CrateType::Cdylib + | CrateType::Staticlib + | CrateType::Sdylib => { // These are crate types for which we will embed pretty printers since they // are treated as leaf crates. true diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index ffeab59b05c3..bfaad8f2f1ef 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -613,7 +613,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { _ => { debug!("unknown intrinsic '{}' -- falling back to default body", name); // Call the fallback body instead of generating the intrinsic code - return Err(ty::Instance::new(instance.def_id(), instance.args)); + return Err(ty::Instance::new_raw(instance.def_id(), instance.args)); } }; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 507cbf20d89e..8f57f0983abb 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -19,6 +19,7 @@ use rustc_session::config::{PrintKind, PrintRequest}; use rustc_span::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport}; use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES}; +use smallvec::{SmallVec, smallvec}; use crate::back::write::create_informational_target_machine; use crate::errors::{ @@ -180,27 +181,27 @@ impl<'a> TargetFeatureFoldStrength<'a> { pub(crate) struct LLVMFeature<'a> { llvm_feature_name: &'a str, - dependency: Option>, + dependencies: SmallVec<[TargetFeatureFoldStrength<'a>; 1]>, } impl<'a> LLVMFeature<'a> { fn new(llvm_feature_name: &'a str) -> Self { - Self { llvm_feature_name, dependency: None } + Self { llvm_feature_name, dependencies: SmallVec::new() } } - fn with_dependency( + fn with_dependencies( llvm_feature_name: &'a str, - dependency: TargetFeatureFoldStrength<'a>, + dependencies: SmallVec<[TargetFeatureFoldStrength<'a>; 1]>, ) -> Self { - Self { llvm_feature_name, dependency: Some(dependency) } + Self { llvm_feature_name, dependencies } } - fn contains(&self, feat: &str) -> bool { + fn contains(&'a self, feat: &str) -> bool { self.iter().any(|dep| dep == feat) } fn iter(&'a self) -> impl Iterator { - let dependencies = self.dependency.iter().map(|feat| feat.as_str()); + let dependencies = self.dependencies.iter().map(|feat| feat.as_str()); std::iter::once(self.llvm_feature_name).chain(dependencies) } } @@ -210,7 +211,7 @@ impl<'a> IntoIterator for LLVMFeature<'a> { type IntoIter = impl Iterator; fn into_iter(self) -> Self::IntoIter { - let dependencies = self.dependency.into_iter().map(|feat| feat.as_str()); + let dependencies = self.dependencies.into_iter().map(|feat| feat.as_str()); std::iter::once(self.llvm_feature_name).chain(dependencies) } } @@ -240,9 +241,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::with_dependency( + ("x86", "sse4.2") => Some(LLVMFeature::with_dependencies( "sse4.2", - TargetFeatureFoldStrength::EnableOnly("crc32"), + smallvec![TargetFeatureFoldStrength::EnableOnly("crc32")], )), ("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")), ("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")), @@ -262,9 +263,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::new("b16b16")), ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")), // Rust ties fp and neon together. - ("aarch64", "neon") => { - Some(LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8"))) - } + ("aarch64", "neon") => Some(LLVMFeature::with_dependencies( + "neon", + smallvec![TargetFeatureFoldStrength::Both("fp-armv8")], + )), // In LLVM neon implicitly enables fp, but we manually enable // neon when a feature only implicitly enables fp ("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")), @@ -281,9 +283,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option None, // Enable the evex512 target feature if an avx512 target feature is enabled. - ("x86", s) if s.starts_with("avx512") => { - Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512"))) - } + ("x86", s) if s.starts_with("avx512") => Some(LLVMFeature::with_dependencies( + s, + smallvec![TargetFeatureFoldStrength::EnableOnly("evex512")], + )), // Support for `wide-arithmetic` will first land in LLVM 20 as part of // llvm/llvm-project#111598 ("wasm32" | "wasm64", "wide-arithmetic") if get_version() < (20, 0, 0) => None, @@ -301,6 +304,21 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option None, + ("x86", "avx10.1") => Some(LLVMFeature::new("avx10.1-512")), + ("x86", "avx10.2") if get_version().0 < 20 => None, + ("x86", "avx10.2") if get_version().0 >= 20 => Some(LLVMFeature::new("avx10.2-512")), + ("x86", "apxf") => Some(LLVMFeature::with_dependencies( + "egpr", + smallvec![ + TargetFeatureFoldStrength::Both("push2pop2"), + TargetFeatureFoldStrength::Both("ppx"), + TargetFeatureFoldStrength::Both("ndd"), + TargetFeatureFoldStrength::Both("ccmp"), + TargetFeatureFoldStrength::Both("cf"), + TargetFeatureFoldStrength::Both("nf"), + TargetFeatureFoldStrength::Both("zu"), + ], + )), (_, s) => Some(LLVMFeature::new(s)), } } @@ -850,7 +868,7 @@ pub(crate) fn global_llvm_features( "{}{}", enable_disable, llvm_feature.llvm_feature_name )) - .chain(llvm_feature.dependency.into_iter().filter_map( + .chain(llvm_feature.dependencies.into_iter().filter_map( move |feat| match (enable, feat) { (_, TargetFeatureFoldStrength::Both(f)) | (true, TargetFeatureFoldStrength::EnableOnly(f)) => { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 323538969d73..159c17b0af75 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1053,9 +1053,10 @@ fn link_natively( strip_with_external_utility(sess, stripcmd, out_filename, &["--strip-debug"]) } // Per the manpage, `-x` is the maximum safe strip level for dynamic libraries. (#93988) - (Strip::Symbols, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) => { - strip_with_external_utility(sess, stripcmd, out_filename, &["-x"]) - } + ( + Strip::Symbols, + CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro | CrateType::Sdylib, + ) => strip_with_external_utility(sess, stripcmd, out_filename, &["-x"]), (Strip::Symbols, _) => { strip_with_external_utility(sess, stripcmd, out_filename, &["--strip-all"]) } @@ -1243,8 +1244,10 @@ fn add_sanitizer_libraries( // which should be linked to both executables and dynamic libraries. // Everywhere else the runtimes are currently distributed as static // libraries which should be linked to executables only. - if matches!(crate_type, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) - && !(sess.target.is_like_darwin || sess.target.is_like_msvc) + if matches!( + crate_type, + CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro | CrateType::Sdylib + ) && !(sess.target.is_like_darwin || sess.target.is_like_msvc) { return; } @@ -1938,6 +1941,7 @@ fn add_late_link_args( codegen_results: &CodegenResults, ) { let any_dynamic_crate = crate_type == CrateType::Dylib + || crate_type == CrateType::Sdylib || codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| { *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic) }); diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index a09eec5dd74b..80ee8ea22288 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -337,7 +337,12 @@ pub(crate) trait Linker { fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]); fn no_crt_objects(&mut self); fn no_default_libraries(&mut self); - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]); + fn export_symbols( + &mut self, + tmpdir: &Path, + crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ); fn subsystem(&mut self, subsystem: &str); fn linker_plugin_lto(&mut self); fn add_eh_frame_header(&mut self) {} @@ -770,7 +775,12 @@ impl<'a> Linker for GccLinker<'a> { } } - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { // Symbol visibility in object files typically takes care of this. if crate_type == CrateType::Executable { let should_export_executable_symbols = @@ -799,7 +809,7 @@ impl<'a> Linker for GccLinker<'a> { // Write a plain, newline-separated list of symbols let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; - for sym in symbols { + for (sym, _) in symbols { debug!(" _{sym}"); writeln!(f, "_{sym}")?; } @@ -814,9 +824,12 @@ impl<'a> Linker for GccLinker<'a> { // .def file similar to MSVC one but without LIBRARY section // because LD doesn't like when it's empty writeln!(f, "EXPORTS")?; - for symbol in symbols { + for (symbol, kind) in symbols { + let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" }; debug!(" _{symbol}"); - writeln!(f, " {symbol}")?; + // Quote the name in case it's reserved by linker in some way + // (this accounts for names with dots in particular). + writeln!(f, " \"{symbol}\"{kind_marker}")?; } }; if let Err(error) = res { @@ -829,7 +842,7 @@ impl<'a> Linker for GccLinker<'a> { writeln!(f, "{{")?; if !symbols.is_empty() { writeln!(f, " global:")?; - for sym in symbols { + for (sym, _) in symbols { debug!(" {sym};"); writeln!(f, " {sym};")?; } @@ -1096,7 +1109,12 @@ impl<'a> Linker for MsvcLinker<'a> { // crates. Upstream rlibs may be linked statically to this dynamic library, // in which case they may continue to transitively be used and hence need // their symbols exported. - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { // Symbol visibility takes care of this typically if crate_type == CrateType::Executable { let should_export_executable_symbols = @@ -1114,9 +1132,10 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - for symbol in symbols { + for (symbol, kind) in symbols { + let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" }; debug!(" _{symbol}"); - writeln!(f, " {symbol}")?; + writeln!(f, " {symbol}{kind_marker}")?; } }; if let Err(error) = res { @@ -1257,14 +1276,19 @@ impl<'a> Linker for EmLinker<'a> { self.cc_arg("-nodefaultlibs"); } - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { debug!("EXPORTED SYMBOLS:"); self.cc_arg("-s"); let mut arg = OsString::from("EXPORTED_FUNCTIONS="); let encoded = serde_json::to_string( - &symbols.iter().map(|sym| "_".to_owned() + sym).collect::>(), + &symbols.iter().map(|(sym, _)| "_".to_owned() + sym).collect::>(), ) .unwrap(); debug!("{encoded}"); @@ -1426,8 +1450,13 @@ impl<'a> Linker for WasmLd<'a> { fn no_default_libraries(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { - for sym in symbols { + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { + for (sym, _) in symbols { self.link_args(&["--export", sym]); } @@ -1561,7 +1590,7 @@ impl<'a> Linker for L4Bender<'a> { self.cc_arg("-nostdlib"); } - fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) { + fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[(String, SymbolExportKind)]) { // ToDo, not implemented, copy from GCC self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented); } @@ -1718,12 +1747,17 @@ impl<'a> Linker for AixLinker<'a> { fn no_default_libraries(&mut self) {} - fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { let path = tmpdir.join("list.exp"); let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; // FIXME: use llvm-nm to generate export list. - for symbol in symbols { + for (symbol, _) in symbols { debug!(" _{symbol}"); writeln!(f, " {symbol}")?; } @@ -1767,9 +1801,12 @@ fn for_each_exported_symbols_include_dep<'tcx>( } } -pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec { +pub(crate) fn exported_symbols( + tcx: TyCtxt<'_>, + crate_type: CrateType, +) -> Vec<(String, SymbolExportKind)> { if let Some(ref exports) = tcx.sess.target.override_export_symbols { - return exports.iter().map(ToString::to_string).collect(); + return exports.iter().map(|name| (name.to_string(), SymbolExportKind::Text)).collect(); } if let CrateType::ProcMacro = crate_type { @@ -1779,7 +1816,10 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec, crate_type: CrateType) -> Vec { +fn exported_symbols_for_non_proc_macro( + tcx: TyCtxt<'_>, + crate_type: CrateType, +) -> Vec<(String, SymbolExportKind)> { let mut symbols = Vec::new(); let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| { @@ -1787,17 +1827,18 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) - // from any cdylib. The latter doesn't work anyway as we use hidden visibility for // compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning. if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) { - symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate( - tcx, symbol, cnum, + symbols.push(( + symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum), + info.kind, )); - symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum); + symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, info, cnum); } }); symbols } -fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec { +fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String, SymbolExportKind)> { // `exported_symbols` will be empty when !should_codegen. if !tcx.sess.opts.output_types.should_codegen() { return Vec::new(); @@ -1807,7 +1848,10 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec { let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx); - vec![proc_macro_decls_name, metadata_symbol_name] + vec![ + (proc_macro_decls_name, SymbolExportKind::Text), + (metadata_symbol_name, SymbolExportKind::Text), + ] } pub(crate) fn linked_symbols( @@ -1815,7 +1859,7 @@ pub(crate) fn linked_symbols( crate_type: CrateType, ) -> Vec<(String, SymbolExportKind)> { match crate_type { - CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => (), + CrateType::Executable | CrateType::Cdylib | CrateType::Dylib | CrateType::Sdylib => (), CrateType::Staticlib | CrateType::ProcMacro | CrateType::Rlib => { return Vec::new(); } @@ -1829,7 +1873,9 @@ pub(crate) fn linked_symbols( || info.used { symbols.push(( - symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum), + symbol_export::linking_symbol_name_for_instance_in_crate( + tcx, symbol, info.kind, cnum, + ), info.kind, )); } @@ -1904,7 +1950,13 @@ impl<'a> Linker for PtxLinker<'a> { fn ehcont_guard(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {} + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + _symbols: &[(String, SymbolExportKind)], + ) { + } fn subsystem(&mut self, _subsystem: &str) {} @@ -1973,10 +2025,15 @@ impl<'a> Linker for LlbcLinker<'a> { fn ehcont_guard(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { match _crate_type { CrateType::Cdylib => { - for sym in symbols { + for (sym, _) in symbols { self.link_args(&["--export-symbol", sym]); } } @@ -2050,11 +2107,16 @@ impl<'a> Linker for BpfLinker<'a> { fn ehcont_guard(&mut self) {} - fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { let path = tmpdir.join("symbols"); let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; - for sym in symbols { + for (sym, _) in symbols { writeln!(f, "{sym}")?; } }; diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index ebcccf1b97d9..ec46c71b0e40 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -270,45 +270,61 @@ pub(super) fn elf_os_abi(sess: &Session) -> u8 { pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 { match architecture { - Architecture::Mips => { - let arch = match sess.target.options.cpu.as_ref() { - "mips1" => elf::EF_MIPS_ARCH_1, - "mips2" => elf::EF_MIPS_ARCH_2, + Architecture::Mips | Architecture::Mips64 | Architecture::Mips64_N32 => { + // "N32" indicates an "ILP32" data model on a 64-bit MIPS CPU + // like SPARC's "v8+", x86_64's "x32", or the watchOS "arm64_32". + let is_32bit = architecture == Architecture::Mips; + let mut e_flags = match sess.target.options.cpu.as_ref() { + "mips1" if is_32bit => elf::EF_MIPS_ARCH_1, + "mips2" if is_32bit => elf::EF_MIPS_ARCH_2, "mips3" => elf::EF_MIPS_ARCH_3, "mips4" => elf::EF_MIPS_ARCH_4, "mips5" => elf::EF_MIPS_ARCH_5, - s if s.contains("r6") => elf::EF_MIPS_ARCH_32R6, - _ => elf::EF_MIPS_ARCH_32R2, + "mips32r2" if is_32bit => elf::EF_MIPS_ARCH_32R2, + "mips32r6" if is_32bit => elf::EF_MIPS_ARCH_32R6, + "mips64r2" if !is_32bit => elf::EF_MIPS_ARCH_64R2, + "mips64r6" if !is_32bit => elf::EF_MIPS_ARCH_64R6, + s if s.starts_with("mips32") && !is_32bit => { + sess.dcx().fatal(format!("invalid CPU `{}` for 64-bit MIPS target", s)) + } + s if s.starts_with("mips64") && is_32bit => { + sess.dcx().fatal(format!("invalid CPU `{}` for 32-bit MIPS target", s)) + } + _ if is_32bit => elf::EF_MIPS_ARCH_32R2, + _ => elf::EF_MIPS_ARCH_64R2, }; - let mut e_flags = elf::EF_MIPS_CPIC | arch; - - // If the ABI is explicitly given, use it or default to O32. - match sess.target.options.llvm_abiname.to_lowercase().as_str() { - "n32" => e_flags |= elf::EF_MIPS_ABI2, - "o32" => e_flags |= elf::EF_MIPS_ABI_O32, - _ => e_flags |= elf::EF_MIPS_ABI_O32, + // If the ABI is explicitly given, use it, or default to O32 on 32-bit MIPS, + // which is the only "true" 32-bit option that LLVM supports. + match sess.target.options.llvm_abiname.as_ref() { + "o32" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32, + "n32" if !is_32bit => e_flags |= elf::EF_MIPS_ABI2, + "n64" if !is_32bit => {} + "" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32, + "" => sess.dcx().fatal("LLVM ABI must be specifed for 64-bit MIPS targets"), + s if is_32bit => { + sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 32-bit MIPS target", s)) + } + s => sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 64-bit MIPS target", s)), }; if sess.target.options.relocation_model != RelocModel::Static { - e_flags |= elf::EF_MIPS_PIC; + // PIC means position-independent code. CPIC means "calls PIC". + // CPIC was mutually exclusive with PIC according to + // the SVR4 MIPS ABI https://refspecs.linuxfoundation.org/elf/mipsabi.pdf + // and should have only appeared on static objects with dynamically calls. + // At some point someone (GCC?) decided to set CPIC even for PIC. + // Nowadays various things expect both set on the same object file + // and may even error if you mix CPIC and non-CPIC object files, + // despite that being the entire point of the CPIC ABI extension! + // As we are in Rome, we do as the Romans do. + e_flags |= elf::EF_MIPS_PIC | elf::EF_MIPS_CPIC; } if sess.target.options.cpu.contains("r6") { e_flags |= elf::EF_MIPS_NAN2008; } e_flags } - Architecture::Mips64 => { - // copied from `mips64el-linux-gnuabi64-gcc foo.c -c` - let e_flags = elf::EF_MIPS_CPIC - | elf::EF_MIPS_PIC - | if sess.target.options.cpu.contains("r6") { - elf::EF_MIPS_ARCH_64R6 | elf::EF_MIPS_NAN2008 - } else { - elf::EF_MIPS_ARCH_64R2 - }; - e_flags - } Architecture::Riscv32 | Architecture::Riscv64 => { // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc let mut e_flags: u32 = 0x0; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 50fb08b28680..06ba5b4f6a75 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -29,7 +29,7 @@ fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel { CrateType::Executable | CrateType::Staticlib | CrateType::ProcMacro | CrateType::Cdylib => { SymbolExportLevel::C } - CrateType::Rlib | CrateType::Dylib => SymbolExportLevel::Rust, + CrateType::Rlib | CrateType::Dylib | CrateType::Sdylib => SymbolExportLevel::Rust, } } @@ -45,7 +45,7 @@ pub fn crates_export_threshold(crate_types: &[CrateType]) -> SymbolExportLevel { } fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap { - if !tcx.sess.opts.output_types.should_codegen() { + if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() { return Default::default(); } @@ -168,7 +168,7 @@ fn exported_symbols_provider_local<'tcx>( tcx: TyCtxt<'tcx>, _: LocalCrate, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { - if !tcx.sess.opts.output_types.should_codegen() { + if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() { return &[]; } @@ -612,7 +612,7 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>( ExportedSymbol::Generic(def_id, args) => { rustc_symbol_mangling::symbol_name_for_instance_in_crate( tcx, - Instance::new(def_id, args), + Instance::new_raw(def_id, args), instantiating_crate, ) } @@ -660,7 +660,7 @@ fn calling_convention_for_symbol<'tcx>( None } ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)), - ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)), + ExportedSymbol::Generic(def_id, args) => Some(Instance::new_raw(def_id, args)), // DropGlue always use the Rust calling convention and thus follow the target's default // symbol decoration scheme. ExportedSymbol::DropGlue(..) => None, @@ -692,6 +692,7 @@ fn calling_convention_for_symbol<'tcx>( pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, + export_kind: SymbolExportKind, instantiating_crate: CrateNum, ) -> String { let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); @@ -712,8 +713,9 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( let prefix = match &target.arch[..] { "x86" => Some('_'), "x86_64" => None, - "arm64ec" => Some('#'), - // Only x86/64 use symbol decorations. + // Only functions are decorated for arm64ec. + "arm64ec" if export_kind == SymbolExportKind::Text => Some('#'), + // Only x86/64 and arm64ec use symbol decorations. _ => return undecorated, }; @@ -753,9 +755,10 @@ pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>( /// Add it to the symbols list for all kernel functions, so that it is exported in the linked /// object. pub(crate) fn extend_exported_symbols<'tcx>( - symbols: &mut Vec, + symbols: &mut Vec<(String, SymbolExportKind)>, tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, + info: SymbolExportInfo, instantiating_crate: CrateNum, ) { let (conv, _) = calling_convention_for_symbol(tcx, symbol); @@ -767,7 +770,7 @@ pub(crate) fn extend_exported_symbols<'tcx>( let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); // Add the symbol for the kernel descriptor (with .kd suffix) - symbols.push(format!("{undecorated}.kd")); + symbols.push((format!("{undecorated}.kd"), info.kind)); } fn maybe_emutls_symbol_name<'tcx>( diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f5480da2808f..93cbd4cbb7cc 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -12,9 +12,9 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; use rustc_data_structures::unord::UnordMap; -use rustc_hir::ItemId; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; +use rustc_hir::{ItemId, Target}; use rustc_metadata::EncodedMetadata; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; @@ -457,7 +457,13 @@ where rustc_hir::InlineAsmOperand::SymFn { expr } => { let ty = cx.tcx().typeck(item_id.owner_id).expr_ty(expr); let instance = match ty.kind() { - &ty::FnDef(def_id, args) => Instance::new(def_id, args), + &ty::FnDef(def_id, args) => Instance::expect_resolve( + cx.tcx(), + ty::TypingEnv::fully_monomorphized(), + def_id, + args, + expr.span, + ), _ => span_bug!(*op_sp, "asm sym is not a function"), }; @@ -1032,21 +1038,35 @@ impl CrateInfo { // by the compiler, but that's ok because all this stuff is unstable anyway. let target = &tcx.sess.target; if !are_upstream_rust_objects_already_included(tcx.sess) { - let missing_weak_lang_items: FxIndexSet = info + let add_prefix = match (target.is_like_windows, target.arch.as_ref()) { + (true, "x86") => |name: String, _: SymbolExportKind| format!("_{name}"), + (true, "arm64ec") => { + // Only functions are decorated for arm64ec. + |name: String, export_kind: SymbolExportKind| match export_kind { + SymbolExportKind::Text => format!("#{name}"), + _ => name, + } + } + _ => |name: String, _: SymbolExportKind| name, + }; + let missing_weak_lang_items: FxIndexSet<(Symbol, SymbolExportKind)> = info .used_crates .iter() .flat_map(|&cnum| tcx.missing_lang_items(cnum)) .filter(|l| l.is_weak()) .filter_map(|&l| { let name = l.link_name()?; - lang_items::required(tcx, l).then_some(name) + let export_kind = match l.target() { + Target::Fn => SymbolExportKind::Text, + Target::Static => SymbolExportKind::Data, + _ => bug!( + "Don't know what the export kind is for lang item of kind {:?}", + l.target() + ), + }; + lang_items::required(tcx, l).then_some((name, export_kind)) }) .collect(); - let prefix = match (target.is_like_windows, target.arch.as_ref()) { - (true, "x86") => "_", - (true, "arm64ec") => "#", - _ => "", - }; // This loop only adds new items to values of the hash map, so the order in which we // iterate over the values is not important. @@ -1059,10 +1079,13 @@ impl CrateInfo { .for_each(|(_, linked_symbols)| { let mut symbols = missing_weak_lang_items .iter() - .map(|item| { + .map(|(item, export_kind)| { ( - format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())), - SymbolExportKind::Text, + add_prefix( + mangle_internal_symbol(tcx, item.as_str()), + *export_kind, + ), + *export_kind, ) }) .collect::>(); @@ -1077,12 +1100,12 @@ impl CrateInfo { // errors. linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| { ( - format!( - "{prefix}{}", + add_prefix( mangle_internal_symbol( tcx, - global_fn_name(method.name).as_str() - ) + global_fn_name(method.name).as_str(), + ), + SymbolExportKind::Text, ), SymbolExportKind::Text, ) @@ -1092,7 +1115,7 @@ impl CrateInfo { } let embed_visualizers = tcx.crate_types().iter().any(|&crate_type| match crate_type { - CrateType::Executable | CrateType::Dylib | CrateType::Cdylib => { + CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::Sdylib => { // These are crate types for which we invoke the linker and can embed // NatVis visualizers. true diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index bfec208c4aed..4f9757f198b8 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -219,7 +219,7 @@ pub struct CrateInfo { pub target_cpu: String, pub target_features: Vec, pub crate_types: Vec, - pub exported_symbols: UnordMap>, + pub exported_symbols: UnordMap>, pub linked_symbols: FxIndexMap>, pub local_crate_name: Symbol, pub compiler_builtins: Option, diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 0301ef437c0d..d2a687359e0b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -95,7 +95,9 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL ); let instance = match mono_type.kind() { - &ty::FnDef(def_id, args) => Instance::new(def_id, args), + &ty::FnDef(def_id, args) => { + Instance::expect_resolve(cx.tcx(), cx.typing_env(), def_id, args, value.span) + } _ => bug!("asm sym is not a function"), }; diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 8f0cb197c445..1dd96297d1fd 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -17,13 +17,13 @@ use hir::def::DefKind; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_hir as hir; +use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult}; use rustc_middle::query::TyCtxtAt; use rustc_middle::span_bug; use rustc_middle::ty::layout::TyAndLayout; use rustc_span::def_id::LocalDefId; -use rustc_span::sym; use tracing::{instrument, trace}; use super::{ @@ -66,6 +66,7 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>( ecx: &mut InterpCx<'tcx, M>, alloc_id: AllocId, mutability: Mutability, + disambiguator: Option<&mut DisambiguatorState>, ) -> Result + 'tcx, ()> { trace!("intern_shallow {:?}", alloc_id); // remove allocation @@ -88,7 +89,13 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>( // link the alloc id to the actual allocation let alloc = ecx.tcx.mk_const_alloc(alloc); if let Some(static_id) = ecx.machine.static_def_id() { - intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc); + intern_as_new_static( + ecx.tcx, + static_id, + alloc_id, + alloc, + disambiguator.expect("disambiguator needed"), + ); } else { ecx.tcx.set_alloc_id_memory(alloc_id, alloc); } @@ -102,11 +109,18 @@ fn intern_as_new_static<'tcx>( static_id: LocalDefId, alloc_id: AllocId, alloc: ConstAllocation<'tcx>, + disambiguator: &mut DisambiguatorState, ) { + // `intern_const_alloc_recursive` is called once per static and it contains the `DisambiguatorState`. + // The `::{{nested}}` path is thus unique to `intern_const_alloc_recursive` and the + // `DisambiguatorState` ensures the generated path is unique for this call as we generate + // `::{{nested#n}}` where `n` is the `n`th `intern_as_new_static` call. let feed = tcx.create_def( static_id, - Some(sym::nested), + None, DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true }, + Some(DefPathData::NestedStatic), + disambiguator, ); tcx.set_nested_alloc_id_static(alloc_id, feed.def_id()); @@ -154,6 +168,8 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval intern_kind: InternKind, ret: &MPlaceTy<'tcx>, ) -> Result<(), InternResult> { + let mut disambiguator = DisambiguatorState::new(); + // We are interning recursively, and for mutability we are distinguishing the "root" allocation // that we are starting in, and all other allocations that we are encountering recursively. let (base_mutability, inner_mutability, is_static) = match intern_kind { @@ -197,7 +213,9 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval alloc.1.mutability = base_mutability; alloc.1.provenance().ptrs().iter().map(|&(_, prov)| prov).collect() } else { - intern_shallow(ecx, base_alloc_id, base_mutability).unwrap().collect() + intern_shallow(ecx, base_alloc_id, base_mutability, Some(&mut disambiguator)) + .unwrap() + .collect() }; // We need to distinguish "has just been interned" from "was already in `tcx`", // so we track this in a separate set. @@ -291,7 +309,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval // okay with losing some potential for immutability here. This can anyway only affect // `static mut`. just_interned.insert(alloc_id); - match intern_shallow(ecx, alloc_id, inner_mutability) { + match intern_shallow(ecx, alloc_id, inner_mutability, Some(&mut disambiguator)) { Ok(nested) => todo.extend(nested), Err(()) => { ecx.tcx.dcx().delayed_bug("found dangling pointer during const interning"); @@ -313,8 +331,9 @@ pub fn intern_const_alloc_for_constprop<'tcx, T, M: CompileTimeMachine<'tcx, T>> return interp_ok(()); } // Move allocation to `tcx`. - if let Some(_) = - (intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))?).next() + if let Some(_) = intern_shallow(ecx, alloc_id, Mutability::Not, None) + .map_err(|()| err_ub!(DeadLocal))? + .next() { // We are not doing recursive interning, so we don't currently support provenance. // (If this assertion ever triggers, we should just implement a @@ -340,7 +359,7 @@ impl<'tcx> InterpCx<'tcx, DummyMachine> { let dest = self.allocate(layout, MemoryKind::Stack)?; f(self, &dest.clone().into())?; let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance - for prov in intern_shallow(self, alloc_id, Mutability::Not).unwrap() { + for prov in intern_shallow(self, alloc_id, Mutability::Not, None).unwrap() { // We are not doing recursive interning, so we don't currently support provenance. // (If this assertion ever triggers, we should just implement a // proper recursive interning loop -- or just call `intern_const_alloc_recursive`. diff --git a/compiler/rustc_data_structures/src/graph/implementation/mod.rs b/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs similarity index 88% rename from compiler/rustc_data_structures/src/graph/implementation/mod.rs rename to compiler/rustc_data_structures/src/graph/linked_graph/mod.rs index a80365938b96..ecb0095626b4 100644 --- a/compiler/rustc_data_structures/src/graph/implementation/mod.rs +++ b/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs @@ -1,4 +1,4 @@ -//! A graph module for use in dataflow, region resolution, and elsewhere. +//! See [`LinkedGraph`]. //! //! # Interface details //! @@ -28,7 +28,23 @@ use tracing::debug; #[cfg(test)] mod tests; -pub struct Graph { +/// A concrete graph implementation that supports: +/// - Nodes and/or edges labelled with custom data types (`N` and `E` respectively). +/// - Incremental addition of new nodes/edges (but not removal). +/// - Flat storage of node/edge data in a pair of vectors. +/// - Iteration over any node's out-edges or in-edges, via linked lists +/// threaded through the node/edge data. +/// +/// # Caution +/// This is an older graph implementation that is still used by some pieces +/// of diagnostic/debugging code. New code that needs a graph data structure +/// should consider using `VecGraph` instead, or implementing its own +/// special-purpose graph with the specific features needed. +/// +/// This graph implementation predates the later [graph traits](crate::graph), +/// and does not implement those traits, so it has its own implementations of a +/// few basic graph algorithms. +pub struct LinkedGraph { nodes: Vec>, edges: Vec>, } @@ -71,13 +87,13 @@ impl NodeIndex { } } -impl Graph { - pub fn new() -> Graph { - Graph { nodes: Vec::new(), edges: Vec::new() } +impl LinkedGraph { + pub fn new() -> Self { + Self { nodes: Vec::new(), edges: Vec::new() } } - pub fn with_capacity(nodes: usize, edges: usize) -> Graph { - Graph { nodes: Vec::with_capacity(nodes), edges: Vec::with_capacity(edges) } + pub fn with_capacity(nodes: usize, edges: usize) -> Self { + Self { nodes: Vec::with_capacity(nodes), edges: Vec::with_capacity(edges) } } // # Simple accessors @@ -249,7 +265,7 @@ impl Graph { // # Iterators pub struct AdjacentEdges<'g, N, E> { - graph: &'g Graph, + graph: &'g LinkedGraph, direction: Direction, next: EdgeIndex, } @@ -285,7 +301,7 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> { } pub struct DepthFirstTraversal<'g, N, E> { - graph: &'g Graph, + graph: &'g LinkedGraph, stack: Vec, visited: DenseBitSet, direction: Direction, @@ -293,7 +309,7 @@ pub struct DepthFirstTraversal<'g, N, E> { impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> { pub fn with_start_node( - graph: &'g Graph, + graph: &'g LinkedGraph, start_node: NodeIndex, direction: Direction, ) -> Self { diff --git a/compiler/rustc_data_structures/src/graph/implementation/tests.rs b/compiler/rustc_data_structures/src/graph/linked_graph/tests.rs similarity index 95% rename from compiler/rustc_data_structures/src/graph/implementation/tests.rs rename to compiler/rustc_data_structures/src/graph/linked_graph/tests.rs index 32a6d9ec881a..357aa81a57ca 100644 --- a/compiler/rustc_data_structures/src/graph/implementation/tests.rs +++ b/compiler/rustc_data_structures/src/graph/linked_graph/tests.rs @@ -1,11 +1,11 @@ use tracing::debug; -use crate::graph::implementation::*; +use super::{Debug, LinkedGraph, NodeIndex}; -type TestGraph = Graph<&'static str, &'static str>; +type TestGraph = LinkedGraph<&'static str, &'static str>; fn create_graph() -> TestGraph { - let mut graph = Graph::new(); + let mut graph = LinkedGraph::new(); // Create a simple graph // @@ -56,7 +56,7 @@ fn each_edge() { } fn test_adjacent_edges( - graph: &Graph, + graph: &LinkedGraph, start_index: NodeIndex, start_data: N, expected_incoming: &[(E, N)], diff --git a/compiler/rustc_data_structures/src/graph/mod.rs b/compiler/rustc_data_structures/src/graph/mod.rs index 4a1e5db6768d..20416b472b21 100644 --- a/compiler/rustc_data_structures/src/graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/mod.rs @@ -1,8 +1,8 @@ use rustc_index::Idx; pub mod dominators; -pub mod implementation; pub mod iterate; +pub mod linked_graph; mod reference; pub mod reversed; pub mod scc; diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 80d49effbf8a..b28c333d860c 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -43,7 +43,7 @@ pub use self::freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard}; pub use self::lock::{Lock, LockGuard, Mode}; pub use self::mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode}; pub use self::parallel::{ - join, par_for_each_in, par_map, parallel_guard, scope, spawn, try_par_for_each_in, + broadcast, join, par_for_each_in, par_map, parallel_guard, scope, spawn, try_par_for_each_in, }; pub use self::vec::{AppendOnlyIndexVec, AppendOnlyVec}; pub use self::worker_local::{Registry, WorkerLocal}; diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index 64db39cc4c6e..ab65c7f3a6b5 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -237,3 +237,13 @@ pub fn par_map, R: DynSend, C: FromIterato } }) } + +pub fn broadcast(op: impl Fn(usize) -> R + DynSync) -> Vec { + if mode::is_dyn_thread_safe() { + let op = FromDyn::from(op); + let results = rayon_core::broadcast(|context| op.derive(op(context.index()))); + results.into_iter().map(|r| r.into_inner()).collect() + } else { + vec![op(0)] + } +} diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c823d11126e2..9da4f2dbc273 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -44,13 +44,13 @@ rustc_privacy = { path = "../rustc_privacy" } rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } -rustc_smir = { path = "../rustc_smir" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" shlex = "1.0" +stable_mir = { path = "../stable_mir", features = ["rustc_internal"] } tracing = { version = "0.1.35" } # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index d18fa8928140..95cfe221d3fe 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -54,8 +54,8 @@ use rustc_metadata::locator; use rustc_middle::ty::TyCtxt; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_session::config::{ - CG_OPTIONS, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, UnstableOptions, - Z_OPTIONS, nightly_options, parse_target_triple, + CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, + UnstableOptions, Z_OPTIONS, nightly_options, parse_target_triple, }; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; @@ -352,6 +352,8 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) passes::write_dep_info(tcx); + passes::write_interface(tcx); + if sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1 { @@ -461,6 +463,7 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col // Allow "E0123" or "0123" form. let upper_cased_code = code.to_ascii_uppercase(); if let Ok(code) = upper_cased_code.strip_prefix('E').unwrap_or(&upper_cased_code).parse::() + && code <= ErrCode::MAX_AS_U32 && let Ok(description) = registry.try_find_description(ErrCode::from_u32(code)) { let mut is_in_code_block = false; @@ -816,6 +819,7 @@ fn print_crate_info( let supported_crate_types = CRATE_TYPES .iter() .filter(|(_, crate_type)| !invalid_output_for_target(&sess, *crate_type)) + .filter(|(_, crate_type)| *crate_type != CrateType::Sdylib) .map(|(crate_type_sym, _)| *crate_type_sym) .collect::>(); for supported_crate_type in supported_crate_types { diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 16d70af7e05d..ec77043cd128 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -10,8 +10,8 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_build::thir::print::{thir_flat, thir_tree}; use rustc_session::Session; use rustc_session::config::{OutFileName, PpHirMode, PpMode, PpSourceMode}; -use rustc_smir::rustc_internal::pretty::write_smir_pretty; use rustc_span::{FileName, Ident}; +use stable_mir::rustc_internal::pretty::write_smir_pretty; use tracing::debug; use {rustc_ast as ast, rustc_hir_pretty as pprust_hir}; diff --git a/compiler/rustc_error_codes/src/error_codes/E0253.md b/compiler/rustc_error_codes/src/error_codes/E0253.md index 705d1bfc53e5..628f5e252fbb 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0253.md +++ b/compiler/rustc_error_codes/src/error_codes/E0253.md @@ -1,9 +1,13 @@ +#### Note: this error code is no longer emitted by the compiler. + Attempt was made to import an unimportable type. This can happen when trying to import a type from a trait. Erroneous code example: -```compile_fail,E0253 +``` +#![feature(import_trait_associated_functions)] + mod foo { pub trait MyTrait { type SomeType; diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 2df3281568be..0994813ecb9c 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -274,7 +274,12 @@ impl<'a> StripUnconfigured<'a> { /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect. pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec { - validate_attr::check_attribute_safety(&self.sess.psess, AttributeSafety::Normal, &cfg_attr); + validate_attr::check_attribute_safety( + &self.sess.psess, + Some(AttributeSafety::Normal), + &cfg_attr, + ast::CRATE_NODE_ID, + ); // A trace attribute left in AST in place of the original `cfg_attr` attribute. // It can later be used by lints or other diagnostics. diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 1f430b0018f5..d4853d1357f3 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1983,7 +1983,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let mut span: Option = None; while let Some(attr) = attrs.next() { rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); - validate_attr::check_attr(&self.cx.sess.psess, attr); + validate_attr::check_attr( + &self.cx.sess.psess, + attr, + self.cx.current_expansion.lint_node_id, + ); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; span = Some(current_span); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index a5e6b1c00d69..c117e0fcf7cc 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -536,6 +536,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Unstable attributes: // ========================================================================== + // Linking: + gated!( + export_stable, Normal, template!(Word), WarnFollowing, + EncodeCrossCrate::No, experimental!(export_stable) + ), + // Testing: gated!( test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 75e09cacb1f1..a5f89b7a076a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -316,6 +316,7 @@ declare_features! ( // Unstable `#[target_feature]` directives. (unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)), (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)), + (unstable, apx_target_feature, "CURRENT_RUSTC_VERSION", Some(139284)), (unstable, arm_target_feature, "1.27.0", Some(44839)), (unstable, avx512_target_feature, "1.27.0", Some(44839)), (unstable, bpf_target_feature, "1.54.0", Some(44839)), @@ -393,6 +394,8 @@ declare_features! ( (unstable, async_for_loop, "1.77.0", Some(118898)), /// Allows `async` trait bound modifier. (unstable, async_trait_bounds, "1.85.0", Some(62290)), + /// Allows using Intel AVX10 target features and intrinsics + (unstable, avx10_target_feature, "CURRENT_RUSTC_VERSION", Some(138843)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled. @@ -483,6 +486,8 @@ declare_features! ( (unstable, explicit_extern_abis, "CURRENT_RUSTC_VERSION", Some(134986)), /// Allows explicit tail calls via `become` expression. (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), + /// Allows using `#[export_stable]` which indicates that an item is exportable. + (incomplete, export_stable, "CURRENT_RUSTC_VERSION", Some(139939)), /// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions /// for functions with varargs. (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)), @@ -506,6 +511,8 @@ declare_features! ( (incomplete, fn_delegation, "1.76.0", Some(118212)), /// Allows impls for the Freeze trait. (internal, freeze_impls, "1.78.0", Some(121675)), + /// Frontmatter `---` blocks for use by external tools. + (unstable, frontmatter, "CURRENT_RUSTC_VERSION", Some(136889)), /// Allows defining gen blocks and `gen fn`. (unstable, gen_blocks, "1.75.0", Some(117078)), /// Infer generic args for both consts and types. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 9372ab532bf3..507c94aca8b9 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -269,18 +269,10 @@ impl DefKind { | DefKind::TyParam | DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()), - // An associated type name will be missing for an RPITIT. - DefKind::AssocTy => { - if let Some(name) = name { - DefPathData::TypeNs(name) - } else { - DefPathData::AnonAssocTy - } - } + // An associated type name will be missing for an RPITIT (DefPathData::AnonAssocTy), + // but those provide their own DefPathData. + DefKind::AssocTy => DefPathData::TypeNs(name.unwrap()), - // It's not exactly an anon const, but wrt DefPathData, there - // is no difference. - DefKind::Static { nested: true, .. } => DefPathData::AnonConst, DefKind::Fn | DefKind::Const | DefKind::ConstParam diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index bf7b1eefcf68..f93b9e5af534 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -68,7 +68,7 @@ impl DefPathTable { // // See the documentation for DefPathHash for more information. panic!( - "found DefPathHash collision between {def_path1:?} and {def_path2:?}. \ + "found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \ Compilation cannot continue." ); } @@ -97,13 +97,31 @@ impl DefPathTable { } } +#[derive(Debug)] +pub struct DisambiguatorState { + next: UnordMap<(LocalDefId, DefPathData), u32>, +} + +impl DisambiguatorState { + pub fn new() -> Self { + Self { next: Default::default() } + } + + /// Creates a `DisambiguatorState` where the next allocated `(LocalDefId, DefPathData)` pair + /// will have `index` as the disambiguator. + pub fn with(def_id: LocalDefId, data: DefPathData, index: u32) -> Self { + let mut this = Self::new(); + this.next.insert((def_id, data), index); + this + } +} + /// The definition table containing node definitions. /// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s. /// It also stores mappings to convert `LocalDefId`s to/from `HirId`s. #[derive(Debug)] pub struct Definitions { table: DefPathTable, - next_disambiguator: UnordMap<(LocalDefId, DefPathData), u32>, } /// A unique identifier that we can use to lookup a definition @@ -127,7 +145,7 @@ impl DefKey { let DisambiguatedDefPathData { ref data, disambiguator } = self.disambiguated_data; std::mem::discriminant(data).hash(&mut hasher); - if let Some(name) = data.get_opt_name() { + if let Some(name) = data.hashed_symbol() { // Get a stable hash by considering the symbol chars rather than // the symbol index. name.as_str().hash(&mut hasher); @@ -173,7 +191,11 @@ impl DisambiguatedDefPathData { } } DefPathDataName::Anon { namespace } => { - write!(writer, "{{{}#{}}}", namespace, self.disambiguator) + if let DefPathData::AnonAssocTy(method) = self.data { + write!(writer, "{}::{{{}#{}}}", method, namespace, self.disambiguator) + } else { + write!(writer, "{{{}#{}}}", namespace, self.disambiguator) + } } } } @@ -287,10 +309,15 @@ pub enum DefPathData { /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. OpaqueTy, - /// An anonymous associated type from an RPITIT. - AnonAssocTy, + /// Used for remapped captured lifetimes in an existential `impl Trait` type node. + OpaqueLifetime(Symbol), + /// An anonymous associated type from an RPITIT. The symbol refers to the name of the method + /// that defined the type. + AnonAssocTy(Symbol), /// A synthetic body for a coroutine's by-move body. SyntheticCoroutineBody, + /// Additional static data referred to by a static. + NestedStatic, } impl Definitions { @@ -342,11 +369,20 @@ impl Definitions { let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) }; assert_eq!(root.local_def_index, CRATE_DEF_INDEX); - Definitions { table, next_disambiguator: Default::default() } + Definitions { table } } - /// Adds a definition with a parent definition. - pub fn create_def(&mut self, parent: LocalDefId, data: DefPathData) -> LocalDefId { + /// Creates a definition with a parent definition. + /// If there are multiple definitions with the same DefPathData and the same parent, use + /// `disambiguator` to differentiate them. Distinct `DisambiguatorState` instances are not + /// guaranteed to generate unique disambiguators and should instead ensure that the `parent` + /// and `data` pair is distinct from other instances. + pub fn create_def( + &mut self, + parent: LocalDefId, + data: DefPathData, + disambiguator: &mut DisambiguatorState, + ) -> LocalDefId { // We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a // reference to `Definitions` and we're already holding a mutable reference. debug!( @@ -354,12 +390,12 @@ impl Definitions { self.def_path(parent).to_string_no_crate_verbose(), ); - // The root node must be created with `create_root_def()`. + // The root node must be created in `new()`. assert!(data != DefPathData::CrateRoot); // Find the next free disambiguator for this key. let disambiguator = { - let next_disamb = self.next_disambiguator.entry((parent, data)).or_insert(0); + let next_disamb = disambiguator.next.entry((parent, data)).or_insert(0); let disambiguator = *next_disamb; *next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow"); disambiguator @@ -411,7 +447,8 @@ impl DefPathData { pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { - TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) + | OpaqueLifetime(name) => Some(name), Impl | ForeignMod @@ -422,17 +459,37 @@ impl DefPathData { | Ctor | AnonConst | OpaqueTy - | AnonAssocTy - | SyntheticCoroutineBody => None, + | AnonAssocTy(..) + | SyntheticCoroutineBody + | NestedStatic => None, + } + } + + fn hashed_symbol(&self) -> Option { + use self::DefPathData::*; + match *self { + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) + | OpaqueLifetime(name) => Some(name), + + Impl + | ForeignMod + | CrateRoot + | Use + | GlobalAsm + | Closure + | Ctor + | AnonConst + | OpaqueTy + | SyntheticCoroutineBody + | NestedStatic => None, } } pub fn name(&self) -> DefPathDataName { use self::DefPathData::*; match *self { - TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => { - DefPathDataName::Named(name) - } + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) + | OpaqueLifetime(name) => DefPathDataName::Named(name), // Note that this does not show up in user print-outs. CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, Impl => DefPathDataName::Anon { namespace: kw::Impl }, @@ -443,8 +500,9 @@ impl DefPathData { Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, - AnonAssocTy => DefPathDataName::Anon { namespace: sym::anon_assoc }, + AnonAssocTy(..) => DefPathDataName::Anon { namespace: sym::anon_assoc }, SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic }, + NestedStatic => DefPathDataName::Anon { namespace: sym::nested }, } } } diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs index 18f8c523f9d3..8684adee29c9 100644 --- a/compiler/rustc_hir/src/hir/tests.rs +++ b/compiler/rustc_hir/src/hir/tests.rs @@ -50,21 +50,14 @@ fn trait_object_roundtrips() { } fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) { - let unambig = TyKind::TraitObject::<'_, ()>( - &[], - TaggedRef::new( - &const { - Lifetime { - hir_id: HirId::INVALID, - ident: Ident::new(sym::name, DUMMY_SP), - kind: LifetimeKind::Static, - source: LifetimeSource::Other, - syntax: LifetimeSyntax::Hidden, - } - }, - syntax, - ), - ); + let lt = Lifetime { + hir_id: HirId::INVALID, + ident: Ident::new(sym::name, DUMMY_SP), + kind: LifetimeKind::Static, + source: LifetimeSource::Other, + syntax: LifetimeSyntax::Hidden, + }; + let unambig = TyKind::TraitObject::<'_, ()>(&[], TaggedRef::new(<, syntax)); let unambig_to_ambig = unsafe { std::mem::transmute::<_, TyKind<'_, AmbigArg>>(unambig) }; match unambig_to_ambig { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index bbf36fef1ddb..fb67f2fd2235 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -5,7 +5,7 @@ use std::iter; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; -use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; +use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; @@ -14,10 +14,10 @@ use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, + TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_middle::{bug, span_bug}; -use rustc_span::Span; +use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -1137,65 +1137,319 @@ fn check_region_bounds_on_impl_item<'tcx>( // but found 0" it's confusing, because it looks like there // are zero. Since I don't quite know how to phrase things at // the moment, give a kind of vague error message. - if trait_params != impl_params { - let span = tcx - .hir_get_generics(impl_m.def_id.expect_local()) - .expect("expected impl item to have generics or else we can't compare them") - .span; + if trait_params == impl_params { + return Ok(()); + } - let mut generics_span = None; - let mut bounds_span = vec![]; - let mut where_span = None; - if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id) - && let Some(trait_generics) = trait_node.generics() - { - generics_span = Some(trait_generics.span); - // FIXME: we could potentially look at the impl's bounds to not point at bounds that - // *are* present in the impl. - for p in trait_generics.predicates { - if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind { - for b in pred.bounds { + if !delay && let Some(guar) = check_region_late_boundedness(tcx, impl_m, trait_m) { + return Err(guar); + } + + let span = tcx + .hir_get_generics(impl_m.def_id.expect_local()) + .expect("expected impl item to have generics or else we can't compare them") + .span; + + let mut generics_span = None; + let mut bounds_span = vec![]; + let mut where_span = None; + + if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id) + && let Some(trait_generics) = trait_node.generics() + { + generics_span = Some(trait_generics.span); + // FIXME: we could potentially look at the impl's bounds to not point at bounds that + // *are* present in the impl. + for p in trait_generics.predicates { + match p.kind { + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { + bounds, + .. + }) + | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { + bounds, + .. + }) => { + for b in *bounds { if let hir::GenericBound::Outlives(lt) = b { bounds_span.push(lt.ident.span); } } } + _ => {} } - if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id) - && let Some(impl_generics) = impl_node.generics() - { - let mut impl_bounds = 0; - for p in impl_generics.predicates { - if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind { - for b in pred.bounds { + } + if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id) + && let Some(impl_generics) = impl_node.generics() + { + let mut impl_bounds = 0; + for p in impl_generics.predicates { + match p.kind { + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { + bounds, + .. + }) + | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { + bounds, + .. + }) => { + for b in *bounds { if let hir::GenericBound::Outlives(_) = b { impl_bounds += 1; } } } - } - if impl_bounds == bounds_span.len() { - bounds_span = vec![]; - } else if impl_generics.has_where_clause_predicates { - where_span = Some(impl_generics.where_clause_span); + _ => {} } } + if impl_bounds == bounds_span.len() { + bounds_span = vec![]; + } else if impl_generics.has_where_clause_predicates { + where_span = Some(impl_generics.where_clause_span); + } } - let reported = tcx - .dcx() - .create_err(LifetimesOrBoundsMismatchOnTrait { - span, - item_kind: impl_m.descr(), - ident: impl_m.ident(tcx), - generics_span, - bounds_span, - where_span, - }) - .emit_unless(delay); - return Err(reported); } - Ok(()) + let reported = tcx + .dcx() + .create_err(LifetimesOrBoundsMismatchOnTrait { + span, + item_kind: impl_m.descr(), + ident: impl_m.ident(tcx), + generics_span, + bounds_span, + where_span, + }) + .emit_unless(delay); + + Err(reported) +} + +#[allow(unused)] +enum LateEarlyMismatch<'tcx> { + EarlyInImpl(DefId, DefId, ty::Region<'tcx>), + LateInImpl(DefId, DefId, ty::Region<'tcx>), +} + +fn check_region_late_boundedness<'tcx>( + tcx: TyCtxt<'tcx>, + impl_m: ty::AssocItem, + trait_m: ty::AssocItem, +) -> Option { + if !impl_m.is_fn() { + return None; + } + + let (infcx, param_env) = tcx + .infer_ctxt() + .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id)); + + let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id); + let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args); + let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig); + + let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id); + let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args); + let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig); + + let ocx = ObligationCtxt::new(&infcx); + + // Equate the signatures so that we can infer whether a late-bound param was present where + // an early-bound param was expected, since we replace the late-bound lifetimes with + // `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will + // resolve to `ReLateParam` if there is a mismatch. + let Ok(()) = ocx.eq( + &ObligationCause::dummy(), + param_env, + ty::Binder::dummy(trait_m_sig), + ty::Binder::dummy(impl_m_sig), + ) else { + return None; + }; + + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + return None; + } + + let mut mismatched = vec![]; + + let impl_generics = tcx.generics_of(impl_m.def_id); + for (id_arg, arg) in + std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args) + { + if let ty::GenericArgKind::Lifetime(r) = arg.unpack() + && let ty::ReVar(vid) = r.kind() + && let r = infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(tcx, vid) + && let ty::ReLateParam(ty::LateParamRegion { + kind: ty::LateParamRegionKind::Named(trait_param_def_id, _), + .. + }) = r.kind() + && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind() + { + mismatched.push(LateEarlyMismatch::EarlyInImpl( + impl_generics.region_param(ebr, tcx).def_id, + trait_param_def_id, + id_arg.expect_region(), + )); + } + } + + let trait_generics = tcx.generics_of(trait_m.def_id); + for (id_arg, arg) in + std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args) + { + if let ty::GenericArgKind::Lifetime(r) = arg.unpack() + && let ty::ReVar(vid) = r.kind() + && let r = infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(tcx, vid) + && let ty::ReLateParam(ty::LateParamRegion { + kind: ty::LateParamRegionKind::Named(impl_param_def_id, _), + .. + }) = r.kind() + && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind() + { + mismatched.push(LateEarlyMismatch::LateInImpl( + impl_param_def_id, + trait_generics.region_param(ebr, tcx).def_id, + id_arg.expect_region(), + )); + } + } + + if mismatched.is_empty() { + return None; + } + + let spans: Vec<_> = mismatched + .iter() + .map(|param| { + let (LateEarlyMismatch::EarlyInImpl(impl_param_def_id, ..) + | LateEarlyMismatch::LateInImpl(impl_param_def_id, ..)) = param; + tcx.def_span(impl_param_def_id) + }) + .collect(); + + let mut diag = tcx + .dcx() + .struct_span_err(spans, "lifetime parameters do not match the trait definition") + .with_note("lifetime parameters differ in whether they are early- or late-bound") + .with_code(E0195); + for mismatch in mismatched { + match mismatch { + LateEarlyMismatch::EarlyInImpl( + impl_param_def_id, + trait_param_def_id, + early_bound_region, + ) => { + let mut multispan = MultiSpan::from_spans(vec![ + tcx.def_span(impl_param_def_id), + tcx.def_span(trait_param_def_id), + ]); + multispan + .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl..."); + multispan + .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait..."); + multispan.push_span_label( + tcx.def_span(impl_param_def_id), + format!("`{}` is early-bound", tcx.item_name(impl_param_def_id)), + ); + multispan.push_span_label( + tcx.def_span(trait_param_def_id), + format!("`{}` is late-bound", tcx.item_name(trait_param_def_id)), + ); + if let Some(span) = + find_region_in_predicates(tcx, impl_m.def_id, early_bound_region) + { + multispan.push_span_label( + span, + format!( + "this lifetime bound makes `{}` early-bound", + tcx.item_name(impl_param_def_id) + ), + ); + } + diag.span_note( + multispan, + format!( + "`{}` differs between the trait and impl", + tcx.item_name(impl_param_def_id) + ), + ); + } + LateEarlyMismatch::LateInImpl( + impl_param_def_id, + trait_param_def_id, + early_bound_region, + ) => { + let mut multispan = MultiSpan::from_spans(vec![ + tcx.def_span(impl_param_def_id), + tcx.def_span(trait_param_def_id), + ]); + multispan + .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl..."); + multispan + .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait..."); + multispan.push_span_label( + tcx.def_span(impl_param_def_id), + format!("`{}` is late-bound", tcx.item_name(impl_param_def_id)), + ); + multispan.push_span_label( + tcx.def_span(trait_param_def_id), + format!("`{}` is early-bound", tcx.item_name(trait_param_def_id)), + ); + if let Some(span) = + find_region_in_predicates(tcx, trait_m.def_id, early_bound_region) + { + multispan.push_span_label( + span, + format!( + "this lifetime bound makes `{}` early-bound", + tcx.item_name(trait_param_def_id) + ), + ); + } + diag.span_note( + multispan, + format!( + "`{}` differs between the trait and impl", + tcx.item_name(impl_param_def_id) + ), + ); + } + } + } + + Some(diag.emit()) +} + +fn find_region_in_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + early_bound_region: ty::Region<'tcx>, +) -> Option { + for (pred, span) in tcx.explicit_predicates_of(def_id).instantiate_identity(tcx) { + if pred.visit_with(&mut FindRegion(early_bound_region)).is_break() { + return Some(span); + } + } + + struct FindRegion<'tcx>(ty::Region<'tcx>); + impl<'tcx> TypeVisitor> for FindRegion<'tcx> { + type Result = ControlFlow<()>; + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { + if r == self.0 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) } + } + } + + None } #[instrument(level = "debug", skip(infcx))] diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index fa36fe797161..2ec14b2f018c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -76,6 +76,36 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { ) } + /// Convenience function to *deeply* normalize during wfcheck. In the old solver, + /// this just dispatches to [`WfCheckingCtxt::normalize`], but in the new solver + /// this calls `deeply_normalize` and reports errors if they are encountered. + /// + /// This function should be called in favor of `normalize` in cases where we will + /// then check the well-formedness of the type, since we only use the normalized + /// signature types for implied bounds when checking regions. + // FIXME(-Znext-solver): This should be removed when we compute implied outlives + // bounds using the unnormalized signature of the function we're checking. + fn deeply_normalize(&self, span: Span, loc: Option, value: T) -> T + where + T: TypeFoldable>, + { + if self.infcx.next_trait_solver() { + match self.ocx.deeply_normalize( + &ObligationCause::new(span, self.body_def_id, ObligationCauseCode::WellFormed(loc)), + self.param_env, + value.clone(), + ) { + Ok(value) => value, + Err(errors) => { + self.infcx.err_ctxt().report_fulfillment_errors(errors); + value + } + } + } else { + self.normalize(span, loc, value) + } + } + fn register_wf_obligation(&self, span: Span, loc: Option, term: ty::Term<'tcx>) { let cause = traits::ObligationCause::new( span, @@ -297,7 +327,8 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() { let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| { let ty = tcx.type_of(def_id).instantiate_identity(); - let item_ty = wfcx.normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty); + let item_ty = + wfcx.deeply_normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty); wfcx.register_wf_obligation( hir_ty.span, Some(WellFormedLoc::Ty(def_id)), @@ -1073,7 +1104,7 @@ fn check_associated_item( match item.kind { ty::AssocKind::Const { .. } => { let ty = tcx.type_of(item.def_id).instantiate_identity(); - let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); + let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); check_sized_if_body( wfcx, @@ -1102,7 +1133,7 @@ fn check_associated_item( } if item.defaultness(tcx).has_value() { let ty = tcx.type_of(item.def_id).instantiate_identity(); - let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); + let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); } Ok(()) @@ -1149,7 +1180,7 @@ fn check_type_defn<'tcx>( let field_id = field.did.expect_local(); let hir::FieldDef { ty: hir_ty, .. } = tcx.hir_node_by_def_id(field_id).expect_field(); - let ty = wfcx.normalize( + let ty = wfcx.deeply_normalize( hir_ty.span, None, tcx.type_of(field.did).instantiate_identity(), @@ -1310,7 +1341,7 @@ fn check_item_type( enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| { let ty = tcx.type_of(item_id).instantiate_identity(); - let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty); + let item_ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty); let forbid_unsized = match unsized_handling { UnsizedHandling::Forbid => true, @@ -1375,7 +1406,7 @@ fn check_impl<'tcx>( // other `Foo` impls are incoherent. tcx.ensure_ok().coherent_trait(trait_ref.def_id)?; let trait_span = hir_trait_ref.path.span; - let trait_ref = wfcx.normalize( + let trait_ref = wfcx.deeply_normalize( trait_span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), trait_ref, @@ -1435,7 +1466,7 @@ fn check_impl<'tcx>( } None => { let self_ty = tcx.type_of(item.owner_id).instantiate_identity(); - let self_ty = wfcx.normalize( + let self_ty = wfcx.deeply_normalize( item.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty, @@ -1640,7 +1671,7 @@ fn check_fn_or_method<'tcx>( sig.inputs_and_output = tcx.mk_type_list_from_iter(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| { - wfcx.normalize( + wfcx.deeply_normalize( arg_span(idx), Some(WellFormedLoc::Param { function: def_id, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 59ab36d98fda..709446d09cd2 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -14,6 +14,7 @@ use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, Res}; +use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; use rustc_hir::{ self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node, @@ -63,6 +64,7 @@ impl ResolvedArg { struct BoundVarContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, rbv: &'a mut ResolveBoundVars, + disambiguator: &'a mut DisambiguatorState, scope: ScopeRef<'a>, } @@ -245,8 +247,12 @@ pub(crate) fn provide(providers: &mut Providers) { #[instrument(level = "debug", skip(tcx))] fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars { let mut rbv = ResolveBoundVars::default(); - let mut visitor = - BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } }; + let mut visitor = BoundVarContext { + tcx, + rbv: &mut rbv, + scope: &Scope::Root { opt_parent_item: None }, + disambiguator: &mut DisambiguatorState::new(), + }; match tcx.hir_owner_node(local_def_id) { hir::OwnerNode::Item(item) => visitor.visit_item(item), hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), @@ -515,9 +521,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque); if capture_all_in_scope_lifetimes { + let tcx = self.tcx; let lifetime_ident = |def_id: LocalDefId| { - let name = self.tcx.item_name(def_id.to_def_id()); - let span = self.tcx.def_span(def_id); + let name = tcx.item_name(def_id.to_def_id()); + let span = tcx.def_span(def_id); Ident::new(name, span) }; @@ -1091,8 +1098,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { where F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>), { - let BoundVarContext { tcx, rbv, .. } = self; - let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope }; + let BoundVarContext { tcx, rbv, disambiguator, .. } = self; + let mut this = BoundVarContext { tcx: *tcx, rbv, disambiguator, scope: &wrap_scope }; let span = debug_span!("scope", scope = ?this.scope.debug_truncated()); { let _enter = span.enter(); @@ -1446,7 +1453,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { #[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)] fn remap_opaque_captures( - &self, + &mut self, opaque_capture_scopes: &Vec<(LocalDefId, &RefCell>)>, mut lifetime: ResolvedArg, ident: Ident, @@ -1462,8 +1469,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() { let mut captures = captures.borrow_mut(); let remapped = *captures.entry(lifetime).or_insert_with(|| { - let feed = - self.tcx.create_def(opaque_def_id, Some(ident.name), DefKind::LifetimeParam); + // `opaque_def_id` is unique to the `BoundVarContext` pass which is executed once + // per `resolve_bound_vars` query. This is the only location that creates + // `OpaqueLifetime` paths. `::OpaqueLifetime(..)` is thus unique + // to this query and duplicates within the query are handled by `self.disambiguator`. + let feed = self.tcx.create_def( + opaque_def_id, + None, + DefKind::LifetimeParam, + Some(DefPathData::OpaqueLifetime(ident.name)), + &mut self.disambiguator, + ); feed.def_span(ident.span); feed.def_ident_span(Some(ident.span)); feed.def_id() diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index bf91eb1b8fda..4419d5dc7d66 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -9,8 +9,8 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{AmbigArg, HirId}; use rustc_middle::bug; use rustc_middle::ty::{ - self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, - TypeVisitor, Upcast, + self as ty, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, Upcast, }; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::traits; @@ -996,7 +996,7 @@ struct GenericParamAndBoundVarCollector<'a, 'tcx> { impl<'tcx> TypeVisitor> for GenericParamAndBoundVarCollector<'_, 'tcx> { type Result = ControlFlow; - fn visit_binder>>( + fn visit_binder>>( &mut self, binder: &ty::Binder<'tcx, T>, ) -> Self::Result { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 88f745892048..f6e5149bd2b1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -172,7 +172,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let principal_trait = regular_traits.into_iter().next(); - let mut needed_associated_types = vec![]; + // A stable ordering of associated types from the principal trait and all its + // supertraits. We use this to ensure that different substitutions of a trait + // don't result in `dyn Trait` types with different projections lists, which + // can be unsound: . + // We achieve a stable ordering by walking over the unsubstituted principal + // trait ref. + let mut ordered_associated_types = vec![]; + if let Some((principal_trait, ref spans)) = principal_trait { let principal_trait = principal_trait.map_bound(|trait_pred| { assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); @@ -197,16 +204,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // FIXME(negative_bounds): Handle this correctly... let trait_ref = tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); - needed_associated_types.extend( + ordered_associated_types.extend( tcx.associated_items(pred.trait_ref.def_id) .in_definition_order() // We only care about associated types. .filter(|item| item.is_type()) // No RPITITs -- they're not dyn-compatible for now. .filter(|item| !item.is_impl_trait_in_trait()) - // If the associated type has a `where Self: Sized` bound, - // we do not need to constrain the associated type. - .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .map(|item| (item.def_id, trait_ref)), ); } @@ -278,14 +282,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + // We compute the list of projection bounds taking the ordered associated types, + // and check if there was an entry in the collected `projection_bounds`. Those + // are computed by first taking the user-written associated types, then elaborating + // the principal trait ref, and only using those if there was no user-written. + // See note below about how we handle missing associated types with `Self: Sized`, + // which are not required to be provided, but are still used if they are provided. let mut missing_assoc_types = FxIndexSet::default(); - let projection_bounds: Vec<_> = needed_associated_types + let projection_bounds: Vec<_> = ordered_associated_types .into_iter() .filter_map(|key| { if let Some(assoc) = projection_bounds.get(&key) { Some(*assoc) } else { - missing_assoc_types.insert(key); + // If the associated type has a `where Self: Sized` bound, then + // we do not need to provide the associated type. This results in + // a `dyn Trait` type that has a different number of projection + // bounds, which may lead to type mismatches. + if !tcx.generics_require_sized_self(key.0) { + missing_assoc_types.insert(key); + } None } }) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index fcb7382549f4..5e79e9320153 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1770,7 +1770,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: Span, opt_self_ty: Option>, item_def_id: DefId, - trait_segment: &hir::PathSegment<'tcx>, + trait_segment: Option<&hir::PathSegment<'tcx>>, item_segment: &hir::PathSegment<'tcx>, ) -> Ty<'tcx> { match self.lower_qpath_shared( @@ -1795,7 +1795,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: Span, opt_self_ty: Option>, item_def_id: DefId, - trait_segment: &hir::PathSegment<'tcx>, + trait_segment: Option<&hir::PathSegment<'tcx>>, item_segment: &hir::PathSegment<'tcx>, ) -> Const<'tcx> { match self.lower_qpath_shared( @@ -1820,7 +1820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: Span, opt_self_ty: Option>, item_def_id: DefId, - trait_segment: &hir::PathSegment<'tcx>, + trait_segment: Option<&hir::PathSegment<'tcx>>, item_segment: &hir::PathSegment<'tcx>, assoc_tag: ty::AssocTag, ) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> { @@ -1840,7 +1840,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?self_ty); let trait_ref = - self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false); + self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment.unwrap(), false); debug!(?trait_ref); let item_args = @@ -2196,16 +2196,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } Res::Def(DefKind::AssocTy, def_id) => { - debug_assert!(path.segments.len() >= 2); - let _ = self.prohibit_generic_args( - path.segments[..path.segments.len() - 2].iter(), - GenericsArgsErrExtend::None, - ); + let trait_segment = if let [modules @ .., trait_, _item] = path.segments { + let _ = self.prohibit_generic_args(modules.iter(), GenericsArgsErrExtend::None); + Some(trait_) + } else { + None + }; self.lower_qpath_ty( span, opt_self_ty, def_id, - &path.segments[path.segments.len() - 2], + trait_segment, path.segments.last().unwrap(), ) } @@ -2413,16 +2414,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args)) } Res::Def(DefKind::AssocConst, did) => { - debug_assert!(path.segments.len() >= 2); - let _ = self.prohibit_generic_args( - path.segments[..path.segments.len() - 2].iter(), - GenericsArgsErrExtend::None, - ); + let trait_segment = if let [modules @ .., trait_, _item] = path.segments { + let _ = self.prohibit_generic_args(modules.iter(), GenericsArgsErrExtend::None); + Some(trait_) + } else { + None + }; self.lower_qpath_const( span, opt_self_ty, did, - &path.segments[path.segments.len() - 2], + trait_segment, path.segments.last().unwrap(), ) } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 309b8f2c7613..91dde13be550 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -216,7 +216,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { check::maybe_check_static_with_link_section(tcx, item_def_id); } DefKind::Const if tcx.generics_of(item_def_id).is_empty() => { - let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty()); + let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty()); let cid = GlobalId { instance, promoted: None }; let typing_env = ty::TypingEnv::fully_monomorphized(); tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid)); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 15e997aebcb8..09bf84ab64fb 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -110,6 +110,7 @@ impl<'a> State<'a> { } self.print_attr_item(&unparsed, unparsed.span); self.word("]"); + self.hardbreak() } hir::Attribute::Parsed(AttributeKind::DocComment { style, kind, comment, .. }) => { self.word(rustc_ast_pretty::pprust::state::doc_comment_to_string( @@ -183,7 +184,7 @@ impl<'a> State<'a> { Node::Ty(a) => self.print_type(a), Node::AssocItemConstraint(a) => self.print_assoc_item_constraint(a), Node::TraitRef(a) => self.print_trait_ref(a), - Node::OpaqueTy(o) => self.print_opaque_ty(o), + Node::OpaqueTy(_) => panic!("cannot print Node::OpaqueTy"), Node::Pat(a) => self.print_pat(a), Node::TyPat(a) => self.print_ty_pat(a), Node::PatField(a) => self.print_patfield(a), @@ -654,10 +655,11 @@ impl<'a> State<'a> { self.bclose(item.span, cb); } hir::ItemKind::GlobalAsm { asm, .. } => { - // FIXME(nnethercote): `ib` is unclosed - let (cb, _ib) = self.head("global_asm!"); + let (cb, ib) = self.head("global_asm!"); self.print_inline_asm(asm); - self.end(cb) + self.word(";"); + self.end(cb); + self.end(ib); } hir::ItemKind::TyAlias(ident, ty, generics) => { let (cb, ib) = self.head("type"); @@ -764,14 +766,6 @@ impl<'a> State<'a> { self.print_path(t.path, false); } - fn print_opaque_ty(&mut self, o: &hir::OpaqueTy<'_>) { - // FIXME(nnethercote): `cb` and `ib` are unclosed - let (_cb, _ib) = self.head("opaque"); - self.word("{"); - self.print_bounds("impl", o.bounds); - self.word("}"); - } - fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) { if !generic_params.is_empty() { self.word("for"); @@ -1509,7 +1503,7 @@ impl<'a> State<'a> { } hir::ExprKind::DropTemps(init) => { // Print `{`: - let cb = self.cbox(INDENT_UNIT); + let cb = self.cbox(0); let ib = self.ibox(0); self.bopen(ib); @@ -1532,16 +1526,18 @@ impl<'a> State<'a> { self.print_if(test, blk, elseopt); } hir::ExprKind::Loop(blk, opt_label, _, _) => { + let cb = self.cbox(0); + let ib = self.ibox(0); if let Some(label) = opt_label { self.print_ident(label.ident); self.word_space(":"); } - let (cb, ib) = self.head("loop"); + self.word_nbsp("loop"); self.print_block(blk, cb, ib); } hir::ExprKind::Match(expr, arms, _) => { - let cb = self.cbox(INDENT_UNIT); - let ib = self.ibox(INDENT_UNIT); + let cb = self.cbox(0); + let ib = self.ibox(0); self.word_nbsp("match"); self.print_expr_as_cond(expr); self.space(); @@ -1572,15 +1568,6 @@ impl<'a> State<'a> { // This is a bare expression. self.ann.nested(self, Nested::Body(body)); - // FIXME(nnethercote): this is bogus - let fake_ib = BoxMarker; - self.end(fake_ib); - - // A box will be closed by `print_expr`, but we didn't want an overall - // wrapper so we closed the corresponding opening. so create an - // empty box to satisfy the close. - // FIXME(nnethercote): this is bogus, and `print_expr` is missing - let _ib = self.ibox(0); } hir::ExprKind::Block(blk, opt_label) => { if let Some(label) = opt_label { diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 38319862334a..61dd8c573073 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -11,7 +11,7 @@ use rustc_trait_selection::traits::{ use tracing::{debug, instrument}; use crate::coercion::{AsCoercionSite, CoerceMany}; -use crate::{Diverges, Expectation, FnCtxt, Needs}; +use crate::{Diverges, Expectation, FnCtxt, GatherLocalsVisitor, Needs}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug", ret)] @@ -43,6 +43,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // #55810: Type check patterns first so we get types for all bindings. let scrut_span = scrut.span.find_ancestor_inside(expr.span).unwrap_or(scrut.span); for arm in arms { + GatherLocalsVisitor::gather_from_arm(self, arm); + self.check_pat_top(arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut), None); } @@ -601,7 +603,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(-Znext-solver): Remove this branch once `replace_opaque_types_with_infer` is gone. ty::Infer(ty::TyVar(_)) => self .inner - .borrow() + .borrow_mut() + .opaque_types() .iter_opaque_types() .find(|(_, v)| v.ty == expected_ty) .map(|(k, _)| (k.def_id, k.args))?, diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index caf36ba47bd7..5bfc3e810d9f 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -1051,20 +1051,19 @@ impl<'a, 'tcx> CastCheck<'tcx> { fn check_ref_cast( &self, fcx: &FnCtxt<'a, 'tcx>, - m_expr: ty::TypeAndMut<'tcx>, - m_cast: ty::TypeAndMut<'tcx>, + mut m_expr: ty::TypeAndMut<'tcx>, + mut m_cast: ty::TypeAndMut<'tcx>, ) -> Result> { // array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const + m_expr.ty = fcx.try_structurally_resolve_type(self.expr_span, m_expr.ty); + m_cast.ty = fcx.try_structurally_resolve_type(self.cast_span, m_cast.ty); + if m_expr.mutbl >= m_cast.mutbl && let ty::Array(ety, _) = m_expr.ty.kind() && fcx.can_eq(fcx.param_env, *ety, m_cast.ty) { - // Due to the limitations of LLVM global constants, - // region pointers end up pointing at copies of - // vector elements instead of the original values. - // To allow raw pointers to work correctly, we - // need to special-case obtaining a raw pointer - // from a region pointer to a vector. + // Due to historical reasons we allow directly casting references of + // arrays into raw pointers of their element type. // Coerce to a raw pointer so that we generate RawPtr in MIR. let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl); diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 2189fdf0f343..99103f14d682 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -3,7 +3,6 @@ use std::cell::RefCell; use rustc_abi::ExternAbi; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::check::check_function_signature; use rustc_infer::infer::RegionVariableOrigin; @@ -50,7 +49,9 @@ pub(super) fn check_fn<'a, 'tcx>( let span = body.value.span; - GatherLocalsVisitor::new(fcx).visit_body(body); + for param in body.params { + GatherLocalsVisitor::gather_from_param(fcx, param); + } // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` // (as it's created inside the body itself, not passed in from outside). diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index db2650ed357e..2c28ffd1fe3d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -16,7 +16,6 @@ use rustc_errors::{ }; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath}; use rustc_hir_analysis::NoVariantNamed; @@ -50,8 +49,8 @@ use crate::errors::{ YieldExprOutsideOfCoroutine, }; use crate::{ - BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, Needs, TupleArgumentsFlag, cast, - fatally_break_rust, report_unexpected_variant_res, type_error_struct, + BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, GatherLocalsVisitor, Needs, + TupleArgumentsFlag, cast, fatally_break_rust, report_unexpected_variant_res, type_error_struct, }; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -1518,11 +1517,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let_expr: &'tcx hir::LetExpr<'tcx>, hir_id: HirId, ) -> Ty<'tcx> { + GatherLocalsVisitor::gather_from_let_expr(self, let_expr, hir_id); + // for let statements, this is done in check_stmt let init = let_expr.init; self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression"); + // otherwise check exactly as a let statement self.check_decl((let_expr, hir_id).into()); + // but return a bool, for this is a boolean expression if let ast::Recovered::Yes(error_guaranteed) = let_expr.recovered { self.set_tainted_by_errors(error_guaranteed); @@ -1827,7 +1830,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Create a new function context. let def_id = block.def_id; let fcx = FnCtxt::new(self, self.param_env, def_id); - crate::GatherLocalsVisitor::new(&fcx).visit_body(body); let ty = fcx.check_expr_with_expectation(body.value, expected); fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::SizedConstOrStatic); diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 17e13ec0a376..3493d359028d 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -158,7 +158,7 @@ pub trait TypeInformationCtxt<'tcx> { fn resolve_vars_if_possible>>(&self, t: T) -> T; - fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>; + fn structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>; fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error; @@ -191,8 +191,8 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> { self.infcx.resolve_vars_if_possible(t) } - fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - (**self).try_structurally_resolve_type(sp, ty) + fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { + (**self).structurally_resolve_type(sp, ty) } fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error { @@ -236,7 +236,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { self.0.maybe_typeck_results().expect("expected typeck results") } - fn try_structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { + fn structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { // FIXME: Maybe need to normalize here. ty } @@ -776,7 +776,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // Select just those fields of the `with` // expression that will actually be used - match self.cx.try_structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() { + match self.cx.structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() { ty::Adt(adt, args) if adt.is_struct() => { // Consume those fields of the with expression that are needed. for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() { @@ -1176,7 +1176,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// two operations: a dereference to reach the array data and then an index to /// jump forward to the relevant item. impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> { - fn resolve_type_vars_or_bug( + fn expect_and_resolve_type( &self, id: HirId, ty: Option>, @@ -1185,12 +1185,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Some(ty) => { let ty = self.cx.resolve_vars_if_possible(ty); self.cx.error_reported_in_ty(ty)?; - if ty.is_ty_var() { - debug!("resolve_type_vars_or_bug: infer var from {:?}", ty); - Err(self.cx.report_bug(self.cx.tcx().hir_span(id), "encountered type variable")) - } else { - Ok(ty) - } + Ok(ty) } None => { // FIXME: We shouldn't be relying on the infcx being tainted. @@ -1201,15 +1196,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } fn node_ty(&self, hir_id: HirId) -> Result, Cx::Error> { - self.resolve_type_vars_or_bug(hir_id, self.cx.typeck_results().node_type_opt(hir_id)) + self.expect_and_resolve_type(hir_id, self.cx.typeck_results().node_type_opt(hir_id)) } fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result, Cx::Error> { - self.resolve_type_vars_or_bug(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr)) + self.expect_and_resolve_type(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr)) } fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result, Cx::Error> { - self.resolve_type_vars_or_bug( + self.expect_and_resolve_type( expr.hir_id, self.cx.typeck_results().expr_ty_adjusted_opt(expr), ) @@ -1264,10 +1259,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // a bind-by-ref means that the base_ty will be the type of the ident itself, // but what we want here is the type of the underlying value being borrowed. // So peel off one-level, turning the &T into T. - match self - .cx - .try_structurally_resolve_type(pat.span, base_ty) - .builtin_deref(false) + match self.cx.structurally_resolve_type(pat.span, base_ty).builtin_deref(false) { Some(ty) => Ok(ty), None => { @@ -1513,10 +1505,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx if node_ty != place_ty && self .cx - .try_structurally_resolve_type( - self.cx.tcx().hir_span(base_place.hir_id), - place_ty, - ) + .structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), place_ty) .is_impl_trait() { projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty }); @@ -1538,7 +1527,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let base_ty = self.expr_ty_adjusted(base)?; let ty::Ref(region, _, mutbl) = - *self.cx.try_structurally_resolve_type(base.span, base_ty).kind() + *self.cx.structurally_resolve_type(base.span, base_ty).kind() else { span_bug!(expr.span, "cat_overloaded_place: base is not a reference"); }; @@ -1556,7 +1545,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let base_curr_ty = base_place.place.ty(); let deref_ty = match self .cx - .try_structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty) + .structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty) .builtin_deref(true) { Some(ty) => ty, @@ -1584,7 +1573,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx ) -> Result { let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id); let ty = self.cx.typeck_results().node_type(pat_hir_id); - let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else { + let ty::Adt(adt_def, _) = self.cx.structurally_resolve_type(span, ty).kind() else { return Err(self .cx .report_bug(span, "struct or tuple struct pattern not applied to an ADT")); @@ -1616,7 +1605,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx span: Span, ) -> Result { let ty = self.cx.typeck_results().node_type(pat_hir_id); - match self.cx.try_structurally_resolve_type(span, ty).kind() { + match self.cx.structurally_resolve_type(span, ty).kind() { ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()), _ => { self.cx @@ -1631,7 +1620,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// Here `pat_hir_id` is the HirId of the pattern itself. fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> Result { let ty = self.cx.typeck_results().node_type(pat_hir_id); - match self.cx.try_structurally_resolve_type(span, ty).kind() { + match self.cx.structurally_resolve_type(span, ty).kind() { ty::Tuple(args) => Ok(args.len()), _ => Err(self.cx.report_bug(span, "tuple pattern not applied to a tuple")), } @@ -1820,7 +1809,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx PatKind::Slice(before, ref slice, after) => { let Some(element_ty) = self .cx - .try_structurally_resolve_type(pat.span, place_with_id.place.ty()) + .structurally_resolve_type(pat.span, place_with_id.place.ty()) .builtin_index() else { debug!("explicit index of non-indexable type {:?}", place_with_id); @@ -1890,7 +1879,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool { - if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() { + if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() { // Note that if a non-exhaustive SingleVariant is defined in another crate, we need // to assume that more cases will be added to the variant in the future. This mean // that we should handle non-exhaustive SingleVariant the same way we would handle diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c804dc5e7fba..6cc7e82bbf73 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -37,8 +37,8 @@ use crate::method::probe::IsSuggestion; use crate::method::probe::Mode::MethodCall; use crate::method::probe::ProbeScope::TraitsInScope; use crate::{ - BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy, Needs, TupleArgumentsFlag, errors, - struct_span_code_err, + BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs, + TupleArgumentsFlag, errors, struct_span_code_err, }; rustc_index::newtype_index! { @@ -1765,6 +1765,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Type check a `let` statement. fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) { + GatherLocalsVisitor::gather_from_local(self, local); + let ty = self.check_decl(local.into()); self.write_ty(local.hir_id, ty); if local.pat.is_never_pattern() { diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 5d87e800096f..a8bbc89dbded 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -55,6 +55,14 @@ impl<'a> From<(&'a hir::LetExpr<'a>, HirId)> for Declaration<'a> { } } +/// The `GatherLocalsVisitor` is responsible for initializing local variable types +/// in the [`ty::TypeckResults`] for all subpatterns in statements and expressions +/// like `let`, `match`, and params of function bodies. It also adds `Sized` bounds +/// for these types (with exceptions for unsized feature gates like `unsized_fn_params`). +/// +/// Failure to visit locals will cause an ICE in writeback when the local's type is +/// resolved. Visiting locals twice will ICE in the `GatherLocalsVisitor`, since it +/// will overwrite the type previously stored in the local. pub(super) struct GatherLocalsVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, // parameters are special cases of patterns, but we want to handle them as @@ -63,9 +71,37 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> { outermost_fn_param_pat: Option<(Span, HirId)>, } +// N.B. additional `gather_*` functions should be careful to only walk the pattern +// for new expressions, since visiting sub-expressions or nested bodies may initialize +// locals which are not conceptually owned by the gathered statement or expression. impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { - pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>) -> Self { - Self { fcx, outermost_fn_param_pat: None } + pub(crate) fn gather_from_local(fcx: &'a FnCtxt<'a, 'tcx>, local: &'tcx hir::LetStmt<'tcx>) { + let mut visitor = GatherLocalsVisitor { fcx, outermost_fn_param_pat: None }; + visitor.declare(local.into()); + visitor.visit_pat(local.pat); + } + + pub(crate) fn gather_from_let_expr( + fcx: &'a FnCtxt<'a, 'tcx>, + let_expr: &'tcx hir::LetExpr<'tcx>, + expr_hir_id: hir::HirId, + ) { + let mut visitor = GatherLocalsVisitor { fcx, outermost_fn_param_pat: None }; + visitor.declare((let_expr, expr_hir_id).into()); + visitor.visit_pat(let_expr.pat); + } + + pub(crate) fn gather_from_param(fcx: &'a FnCtxt<'a, 'tcx>, param: &'tcx hir::Param<'tcx>) { + let mut visitor = GatherLocalsVisitor { + fcx, + outermost_fn_param_pat: Some((param.ty_span, param.hir_id)), + }; + visitor.visit_pat(param.pat); + } + + pub(crate) fn gather_from_arm(fcx: &'a FnCtxt<'a, 'tcx>, local: &'tcx hir::Arm<'tcx>) { + let mut visitor = GatherLocalsVisitor { fcx, outermost_fn_param_pat: None }; + visitor.visit_pat(local.pat); } fn assign(&mut self, span: Span, nid: HirId, ty_opt: Option>) -> Ty<'tcx> { @@ -73,12 +109,12 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { None => { // Infer the variable's type. let var_ty = self.fcx.next_ty_var(span); - self.fcx.locals.borrow_mut().insert(nid, var_ty); + assert_eq!(self.fcx.locals.borrow_mut().insert(nid, var_ty), None); var_ty } Some(typ) => { // Take type that the user specified. - self.fcx.locals.borrow_mut().insert(nid, typ); + assert_eq!(self.fcx.locals.borrow_mut().insert(nid, typ), None); typ } } @@ -133,13 +169,6 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { intravisit::walk_expr(self, expr) } - fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - let old_outermost_fn_param_pat = - self.outermost_fn_param_pat.replace((param.ty_span, param.hir_id)); - intravisit::walk_param(self, param); - self.outermost_fn_param_pat = old_outermost_fn_param_pat; - } - // Add pattern bindings. fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) { if let PatKind::Binding(_, _, ident, _) = p.kind { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index d861a4f81b0e..60187abd5589 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -32,6 +32,7 @@ mod gather_locals; mod intrinsicck; mod method; mod op; +mod opaque_types; mod pat; mod place_op; mod rvalue_scopes; @@ -46,7 +47,6 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::intravisit::Visitor; use rustc_hir::{HirId, HirIdMap, Node}; use rustc_hir_analysis::check::check_abi; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; @@ -191,9 +191,6 @@ fn typeck_with_inspect<'tcx>( let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id))); fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code); - // Gather locals in statics (because of block expressions). - GatherLocalsVisitor::new(&fcx).visit_body(body); - fcx.check_expr_coercible_to_type(body.value, expected_type, None); fcx.write_ty(id, expected_type); @@ -249,9 +246,7 @@ fn typeck_with_inspect<'tcx>( let typeck_results = fcx.resolve_type_vars_in_body(body); - // We clone the defined opaque types during writeback in the new solver - // because we have to use them during normalization. - let _ = fcx.infcx.take_opaque_types(); + fcx.detect_opaque_types_added_during_writeback(); // Consistency check our TypeckResults instance can hold all ItemLocalIds // it will need to hold. diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs new file mode 100644 index 000000000000..e0224f8c6e1b --- /dev/null +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -0,0 +1,26 @@ +use super::FnCtxt; +impl<'tcx> FnCtxt<'_, 'tcx> { + /// We may in theory add further uses of an opaque after cloning the opaque + /// types storage during writeback when computing the defining uses. + /// + /// Silently ignoring them is dangerous and could result in ICE or even in + /// unsoundness, so we make sure we catch such cases here. There's currently + /// no known code where this actually happens, even with the new solver which + /// does normalize types in writeback after cloning the opaque type storage. + /// + /// FIXME(@lcnr): I believe this should be possible in theory and would like + /// an actual test here. After playing around with this for an hour, I wasn't + /// able to do anything which didn't already try to normalize the opaque before + /// then, either allowing compilation to succeed or causing an ambiguity error. + pub(super) fn detect_opaque_types_added_during_writeback(&self) { + let num_entries = self.checked_opaque_types_storage_entries.take().unwrap(); + for (key, hidden_type) in + self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries) + { + let opaque_type_string = self.tcx.def_path_str(key.def_id); + let msg = format!("unexpected cyclic definition of `{opaque_type_string}`"); + self.dcx().span_delayed_bug(hidden_type.span, msg); + } + let _ = self.take_opaque_types(); + } +} diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 7520782930a2..17d48184dd97 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -177,16 +177,20 @@ enum PeelKind { /// Only peel reference types. This is used for explicit `deref!(_)` patterns, which dereference /// any number of `&`/`&mut` references, plus a single smart pointer. ExplicitDerefPat, - /// Implicitly peel any number of references, and if `deref_patterns` is enabled, smart pointer - /// ADTs. In order to peel only as much as necessary for the pattern to match, the `until_adt` - /// field contains the ADT def that the pattern is a constructor for, if applicable, so that we - /// don't peel it. See [`ResolvedPat`] for more information. - Implicit { until_adt: Option }, + /// Implicitly peel references, and if `deref_patterns` is enabled, smart pointer ADTs. + Implicit { + /// The ADT the pattern is a constructor for, if applicable, so that we don't peel it. See + /// [`ResolvedPat`] for more information. + until_adt: Option, + /// The number of references at the head of the pattern's type, so we can leave that many + /// untouched. This is `1` for string literals, and `0` for most patterns. + pat_ref_layers: usize, + }, } impl AdjustMode { const fn peel_until_adt(opt_adt_def: Option) -> AdjustMode { - AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: opt_adt_def } } + AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: opt_adt_def, pat_ref_layers: 0 } } } const fn peel_all() -> AdjustMode { AdjustMode::peel_until_adt(None) @@ -488,9 +492,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match pat.kind { // Peel off a `&` or `&mut` from the scrutinee type. See the examples in // `tests/ui/rfcs/rfc-2005-default-binding-mode`. - _ if let AdjustMode::Peel { .. } = adjust_mode + _ if let AdjustMode::Peel { kind: peel_kind } = adjust_mode && pat.default_binding_modes - && let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() => + && let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() + && self.should_peel_ref(peel_kind, expected) => { debug!("inspecting {:?}", expected); @@ -531,24 +536,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If `deref_patterns` is enabled, peel a smart pointer from the scrutinee type. See the // examples in `tests/ui/pattern/deref_patterns/`. _ if self.tcx.features().deref_patterns() - && let AdjustMode::Peel { kind: PeelKind::Implicit { until_adt } } = adjust_mode + && let AdjustMode::Peel { kind: peel_kind } = adjust_mode && pat.default_binding_modes - // For simplicity, only apply overloaded derefs if `expected` is a known ADT. - // FIXME(deref_patterns): we'll get better diagnostics for users trying to - // implicitly deref generics if we allow them here, but primitives, tuples, and - // inference vars definitely should be stopped. Figure out what makes most sense. - && let ty::Adt(scrutinee_adt, _) = *expected.kind() - // Don't peel if the pattern type already matches the scrutinee. E.g., stop here if - // matching on a `Cow<'a, T>` scrutinee with a `Cow::Owned(_)` pattern. - && until_adt != Some(scrutinee_adt.did()) - // At this point, the pattern isn't able to match `expected` without peeling. Check - // that it implements `Deref` before assuming it's a smart pointer, to get a normal - // type error instead of a missing impl error if not. This only checks for `Deref`, - // not `DerefPure`: we require that too, but we want a trait error if it's missing. - && let Some(deref_trait) = self.tcx.lang_items().deref_trait() - && self - .type_implements_trait(deref_trait, [expected], self.param_env) - .may_apply() => + && self.should_peel_smart_pointer(peel_kind, expected) => { debug!("scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref"); // The scrutinee is a smart pointer; implicitly dereference it. This adds a @@ -660,14 +650,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &pat.kind { // Type checking these product-like types successfully always require // that the expected type be of those types and not reference types. - PatKind::Tuple(..) - | PatKind::Range(..) - | PatKind::Slice(..) => AdjustMode::peel_all(), + PatKind::Tuple(..) | PatKind::Range(..) | PatKind::Slice(..) => AdjustMode::peel_all(), // When checking an explicit deref pattern, only peel reference types. // FIXME(deref_patterns): If box patterns and deref patterns need to coexist, box // patterns may want `PeelKind::Implicit`, stopping on encountering a box. - | PatKind::Box(_) - | PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat }, + PatKind::Box(_) | PatKind::Deref(_) => { + AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat } + } // A never pattern behaves somewhat like a literal or unit variant. PatKind::Never => AdjustMode::peel_all(), // For patterns with paths, how we peel the scrutinee depends on the path's resolution. @@ -680,23 +669,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // String and byte-string literals result in types `&str` and `&[u8]` respectively. // All other literals result in non-reference types. - // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`. - // - // Call `resolve_vars_if_possible` here for inline const blocks. - PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() { - ty::Ref(..) => AdjustMode::Pass, - _ => { - // Path patterns have already been handled, and inline const blocks currently - // aren't possible to write, so any handling for them would be untested. - if cfg!(debug_assertions) - && self.tcx.features().deref_patterns() - && !matches!(lt.kind, PatExprKind::Lit { .. }) - { - span_bug!(lt.span, "FIXME(deref_patterns): adjust mode unimplemented for {:?}", lt.kind); - } - AdjustMode::peel_all() + // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}` unless + // `deref_patterns` is enabled. + PatKind::Expr(lt) => { + // Path patterns have already been handled, and inline const blocks currently + // aren't possible to write, so any handling for them would be untested. + if cfg!(debug_assertions) + && self.tcx.features().deref_patterns() + && !matches!(lt.kind, PatExprKind::Lit { .. }) + { + span_bug!( + lt.span, + "FIXME(deref_patterns): adjust mode unimplemented for {:?}", + lt.kind + ); } - }, + // Call `resolve_vars_if_possible` here for inline const blocks. + let lit_ty = self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)); + // If `deref_patterns` is enabled, allow `if let "foo" = &&"foo" {}`. + if self.tcx.features().deref_patterns() { + let mut peeled_ty = lit_ty; + let mut pat_ref_layers = 0; + while let ty::Ref(_, inner_ty, mutbl) = + *self.try_structurally_resolve_type(pat.span, peeled_ty).kind() + { + // We rely on references at the head of constants being immutable. + debug_assert!(mutbl.is_not()); + pat_ref_layers += 1; + peeled_ty = inner_ty; + } + AdjustMode::Peel { + kind: PeelKind::Implicit { until_adt: None, pat_ref_layers }, + } + } else { + if lit_ty.is_ref() { AdjustMode::Pass } else { AdjustMode::peel_all() } + } + } // Ref patterns are complicated, we handle them in `check_pat_ref`. PatKind::Ref(..) @@ -720,6 +728,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Assuming `expected` is a reference type, determine whether to peel it before matching. + fn should_peel_ref(&self, peel_kind: PeelKind, mut expected: Ty<'tcx>) -> bool { + debug_assert!(expected.is_ref()); + let pat_ref_layers = match peel_kind { + PeelKind::ExplicitDerefPat => 0, + PeelKind::Implicit { pat_ref_layers, .. } => pat_ref_layers, + }; + + // Most patterns don't have reference types, so we'll want to peel all references from the + // scrutinee before matching. To optimize for the common case, return early. + if pat_ref_layers == 0 { + return true; + } + debug_assert!( + self.tcx.features().deref_patterns(), + "Peeling for patterns with reference types is gated by `deref_patterns`." + ); + + // If the pattern has as many or more layers of reference as the expected type, we can match + // without peeling more, unless we find a smart pointer or `&mut` that we also need to peel. + // We don't treat `&` and `&mut` as interchangeable, but by peeling `&mut`s before matching, + // we can still, e.g., match on a `&mut str` with a string literal pattern. This is because + // string literal patterns may be used where `str` is expected. + let mut expected_ref_layers = 0; + while let ty::Ref(_, inner_ty, mutbl) = *expected.kind() { + if mutbl.is_mut() { + // Mutable references can't be in the final value of constants, thus they can't be + // at the head of their types, thus we should always peel `&mut`. + return true; + } + expected_ref_layers += 1; + expected = inner_ty; + } + pat_ref_layers < expected_ref_layers || self.should_peel_smart_pointer(peel_kind, expected) + } + + /// Determine whether `expected` is a smart pointer type that should be peeled before matching. + fn should_peel_smart_pointer(&self, peel_kind: PeelKind, expected: Ty<'tcx>) -> bool { + // Explicit `deref!(_)` patterns match against smart pointers; don't peel in that case. + if let PeelKind::Implicit { until_adt, .. } = peel_kind + // For simplicity, only apply overloaded derefs if `expected` is a known ADT. + // FIXME(deref_patterns): we'll get better diagnostics for users trying to + // implicitly deref generics if we allow them here, but primitives, tuples, and + // inference vars definitely should be stopped. Figure out what makes most sense. + && let ty::Adt(scrutinee_adt, _) = *expected.kind() + // Don't peel if the pattern type already matches the scrutinee. E.g., stop here if + // matching on a `Cow<'a, T>` scrutinee with a `Cow::Owned(_)` pattern. + && until_adt != Some(scrutinee_adt.did()) + // At this point, the pattern isn't able to match `expected` without peeling. Check + // that it implements `Deref` before assuming it's a smart pointer, to get a normal + // type error instead of a missing impl error if not. This only checks for `Deref`, + // not `DerefPure`: we require that too, but we want a trait error if it's missing. + && let Some(deref_trait) = self.tcx.lang_items().deref_trait() + && self.type_implements_trait(deref_trait, [expected], self.param_env).may_apply() + { + true + } else { + false + } + } + fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> { let ty = match <.kind { rustc_hir::PatExprKind::Lit { lit, negated } => { @@ -866,6 +935,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // be peeled to `str` while ty here is still `&str`, if we don't // err early here, a rather confusing unification error will be // emitted instead). + let ty = self.try_structurally_resolve_type(expr.span, ty); let fail = !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error()); Some((fail, ty, expr.span)) diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index 56859eef45f7..26be5fc6d190 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -1,10 +1,10 @@ -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::ops::Deref; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, HirId, HirIdMap, LangItem}; -use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt}; use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::Span; @@ -37,6 +37,11 @@ pub(crate) struct TypeckRootCtxt<'tcx> { pub(super) fulfillment_cx: RefCell>>>, + // Used to detect opaque types uses added after we've already checked them. + // + // See [FnCtxt::detect_opaque_types_added_during_writeback] for more details. + pub(super) checked_opaque_types_storage_entries: Cell>, + /// Some additional `Sized` obligations badly affect type inference. /// These obligations are added in a later stage of typeck. /// Removing these may also cause additional complications, see #101066. @@ -85,12 +90,14 @@ impl<'tcx> TypeckRootCtxt<'tcx> { let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::typeck_for_body(tcx, def_id)); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); + let fulfillment_cx = RefCell::new(>::new(&infcx)); TypeckRootCtxt { - typeck_results, - fulfillment_cx: RefCell::new(>::new(&infcx)), infcx, + typeck_results, locals: RefCell::new(Default::default()), + fulfillment_cx, + checked_opaque_types_storage_entries: Cell::new(None), deferred_sized_obligations: RefCell::new(Vec::new()), deferred_call_resolutions: RefCell::new(Default::default()), deferred_cast_checks: RefCell::new(Vec::new()), diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 4a171a08ef72..9be041f75d76 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -535,13 +535,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let tcx = self.tcx(); // We clone the opaques instead of stealing them here as they are still used for // normalization in the next generation trait solver. - // - // FIXME(-Znext-solver): Opaque types defined after this would simply get dropped - // at the end of typeck. While this seems unlikely to happen in practice this - // should still get fixed. Either by preventing writeback from defining new opaque - // types or by using this function at the end of writeback and running it as a - // fixpoint. let opaque_types = self.fcx.infcx.clone_opaque_types(); + let num_entries = self.fcx.inner.borrow_mut().opaque_types().num_entries(); + let prev = self.fcx.checked_opaque_types_storage_entries.replace(Some(num_entries)); + debug_assert_eq!(prev, None); for (opaque_type_key, hidden_type) in opaque_types { let hidden_type = self.resolve(hidden_type, &hidden_type.span); let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span); @@ -555,15 +552,16 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - if let Err(guar) = check_opaque_type_parameter_valid( + if let Err(err) = check_opaque_type_parameter_valid( &self.fcx, opaque_type_key, hidden_type.span, DefiningScopeKind::HirTypeck, ) { - self.typeck_results - .concrete_opaque_types - .insert(opaque_type_key.def_id, ty::OpaqueHiddenType::new_error(tcx, guar)); + self.typeck_results.concrete_opaque_types.insert( + opaque_type_key.def_id, + ty::OpaqueHiddenType::new_error(tcx, err.report(self.fcx)), + ); } let hidden_type = hidden_type.remap_generic_params_to_declaration_params( diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 1b2056f541f3..0e04a2a784ec 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -38,7 +38,7 @@ use std::fs::{self, File}; use std::io::Write; use rustc_data_structures::fx::FxIndexSet; -use rustc_data_structures::graph::implementation::{Direction, INCOMING, NodeIndex, OUTGOING}; +use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, NodeIndex, OUTGOING}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::dep_graph::{ diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 94ce6d9fa81f..58fea3278a83 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -44,10 +44,6 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) { sess.time("assert_dep_graph", || assert_dep_graph(tcx)); sess.time("check_dirty_clean", || dirty_clean::check_dirty_clean_annotations(tcx)); - if sess.opts.unstable_opts.incremental_info { - tcx.dep_graph.print_incremental_info() - } - join( move || { sess.time("incr_comp_persist_dep_graph", || { @@ -172,12 +168,5 @@ pub(crate) fn build_dep_graph( // First encode the commandline arguments hash sess.opts.dep_tracking_hash(false).encode(&mut encoder); - Some(DepGraph::new( - sess, - prev_graph, - prev_work_products, - encoder, - sess.opts.unstable_opts.query_dep_graph, - sess.opts.unstable_opts.incremental_info, - )) + Some(DepGraph::new(sess, prev_graph, prev_work_products, encoder)) } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 5220071c5005..1ae864c454f2 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -132,7 +132,13 @@ impl<'tcx> InferCtxt<'tcx> { let certainty = if errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous }; - let opaque_types = self.take_opaque_types_for_query_response(); + let opaque_types = self + .inner + .borrow_mut() + .opaque_type_storage + .take_opaque_types() + .map(|(k, v)| (k, v.ty)) + .collect(); Ok(QueryResponse { var_values: inference_vars, @@ -143,24 +149,6 @@ impl<'tcx> InferCtxt<'tcx> { }) } - /// Used by the new solver as that one takes the opaque types at the end of a probe - /// to deal with multiple candidates without having to recompute them. - pub fn clone_opaque_types_for_query_response( - &self, - ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { - self.inner - .borrow() - .opaque_type_storage - .opaque_types - .iter() - .map(|(k, v)| (*k, v.ty)) - .collect() - } - - fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { - self.take_opaque_types().into_iter().map(|(k, v)| (k, v.ty)).collect() - } - /// Given the (canonicalized) result to a canonical query, /// instantiates the result so it can be used, plugging in the /// values from the canonical query. (Note that the result may diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 75affa139770..359b9da11ced 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -6,7 +6,10 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; -use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin}; +use super::{ + BoundRegionConversionTime, InferCtxt, OpaqueTypeStorageEntries, RegionVariableOrigin, + SubregionOrigin, +}; impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { type Interner = TyCtxt<'tcx>; @@ -121,19 +124,19 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.enter_forall(value, f) } - fn equate_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) { + fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) { self.inner.borrow_mut().type_variables().equate(a, b); } - fn equate_int_vids_raw(&self, a: rustc_type_ir::IntVid, b: rustc_type_ir::IntVid) { + fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid) { self.inner.borrow_mut().int_unification_table().union(a, b); } - fn equate_float_vids_raw(&self, a: rustc_type_ir::FloatVid, b: rustc_type_ir::FloatVid) { + fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid) { self.inner.borrow_mut().float_unification_table().union(a, b); } - fn equate_const_vids_raw(&self, a: rustc_type_ir::ConstVid, b: rustc_type_ir::ConstVid) { + fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid) { self.inner.borrow_mut().const_unification_table().union(a, b); } @@ -141,8 +144,8 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { &self, relation: &mut R, target_is_expected: bool, - target_vid: rustc_type_ir::TyVid, - instantiation_variance: rustc_type_ir::Variance, + target_vid: ty::TyVid, + instantiation_variance: ty::Variance, source_ty: Ty<'tcx>, ) -> RelateResult<'tcx, ()> { self.instantiate_ty_var( @@ -154,19 +157,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { ) } - fn instantiate_int_var_raw( - &self, - vid: rustc_type_ir::IntVid, - value: rustc_type_ir::IntVarValue, - ) { + fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue) { self.inner.borrow_mut().int_unification_table().union_value(vid, value); } - fn instantiate_float_var_raw( - &self, - vid: rustc_type_ir::FloatVid, - value: rustc_type_ir::FloatVarValue, - ) { + fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue) { self.inner.borrow_mut().float_unification_table().union_value(vid, value); } @@ -174,7 +169,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { &self, relation: &mut R, target_is_expected: bool, - target_vid: rustc_type_ir::ConstVid, + target_vid: ty::ConstVid, source_ct: ty::Const<'tcx>, ) -> RelateResult<'tcx, ()> { self.instantiate_const_var(relation, target_is_expected, target_vid, source_ct) @@ -221,4 +216,58 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) { self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span)); } + + type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries; + fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries { + self.inner.borrow_mut().opaque_types().num_entries() + } + fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect() + } + fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + self.inner + .borrow_mut() + .opaque_types() + .iter_duplicate_entries() + .map(|(k, h)| (k, h.ty)) + .collect() + } + fn clone_opaque_types_added_since( + &self, + prev_entries: OpaqueTypeStorageEntries, + ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + self.inner + .borrow_mut() + .opaque_types() + .opaque_types_added_since(prev_entries) + .map(|(k, h)| (k, h.ty)) + .collect() + } + + fn register_hidden_type_in_storage( + &self, + opaque_type_key: ty::OpaqueTypeKey<'tcx>, + hidden_ty: Ty<'tcx>, + span: Span, + ) -> Option> { + self.register_hidden_type_in_storage( + opaque_type_key, + ty::OpaqueHiddenType { span, ty: hidden_ty }, + ) + } + fn add_duplicate_opaque_type( + &self, + opaque_type_key: ty::OpaqueTypeKey<'tcx>, + hidden_ty: Ty<'tcx>, + span: Span, + ) { + self.inner + .borrow_mut() + .opaque_types() + .add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty }) + } + + fn reset_opaque_types(&self) { + let _ = self.take_opaque_types(); + } } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index e3522137d838..2185886901e5 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -3,8 +3,8 @@ use std::fmt; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::graph::implementation::{ - Direction, Graph, INCOMING, NodeIndex, OUTGOING, +use rustc_data_structures::graph::linked_graph::{ + Direction, INCOMING, LinkedGraph, NodeIndex, OUTGOING, }; use rustc_data_structures::intern::Interned; use rustc_data_structures::unord::UnordSet; @@ -118,7 +118,7 @@ struct RegionAndOrigin<'tcx> { origin: SubregionOrigin<'tcx>, } -type RegionGraph<'tcx> = Graph<(), Constraint<'tcx>>; +type RegionGraph<'tcx> = LinkedGraph<(), Constraint<'tcx>>; struct LexicalResolver<'cx, 'tcx> { region_rels: &'cx RegionRelations<'cx, 'tcx>, @@ -668,7 +668,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { fn construct_graph(&self) -> RegionGraph<'tcx> { let num_vars = self.num_vars(); - let mut graph = Graph::new(); + let mut graph = LinkedGraph::new(); for _ in 0..num_vars { graph.add_node(()); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index d25542dadd59..b408d76010d7 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -9,7 +9,7 @@ use free_regions::RegionRelations; pub use freshen::TypeFreshener; use lexical_region_resolve::LexicalRegionResolutions; pub use lexical_region_resolve::RegionResolutionError; -use opaque_types::OpaqueTypeStorage; +pub use opaque_types::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable}; use region_constraints::{ GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound, }; @@ -31,9 +31,9 @@ use rustc_middle::traits::solve::Goal; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, - GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Term, TermKind, - Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, - TypeVisitableExt, TypingEnv, TypingMode, fold_regions, + GenericArgsRef, GenericParamDefKind, InferConst, IntVid, OpaqueHiddenType, OpaqueTypeKey, + PseudoCanonicalInput, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions, }; use rustc_span::{Span, Symbol}; use snapshot::undo_log::InferCtxtUndoLogs; @@ -198,7 +198,7 @@ impl<'tcx> InferCtxtInner<'tcx> { } #[inline] - fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> { + pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> { self.opaque_type_storage.with_log(&mut self.undo_log) } @@ -224,15 +224,6 @@ impl<'tcx> InferCtxtInner<'tcx> { .expect("region constraints already solved") .with_log(&mut self.undo_log) } - - // Iterates through the opaque type definitions without taking them; this holds the - // `InferCtxtInner` lock, so make sure to not do anything with `InferCtxt` side-effects - // while looping through this. - pub fn iter_opaque_types( - &self, - ) -> impl Iterator, ty::OpaqueHiddenType<'tcx>)> { - self.opaque_type_storage.opaque_types.iter().map(|(&k, &v)| (k, v)) - } } pub struct InferCtxt<'tcx> { @@ -954,13 +945,13 @@ impl<'tcx> InferCtxt<'tcx> { } #[instrument(level = "debug", skip(self), ret)] - pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> { - std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types) + pub fn take_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> { + self.inner.borrow_mut().opaque_type_storage.take_opaque_types().collect() } #[instrument(level = "debug", skip(self), ret)] - pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> { - self.inner.borrow().opaque_type_storage.opaque_types.clone() + pub fn clone_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> { + self.inner.borrow_mut().opaque_type_storage.iter_opaque_types().collect() } #[inline(always)] diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index ce5d2e6e17a9..220d5e9bda2d 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -1,5 +1,4 @@ use hir::def_id::{DefId, LocalDefId}; -use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_middle::bug; use rustc_middle::traits::ObligationCause; @@ -19,8 +18,7 @@ use crate::traits::{self, Obligation, PredicateObligations}; mod table; -pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap, OpaqueHiddenType<'tcx>>; -pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable}; +pub use table::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable}; impl<'tcx> InferCtxt<'tcx> { /// This is a backwards compatibility hack to prevent breaking changes from diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index ba6cc0d783dd..46752840e1ba 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -1,18 +1,27 @@ +use std::ops::Deref; + +use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::bug; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty}; use tracing::instrument; -use super::OpaqueTypeMap; use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog}; #[derive(Default, Debug, Clone)] -pub(crate) struct OpaqueTypeStorage<'tcx> { - /// Opaque types found in explicit return types and their - /// associated fresh inference variable. Writeback resolves these - /// variables to get the concrete type, which can be used to - /// 'de-opaque' OpaqueHiddenType, after typeck is done with all functions. - pub opaque_types: OpaqueTypeMap<'tcx>, +pub struct OpaqueTypeStorage<'tcx> { + opaque_types: FxIndexMap, OpaqueHiddenType<'tcx>>, + duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>, +} + +/// The number of entries in the opaque type storage at a given point. +/// +/// Used to check that we haven't added any new opaque types after checking +/// the opaque types currently in the storage. +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] +pub struct OpaqueTypeStorageEntries { + opaque_types: usize, + duplicate_entries: usize, } impl<'tcx> OpaqueTypeStorage<'tcx> { @@ -33,6 +42,70 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { } } + pub(crate) fn pop_duplicate_entry(&mut self) { + let entry = self.duplicate_entries.pop(); + assert!(entry.is_some()); + } + + pub(crate) fn is_empty(&self) -> bool { + let OpaqueTypeStorage { opaque_types, duplicate_entries } = self; + opaque_types.is_empty() && duplicate_entries.is_empty() + } + + pub(crate) fn take_opaque_types( + &mut self, + ) -> impl Iterator, OpaqueHiddenType<'tcx>)> { + let OpaqueTypeStorage { opaque_types, duplicate_entries } = self; + std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries)) + } + + pub fn num_entries(&self) -> OpaqueTypeStorageEntries { + OpaqueTypeStorageEntries { + opaque_types: self.opaque_types.len(), + duplicate_entries: self.duplicate_entries.len(), + } + } + + pub fn opaque_types_added_since( + &self, + prev_entries: OpaqueTypeStorageEntries, + ) -> impl Iterator, OpaqueHiddenType<'tcx>)> { + self.opaque_types + .iter() + .skip(prev_entries.opaque_types) + .map(|(k, v)| (*k, *v)) + .chain(self.duplicate_entries.iter().skip(prev_entries.duplicate_entries).copied()) + } + + /// Only returns the opaque types from the lookup table. These are used + /// when normalizing opaque types and have a unique key. + /// + /// Outside of canonicalization one should generally use `iter_opaque_types` + /// to also consider duplicate entries. + pub fn iter_lookup_table( + &self, + ) -> impl Iterator, OpaqueHiddenType<'tcx>)> { + self.opaque_types.iter().map(|(k, v)| (*k, *v)) + } + + /// Only returns the opaque types which are stored in `duplicate_entries`. + /// + /// These have to considered when checking all opaque type uses but are e.g. + /// irrelevant for canonical inputs as nested queries never meaningfully + /// accesses them. + pub fn iter_duplicate_entries( + &self, + ) -> impl Iterator, OpaqueHiddenType<'tcx>)> { + self.duplicate_entries.iter().copied() + } + + pub fn iter_opaque_types( + &self, + ) -> impl Iterator, OpaqueHiddenType<'tcx>)> { + let OpaqueTypeStorage { opaque_types, duplicate_entries } = self; + opaque_types.iter().map(|(k, v)| (*k, *v)).chain(duplicate_entries.iter().copied()) + } + #[inline] pub(crate) fn with_log<'a>( &'a mut self, @@ -44,21 +117,27 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { impl<'tcx> Drop for OpaqueTypeStorage<'tcx> { fn drop(&mut self) { - if !self.opaque_types.is_empty() { + if !self.is_empty() { ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{:?}", self.opaque_types))); } } } -pub(crate) struct OpaqueTypeTable<'a, 'tcx> { +pub struct OpaqueTypeTable<'a, 'tcx> { storage: &'a mut OpaqueTypeStorage<'tcx>, undo_log: &'a mut InferCtxtUndoLogs<'tcx>, } +impl<'tcx> Deref for OpaqueTypeTable<'_, 'tcx> { + type Target = OpaqueTypeStorage<'tcx>; + fn deref(&self) -> &Self::Target { + self.storage + } +} impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { #[instrument(skip(self), level = "debug")] - pub(crate) fn register( + pub fn register( &mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>, @@ -72,4 +151,9 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { self.undo_log.push(UndoLog::OpaqueTypes(key, None)); None } + + pub fn add_duplicate(&mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>) { + self.storage.duplicate_entries.push((key, hidden_type)); + self.undo_log.push(UndoLog::DuplicateOpaqueType); + } } diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index c44d9723f29d..2a4b9776f68c 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -24,10 +24,6 @@ impl<'tcx, OP> TypeVisitor> for FreeRegionsVisitor<'tcx, OP> where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { - t.super_visit_with(self); - } - fn visit_region(&mut self, r: ty::Region<'tcx>) { match r.kind() { // ignore bound regions, keep visiting diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index a89cef50c9b4..8dde99c45cfa 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -63,11 +63,11 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::bug; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::NoSolution; +use rustc_middle::ty::outlives::{Component, push_outlives_components}; use rustc_middle::ty::{ self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesPredicate, Region, Ty, TyCtxt, TypeFoldable as _, TypeVisitableExt, }; -use rustc_type_ir::outlives::{Component, push_outlives_components}; use smallvec::smallvec; use tracing::{debug, instrument}; diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index c14c288c6e4e..69feecfe30a4 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -1,7 +1,7 @@ use std::assert_matches::assert_matches; +use rustc_middle::ty::outlives::{Component, compute_alias_components_recursive}; use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt}; -use rustc_type_ir::outlives::{Component, compute_alias_components_recursive}; use smallvec::smallvec; use tracing::{debug, instrument, trace}; diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index 1bee9632110b..2a4f9db8963c 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -1,7 +1,8 @@ use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty; use super::InferCtxt; +use crate::infer::Term; use crate::traits::{Obligation, PredicateObligations}; impl<'tcx> InferCtxt<'tcx> { @@ -11,24 +12,32 @@ impl<'tcx> InferCtxt<'tcx> { /// of the given projection. This allows us to proceed with projections /// while they cannot be resolved yet due to missing information or /// simply due to the lack of access to the trait resolution machinery. - pub fn projection_ty_to_infer( + pub fn projection_term_to_infer( &self, param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::AliasTy<'tcx>, + alias_term: ty::AliasTerm<'tcx>, cause: ObligationCause<'tcx>, recursion_depth: usize, obligations: &mut PredicateObligations<'tcx>, - ) -> Ty<'tcx> { + ) -> Term<'tcx> { debug_assert!(!self.next_trait_solver()); - let ty_var = self.next_ty_var(self.tcx.def_span(projection_ty.def_id)); + + let span = self.tcx.def_span(alias_term.def_id); + let infer_var = if alias_term.kind(self.tcx).is_type() { + self.next_ty_var(span).into() + } else { + self.next_const_var(span).into() + }; + let projection = ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_term: projection_ty.into(), - term: ty_var.into(), + projection_term: alias_term, + term: infer_var, })); let obligation = Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); obligations.push(obligation); - ty_var + + infer_var } } diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs index e6d1003cab61..6d25dfeb8593 100644 --- a/compiler/rustc_infer/src/infer/relate/mod.rs +++ b/compiler/rustc_infer/src/infer/relate/mod.rs @@ -2,9 +2,8 @@ //! (except for some relations used for diagnostics and heuristics in the compiler). //! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc). -pub use rustc_middle::ty::relate::RelateResult; -pub use rustc_type_ir::relate::combine::PredicateEmittingRelation; -pub use rustc_type_ir::relate::*; +pub use rustc_middle::ty::relate::combine::PredicateEmittingRelation; +pub use rustc_middle::ty::relate::{RelateResult, *}; mod generalize; mod higher_ranked; diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 009271a8378f..04ff776594e6 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -3,9 +3,8 @@ use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys} use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, relate_args_invariantly, relate_args_with_variances, }; -use rustc_middle::ty::{self, Ty, TyCtxt, TyVar}; +use rustc_middle::ty::{self, DelayedSet, Ty, TyCtxt, TyVar}; use rustc_span::Span; -use rustc_type_ir::data_structures::DelayedSet; use tracing::{debug, instrument}; use crate::infer::BoundRegionConversionTime::HigherRankedType; diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 245f1a4ac5ed..4b0ace8c554d 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,9 +1,8 @@ use rustc_middle::bug; use rustc_middle::ty::{ - self, Const, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder, + self, Const, DelayedMap, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; -use rustc_type_ir::data_structures::DelayedMap; use super::{FixupError, FixupResult, InferCtxt}; diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index 39c8c40ea7d8..e210479581ba 100644 --- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -3,9 +3,8 @@ use std::ops::Range; use rustc_data_structures::{snapshot_vec as sv, unify as ut}; use rustc_middle::ty::{ self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, - TypeSuperFoldable, + TypeSuperFoldable, TypeVisitableExt, }; -use rustc_type_ir::TypeVisitableExt; use tracing::instrument; use ut::UnifyKey; diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs index ba7d8f588e68..b7412d3d6a6d 100644 --- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs +++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs @@ -17,6 +17,7 @@ pub struct Snapshot<'tcx> { /// Records the "undo" data for a single operation that affects some form of inference variable. #[derive(Clone)] pub(crate) enum UndoLog<'tcx> { + DuplicateOpaqueType, OpaqueTypes(OpaqueTypeKey<'tcx>, Option>), TypeVariables(sv::UndoLog>>), ConstUnificationTable(sv::UndoLog>>), @@ -58,6 +59,7 @@ impl_from! { impl<'tcx> Rollback> for InferCtxtInner<'tcx> { fn reverse(&mut self, undo: UndoLog<'tcx>) { match undo { + UndoLog::DuplicateOpaqueType => self.opaque_type_storage.pop_duplicate_entry(), UndoLog::OpaqueTypes(key, idx) => self.opaque_type_storage.remove(key, idx), UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo), UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo), diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 66ed49fe3267..6461fbe0d33b 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -1,7 +1,7 @@ use rustc_data_structures::fx::FxHashSet; +pub use rustc_middle::ty::elaborate::*; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{Ident, Span}; -pub use rustc_type_ir::elaborate::*; use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation}; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 493b1d5eaa93..f4d11a7c0be2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -31,10 +31,11 @@ use rustc_resolve::Resolver; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; use rustc_session::output::{collect_crate_types, filename_for_input}; +use rustc_session::parse::feature_err; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::{ - ErrorGuaranteed, FileName, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym, + DUMMY_SP, ErrorGuaranteed, FileName, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym, }; use rustc_target::spec::PanicStrategy; use rustc_trait_selection::traits; @@ -237,6 +238,7 @@ fn configure_and_expand( sess, features, &krate, + tcx.is_sdylib_interface_build(), resolver.lint_buffer(), ) }); @@ -253,6 +255,9 @@ fn configure_and_expand( sess.dcx().emit_err(errors::MixedProcMacroCrate); } } + if crate_types.contains(&CrateType::Sdylib) && !tcx.features().export_stable() { + feature_err(sess, sym::export_stable, DUMMY_SP, "`sdylib` crate type is unstable").emit(); + } if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort { sess.dcx().emit_warn(errors::ProcMacroCratePanicAbort); @@ -742,6 +747,25 @@ pub fn write_dep_info(tcx: TyCtxt<'_>) { } } +pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) { + if !tcx.crate_types().contains(&rustc_session::config::CrateType::Sdylib) { + return; + } + let _timer = tcx.sess.timer("write_interface"); + let (_, krate) = &*tcx.resolver_for_lowering().borrow(); + + let krate = rustc_ast_pretty::pprust::print_crate_as_interface( + krate, + tcx.sess.psess.edition, + &tcx.sess.psess.attr_id_generator, + ); + let export_output = tcx.output_filenames(()).interface_path(); + let mut file = fs::File::create_buffered(export_output).unwrap(); + if let Err(err) = write!(file, "{}", krate) { + tcx.dcx().fatal(format!("error writing interface file: {}", err)); + } +} + pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; @@ -930,6 +954,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { CStore::from_tcx(tcx).report_unused_deps(tcx); }, { + tcx.ensure_ok().exportable_items(LOCAL_CRATE); + tcx.ensure_ok().stable_order_of_exportable_impls(LOCAL_CRATE); tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_mod_loops(module); tcx.ensure_ok().check_mod_attrs(module); diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs index e0e3bd0e30b1..526693d3de1f 100644 --- a/compiler/rustc_lexer/src/cursor.rs +++ b/compiler/rustc_lexer/src/cursor.rs @@ -1,5 +1,10 @@ use std::str::Chars; +pub enum FrontmatterAllowed { + Yes, + No, +} + /// Peekable iterator over a char sequence. /// /// Next characters can be peeked via `first` method, @@ -8,6 +13,7 @@ pub struct Cursor<'a> { len_remaining: usize, /// Iterator over chars. Slightly faster than a &str. chars: Chars<'a>, + pub(crate) frontmatter_allowed: FrontmatterAllowed, #[cfg(debug_assertions)] prev: char, } @@ -15,10 +21,11 @@ pub struct Cursor<'a> { pub(crate) const EOF_CHAR: char = '\0'; impl<'a> Cursor<'a> { - pub fn new(input: &'a str) -> Cursor<'a> { + pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> { Cursor { len_remaining: input.len(), chars: input.chars(), + frontmatter_allowed, #[cfg(debug_assertions)] prev: EOF_CHAR, } @@ -95,6 +102,11 @@ impl<'a> Cursor<'a> { Some(c) } + /// Moves to a substring by a number of bytes. + pub(crate) fn bump_bytes(&mut self, n: usize) { + self.chars = self.as_str()[n..].chars(); + } + /// Eats symbols while predicate returns true or until the end of file is reached. pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { // It was tried making optimized version of this for eg. line comments, but diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index f9c71b2fa651..2374f3882509 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -35,8 +35,8 @@ pub use unicode_xid::UNICODE_VERSION as UNICODE_XID_VERSION; use self::LiteralKind::*; use self::TokenKind::*; -pub use crate::cursor::Cursor; use crate::cursor::EOF_CHAR; +pub use crate::cursor::{Cursor, FrontmatterAllowed}; /// Parsed token. /// It doesn't contain information about data that has been parsed, @@ -57,17 +57,27 @@ impl Token { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum TokenKind { /// A line comment, e.g. `// comment`. - LineComment { doc_style: Option }, + LineComment { + doc_style: Option, + }, /// A block comment, e.g. `/* block comment */`. /// /// Block comments can be recursive, so a sequence like `/* /* */` /// will not be considered terminated and will result in a parsing error. - BlockComment { doc_style: Option, terminated: bool }, + BlockComment { + doc_style: Option, + terminated: bool, + }, /// Any whitespace character sequence. Whitespace, + Frontmatter { + has_invalid_preceding_whitespace: bool, + invalid_infostring: bool, + }, + /// An identifier or keyword, e.g. `ident` or `continue`. Ident, @@ -109,10 +119,15 @@ pub enum TokenKind { /// this type will need to check for and reject that case. /// /// See [LiteralKind] for more details. - Literal { kind: LiteralKind, suffix_start: u32 }, + Literal { + kind: LiteralKind, + suffix_start: u32, + }, /// A lifetime, e.g. `'a`. - Lifetime { starts_with_number: bool }, + Lifetime { + starts_with_number: bool, + }, /// `;` Semi, @@ -280,7 +295,7 @@ pub fn strip_shebang(input: &str) -> Option { #[inline] pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError> { debug_assert!(!input.is_empty()); - let mut cursor = Cursor::new(input); + let mut cursor = Cursor::new(input, FrontmatterAllowed::No); // Move past the leading `r` or `br`. for _ in 0..prefix_len { cursor.bump().unwrap(); @@ -290,7 +305,7 @@ pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError> /// Creates an iterator that produces tokens from the input string. pub fn tokenize(input: &str) -> impl Iterator { - let mut cursor = Cursor::new(input); + let mut cursor = Cursor::new(input, FrontmatterAllowed::No); std::iter::from_fn(move || { let token = cursor.advance_token(); if token.kind != TokenKind::Eof { Some(token) } else { None } @@ -361,7 +376,34 @@ impl Cursor<'_> { Some(c) => c, None => return Token::new(TokenKind::Eof, 0), }; + let token_kind = match first_char { + c if matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes) + && is_whitespace(c) => + { + let mut last = first_char; + while is_whitespace(self.first()) { + let Some(c) = self.bump() else { + break; + }; + last = c; + } + // invalid frontmatter opening as whitespace preceding it isn't newline. + // combine the whitespace and the frontmatter to a single token as we shall + // error later. + if last != '\n' && self.as_str().starts_with("---") { + self.bump(); + self.frontmatter(true) + } else { + Whitespace + } + } + '-' if matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes) + && self.as_str().starts_with("--") => + { + // happy path + self.frontmatter(false) + } // Slash, comment or block comment. '/' => match self.first() { '/' => self.line_comment(), @@ -464,11 +506,110 @@ impl Cursor<'_> { c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(), _ => Unknown, }; + if matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes) + && !matches!(token_kind, Whitespace) + { + // stop allowing frontmatters after first non-whitespace token + self.frontmatter_allowed = FrontmatterAllowed::No; + } let res = Token::new(token_kind, self.pos_within_token()); self.reset_pos_within_token(); res } + /// Given that one `-` was eaten, eat the rest of the frontmatter. + fn frontmatter(&mut self, has_invalid_preceding_whitespace: bool) -> TokenKind { + debug_assert_eq!('-', self.prev()); + + let pos = self.pos_within_token(); + self.eat_while(|c| c == '-'); + + // one `-` is eaten by the caller. + let length_opening = self.pos_within_token() - pos + 1; + + // must be ensured by the caller + debug_assert!(length_opening >= 3); + + // whitespace between the opening and the infostring. + self.eat_while(|ch| ch != '\n' && is_whitespace(ch)); + + // copied from `eat_identifier`, but allows `.` in infostring to allow something like + // `---Cargo.toml` as a valid opener + if is_id_start(self.first()) { + self.bump(); + self.eat_while(|c| is_id_continue(c) || c == '.'); + } + + self.eat_while(|ch| ch != '\n' && is_whitespace(ch)); + let invalid_infostring = self.first() != '\n'; + + let mut s = self.as_str(); + let mut found = false; + while let Some(closing) = s.find(&"-".repeat(length_opening as usize)) { + let preceding_chars_start = s[..closing].rfind("\n").map_or(0, |i| i + 1); + if s[preceding_chars_start..closing].chars().all(is_whitespace) { + // candidate found + self.bump_bytes(closing); + // in case like + // ---cargo + // --- blahblah + // or + // ---cargo + // ---- + // combine those stuff into this frontmatter token such that it gets detected later. + self.eat_until(b'\n'); + found = true; + break; + } else { + s = &s[closing + length_opening as usize..]; + } + } + + if !found { + // recovery strategy: a closing statement might have precending whitespace/newline + // but not have enough dashes to properly close. In this case, we eat until there, + // and report a mismatch in the parser. + let mut rest = self.as_str(); + // We can look for a shorter closing (starting with four dashes but closing with three) + // and other indications that Rust has started and the infostring has ended. + let mut potential_closing = rest + .find("\n---") + // n.b. only in the case where there are dashes, we move the index to the line where + // the dashes start as we eat to include that line. For other cases those are Rust code + // and not included in the frontmatter. + .map(|x| x + 1) + .or_else(|| rest.find("\nuse ")) + .or_else(|| rest.find("\n//!")) + .or_else(|| rest.find("\n#![")); + + if potential_closing.is_none() { + // a less fortunate recovery if all else fails which finds any dashes preceded by whitespace + // on a standalone line. Might be wrong. + while let Some(closing) = rest.find("---") { + let preceding_chars_start = rest[..closing].rfind("\n").map_or(0, |i| i + 1); + if rest[preceding_chars_start..closing].chars().all(is_whitespace) { + // candidate found + potential_closing = Some(closing); + break; + } else { + rest = &rest[closing + 3..]; + } + } + } + + if let Some(potential_closing) = potential_closing { + // bump to the potential closing, and eat everything on that line. + self.bump_bytes(potential_closing); + self.eat_until(b'\n'); + } else { + // eat everything. this will get reported as an unclosed frontmatter. + self.eat_while(|_| true); + } + } + + Frontmatter { has_invalid_preceding_whitespace, invalid_infostring } + } + fn line_comment(&mut self) -> TokenKind { debug_assert!(self.prev() == '/' && self.first() == '/'); self.bump(); diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs index 8203ae70b070..fc8d9b9d57bc 100644 --- a/compiler/rustc_lexer/src/tests.rs +++ b/compiler/rustc_lexer/src/tests.rs @@ -4,7 +4,7 @@ use super::*; fn check_raw_str(s: &str, expected: Result) { let s = &format!("r{}", s); - let mut cursor = Cursor::new(s); + let mut cursor = Cursor::new(s, FrontmatterAllowed::No); cursor.bump(); let res = cursor.raw_double_quoted_string(0); assert_eq!(res, expected); diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs index ddab13190beb..91d58d92466a 100644 --- a/compiler/rustc_lint/src/autorefs.rs +++ b/compiler/rustc_lint/src/autorefs.rs @@ -15,9 +15,9 @@ declare_lint! { /// /// ```rust /// unsafe fn fun(ptr: *mut [u8]) -> *mut [u8] { - /// &raw mut (*ptr)[..16] - /// // ^^^^^^ this calls `IndexMut::index_mut(&mut ..., ..16)`, - /// // implicitly creating a reference + /// unsafe { &raw mut (*ptr)[..16] } + /// // ^^^^^^ this calls `IndexMut::index_mut(&mut ..., ..16)`, + /// // implicitly creating a reference /// } /// ``` /// @@ -34,17 +34,17 @@ declare_lint! { /// /// ```rust /// unsafe fn fun(ptr: *mut [u8]) -> *mut [u8] { - /// &raw mut (&mut *ptr)[..16] + /// unsafe { &raw mut (&mut *ptr)[..16] } /// } /// ``` /// /// Otherwise try to find an alternative way to achive your goals using only raw pointers: /// /// ```rust - /// use std::slice; + /// use std::ptr; /// - /// unsafe fn fun(ptr: *mut [u8]) -> *mut [u8] { - /// slice::from_raw_parts_mut(ptr.cast(), 16) + /// fn fun(ptr: *mut [u8]) -> *mut [u8] { + /// ptr::slice_from_raw_parts_mut(ptr.cast(), 16) /// } /// ``` pub DANGEROUS_IMPLICIT_AUTOREFS, diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 757fc1f58bd5..a56b753bda72 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -49,6 +49,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let Some((pat, arg)) = extract_for_loop(expr) else { return }; + let arg_span = arg.span.source_callsite(); + let ty = cx.typeck_results().expr_ty(arg); let (adt, args, ref_mutability) = match ty.kind() { @@ -78,27 +80,27 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span) { ForLoopsOverFalliblesLoopSub::RemoveNext { - suggestion: recv.span.between(arg.span.shrink_to_hi()), + suggestion: recv.span.between(arg_span.shrink_to_hi()), recv_snip, } } else { ForLoopsOverFalliblesLoopSub::UseWhileLet { start_span: expr.span.with_hi(pat.span.lo()), - end_span: pat.span.between(arg.span), + end_span: pat.span.between(arg_span), var, } }; let question_mark = suggest_question_mark(cx, adt, args, expr.span) - .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() }); + .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg_span.shrink_to_hi() }); let suggestion = ForLoopsOverFalliblesSuggestion { var, start_span: expr.span.with_hi(pat.span.lo()), - end_span: pat.span.between(arg.span), + end_span: pat.span.between(arg_span), }; cx.emit_span_lint( FOR_LOOPS_OVER_FALLIBLES, - arg.span, + arg_span, ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion }, ); } diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 0494c78a7a97..d0668794198a 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -104,7 +104,7 @@ impl ClashingExternDeclarations { /// for the item, return its HirId without updating the set. fn insert(&mut self, tcx: TyCtxt<'_>, fi: hir::ForeignItemId) -> Option { let did = fi.owner_id.to_def_id(); - let instance = Instance::new(did, ty::List::identity_for_item(tcx, did)); + let instance = Instance::new_raw(did, ty::List::identity_for_item(tcx, did)); let name = Symbol::intern(tcx.symbol_name(instance).name); if let Some(&existing_id) = self.seen_decls.get(&name) { // Avoid updating the map with the new entry when we do find a collision. We want to diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 7f4789ad0d9b..a8f45d043be9 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -15,7 +15,8 @@ use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys, }; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + TypeVisitor, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint::FutureIncompatibilityReason; @@ -209,7 +210,7 @@ where VarFn: FnOnce() -> FxHashMap, OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>, { - fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { // When we get into a binder, we need to add its own bound vars to the scope. let mut added = vec![]; for arg in t.bound_vars() { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 03b8112938cf..3cea24634fee 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2352,37 +2352,11 @@ declare_lint! { } declare_lint! { - /// The `soft_unstable` lint detects unstable features that were - /// unintentionally allowed on stable. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #[cfg(test)] - /// extern crate test; - /// - /// #[bench] - /// fn name(b: &mut test::Bencher) { - /// b.iter(|| 123) - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// The [`bench` attribute] was accidentally allowed to be specified on - /// the [stable release channel]. Turning this to a hard error would have - /// broken some projects. This lint allows those projects to continue to - /// build correctly when [`--cap-lints`] is used, but otherwise signal an - /// error that `#[bench]` should not be used on the stable channel. This - /// is a [future-incompatible] lint to transition this to a hard error in - /// the future. See [issue #64266] for more details. + /// The `soft_unstable` lint detects unstable features that were unintentionally allowed on + /// stable. This is a [future-incompatible] lint to transition this to a hard error in the + /// future. See [issue #64266] for more details. /// /// [issue #64266]: https://github.com/rust-lang/rust/issues/64266 - /// [`bench` attribute]: https://doc.rust-lang.org/nightly/unstable-book/library-features/test.html - /// [stable release channel]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html - /// [`--cap-lints`]: https://doc.rust-lang.org/rustc/lints/levels.html#capping-lints /// [future-incompatible]: ../index.md#future-incompatible-lints pub SOFT_UNSTABLE, Deny, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index ebe8eb57f2cd..d4a05fbbbc5d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -512,8 +512,13 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( #endif } +#if LLVM_VERSION_GE(21, 0) + TargetMachine *TM = TheTarget->createTargetMachine(Trip, CPU, Feature, + Options, RM, CM, OptLevel); +#else TargetMachine *TM = TheTarget->createTargetMachine( Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel); +#endif return wrap(TM); } diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 49dd388f14cc..1bb502ca3d06 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -37,6 +37,7 @@ use std::env::{self, VarError}; use std::fmt::{self, Display}; use std::io::{self, IsTerminal}; +use tracing::dispatcher::SetGlobalDefaultError; use tracing_core::{Event, Subscriber}; use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; use tracing_subscriber::fmt::FmtContext; @@ -131,10 +132,10 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { .without_time() .event_format(BacktraceFormatter { backtrace_target }); let subscriber = subscriber.with(fmt_layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); + tracing::subscriber::set_global_default(subscriber)?; } Err(_) => { - tracing::subscriber::set_global_default(subscriber).unwrap(); + tracing::subscriber::set_global_default(subscriber)?; } }; @@ -180,6 +181,7 @@ pub enum Error { InvalidColorValue(String), NonUnicodeColorValue, InvalidWraptree(String), + AlreadyInit(SetGlobalDefaultError), } impl std::error::Error for Error {} @@ -199,6 +201,13 @@ impl Display for Error { formatter, "invalid log WRAPTREE value '{value}': expected a non-negative integer", ), + Error::AlreadyInit(tracing_error) => Display::fmt(tracing_error, formatter), } } } + +impl From for Error { + fn from(tracing_error: SetGlobalDefaultError) -> Self { + Error::AlreadyInit(tracing_error) + } +} diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index b11f9260be7c..26878c488b74 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -26,6 +26,7 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } +tempfile = "3.7.1" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 1c3222bbfeb6..07fb2de8a3e0 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -148,7 +148,7 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { writeln!(fmt, " hash: {}", data.hash())?; writeln!(fmt, " reqd: {:?}", data.dep_kind())?; writeln!(fmt, " priv: {:?}", data.is_private_dep())?; - let CrateSource { dylib, rlib, rmeta } = data.source(); + let CrateSource { dylib, rlib, rmeta, sdylib_interface } = data.source(); if let Some(dylib) = dylib { writeln!(fmt, " dylib: {}", dylib.0.display())?; } @@ -158,6 +158,9 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { if let Some(rmeta) = rmeta { writeln!(fmt, " rmeta: {}", rmeta.0.display())?; } + if let Some(sdylib_interface) = sdylib_interface { + writeln!(fmt, " sdylib interface: {}", sdylib_interface.0.display())?; + } } Ok(()) } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index be31aa629c86..fcae33c73c9c 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -88,45 +88,42 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { return IndexVec::new(); } - let preferred_linkage = match ty { - // Generating a dylib without `-C prefer-dynamic` means that we're going - // to try to eagerly statically link all dependencies. This is normally - // done for end-product dylibs, not intermediate products. - // - // Treat cdylibs and staticlibs similarly. If `-C prefer-dynamic` is set, - // the caller may be code-size conscious, but without it, it makes sense - // to statically link a cdylib or staticlib. For staticlibs we use - // `-Z staticlib-prefer-dynamic` for now. This may be merged into - // `-C prefer-dynamic` in the future. - CrateType::Dylib | CrateType::Cdylib => { - if sess.opts.cg.prefer_dynamic { - Linkage::Dynamic - } else { + let preferred_linkage = + match ty { + // Generating a dylib without `-C prefer-dynamic` means that we're going + // to try to eagerly statically link all dependencies. This is normally + // done for end-product dylibs, not intermediate products. + // + // Treat cdylibs and staticlibs similarly. If `-C prefer-dynamic` is set, + // the caller may be code-size conscious, but without it, it makes sense + // to statically link a cdylib or staticlib. For staticlibs we use + // `-Z staticlib-prefer-dynamic` for now. This may be merged into + // `-C prefer-dynamic` in the future. + CrateType::Dylib | CrateType::Cdylib | CrateType::Sdylib => { + if sess.opts.cg.prefer_dynamic { Linkage::Dynamic } else { Linkage::Static } + } + CrateType::Staticlib => { + if sess.opts.unstable_opts.staticlib_prefer_dynamic { + Linkage::Dynamic + } else { + Linkage::Static + } + } + + // If the global prefer_dynamic switch is turned off, or the final + // executable will be statically linked, prefer static crate linkage. + CrateType::Executable if !sess.opts.cg.prefer_dynamic || sess.crt_static(Some(ty)) => { Linkage::Static } - } - CrateType::Staticlib => { - if sess.opts.unstable_opts.staticlib_prefer_dynamic { - Linkage::Dynamic - } else { - Linkage::Static - } - } + CrateType::Executable => Linkage::Dynamic, - // If the global prefer_dynamic switch is turned off, or the final - // executable will be statically linked, prefer static crate linkage. - CrateType::Executable if !sess.opts.cg.prefer_dynamic || sess.crt_static(Some(ty)) => { - Linkage::Static - } - CrateType::Executable => Linkage::Dynamic, + // proc-macro crates are mostly cdylibs, but we also need metadata. + CrateType::ProcMacro => Linkage::Static, - // proc-macro crates are mostly cdylibs, but we also need metadata. - CrateType::ProcMacro => Linkage::Static, - - // No linkage happens with rlibs, we just needed the metadata (which we - // got long ago), so don't bother with anything. - CrateType::Rlib => Linkage::NotLinked, - }; + // No linkage happens with rlibs, we just needed the metadata (which we + // got long ago), so don't bother with anything. + CrateType::Rlib => Linkage::NotLinked, + }; let mut unavailable_as_static = Vec::new(); @@ -165,7 +162,9 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { let all_dylibs = || { tcx.crates(()).iter().filter(|&&cnum| { - !tcx.dep_kind(cnum).macros_only() && tcx.used_crate_source(cnum).dylib.is_some() + !tcx.dep_kind(cnum).macros_only() + && (tcx.used_crate_source(cnum).dylib.is_some() + || tcx.used_crate_source(cnum).sdylib_interface.is_some()) }) }; @@ -273,7 +272,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { match *kind { Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static if src.rlib.is_some() => continue, - Linkage::Dynamic if src.dylib.is_some() => continue, + Linkage::Dynamic if src.dylib.is_some() || src.sdylib_interface.is_some() => continue, kind => { let kind = match kind { Linkage::Static => "rlib", diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index f0a898d678ca..10123cb9a9dd 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -220,7 +220,7 @@ use std::{cmp, fmt}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::owned_slice::slice_owned; +use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned}; use rustc_data_structures::svh::Svh; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_fs_util::try_canonicalize; @@ -231,6 +231,7 @@ use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; use rustc_span::{Span, Symbol}; use rustc_target::spec::{Target, TargetTuple}; +use tempfile::Builder as TempFileBuilder; use tracing::{debug, info}; use crate::creader::{Library, MetadataLoader}; @@ -277,6 +278,7 @@ pub(crate) enum CrateFlavor { Rlib, Rmeta, Dylib, + SDylib, } impl fmt::Display for CrateFlavor { @@ -285,6 +287,7 @@ impl fmt::Display for CrateFlavor { CrateFlavor::Rlib => "rlib", CrateFlavor::Rmeta => "rmeta", CrateFlavor::Dylib => "dylib", + CrateFlavor::SDylib => "sdylib", }) } } @@ -295,6 +298,7 @@ impl IntoDiagArg for CrateFlavor { CrateFlavor::Rlib => DiagArgValue::Str(Cow::Borrowed("rlib")), CrateFlavor::Rmeta => DiagArgValue::Str(Cow::Borrowed("rmeta")), CrateFlavor::Dylib => DiagArgValue::Str(Cow::Borrowed("dylib")), + CrateFlavor::SDylib => DiagArgValue::Str(Cow::Borrowed("sdylib")), } } } @@ -379,14 +383,18 @@ impl<'a> CrateLocator<'a> { &format!("{}{}{}", self.target.dll_prefix, self.crate_name, extra_prefix); let staticlib_prefix = &format!("{}{}{}", self.target.staticlib_prefix, self.crate_name, extra_prefix); + let interface_prefix = rmeta_prefix; let rmeta_suffix = ".rmeta"; let rlib_suffix = ".rlib"; let dylib_suffix = &self.target.dll_suffix; let staticlib_suffix = &self.target.staticlib_suffix; + let interface_suffix = ".rs"; - let mut candidates: FxIndexMap<_, (FxIndexMap<_, _>, FxIndexMap<_, _>, FxIndexMap<_, _>)> = - Default::default(); + let mut candidates: FxIndexMap< + _, + (FxIndexMap<_, _>, FxIndexMap<_, _>, FxIndexMap<_, _>, FxIndexMap<_, _>), + > = Default::default(); // First, find all possible candidate rlibs and dylibs purely based on // the name of the files themselves. We're trying to match against an @@ -417,6 +425,7 @@ impl<'a> CrateLocator<'a> { (rlib_prefix.as_str(), rlib_suffix, CrateFlavor::Rlib), (rmeta_prefix.as_str(), rmeta_suffix, CrateFlavor::Rmeta), (dylib_prefix, dylib_suffix, CrateFlavor::Dylib), + (interface_prefix, interface_suffix, CrateFlavor::SDylib), ] { if prefix == staticlib_prefix && suffix == staticlib_suffix { should_check_staticlibs = false; @@ -425,7 +434,7 @@ impl<'a> CrateLocator<'a> { for (hash, spf) in matches { info!("lib candidate: {}", spf.path.display()); - let (rlibs, rmetas, dylibs) = + let (rlibs, rmetas, dylibs, interfaces) = candidates.entry(hash.to_string()).or_default(); { // As a perforamnce optimisation we canonicalize the path and skip @@ -446,6 +455,7 @@ impl<'a> CrateLocator<'a> { CrateFlavor::Rlib => rlibs.insert(path, search_path.kind), CrateFlavor::Rmeta => rmetas.insert(path, search_path.kind), CrateFlavor::Dylib => dylibs.insert(path, search_path.kind), + CrateFlavor::SDylib => interfaces.insert(path, search_path.kind), }; } } @@ -472,8 +482,8 @@ impl<'a> CrateLocator<'a> { // libraries corresponds to the crate id and hash criteria that this // search is being performed for. let mut libraries = FxIndexMap::default(); - for (_hash, (rlibs, rmetas, dylibs)) in candidates { - if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs)? { + for (_hash, (rlibs, rmetas, dylibs, interfaces)) in candidates { + if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs, interfaces)? { libraries.insert(svh, lib); } } @@ -508,6 +518,7 @@ impl<'a> CrateLocator<'a> { rlibs: FxIndexMap, rmetas: FxIndexMap, dylibs: FxIndexMap, + interfaces: FxIndexMap, ) -> Result, CrateError> { let mut slot = None; // Order here matters, rmeta should come first. @@ -515,12 +526,17 @@ impl<'a> CrateLocator<'a> { // Make sure there's at most one rlib and at most one dylib. // // See comment in `extract_one` below. - let source = CrateSource { - rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot)?, - rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot)?, - dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot)?, - }; - Ok(slot.map(|(svh, metadata, _)| (svh, Library { source, metadata }))) + let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot)?; + let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot)?; + let sdylib_interface = self.extract_one(interfaces, CrateFlavor::SDylib, &mut slot)?; + let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot)?; + + if sdylib_interface.is_some() && dylib.is_none() { + return Err(CrateError::FullMetadataNotFound(self.crate_name, CrateFlavor::SDylib)); + } + + let source = CrateSource { rmeta, rlib, dylib, sdylib_interface }; + Ok(slot.map(|(svh, metadata, _, _)| (svh, Library { source, metadata }))) } fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool { @@ -550,7 +566,7 @@ impl<'a> CrateLocator<'a> { &mut self, m: FxIndexMap, flavor: CrateFlavor, - slot: &mut Option<(Svh, MetadataBlob, PathBuf)>, + slot: &mut Option<(Svh, MetadataBlob, PathBuf, CrateFlavor)>, ) -> Result, CrateError> { // If we are producing an rlib, and we've already loaded metadata, then // we should not attempt to discover further crate sources (unless we're @@ -586,6 +602,7 @@ impl<'a> CrateLocator<'a> { &lib, self.metadata_loader, self.cfg_version, + Some(self.crate_name), ) { Ok(blob) => { if let Some(h) = self.crate_matches(&blob, &lib) { @@ -610,6 +627,11 @@ impl<'a> CrateLocator<'a> { } Err(MetadataError::LoadFailure(err)) => { info!("no metadata found: {}", err); + // Metadata was loaded from interface file earlier. + if let Some((.., CrateFlavor::SDylib)) = slot { + ret = Some((lib, kind)); + continue; + } // The file was present and created by the same compiler version, but we // couldn't load it for some reason. Give a hard error instead of silently // ignoring it, but only if we would have given an error anyway. @@ -679,7 +701,7 @@ impl<'a> CrateLocator<'a> { return Err(CrateError::FullMetadataNotFound(self.crate_name, flavor)); } } else { - *slot = Some((hash, metadata, lib.clone())); + *slot = Some((hash, metadata, lib.clone(), flavor)); } ret = Some((lib, kind)); } @@ -736,6 +758,7 @@ impl<'a> CrateLocator<'a> { let mut rlibs = FxIndexMap::default(); let mut rmetas = FxIndexMap::default(); let mut dylibs = FxIndexMap::default(); + let mut sdylib_interfaces = FxIndexMap::default(); for loc in &self.exact_paths { let loc_canon = loc.canonicalized(); let loc_orig = loc.original(); @@ -763,6 +786,9 @@ impl<'a> CrateLocator<'a> { rmetas.insert(loc_canon.clone(), PathKind::ExternFlag); continue; } + if file.ends_with(".rs") { + sdylib_interfaces.insert(loc_canon.clone(), PathKind::ExternFlag); + } } let dll_prefix = self.target.dll_prefix.as_ref(); let dll_suffix = self.target.dll_suffix.as_ref(); @@ -776,7 +802,8 @@ impl<'a> CrateLocator<'a> { } // Extract the dylib/rlib/rmeta triple. - self.extract_lib(rlibs, rmetas, dylibs).map(|opt| opt.map(|(_, lib)| lib)) + self.extract_lib(rlibs, rmetas, dylibs, sdylib_interfaces) + .map(|opt| opt.map(|(_, lib)| lib)) } pub(crate) fn into_error(self, dep_root: Option) -> CrateError { @@ -797,6 +824,7 @@ fn get_metadata_section<'p>( filename: &'p Path, loader: &dyn MetadataLoader, cfg_version: &'static str, + crate_name: Option, ) -> Result> { if !filename.exists() { return Err(MetadataError::NotPresent(filename)); @@ -805,6 +833,55 @@ fn get_metadata_section<'p>( CrateFlavor::Rlib => { loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)? } + CrateFlavor::SDylib => { + let compiler = std::env::current_exe().map_err(|_err| { + MetadataError::LoadFailure( + "couldn't obtain current compiler binary when loading sdylib interface" + .to_string(), + ) + })?; + + let tmp_path = match TempFileBuilder::new().prefix("rustc").tempdir() { + Ok(tmp_path) => tmp_path, + Err(error) => { + return Err(MetadataError::LoadFailure(format!( + "couldn't create a temp dir: {}", + error + ))); + } + }; + + let crate_name = crate_name.unwrap(); + debug!("compiling {}", filename.display()); + // FIXME: This will need to be done either within the current compiler session or + // as a separate compiler session in the same process. + let res = std::process::Command::new(compiler) + .arg(&filename) + .arg("--emit=metadata") + .arg(format!("--crate-name={}", crate_name)) + .arg(format!("--out-dir={}", tmp_path.path().display())) + .arg("-Zbuild-sdylib-interface") + .output() + .map_err(|err| { + MetadataError::LoadFailure(format!("couldn't compile interface: {}", err)) + })?; + + if !res.status.success() { + return Err(MetadataError::LoadFailure(format!( + "couldn't compile interface: {}", + std::str::from_utf8(&res.stderr).unwrap_or_default() + ))); + } + + // Load interface metadata instead of crate metadata. + let interface_metadata_name = format!("lib{}.rmeta", crate_name); + let rmeta_file = tmp_path.path().join(interface_metadata_name); + debug!("loading interface metadata from {}", rmeta_file.display()); + let rmeta = get_rmeta_metadata_section(&rmeta_file)?; + let _ = std::fs::remove_file(rmeta_file); + + rmeta + } CrateFlavor::Dylib => { let buf = loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?; @@ -834,24 +911,7 @@ fn get_metadata_section<'p>( // Header is okay -> inflate the actual metadata buf.slice(|buf| &buf[data_start..(data_start + metadata_len)]) } - CrateFlavor::Rmeta => { - // mmap the file, because only a small fraction of it is read. - let file = std::fs::File::open(filename).map_err(|_| { - MetadataError::LoadFailure(format!( - "failed to open rmeta metadata: '{}'", - filename.display() - )) - })?; - let mmap = unsafe { Mmap::map(file) }; - let mmap = mmap.map_err(|_| { - MetadataError::LoadFailure(format!( - "failed to mmap rmeta metadata: '{}'", - filename.display() - )) - })?; - - slice_owned(mmap, Deref::deref) - } + CrateFlavor::Rmeta => get_rmeta_metadata_section(filename)?, }; let Ok(blob) = MetadataBlob::new(raw_bytes) else { return Err(MetadataError::LoadFailure(format!( @@ -877,6 +937,25 @@ fn get_metadata_section<'p>( } } +fn get_rmeta_metadata_section<'a, 'p>(filename: &'p Path) -> Result> { + // mmap the file, because only a small fraction of it is read. + let file = std::fs::File::open(filename).map_err(|_| { + MetadataError::LoadFailure(format!( + "failed to open rmeta metadata: '{}'", + filename.display() + )) + })?; + let mmap = unsafe { Mmap::map(file) }; + let mmap = mmap.map_err(|_| { + MetadataError::LoadFailure(format!( + "failed to mmap rmeta metadata: '{}'", + filename.display() + )) + })?; + + Ok(slice_owned(mmap, Deref::deref)) +} + /// A diagnostic function for dumping crate metadata to an output stream. pub fn list_file_metadata( target: &Target, @@ -887,7 +966,7 @@ pub fn list_file_metadata( cfg_version: &'static str, ) -> IoResult<()> { let flavor = get_flavor_from_path(path); - match get_metadata_section(target, flavor, path, metadata_loader, cfg_version) { + match get_metadata_section(target, flavor, path, metadata_loader, cfg_version, None) { Ok(metadata) => metadata.list_crate_metadata(out, ls_kinds), Err(msg) => write!(out, "{msg}\n"), } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 3c2245347f97..bd813cadedcd 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1489,6 +1489,17 @@ impl<'a> CrateMetadataRef<'a> { tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self)) } + fn get_exportable_items(self) -> impl Iterator { + self.root.exportable_items.decode(self).map(move |index| self.local_def_id(index)) + } + + fn get_stable_order_of_exportable_impls(self) -> impl Iterator { + self.root + .stable_order_of_exportable_impls + .decode(self) + .map(move |v| (self.local_def_id(v.0), v.1)) + } + fn exported_symbols<'tcx>( self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index ecc2dcc5318d..76bae39ef8c0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -406,6 +406,8 @@ provide! { tcx, def_id, other, cdata, used_crate_source => { Arc::clone(&cdata.source) } debugger_visualizers => { cdata.get_debugger_visualizers() } + exportable_items => { tcx.arena.alloc_from_iter(cdata.get_exportable_items()) } + stable_order_of_exportable_impls => { tcx.arena.alloc(cdata.get_stable_order_of_exportable_impls().collect()) } exported_symbols => { let syms = cdata.exported_symbols(tcx); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3ea61d1b40a6..7ac72ef814a9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -551,8 +551,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { match source_file.name { FileName::Real(ref original_file_name) => { - // FIXME: This should probably to conditionally remapped under - // a RemapPathScopeComponents but which one? let adapted_file_name = source_map .path_mapping() .to_embeddable_absolute_path(original_file_name.clone(), working_directory); @@ -673,6 +671,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let debugger_visualizers = stat!("debugger-visualizers", || self.encode_debugger_visualizers()); + let exportable_items = stat!("exportable-items", || self.encode_exportable_items()); + + let stable_order_of_exportable_impls = + stat!("exportable-items", || self.encode_stable_order_of_exportable_impls()); + // Encode exported symbols info. This is prefetched in `encode_metadata`. let exported_symbols = stat!("exported-symbols", || { self.encode_exported_symbols(tcx.exported_symbols(LOCAL_CRATE)) @@ -740,6 +743,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { traits, impls, incoherent_impls, + exportable_items, + stable_order_of_exportable_impls, exported_symbols, interpret_alloc_index, tables, @@ -2149,6 +2154,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_array(&all_impls) } + fn encode_exportable_items(&mut self) -> LazyArray { + empty_proc_macro!(self); + self.lazy_array(self.tcx.exportable_items(LOCAL_CRATE).iter().map(|def_id| def_id.index)) + } + + fn encode_stable_order_of_exportable_impls(&mut self) -> LazyArray<(DefIndex, usize)> { + empty_proc_macro!(self); + let stable_order_of_exportable_impls = + self.tcx.stable_order_of_exportable_impls(LOCAL_CRATE); + self.lazy_array( + stable_order_of_exportable_impls.iter().map(|(def_id, idx)| (def_id.index, *idx)), + ) + } + // Encodes all symbols exported from this crate into the metadata. // // This pass is seeded off the reachability list calculated in the diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 5aa81f41b7b4..c86cf567283f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -280,6 +280,8 @@ pub(crate) struct CrateRoot { tables: LazyTables, debugger_visualizers: LazyArray, + exportable_items: LazyArray, + stable_order_of_exportable_impls: LazyArray<(DefIndex, usize)>, exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>, syntax_contexts: SyntaxContextTable, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 2dcb0de92b78..a0f459740893 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -91,6 +91,8 @@ macro_rules! arena_types { [] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem, [] ordered_name_set: rustc_data_structures::fx::FxIndexSet, [] valtree: rustc_middle::ty::ValTreeKind<'tcx>, + [] stable_order_of_exportable_impls: + rustc_data_structures::fx::FxIndexMap, // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 711036865bbd..979608df79c0 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -27,7 +27,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::potential_query_instability)] #![allow(rustc::untranslatable_diagnostic)] #![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index 3c62017072e4..64a1f2aff15c 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -22,7 +22,7 @@ impl SymbolExportLevel { } /// Kind of exported symbols. -#[derive(Eq, PartialEq, Debug, Copy, Clone, Encodable, Decodable, HashStable)] +#[derive(Eq, PartialEq, Debug, Copy, Clone, Encodable, Decodable, HashStable, Hash)] pub enum SymbolExportKind { Text, Data, @@ -56,7 +56,7 @@ impl<'tcx> ExportedSymbol<'tcx> { match *self { ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)), ExportedSymbol::Generic(def_id, args) => { - tcx.symbol_name(ty::Instance::new(def_id, args)) + tcx.symbol_name(ty::Instance::new_raw(def_id, args)) } ExportedSymbol::DropGlue(ty) => { tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty)) diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index e5d1dda3aa0f..4a5c42c721c1 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -23,7 +23,7 @@ impl<'tcx> TyCtxt<'tcx> { // into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are // encountered. let args = GenericArgs::identity_for_item(self, def_id); - let instance = ty::Instance::new(def_id, args); + let instance = ty::Instance::new_raw(def_id, args); let cid = GlobalId { instance, promoted: None }; let typing_env = ty::TypingEnv::post_analysis(self, def_id); self.const_eval_global_id(typing_env, cid, DUMMY_SP) @@ -39,7 +39,7 @@ impl<'tcx> TyCtxt<'tcx> { // into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are // encountered. let args = GenericArgs::identity_for_item(self, def_id); - let instance = ty::Instance::new(def_id, args); + let instance = ty::Instance::new_raw(def_id, args); let cid = GlobalId { instance, promoted: None }; let typing_env = ty::TypingEnv::post_analysis(self, def_id); let inputs = self.erase_regions(typing_env.as_query_input(cid)); @@ -209,7 +209,7 @@ impl<'tcx> TyCtxtEnsureOk<'tcx> { // into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are // encountered. let args = GenericArgs::identity_for_item(self.tcx, def_id); - let instance = ty::Instance::new(def_id, self.tcx.erase_regions(args)); + let instance = ty::Instance::new_raw(def_id, self.tcx.erase_regions(args)); let cid = GlobalId { instance, promoted: None }; let typing_env = ty::TypingEnv::post_analysis(self.tcx, def_id); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 6b413a7383a5..7243f87ee638 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -318,7 +318,7 @@ impl<'tcx> fmt::Display for MonoItem<'tcx> { match *self { MonoItem::Fn(instance) => write!(f, "fn {instance}"), MonoItem::Static(def_id) => { - write!(f, "static {}", Instance::new(def_id, GenericArgs::empty())) + write!(f, "static {}", Instance::new_raw(def_id, GenericArgs::empty())) } MonoItem::GlobalAsm(..) => write!(f, "global_asm"), } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 8a1ead7d19d0..0834fa8844c0 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -437,8 +437,8 @@ impl<'tcx> Terminator<'tcx> { } #[inline] - pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { - self.kind.successors_mut() + pub fn successors_mut<'a>(&'a mut self, f: impl FnMut(&'a mut BasicBlock)) { + self.kind.successors_mut(f) } #[inline] @@ -486,7 +486,6 @@ pub use helper::*; mod helper { use super::*; pub type Successors<'a> = impl DoubleEndedIterator + 'a; - pub type SuccessorsMut<'a> = impl DoubleEndedIterator + 'a; impl SwitchTargets { /// Like [`SwitchTargets::target_for_value`], but returning the same type as @@ -560,69 +559,63 @@ mod helper { } #[inline] - #[define_opaque(SuccessorsMut)] - pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { + pub fn successors_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut BasicBlock)) { use self::TerminatorKind::*; - match *self { - // 3-successors for async drop: target, unwind, dropline (parent coroutine drop) - Drop { - target: ref mut t, - unwind: UnwindAction::Cleanup(ref mut u), - drop: Some(ref mut d), - .. - } => slice::from_mut(t).into_iter().chain(Some(u).into_iter().chain(Some(d))), - // 2-successors - Call { - target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), .. + match self { + Drop { target, unwind, drop, .. } => { + f(target); + if let UnwindAction::Cleanup(u) = unwind { + f(u) + } + if let Some(d) = drop { + f(d) + } } - | Yield { resume: ref mut t, drop: Some(ref mut u), .. } - | Drop { - target: ref mut t, - unwind: UnwindAction::Cleanup(ref mut u), - drop: None, - .. + Call { target, unwind, .. } => { + if let Some(target) = target { + f(target); + } + if let UnwindAction::Cleanup(u) = unwind { + f(u) + } } - | Drop { target: ref mut t, unwind: _, drop: Some(ref mut u), .. } - | Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. } - | FalseUnwind { - real_target: ref mut t, - unwind: UnwindAction::Cleanup(ref mut u), - } => slice::from_mut(t).into_iter().chain(Some(u).into_iter().chain(None)), - // single successor - Goto { target: ref mut t } - | Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. } - | Call { target: Some(ref mut t), unwind: _, .. } - | Yield { resume: ref mut t, drop: None, .. } - | Drop { target: ref mut t, unwind: _, .. } - | Assert { target: ref mut t, unwind: _, .. } - | FalseUnwind { real_target: ref mut t, unwind: _ } => { - slice::from_mut(t).into_iter().chain(None.into_iter().chain(None)) + Yield { resume, drop, .. } => { + f(resume); + if let Some(d) = drop { + f(d) + } + } + Assert { target, unwind, .. } | FalseUnwind { real_target: target, unwind } => { + f(target); + if let UnwindAction::Cleanup(u) = unwind { + f(u) + } + } + Goto { target } => { + f(target); } - // No successors UnwindResume | UnwindTerminate(_) | CoroutineDrop | Return | Unreachable - | TailCall { .. } - | Call { target: None, unwind: _, .. } => { - (&mut []).into_iter().chain(None.into_iter().chain(None)) + | TailCall { .. } => {} + InlineAsm { targets, unwind, .. } => { + for target in targets { + f(target); + } + if let UnwindAction::Cleanup(u) = unwind { + f(u) + } } - // Multiple successors - InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => { - targets.iter_mut().chain(Some(u).into_iter().chain(None)) + SwitchInt { targets, .. } => { + for target in &mut targets.targets { + f(target); + } } - InlineAsm { ref mut targets, unwind: _, .. } => { - targets.iter_mut().chain(None.into_iter().chain(None)) - } - SwitchInt { ref mut targets, .. } => { - targets.targets.iter_mut().chain(None.into_iter().chain(None)) - } - // FalseEdge - FalseEdge { ref mut real_target, ref mut imaginary_target } => { - slice::from_mut(real_target) - .into_iter() - .chain(Some(imaginary_target).into_iter().chain(None)) + FalseEdge { real_target, imaginary_target } => { + f(real_target); + f(imaginary_target); } } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 88f4c4ae4d36..b2133fea08cc 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -387,7 +387,7 @@ rustc_queries! { } } - query stalled_generators_within( + query nested_bodies_within( key: LocalDefId ) -> &'tcx ty::List { desc { @@ -2205,7 +2205,7 @@ rustc_queries! { query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet { desc { "fetching potentially unused trait imports" } } - query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx UnordSet { + query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxIndexSet { desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id) } } @@ -2239,6 +2239,16 @@ rustc_queries! { separate_provide_extern } + query stable_order_of_exportable_impls(_: CrateNum) -> &'tcx FxIndexMap { + desc { "fetching the stable impl's order" } + separate_provide_extern + } + + query exportable_items(_: CrateNum) -> &'tcx [DefId] { + desc { "fetching all exportable items in a crate" } + separate_provide_extern + } + /// The list of symbols exported from the given crate. /// /// - All names contained in `exported_symbols(cnum)` are guaranteed to @@ -2471,7 +2481,7 @@ rustc_queries! { query resolve_instance_raw( key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)> ) -> Result>, ErrorGuaranteed> { - desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } + desc { "resolving instance `{}`", ty::Instance::new_raw(key.value.0, key.value.1) } } query reveal_opaque_types_in_bounds(key: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> { diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 5431097cb1d7..e1876f8f0f9b 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -2,7 +2,7 @@ use std::collections::hash_map::Entry; use std::mem; use std::sync::Arc; -use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::sync::{HashMapExt, Lock, RwLock}; use rustc_data_structures::unhash::UnhashMap; @@ -57,7 +57,7 @@ pub struct OnDiskCache { // Collects all `QuerySideEffect` created during the current compilation // session. - current_side_effects: Lock>, + current_side_effects: Lock>, file_index_to_stable_id: FxHashMap, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3ea285d3d8eb..0759fa3da428 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -29,13 +29,12 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{ self, DynSend, DynSync, FreezeReadGuard, Lock, RwLock, WorkerLocal, }; -use rustc_data_structures::unord::UnordSet; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan, }; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::definitions::Definitions; +use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState}; use rustc_hir::intravisit::VisitorExt; use rustc_hir::lang_items::LangItem; use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate}; @@ -243,10 +242,18 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ty::AliasTermKind::ProjectionTy } } + DefKind::AssocConst => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) + { + ty::AliasTermKind::InherentConst + } else { + ty::AliasTermKind::ProjectionConst + } + } DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy, DefKind::TyAlias => ty::AliasTermKind::FreeTy, - DefKind::AssocConst => ty::AliasTermKind::ProjectionConst, - DefKind::AnonConst | DefKind::Const | DefKind::Ctor(_, CtorKind::Const) => { + DefKind::Const => ty::AliasTermKind::FreeConst, + DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => { ty::AliasTermKind::UnevaluatedConst } kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), @@ -684,15 +691,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.opaque_types_defined_by(defining_anchor) } - fn opaque_types_and_generators_defined_by( + fn opaque_types_and_coroutines_defined_by( self, defining_anchor: Self::LocalDefId, ) -> Self::LocalDefIds { if self.next_trait_solver_globally() { + let coroutines_defined_by = self + .nested_bodies_within(defining_anchor) + .iter() + .filter(|def_id| self.is_coroutine(def_id.to_def_id())); self.mk_local_def_ids_from_iter( - self.opaque_types_defined_by(defining_anchor) - .iter() - .chain(self.stalled_generators_within(defining_anchor)), + self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by), ) } else { self.opaque_types_defined_by(defining_anchor) @@ -1820,9 +1829,10 @@ impl<'tcx> TyCtxt<'tcx> { self.crate_types() .iter() .map(|ty| match *ty { - CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => { - MetadataKind::None - } + CrateType::Executable + | CrateType::Staticlib + | CrateType::Cdylib + | CrateType::Sdylib => MetadataKind::None, CrateType::Rlib => MetadataKind::Uncompressed, CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed, }) @@ -1969,8 +1979,11 @@ impl<'tcx> TyCtxtAt<'tcx> { parent: LocalDefId, name: Option, def_kind: DefKind, + override_def_path_data: Option, + disambiguator: &mut DisambiguatorState, ) -> TyCtxtFeed<'tcx, LocalDefId> { - let feed = self.tcx.create_def(parent, name, def_kind); + let feed = + self.tcx.create_def(parent, name, def_kind, override_def_path_data, disambiguator); feed.def_span(self.span); feed @@ -1984,8 +1997,10 @@ impl<'tcx> TyCtxt<'tcx> { parent: LocalDefId, name: Option, def_kind: DefKind, + override_def_path_data: Option, + disambiguator: &mut DisambiguatorState, ) -> TyCtxtFeed<'tcx, LocalDefId> { - let data = def_kind.def_path_data(name); + let data = override_def_path_data.unwrap_or_else(|| def_kind.def_path_data(name)); // The following call has the side effect of modifying the tables inside `definitions`. // These very tables are relied on by the incr. comp. engine to decode DepNodes and to // decode the on-disk cache. @@ -1995,12 +2010,7 @@ impl<'tcx> TyCtxt<'tcx> { // - has been created by this call to `create_def`. // As a consequence, this LocalDefId is always re-created before it is needed by the incr. // comp. engine itself. - // - // This call also writes to the value of the `source_span` query. - // This is fine because: - // - that query is `eval_always` so we won't miss its result changing; - // - this write will have happened before that query is called. - let def_id = self.untracked.definitions.write().create_def(parent, data); + let def_id = self.untracked.definitions.write().create_def(parent, data, disambiguator); // This function modifies `self.definitions` using a side-effect. // We need to ensure that these side effects are re-run by the incr. comp. engine. @@ -2125,7 +2135,8 @@ impl<'tcx> TyCtxt<'tcx> { CrateType::Executable | CrateType::Staticlib | CrateType::ProcMacro - | CrateType::Cdylib => false, + | CrateType::Cdylib + | CrateType::Sdylib => false, // FIXME rust-lang/rust#64319, rust-lang/rust#64872: // We want to block export of generics from dylibs, @@ -2413,6 +2424,8 @@ macro_rules! sty_debug_print { $(let mut $variant = total;)* for shard in tcx.interners.type_.lock_shards() { + // It seems that ordering doesn't affect anything here. + #[allow(rustc::potential_query_instability)] let types = shard.iter(); for &(InternedInSet(t), ()) in types { let variant = match t.internee { @@ -3307,6 +3320,10 @@ impl<'tcx> TyCtxt<'tcx> { && self.impl_trait_header(def_id).unwrap().constness == hir::Constness::Const } + pub fn is_sdylib_interface_build(self) -> bool { + self.sess.opts.unstable_opts.build_sdylib_interface + } + pub fn intrinsic(self, def_id: impl IntoQueryParam + Copy) -> Option { match self.def_kind(def_id) { DefKind::Fn | DefKind::AssocFn => {} @@ -3399,9 +3416,7 @@ pub fn provide(providers: &mut Providers) { providers.maybe_unused_trait_imports = |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports; providers.names_imported_by_glob_use = |tcx, id| { - tcx.arena.alloc(UnordSet::from( - tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default(), - )) + tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default()) }; providers.extern_mod_stmt_cnum = diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index fbb57b8df6bb..b122ada0925d 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -3,7 +3,7 @@ use std::fmt::Write; use std::ops::ControlFlow; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::{ Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, listify, pluralize, }; @@ -287,7 +287,7 @@ pub fn suggest_constraining_type_params<'a>( param_names_and_constraints: impl Iterator)>, span_to_replace: Option, ) -> bool { - let mut grouped = FxHashMap::default(); + let mut grouped = FxIndexMap::default(); let mut unstable_suggestion = false; param_names_and_constraints.for_each(|(param_name, constraint, def_id)| { let stable = match def_id { diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index d660e7d0d602..0d99a1b51499 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -491,7 +491,15 @@ fn resolve_async_drop_poll<'tcx>(mut cor_ty: Ty<'tcx>) -> Instance<'tcx> { } impl<'tcx> Instance<'tcx> { - pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> { + /// Creates a new [`InstanceKind::Item`] from the `def_id` and `args`. + /// + /// Note that this item corresponds to the body of `def_id` directly, which + /// likely does not make sense for trait items which need to be resolved to an + /// implementation, and which may not even have a body themselves. Usages of + /// this function should probably use [`Instance::expect_resolve`], or if run + /// in a polymorphic environment or within a lint (that may encounter ambiguity) + /// [`Instance::try_resolve`] instead. + pub fn new_raw(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> { assert!( !args.has_escaping_bound_vars(), "args of instance {def_id:?} has escaping bound vars: {args:?}" @@ -510,7 +518,7 @@ impl<'tcx> Instance<'tcx> { } }); - Instance::new(def_id, args) + Instance::new_raw(def_id, args) } #[inline] @@ -603,7 +611,7 @@ impl<'tcx> Instance<'tcx> { let type_length = type_length(args); if !tcx.type_length_limit().value_within_limit(type_length) { let (shrunk, written_to_path) = - shrunk_instance_name(tcx, Instance::new(def_id, args)); + shrunk_instance_name(tcx, Instance::new_raw(def_id, args)); let mut path = PathBuf::new(); let was_written = if let Some(path2) = written_to_path { path = path2; @@ -773,7 +781,7 @@ impl<'tcx> Instance<'tcx> { match needs_fn_once_adapter_shim(actual_kind, requested_kind) { Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args), - _ => Instance::new(def_id, args), + _ => Instance::new_raw(def_id, args), } } @@ -899,7 +907,7 @@ impl<'tcx> Instance<'tcx> { // This is important for `Iterator`'s combinators, but also useful for // adding future default methods to `Future`, for instance. debug_assert!(tcx.defaultness(trait_item_id).has_value()); - Some(Instance::new(trait_item_id, rcvr_args)) + Some(Instance::new_raw(trait_item_id, rcvr_args)) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2f4c03f0953d..2d69a1c2b553 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -38,6 +38,7 @@ use rustc_errors::{Diag, ErrorGuaranteed}; use rustc_hir::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; +use rustc_hir::definitions::DisambiguatorState; use rustc_index::IndexVec; use rustc_index::bit_set::BitMatrix; use rustc_macros::{ @@ -50,9 +51,17 @@ use rustc_session::lint::LintBuffer; pub use rustc_session::lint::RegisteredTools; use rustc_span::hygiene::MacroKind; use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym}; -pub use rustc_type_ir::data_structures::DelayedSet; +pub use rustc_type_ir::data_structures::{DelayedMap, DelayedSet}; +#[allow( + hidden_glob_reexports, + rustc::usage_of_type_ir_inherent, + rustc::non_glob_import_of_type_ir_inherent +)] +use rustc_type_ir::inherent; pub use rustc_type_ir::relate::VarianceDiagInfo; pub use rustc_type_ir::*; +#[allow(hidden_glob_reexports, unused_imports)] +use rustc_type_ir::{InferCtxtLike, Interner}; use tracing::{debug, instrument}; pub use vtable::*; use {rustc_ast as ast, rustc_attr_data_structures as attr, rustc_hir as hir}; @@ -173,7 +182,7 @@ pub struct ResolverGlobalCtxt { pub extern_crate_map: UnordMap, pub maybe_unused_trait_imports: FxIndexSet, pub module_children: LocalDefIdMap>, - pub glob_map: FxHashMap>, + pub glob_map: FxIndexMap>, pub main_def: Option, pub trait_impls: FxIndexMap>, /// A list of proc macro LocalDefIds, written out in the order in which @@ -209,6 +218,8 @@ pub struct ResolverAstLowering { pub node_id_to_def_id: NodeMap, + pub disambiguator: DisambiguatorState, + pub trait_map: NodeMap>, /// List functions and methods for which lifetime elision was successful. pub lifetime_elision_allowed: FxHashSet, @@ -298,7 +309,10 @@ impl Visibility { } else if restricted_id == tcx.parent_module_from_def_id(def_id).to_local_def_id() { "pub(self)".to_string() } else { - format!("pub({})", tcx.item_name(restricted_id.to_def_id())) + format!( + "pub(in crate{})", + tcx.def_path(restricted_id.to_def_id()).to_string_no_crate_verbose() + ) } } ty::Visibility::Public => "pub".to_string(), @@ -1929,13 +1943,17 @@ impl<'tcx> TyCtxt<'tcx> { if arg_cor_ty.is_coroutine() { let span = self.def_span(def_id); let source_info = SourceInfo::outermost(span); + // Even minimal, empty coroutine has 3 states (RESERVED_VARIANTS), + // so variant_fields and variant_source_info should have 3 elements. let variant_fields: IndexVec> = iter::repeat(IndexVec::new()).take(CoroutineArgs::RESERVED_VARIANTS).collect(); + let variant_source_info: IndexVec = + iter::repeat(source_info).take(CoroutineArgs::RESERVED_VARIANTS).collect(); let proxy_layout = CoroutineLayout { field_tys: [].into(), field_names: [].into(), variant_fields, - variant_source_info: [source_info].into(), + variant_source_info, storage_conflicts: BitMatrix::new(0, 0), }; return Some(self.arena.alloc(proxy_layout)); @@ -1978,6 +1996,10 @@ impl<'tcx> TyCtxt<'tcx> { None } + pub fn is_exportable(self, def_id: DefId) -> bool { + self.exportable_items(def_id.krate).contains(&def_id) + } + /// Check if the given `DefId` is `#\[automatically_derived\]`, *and* /// whether it was produced by expanding a builtin derive macro. pub fn is_builtin_derived(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ad8677f7c7da..0250c777faf7 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -6,7 +6,7 @@ use std::ops::{Deref, DerefMut}; use rustc_abi::{ExternAbi, Size}; use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; use rustc_hir::LangItem; @@ -2934,7 +2934,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { fn prepare_region_info(&mut self, value: &ty::Binder<'tcx, T>) where - T: TypeVisitable>, + T: TypeFoldable>, { struct RegionNameCollector<'tcx> { used_region_names: FxHashSet, @@ -3195,7 +3195,7 @@ define_print! { ty::AliasTerm<'tcx> { match self.kind(cx.tcx()) { - ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)), + ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => p!(pretty_print_inherent_projection(*self)), ty::AliasTermKind::ProjectionTy => { if !(cx.should_print_verbose() || with_reduced_queries()) && cx.tcx().is_impl_trait_in_trait(self.def_id) @@ -3205,7 +3205,8 @@ define_print! { p!(print_def_path(self.def_id, self.args)); } } - | ty::AliasTermKind::FreeTy + ty::AliasTermKind::FreeTy + | ty::AliasTermKind::FreeConst | ty::AliasTermKind::OpaqueTy | ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => { @@ -3496,8 +3497,8 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { // Once constructed, unique namespace+symbol pairs will have a `Some(_)` entry, while // non-unique pairs will have a `None` entry. - let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option> = - &mut FxHashMap::default(); + let unique_symbols_rev: &mut FxIndexMap<(Namespace, Symbol), Option> = + &mut FxIndexMap::default(); for symbol_set in tcx.resolutions(()).glob_map.values() { for symbol in symbol_set { @@ -3507,27 +3508,23 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { } } - for_each_def(tcx, |ident, ns, def_id| { - use std::collections::hash_map::Entry::{Occupied, Vacant}; - - match unique_symbols_rev.entry((ns, ident.name)) { - Occupied(mut v) => match v.get() { - None => {} - Some(existing) => { - if *existing != def_id { - v.insert(None); - } + for_each_def(tcx, |ident, ns, def_id| match unique_symbols_rev.entry((ns, ident.name)) { + IndexEntry::Occupied(mut v) => match v.get() { + None => {} + Some(existing) => { + if *existing != def_id { + v.insert(None); } - }, - Vacant(v) => { - v.insert(Some(def_id)); } + }, + IndexEntry::Vacant(v) => { + v.insert(Some(def_id)); } }); // Put the symbol from all the unique namespace+symbol pairs into `map`. let mut map: DefIdMap = Default::default(); - for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() { + for ((_, symbol), opt_def_id) in unique_symbols_rev.drain(..) { use std::collections::hash_map::Entry::{Occupied, Vacant}; if let Some(def_id) = opt_def_id { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 2165cf186bd5..c31ce1bc6307 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -723,7 +723,10 @@ impl<'tcx> Ty<'tcx> { repr: DynKind, ) -> Ty<'tcx> { if cfg!(debug_assertions) { - let projection_count = obj.projection_bounds().count(); + let projection_count = obj + .projection_bounds() + .filter(|item| !tcx.generics_require_sized_self(item.item_def_id())) + .count(); let expected_count: usize = obj .principal_def_id() .into_iter() diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index f5158edffcff..6fe5927c29fc 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -966,7 +966,9 @@ impl<'tcx> TyCtxt<'tcx> { } ty::AliasTermKind::OpaqueTy => Some(self.variances_of(def_id)), ty::AliasTermKind::InherentTy + | ty::AliasTermKind::InherentConst | ty::AliasTermKind::FreeTy + | ty::AliasTermKind::FreeConst | ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => None, } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 3853a804a920..f80421745991 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -66,7 +66,7 @@ impl<'tcx> TyCtxt<'tcx> { { type Result = ControlFlow<()>; - fn visit_binder>>( + fn visit_binder>>( &mut self, t: &Binder<'tcx, T>, ) -> Self::Result { @@ -168,7 +168,7 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { - fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) { + fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) { self.current_index.shift_in(1); t.super_visit_with(self); self.current_index.shift_out(1); diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 59a52ae67cb1..9cf051a8760b 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -998,7 +998,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.source_scope = source_scope; } - if self.tcx.intrinsic(self.def_id).is_some_and(|i| i.must_be_overridden) { + if self.tcx.intrinsic(self.def_id).is_some_and(|i| i.must_be_overridden) + || self.tcx.is_sdylib_interface_build() + { let source_info = self.source_info(rustc_span::DUMMY_SP); self.cfg.terminate(block, source_info, TerminatorKind::Unreachable); self.cfg.start_new_block().unit() diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 8e69ff568b92..fcd106d78e25 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -553,8 +553,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let res = self.typeck_results.qpath_res(qpath, id); let (def_id, user_ty) = match res { - Res::Def(DefKind::Const, def_id) => (def_id, None), - Res::Def(DefKind::AssocConst, def_id) => { + Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => { (def_id, self.typeck_results.user_provided_types().get(id)) } @@ -568,6 +567,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Lower the named constant to a THIR pattern. let args = self.typeck_results.node_args(id); + // FIXME(mgca): we will need to special case IACs here to have type system compatible + // generic args, instead of how we represent them in body expressions. let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args }); let mut pattern = self.const_to_pat(c, ty, id, span); diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index d5005768b80b..3f6e7a066192 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -1,5 +1,6 @@ //! Random access inspection of the results of a dataflow analysis. +use std::borrow::Cow; use std::cmp::Ordering; use std::ops::{Deref, DerefMut}; @@ -9,38 +10,30 @@ use rustc_middle::mir::{self, BasicBlock, Location}; use super::{Analysis, Direction, Effect, EffectIndex, Results}; -/// Some `ResultsCursor`s want to own a `Results`, and some want to borrow a `Results`, either -/// mutable or immutably. This type allows all of the above. It's similar to `Cow`. -pub enum ResultsHandle<'a, 'tcx, A> -where - A: Analysis<'tcx>, -{ - BorrowedMut(&'a mut Results<'tcx, A>), - Owned(Results<'tcx, A>), +/// Some `ResultsCursor`s want to own an `Analysis`, and some want to borrow an `Analysis`, either +/// mutable or immutably. This type allows all of the above. It's similar to `Cow`, but `Cow` +/// doesn't allow mutable borrowing. +enum CowMut<'a, T> { + BorrowedMut(&'a mut T), + Owned(T), } -impl<'tcx, A> Deref for ResultsHandle<'_, 'tcx, A> -where - A: Analysis<'tcx>, -{ - type Target = Results<'tcx, A>; +impl Deref for CowMut<'_, T> { + type Target = T; - fn deref(&self) -> &Results<'tcx, A> { + fn deref(&self) -> &T { match self { - ResultsHandle::BorrowedMut(borrowed) => borrowed, - ResultsHandle::Owned(owned) => owned, + CowMut::BorrowedMut(borrowed) => borrowed, + CowMut::Owned(owned) => owned, } } } -impl<'tcx, A> DerefMut for ResultsHandle<'_, 'tcx, A> -where - A: Analysis<'tcx>, -{ - fn deref_mut(&mut self) -> &mut Results<'tcx, A> { +impl DerefMut for CowMut<'_, T> { + fn deref_mut(&mut self) -> &mut T { match self { - ResultsHandle::BorrowedMut(borrowed) => borrowed, - ResultsHandle::Owned(owned) => owned, + CowMut::BorrowedMut(borrowed) => borrowed, + CowMut::Owned(owned) => owned, } } } @@ -60,7 +53,8 @@ where A: Analysis<'tcx>, { body: &'mir mir::Body<'tcx>, - results: ResultsHandle<'mir, 'tcx, A>, + analysis: CowMut<'mir, A>, + results: Cow<'mir, Results>, state: A::Domain, pos: CursorPosition, @@ -88,11 +82,15 @@ where self.body } - /// Returns a new cursor that can inspect `results`. - pub fn new(body: &'mir mir::Body<'tcx>, results: ResultsHandle<'mir, 'tcx, A>) -> Self { - let bottom_value = results.analysis.bottom_value(body); + fn new( + body: &'mir mir::Body<'tcx>, + analysis: CowMut<'mir, A>, + results: Cow<'mir, Results>, + ) -> Self { + let bottom_value = analysis.bottom_value(body); ResultsCursor { body, + analysis, results, // Initialize to the `bottom_value` and set `state_needs_reset` to tell the cursor that @@ -107,6 +105,24 @@ where } } + /// Returns a new cursor that takes ownership of and inspects analysis results. + pub fn new_owning( + body: &'mir mir::Body<'tcx>, + analysis: A, + results: Results, + ) -> Self { + Self::new(body, CowMut::Owned(analysis), Cow::Owned(results)) + } + + /// Returns a new cursor that borrows and inspects analysis results. + pub fn new_borrowing( + body: &'mir mir::Body<'tcx>, + analysis: &'mir mut A, + results: &'mir Results, + ) -> Self { + Self::new(body, CowMut::BorrowedMut(analysis), Cow::Borrowed(results)) + } + /// Allows inspection of unreachable basic blocks even with `debug_assertions` enabled. #[cfg(test)] pub(crate) fn allow_unreachable(&mut self) { @@ -116,7 +132,7 @@ where /// Returns the `Analysis` used to generate the underlying `Results`. pub fn analysis(&self) -> &A { - &self.results.analysis + &self.analysis } /// Resets the cursor to hold the entry set for the given basic block. @@ -128,7 +144,7 @@ where #[cfg(debug_assertions)] assert!(self.reachable_blocks.contains(block)); - self.state.clone_from(self.results.entry_set_for_block(block)); + self.state.clone_from(&self.results[block]); self.pos = CursorPosition::block_entry(block); self.state_needs_reset = false; } @@ -220,7 +236,7 @@ where let target_effect_index = effect.at_index(target.statement_index); A::Direction::apply_effects_in_range( - &mut self.results.analysis, + &mut *self.analysis, &mut self.state, target.block, block_data, @@ -236,7 +252,7 @@ where /// This can be used, e.g., to apply the call return effect directly to the cursor without /// creating an extra copy of the dataflow state. pub fn apply_custom_effect(&mut self, f: impl FnOnce(&mut A, &mut A::Domain)) { - f(&mut self.results.analysis, &mut self.state); + f(&mut self.analysis, &mut self.state); self.state_needs_reset = true; } } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index b8c26dad59f4..e955e38ad10f 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::{ }; use super::visitor::ResultsVisitor; -use super::{Analysis, Effect, EffectIndex, Results}; +use super::{Analysis, Effect, EffectIndex}; pub trait Direction { const IS_FORWARD: bool; @@ -36,13 +36,13 @@ pub trait Direction { A: Analysis<'tcx>; /// Called by `ResultsVisitor` to recompute the analysis domain values for - /// all locations in a basic block (starting from the entry value stored - /// in `Results`) and to visit them with `vis`. + /// all locations in a basic block (starting from `entry_state` and to + /// visit them with `vis`. fn visit_results_in_block<'mir, 'tcx, A>( state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut Results<'tcx, A>, + analysis: &mut A, vis: &mut impl ResultsVisitor<'tcx, A>, ) where A: Analysis<'tcx>; @@ -211,28 +211,26 @@ impl Direction for Backward { state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut Results<'tcx, A>, + analysis: &mut A, vis: &mut impl ResultsVisitor<'tcx, A>, ) where A: Analysis<'tcx>, { - state.clone_from(results.entry_set_for_block(block)); - vis.visit_block_end(state); let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.analysis.apply_early_terminator_effect(state, term, loc); - vis.visit_after_early_terminator_effect(results, state, term, loc); - results.analysis.apply_primary_terminator_effect(state, term, loc); - vis.visit_after_primary_terminator_effect(results, state, term, loc); + analysis.apply_early_terminator_effect(state, term, loc); + vis.visit_after_early_terminator_effect(analysis, state, term, loc); + analysis.apply_primary_terminator_effect(state, term, loc); + vis.visit_after_primary_terminator_effect(analysis, state, term, loc); for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() { let loc = Location { block, statement_index }; - results.analysis.apply_early_statement_effect(state, stmt, loc); - vis.visit_after_early_statement_effect(results, state, stmt, loc); - results.analysis.apply_primary_statement_effect(state, stmt, loc); - vis.visit_after_primary_statement_effect(results, state, stmt, loc); + analysis.apply_early_statement_effect(state, stmt, loc); + vis.visit_after_early_statement_effect(analysis, state, stmt, loc); + analysis.apply_primary_statement_effect(state, stmt, loc); + vis.visit_after_primary_statement_effect(analysis, state, stmt, loc); } vis.visit_block_start(state); @@ -393,29 +391,27 @@ impl Direction for Forward { state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut Results<'tcx, A>, + analysis: &mut A, vis: &mut impl ResultsVisitor<'tcx, A>, ) where A: Analysis<'tcx>, { - state.clone_from(results.entry_set_for_block(block)); - vis.visit_block_start(state); for (statement_index, stmt) in block_data.statements.iter().enumerate() { let loc = Location { block, statement_index }; - results.analysis.apply_early_statement_effect(state, stmt, loc); - vis.visit_after_early_statement_effect(results, state, stmt, loc); - results.analysis.apply_primary_statement_effect(state, stmt, loc); - vis.visit_after_primary_statement_effect(results, state, stmt, loc); + analysis.apply_early_statement_effect(state, stmt, loc); + vis.visit_after_early_statement_effect(analysis, state, stmt, loc); + analysis.apply_primary_statement_effect(state, stmt, loc); + vis.visit_after_primary_statement_effect(analysis, state, stmt, loc); } let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.analysis.apply_early_terminator_effect(state, term, loc); - vis.visit_after_early_terminator_effect(results, state, term, loc); - results.analysis.apply_primary_terminator_effect(state, term, loc); - vis.visit_after_primary_terminator_effect(results, state, term, loc); + analysis.apply_early_terminator_effect(state, term, loc); + vis.visit_after_early_terminator_effect(analysis, state, term, loc); + analysis.apply_primary_terminator_effect(state, term, loc); + vis.visit_after_primary_terminator_effect(analysis, state, term, loc); vis.visit_block_end(state); } diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index b5e9a0b89324..a7d5422a3d72 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -21,7 +21,9 @@ use tracing::debug; use {rustc_ast as ast, rustc_graphviz as dot}; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; -use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor}; +use super::{ + Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor, visit_results, +}; use crate::errors::{ DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, }; @@ -32,7 +34,8 @@ use crate::errors::{ pub(super) fn write_graphviz_results<'tcx, A>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - results: &mut Results<'tcx, A>, + analysis: &mut A, + results: &Results, pass_name: Option<&'static str>, ) -> std::io::Result<()> where @@ -77,7 +80,7 @@ where let mut buf = Vec::new(); - let graphviz = Formatter::new(body, results, style); + let graphviz = Formatter::new(body, analysis, results, style); let mut render_opts = vec![dot::RenderOption::Fontname(tcx.sess.opts.unstable_opts.graphviz_font.clone())]; if tcx.sess.opts.unstable_opts.graphviz_dark_mode { @@ -203,10 +206,11 @@ where { body: &'mir Body<'tcx>, // The `RefCell` is used because `::node_label` - // takes `&self`, but it needs to modify the results. This is also the + // takes `&self`, but it needs to modify the analysis. This is also the // reason for the `Formatter`/`BlockFormatter` split; `BlockFormatter` has // the operations that involve the mutation, i.e. within the `borrow_mut`. - results: RefCell<&'mir mut Results<'tcx, A>>, + analysis: RefCell<&'mir mut A>, + results: &'mir Results, style: OutputStyle, reachable: DenseBitSet, } @@ -217,11 +221,12 @@ where { fn new( body: &'mir Body<'tcx>, - results: &'mir mut Results<'tcx, A>, + analysis: &'mir mut A, + results: &'mir Results, style: OutputStyle, ) -> Self { let reachable = traversal::reachable_as_bitset(body); - Formatter { body, results: results.into(), style, reachable } + Formatter { body, analysis: analysis.into(), results, style, reachable } } } @@ -259,12 +264,12 @@ where } fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> { - let mut results = self.results.borrow_mut(); + let analysis = &mut **self.analysis.borrow_mut(); - let diffs = StateDiffCollector::run(self.body, *block, *results, self.style); + let diffs = StateDiffCollector::run(self.body, *block, analysis, self.results, self.style); let mut fmt = BlockFormatter { - cursor: results.as_results_cursor(self.body), + cursor: ResultsCursor::new_borrowing(self.body, analysis, self.results), style: self.style, bg: Background::Light, }; @@ -692,7 +697,8 @@ impl StateDiffCollector { fn run<'tcx, A>( body: &Body<'tcx>, block: BasicBlock, - results: &mut Results<'tcx, A>, + analysis: &mut A, + results: &Results, style: OutputStyle, ) -> Self where @@ -700,12 +706,12 @@ impl StateDiffCollector { D: DebugWithContext, { let mut collector = StateDiffCollector { - prev_state: results.analysis.bottom_value(body), + prev_state: analysis.bottom_value(body), after: vec![], before: (style == OutputStyle::BeforeAndAfter).then_some(vec![]), }; - results.visit_with(body, std::iter::once(block), &mut collector); + visit_results(body, std::iter::once(block), analysis, results, &mut collector); collector } } @@ -729,49 +735,49 @@ where fn visit_after_early_statement_effect( &mut self, - results: &mut Results<'tcx, A>, + analysis: &mut A, state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, ) { if let Some(before) = self.before.as_mut() { - before.push(diff_pretty(state, &self.prev_state, &results.analysis)); + before.push(diff_pretty(state, &self.prev_state, analysis)); self.prev_state.clone_from(state) } } fn visit_after_primary_statement_effect( &mut self, - results: &mut Results<'tcx, A>, + analysis: &mut A, state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, ) { - self.after.push(diff_pretty(state, &self.prev_state, &results.analysis)); + self.after.push(diff_pretty(state, &self.prev_state, analysis)); self.prev_state.clone_from(state) } fn visit_after_early_terminator_effect( &mut self, - results: &mut Results<'tcx, A>, + analysis: &mut A, state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, ) { if let Some(before) = self.before.as_mut() { - before.push(diff_pretty(state, &self.prev_state, &results.analysis)); + before.push(diff_pretty(state, &self.prev_state, analysis)); self.prev_state.clone_from(state) } } fn visit_after_primary_terminator_effect( &mut self, - results: &mut Results<'tcx, A>, + analysis: &mut A, state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, ) { - self.after.push(diff_pretty(state, &self.prev_state, &results.analysis)); + self.after.push(diff_pretty(state, &self.prev_state, analysis)); self.prev_state.clone_from(state) } } diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 09f6cdb5c4a7..9cadec100b53 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -58,8 +58,9 @@ mod visitor; pub use self::cursor::ResultsCursor; pub use self::direction::{Backward, Direction, Forward}; pub use self::lattice::{JoinSemiLattice, MaybeReachable}; -pub use self::results::{EntryStates, Results}; -pub use self::visitor::{ResultsVisitor, visit_results}; +pub(crate) use self::results::AnalysisAndResults; +pub use self::results::Results; +pub use self::visitor::{ResultsVisitor, visit_reachable_results, visit_results}; /// Analysis domains are all bitsets of various kinds. This trait holds /// operations needed by all of them. @@ -247,17 +248,15 @@ pub trait Analysis<'tcx> { tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, pass_name: Option<&'static str>, - ) -> Results<'tcx, Self> + ) -> AnalysisAndResults<'tcx, Self> where Self: Sized, Self::Domain: DebugWithContext, { - let mut entry_states = - IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len()); - self.initialize_start_block(body, &mut entry_states[mir::START_BLOCK]); + let mut results = IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len()); + self.initialize_start_block(body, &mut results[mir::START_BLOCK]); - if Self::Direction::IS_BACKWARD && entry_states[mir::START_BLOCK] != self.bottom_value(body) - { + if Self::Direction::IS_BACKWARD && results[mir::START_BLOCK] != self.bottom_value(body) { bug!("`initialize_start_block` is not yet supported for backward dataflow analyses"); } @@ -280,10 +279,9 @@ pub trait Analysis<'tcx> { // every iteration. let mut state = self.bottom_value(body); while let Some(bb) = dirty_queue.pop() { - // Set the state to the entry state of the block. - // This is equivalent to `state = entry_states[bb].clone()`, - // but it saves an allocation, thus improving compile times. - state.clone_from(&entry_states[bb]); + // Set the state to the entry state of the block. This is equivalent to `state = + // results[bb].clone()`, but it saves an allocation, thus improving compile times. + state.clone_from(&results[bb]); Self::Direction::apply_effects_in_block( &mut self, @@ -292,7 +290,7 @@ pub trait Analysis<'tcx> { bb, &body[bb], |target: BasicBlock, state: &Self::Domain| { - let set_changed = entry_states[target].join(state); + let set_changed = results[target].join(state); if set_changed { dirty_queue.insert(target); } @@ -300,16 +298,14 @@ pub trait Analysis<'tcx> { ); } - let mut results = Results { analysis: self, entry_states }; - if tcx.sess.opts.unstable_opts.dump_mir_dataflow { - let res = write_graphviz_results(tcx, body, &mut results, pass_name); + let res = write_graphviz_results(tcx, body, &mut self, &results, pass_name); if let Err(e) = res { error!("Failed to write graphviz dataflow results: {}", e); } } - results + AnalysisAndResults { analysis: self, results } } } diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index 93dfc06a878a..7b7e981d3a55 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -1,63 +1,30 @@ //! Dataflow analysis results. use rustc_index::IndexVec; -use rustc_middle::mir::{BasicBlock, Body, traversal}; +use rustc_middle::mir::{BasicBlock, Body}; -use super::{Analysis, ResultsCursor, ResultsVisitor, visit_results}; -use crate::framework::cursor::ResultsHandle; +use super::{Analysis, ResultsCursor}; -pub type EntryStates<'tcx, A> = IndexVec>::Domain>; +/// The results of a dataflow analysis that has converged to fixpoint. It only holds the domain +/// values at the entry of each basic block. Domain values in other parts of the block are +/// recomputed on the fly by visitors (i.e. `ResultsCursor`, or `ResultsVisitor` impls). +pub type Results = IndexVec; -/// A dataflow analysis that has converged to fixpoint. It only holds the domain values at the -/// entry of each basic block. Domain values in other parts of the block are recomputed on the fly -/// by visitors (i.e. `ResultsCursor`, or `ResultsVisitor` impls). -#[derive(Clone)] -pub struct Results<'tcx, A> +/// Utility type used in a few places where it's convenient to bundle an analysis with its results. +pub struct AnalysisAndResults<'tcx, A> where A: Analysis<'tcx>, { pub analysis: A, - pub entry_states: EntryStates<'tcx, A>, + pub results: Results, } -impl<'tcx, A> Results<'tcx, A> +impl<'tcx, A> AnalysisAndResults<'tcx, A> where A: Analysis<'tcx>, { - /// Creates a `ResultsCursor` that mutably borrows the `Results`, which is appropriate when the - /// `Results` is also used outside the cursor. - pub fn as_results_cursor<'mir>( - &'mir mut self, - body: &'mir Body<'tcx>, - ) -> ResultsCursor<'mir, 'tcx, A> { - ResultsCursor::new(body, ResultsHandle::BorrowedMut(self)) - } - - /// Creates a `ResultsCursor` that takes ownership of the `Results`. + /// Creates a `ResultsCursor` that takes ownership of `self`. pub fn into_results_cursor<'mir>(self, body: &'mir Body<'tcx>) -> ResultsCursor<'mir, 'tcx, A> { - ResultsCursor::new(body, ResultsHandle::Owned(self)) - } - - /// Gets the dataflow state for the given block. - pub fn entry_set_for_block(&self, block: BasicBlock) -> &A::Domain { - &self.entry_states[block] - } - - pub fn visit_with<'mir>( - &mut self, - body: &'mir Body<'tcx>, - blocks: impl IntoIterator, - vis: &mut impl ResultsVisitor<'tcx, A>, - ) { - visit_results(body, blocks, self, vis) - } - - pub fn visit_reachable_with<'mir>( - &mut self, - body: &'mir Body<'tcx>, - vis: &mut impl ResultsVisitor<'tcx, A>, - ) { - let blocks = traversal::reachable(body); - visit_results(body, blocks.map(|(bb, _)| bb), self, vis) + ResultsCursor::new_owning(body, self.analysis, self.results) } } diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index ae0f1179e6fa..8602bb557652 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -79,7 +79,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { /// /// The `102` in the block's entry set is derived from the basic block index and ensures that the /// expected state is unique across all basic blocks. Remember, it is generated by -/// `mock_entry_states`, not from actually running `MockAnalysis` to fixpoint. +/// `mock_results`, not from actually running `MockAnalysis` to fixpoint. struct MockAnalysis<'tcx, D> { body: &'tcx mir::Body<'tcx>, dir: PhantomData, @@ -96,7 +96,7 @@ impl MockAnalysis<'_, D> { ret } - fn mock_entry_states(&self) -> IndexVec> { + fn mock_results(&self) -> IndexVec> { let empty = self.bottom_value(self.body); let mut ret = IndexVec::from_elem(empty, &self.body.basic_blocks); @@ -255,7 +255,7 @@ fn test_cursor(analysis: MockAnalysis<'_, D>) { let body = analysis.body; let mut cursor = - Results { entry_states: analysis.mock_entry_states(), analysis }.into_results_cursor(body); + AnalysisAndResults { results: analysis.mock_results(), analysis }.into_results_cursor(body); cursor.allow_unreachable(); diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs index c9fdf46c4f5b..fbb9e4108726 100644 --- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir::{self, BasicBlock, Location}; +use rustc_middle::mir::{self, BasicBlock, Location, traversal}; use super::{Analysis, Direction, Results}; @@ -7,12 +7,13 @@ use super::{Analysis, Direction, Results}; pub fn visit_results<'mir, 'tcx, A>( body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, - results: &mut Results<'tcx, A>, + analysis: &mut A, + results: &Results, vis: &mut impl ResultsVisitor<'tcx, A>, ) where A: Analysis<'tcx>, { - let mut state = results.analysis.bottom_value(body); + let mut state = analysis.bottom_value(body); #[cfg(debug_assertions)] let reachable_blocks = mir::traversal::reachable_as_bitset(body); @@ -22,10 +23,24 @@ pub fn visit_results<'mir, 'tcx, A>( assert!(reachable_blocks.contains(block)); let block_data = &body[block]; - A::Direction::visit_results_in_block(&mut state, block, block_data, results, vis); + state.clone_from(&results[block]); + A::Direction::visit_results_in_block(&mut state, block, block_data, analysis, vis); } } +/// Like `visit_results`, but only for reachable blocks. +pub fn visit_reachable_results<'mir, 'tcx, A>( + body: &'mir mir::Body<'tcx>, + analysis: &mut A, + results: &Results, + vis: &mut impl ResultsVisitor<'tcx, A>, +) where + A: Analysis<'tcx>, +{ + let blocks = traversal::reachable(body).map(|(bb, _)| bb); + visit_results(body, blocks, analysis, results, vis) +} + /// A visitor over the results of an `Analysis`. Use this when you want to inspect domain values in /// many or all locations; use `ResultsCursor` if you want to inspect domain values only in certain /// locations. @@ -38,7 +53,7 @@ where /// Called after the "early" effect of the given statement is applied to `state`. fn visit_after_early_statement_effect( &mut self, - _results: &mut Results<'tcx, A>, + _analysis: &mut A, _state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, @@ -48,7 +63,7 @@ where /// Called after the "primary" effect of the given statement is applied to `state`. fn visit_after_primary_statement_effect( &mut self, - _results: &mut Results<'tcx, A>, + _analysis: &mut A, _state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, @@ -58,7 +73,7 @@ where /// Called after the "early" effect of the given terminator is applied to `state`. fn visit_after_early_terminator_effect( &mut self, - _results: &mut Results<'tcx, A>, + _analysis: &mut A, _state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, @@ -70,7 +85,7 @@ where /// The `call_return_effect` (if one exists) will *not* be applied to `state`. fn visit_after_primary_terminator_effect( &mut self, - _results: &mut Results<'tcx, A>, + _analysis: &mut A, _state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 38f82b127465..658fbf505e44 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -18,8 +18,8 @@ pub use self::drop_flag_effects::{ move_path_children_matching, on_all_children_bits, on_lookup_result_bits, }; pub use self::framework::{ - Analysis, Backward, Direction, EntryStates, Forward, GenKill, JoinSemiLattice, MaybeReachable, - Results, ResultsCursor, ResultsVisitor, fmt, graphviz, lattice, visit_results, + Analysis, Backward, Direction, Forward, GenKill, JoinSemiLattice, MaybeReachable, Results, + ResultsCursor, ResultsVisitor, fmt, graphviz, lattice, visit_reachable_results, visit_results, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs index 21590ff1bbad..70d1a34b5fb1 100644 --- a/compiler/rustc_mir_dataflow/src/points.rs +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -98,7 +98,8 @@ rustc_index::newtype_index! { pub fn save_as_intervals<'tcx, N, A>( elements: &DenseLocationMap, body: &mir::Body<'tcx>, - mut results: Results<'tcx, A>, + mut analysis: A, + results: Results, ) -> SparseIntervalMatrix where N: Idx, @@ -109,7 +110,8 @@ where visit_results( body, body.basic_blocks.reverse_postorder().iter().copied(), - &mut results, + &mut analysis, + &results, &mut visitor, ); visitor.values @@ -127,7 +129,7 @@ where { fn visit_after_primary_statement_effect<'mir>( &mut self, - _results: &mut Results<'tcx, A>, + _analysis: &mut A, state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, location: Location, @@ -141,7 +143,7 @@ where fn visit_after_primary_terminator_effect<'mir>( &mut self, - _results: &mut Results<'tcx, A>, + _analysis: &mut A, state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, location: Location, diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 399141aa9212..303fc767b9a3 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -39,23 +39,23 @@ pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let move_data = MoveData::gather_moves(body, tcx, |_| true); if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { - let flow_inits = - MaybeInitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint(tcx, body, None); - - sanity_check_via_rustc_peek(tcx, flow_inits.into_results_cursor(body)); + let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) + .iterate_to_fixpoint(tcx, body, None) + .into_results_cursor(body); + sanity_check_via_rustc_peek(tcx, flow_inits); } if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) - .iterate_to_fixpoint(tcx, body, None); - - sanity_check_via_rustc_peek(tcx, flow_uninits.into_results_cursor(body)); + .iterate_to_fixpoint(tcx, body, None) + .into_results_cursor(body); + sanity_check_via_rustc_peek(tcx, flow_uninits); } if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() { - let flow_liveness = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None); - - sanity_check_via_rustc_peek(tcx, flow_liveness.into_results_cursor(body)); + let flow_liveness = + MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None).into_results_cursor(body); + sanity_check_via_rustc_peek(tcx, flow_liveness); } if has_rustc_mir_with(tcx, def_id, sym::stop_after_dataflow).is_some() { diff --git a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs index 4aff127908ee..8da17a056e31 100644 --- a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs +++ b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs @@ -55,18 +55,45 @@ impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> { }, // char → u32 (Char, Uint(UintTy::U32)) => err(format!("u32::from({arg})")), + // char (→ u32) → i32 + (Char, Int(IntTy::I32)) => err(format!("u32::from({arg}).cast_signed()")), // u32 → char (Uint(UintTy::U32), Char) => Error { sugg: format!("char::from_u32_unchecked({arg})"), help: Some("consider `char::from_u32(…).unwrap()`"), span, }, + // i32 → char + (Int(IntTy::I32), Char) => Error { + sugg: format!("char::from_u32_unchecked(i32::cast_unsigned({arg}))"), + help: Some("consider `char::from_u32(i32::cast_unsigned(…)).unwrap()`"), + span, + }, // uNN → iNN (Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())), // iNN → uNN (Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())), + // fNN → xsize + (Float(ty), Uint(UintTy::Usize)) => { + err(format!("{}::to_bits({arg}) as usize", ty.name_str())) + } + (Float(ty), Int(IntTy::Isize)) => { + err(format!("{}::to_bits({arg}) as isize", ty.name_str())) + } + // fNN (→ uNN) → iNN + (Float(ty), Int(..)) => err(format!("{}::to_bits({arg}).cast_signed()", ty.name_str())), // fNN → uNN (Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())), + // xsize → fNN + (Uint(UintTy::Usize) | Int(IntTy::Isize), Float(ty)) => { + err(format!("{}::from_bits({arg} as _)", ty.name_str(),)) + } + // iNN (→ uNN) → fNN + (Int(int_ty), Float(ty)) => err(format!( + "{}::from_bits({}::cast_unsigned({arg}))", + ty.name_str(), + int_ty.name_str() + )), // uNN → fNN (Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())), // bool → { x8 } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 263f0c40f5a5..cddb2f847785 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -79,7 +79,9 @@ use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, always_storage_live_locals, }; -use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor}; +use rustc_mir_dataflow::{ + Analysis, Results, ResultsCursor, ResultsVisitor, visit_reachable_results, +}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::source_map::dummy_spanned; use rustc_span::symbol::sym; @@ -680,18 +682,29 @@ fn locals_live_across_suspend_points<'tcx>( .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body); - // Calculate the MIR locals which have been previously - // borrowed (even if they are still active). - let borrowed_locals_results = - MaybeBorrowedLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")); - - let mut borrowed_locals_cursor = borrowed_locals_results.clone().into_results_cursor(body); + // Calculate the MIR locals that have been previously borrowed (even if they are still active). + let borrowed_locals = MaybeBorrowedLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")); + let mut borrowed_locals_analysis1 = borrowed_locals.analysis; + let mut borrowed_locals_analysis2 = borrowed_locals_analysis1.clone(); // trivial + let borrowed_locals_cursor1 = ResultsCursor::new_borrowing( + body, + &mut borrowed_locals_analysis1, + &borrowed_locals.results, + ); + let mut borrowed_locals_cursor2 = ResultsCursor::new_borrowing( + body, + &mut borrowed_locals_analysis2, + &borrowed_locals.results, + ); // Calculate the MIR locals that we need to keep storage around for. - let mut requires_storage_results = - MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body)) - .iterate_to_fixpoint(tcx, body, None); - let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body); + let mut requires_storage = + MaybeRequiresStorage::new(borrowed_locals_cursor1).iterate_to_fixpoint(tcx, body, None); + let mut requires_storage_cursor = ResultsCursor::new_borrowing( + body, + &mut requires_storage.analysis, + &requires_storage.results, + ); // Calculate the liveness of MIR locals ignoring borrows. let mut liveness = @@ -720,8 +733,8 @@ fn locals_live_across_suspend_points<'tcx>( // If a borrow is converted to a raw reference, we must also assume that it lives // forever. Note that the final liveness is still bounded by the storage liveness // of the local, which happens using the `intersect` operation below. - borrowed_locals_cursor.seek_before_primary_effect(loc); - live_locals.union(borrowed_locals_cursor.get()); + borrowed_locals_cursor2.seek_before_primary_effect(loc); + live_locals.union(borrowed_locals_cursor2.get()); } // Store the storage liveness for later use so we can restore the state @@ -763,7 +776,8 @@ fn locals_live_across_suspend_points<'tcx>( body, &saved_locals, always_live_locals.clone(), - requires_storage_results, + &mut requires_storage.analysis, + &requires_storage.results, ); LivenessInfo { @@ -828,7 +842,8 @@ fn compute_storage_conflicts<'mir, 'tcx>( body: &'mir Body<'tcx>, saved_locals: &'mir CoroutineSavedLocals, always_live_locals: DenseBitSet, - mut requires_storage: Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, + analysis: &mut MaybeRequiresStorage<'mir, 'tcx>, + results: &Results>, ) -> BitMatrix { assert_eq!(body.local_decls.len(), saved_locals.domain_size()); @@ -848,7 +863,7 @@ fn compute_storage_conflicts<'mir, 'tcx>( eligible_storage_live: DenseBitSet::new_empty(body.local_decls.len()), }; - requires_storage.visit_reachable_with(body, &mut visitor); + visit_reachable_results(body, analysis, results, &mut visitor); let local_conflicts = visitor.local_conflicts; @@ -891,7 +906,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, MaybeRequiresStorage<'a, 'tcx>> { fn visit_after_early_statement_effect( &mut self, - _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, + _analysis: &mut MaybeRequiresStorage<'a, 'tcx>, state: &DenseBitSet, _statement: &Statement<'tcx>, loc: Location, @@ -901,7 +916,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, MaybeRequiresStorage<'a, 'tcx>> fn visit_after_early_terminator_effect( &mut self, - _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, + _analysis: &mut MaybeRequiresStorage<'a, 'tcx>, state: &DenseBitSet, _terminator: &Terminator<'tcx>, loc: Location, @@ -1064,10 +1079,8 @@ fn insert_switch<'tcx>( }, ); - let blocks = body.basic_blocks_mut().iter_mut(); - - for target in blocks.flat_map(|b| b.terminator_mut().successors_mut()) { - *target += 1; + for b in body.basic_blocks_mut().iter_mut() { + b.terminator_mut().successors_mut(|target| *target += 1); } } diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index dd0e07f2218e..0a839d91404e 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -73,6 +73,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::definitions::DisambiguatorState; use rustc_middle::bug; use rustc_middle::hir::place::{Projection, ProjectionKind}; use rustc_middle::mir::visit::MutVisitor; @@ -213,8 +214,15 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( let mut by_move_body = body.clone(); MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); - // This will always be `{closure#1}`, since the original coroutine is `{closure#0}`. - let body_def = tcx.create_def(parent_def_id, None, DefKind::SyntheticCoroutineBody); + // This path is unique since we're in a query so we'll only be called once with `parent_def_id` + // and this is the only location creating `SyntheticCoroutineBody`. + let body_def = tcx.create_def( + parent_def_id, + None, + DefKind::SyntheticCoroutineBody, + None, + &mut DisambiguatorState::new(), + ); by_move_body.source = mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(())); diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index 73bd2d0705e1..b4b4d0416fb9 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -91,7 +91,7 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>( // When debugging flag `-Zcoverage-options=no-mir-spans` is set, we need // to give the same treatment to _all_ functions, because `llvm-cov` // seems to ignore functions that don't have any ordinary code spans. - if let Some(span) = hir_info.fn_sig_span_extended { + if let Some(span) = hir_info.fn_sig_span { code_mappings.push(CodeMapping { span, bcb: START_BCB }); } } else { diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index f2e8f9e1bcd6..702c62eddc7f 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -268,9 +268,9 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb struct ExtractedHirInfo { function_source_hash: u64, is_async_fn: bool, - /// The span of the function's signature, extended to the start of `body_span`. + /// The span of the function's signature, if available. /// Must have the same context and filename as the body span. - fn_sig_span_extended: Option, + fn_sig_span: Option, body_span: Span, /// "Holes" are regions within the function body (or its expansions) that /// should not be included in coverage spans for this function @@ -308,30 +308,20 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir // The actual signature span is only used if it has the same context and // filename as the body, and precedes the body. - let fn_sig_span_extended = maybe_fn_sig - .map(|fn_sig| fn_sig.span) - .filter(|&fn_sig_span| { - let source_map = tcx.sess.source_map(); - let file_idx = |span: Span| source_map.lookup_source_file_idx(span.lo()); + let fn_sig_span = maybe_fn_sig.map(|fn_sig| fn_sig.span).filter(|&fn_sig_span| { + let source_map = tcx.sess.source_map(); + let file_idx = |span: Span| source_map.lookup_source_file_idx(span.lo()); - fn_sig_span.eq_ctxt(body_span) - && fn_sig_span.hi() <= body_span.lo() - && file_idx(fn_sig_span) == file_idx(body_span) - }) - // If so, extend it to the start of the body span. - .map(|fn_sig_span| fn_sig_span.with_hi(body_span.lo())); + fn_sig_span.eq_ctxt(body_span) + && fn_sig_span.hi() <= body_span.lo() + && file_idx(fn_sig_span) == file_idx(body_span) + }); let function_source_hash = hash_mir_source(tcx, hir_body); let hole_spans = extract_hole_spans_from_hir(tcx, hir_body); - ExtractedHirInfo { - function_source_hash, - is_async_fn, - fn_sig_span_extended, - body_span, - hole_spans, - } + ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span, body_span, hole_spans } } fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx hir::Body<'tcx>) -> u64 { diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index f57a158e3e4a..ec76076020eb 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,11 +1,8 @@ -use std::collections::VecDeque; -use std::iter; - use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; use rustc_middle::ty::TyCtxt; use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span}; -use tracing::{debug, debug_span, instrument}; +use tracing::instrument; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; use crate::coverage::spans::from_mir::{Hole, RawSpanFromMir, SpanFromMir}; @@ -42,12 +39,12 @@ pub(super) fn extract_refined_covspans<'tcx>( return; } - // Also add the adjusted function signature span, if available. + // Also add the function signature span, if available. // Otherwise, add a fake span at the start of the body, to avoid an ugly // gap between the start of the body and the first real span. // FIXME: Find a more principled way to solve this problem. covspans.push(SpanFromMir::for_fn_sig( - hir_info.fn_sig_span_extended.unwrap_or_else(|| body_span.shrink_to_lo()), + hir_info.fn_sig_span.unwrap_or_else(|| body_span.shrink_to_lo()), )); // First, perform the passes that need macro information. @@ -83,24 +80,17 @@ pub(super) fn extract_refined_covspans<'tcx>( holes.sort_by(|a, b| compare_spans(a.span, b.span)); holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b)); - // Split the covspans into separate buckets that don't overlap any holes. - let buckets = divide_spans_into_buckets(covspans, &holes); + // Discard any span that overlaps with a hole. + discard_spans_overlapping_holes(&mut covspans, &holes); - for covspans in buckets { - let _span = debug_span!("processing bucket", ?covspans).entered(); + // Perform more refinement steps after holes have been dealt with. + let mut covspans = remove_unwanted_overlapping_spans(covspans); + covspans.dedup_by(|b, a| a.merge_if_eligible(b)); - let mut covspans = remove_unwanted_overlapping_spans(covspans); - debug!(?covspans, "after removing overlaps"); - - // Do one last merge pass, to simplify the output. - covspans.dedup_by(|b, a| a.merge_if_eligible(b)); - debug!(?covspans, "after merge"); - - code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| { - // Each span produced by the refiner represents an ordinary code region. - mappings::CodeMapping { span, bcb } - })); - } + code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| { + // Each span produced by the refiner represents an ordinary code region. + mappings::CodeMapping { span, bcb } + })); } /// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate @@ -142,52 +132,36 @@ fn shrink_visible_macro_spans(tcx: TyCtxt<'_>, covspans: &mut Vec) } } -/// Uses the holes to divide the given covspans into buckets, such that: -/// - No span in any hole overlaps a bucket (discarding spans if necessary). -/// - The spans in each bucket are strictly after all spans in previous buckets, -/// and strictly before all spans in subsequent buckets. +/// Discard all covspans that overlap a hole. /// -/// The lists of covspans and holes must be sorted. -/// The resulting buckets are sorted relative to each other, and each bucket's -/// contents are sorted. -#[instrument(level = "debug")] -fn divide_spans_into_buckets(input_covspans: Vec, holes: &[Hole]) -> Vec> { - debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); +/// The lists of covspans and holes must be sorted, and any holes that overlap +/// with each other must have already been merged. +fn discard_spans_overlapping_holes(covspans: &mut Vec, holes: &[Hole]) { + debug_assert!(covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); + debug_assert!(holes.array_windows().all(|[a, b]| !a.span.overlaps_or_adjacent(b.span))); - // Now we're ready to start grouping spans into buckets separated by holes. + let mut curr_hole = 0usize; + let mut overlaps_hole = |covspan: &Covspan| -> bool { + while let Some(hole) = holes.get(curr_hole) { + // Both lists are sorted, so we can permanently skip any holes that + // end before the start of the current span. + if hole.span.hi() <= covspan.span.lo() { + curr_hole += 1; + continue; + } - let mut input_covspans = VecDeque::from(input_covspans); + return hole.span.overlaps(covspan.span); + } - // For each hole: - // - Identify the spans that are entirely or partly before the hole. - // - Discard any that overlap with the hole. - // - Add the remaining identified spans to the corresponding bucket. - let mut buckets = (0..holes.len()).map(|_| vec![]).collect::>(); - for (hole, bucket) in holes.iter().zip(&mut buckets) { - bucket.extend( - drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi()) - .filter(|c| !c.span.overlaps(hole.span)), - ); - } + // No holes left, so this covspan doesn't overlap with any holes. + false + }; - // Any remaining spans form their own final bucket, after the final hole. - // (If there were no holes, this will just be all of the initial spans.) - buckets.push(Vec::from(input_covspans)); - - buckets + covspans.retain(|covspan| !overlaps_hole(covspan)); } -/// Similar to `.drain(..)`, but stops just before it would remove an item not -/// satisfying the predicate. -fn drain_front_while<'a, T>( - queue: &'a mut VecDeque, - mut pred_fn: impl FnMut(&T) -> bool, -) -> impl Iterator { - iter::from_fn(move || queue.pop_front_if(|x| pred_fn(x))) -} - -/// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines" +/// Takes a list of sorted spans extracted from MIR, and "refines" /// those spans by removing spans that overlap in unwanted ways. #[instrument(level = "debug")] fn remove_unwanted_overlapping_spans(sorted_spans: Vec) -> Vec { @@ -227,19 +201,21 @@ struct Covspan { } impl Covspan { - /// If `self` and `other` can be merged (i.e. they have the same BCB), - /// mutates `self.span` to also include `other.span` and returns true. + /// If `self` and `other` can be merged, mutates `self.span` to also + /// include `other.span` and returns true. /// - /// Note that compatible covspans can be merged even if their underlying - /// spans are not overlapping/adjacent; any space between them will also be - /// part of the merged covspan. + /// Two covspans can be merged if they have the same BCB, and they are + /// overlapping or adjacent. fn merge_if_eligible(&mut self, other: &Self) -> bool { - if self.bcb != other.bcb { - return false; - } + let eligible_for_merge = + |a: &Self, b: &Self| (a.bcb == b.bcb) && a.span.overlaps_or_adjacent(b.span); - self.span = self.span.to(other.span); - true + if eligible_for_merge(self, other) { + self.span = self.span.to(other.span); + true + } else { + false + } } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index a2103a004d2d..99b95e7312bd 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -23,7 +23,7 @@ use rustc_mir_dataflow::lattice::{FlatSet, HasBottom}; use rustc_mir_dataflow::value_analysis::{ Map, PlaceIndex, State, TrackElem, ValueOrPlace, debug_with_context, }; -use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor}; +use rustc_mir_dataflow::{Analysis, ResultsVisitor, visit_reachable_results}; use rustc_span::DUMMY_SP; use tracing::{debug, debug_span, instrument}; @@ -61,13 +61,14 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { let map = Map::new(tcx, body, place_limit); // Perform the actual dataflow analysis. - let analysis = ConstAnalysis::new(tcx, body, map); - let mut results = - debug_span!("analyze").in_scope(|| analysis.iterate_to_fixpoint(tcx, body, None)); + let mut const_ = debug_span!("analyze") + .in_scope(|| ConstAnalysis::new(tcx, body, map).iterate_to_fixpoint(tcx, body, None)); // Collect results and patch the body afterwards. let mut visitor = Collector::new(tcx, &body.local_decls); - debug_span!("collect").in_scope(|| results.visit_reachable_with(body, &mut visitor)); + debug_span!("collect").in_scope(|| { + visit_reachable_results(body, &mut const_.analysis, &const_.results, &mut visitor) + }); let mut patch = visitor.patch; debug_span!("patch").in_scope(|| patch.visit_body_preserves_cfg(body)); } @@ -959,10 +960,10 @@ fn try_write_constant<'tcx>( } impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> { - #[instrument(level = "trace", skip(self, results, statement))] + #[instrument(level = "trace", skip(self, analysis, statement))] fn visit_after_early_statement_effect( &mut self, - results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, + analysis: &mut ConstAnalysis<'_, 'tcx>, state: &State>, statement: &Statement<'tcx>, location: Location, @@ -972,8 +973,8 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> OperandCollector { state, visitor: self, - ecx: &mut results.analysis.ecx, - map: &results.analysis.map, + ecx: &mut analysis.ecx, + map: &analysis.map, } .visit_rvalue(rvalue, location); } @@ -981,10 +982,10 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> } } - #[instrument(level = "trace", skip(self, results, statement))] + #[instrument(level = "trace", skip(self, analysis, statement))] fn visit_after_primary_statement_effect( &mut self, - results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, + analysis: &mut ConstAnalysis<'_, 'tcx>, state: &State>, statement: &Statement<'tcx>, location: Location, @@ -994,12 +995,9 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> // Don't overwrite the assignment if it already uses a constant (to keep the span). } StatementKind::Assign(box (place, _)) => { - if let Some(value) = self.try_make_constant( - &mut results.analysis.ecx, - place, - state, - &results.analysis.map, - ) { + if let Some(value) = + self.try_make_constant(&mut analysis.ecx, place, state, &analysis.map) + { self.patch.assignments.insert(location, value); } } @@ -1009,18 +1007,13 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> fn visit_after_early_terminator_effect( &mut self, - results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, + analysis: &mut ConstAnalysis<'_, 'tcx>, state: &State>, terminator: &Terminator<'tcx>, location: Location, ) { - OperandCollector { - state, - visitor: self, - ecx: &mut results.analysis.ecx, - map: &results.analysis.map, - } - .visit_terminator(terminator, location); + OperandCollector { state, visitor: self, ecx: &mut analysis.ecx, map: &analysis.map } + .visit_terminator(terminator, location); } } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 7395ad496dbd..4c94a6c524e0 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -171,7 +171,7 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { let live = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("MaybeLiveLocals-DestProp")); let points = DenseLocationMap::new(body); - let mut live = save_as_intervals(&points, body, live); + let mut live = save_as_intervals(&points, body, live.analysis, live.results); // In order to avoid having to collect data for every single pair of locals in the body, we // do not allow doing more than one merge for places that are derived from the same local at diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index ada2c0b76cf7..31b361ec1a92 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -757,12 +757,12 @@ impl OpportunitySet { // Replace `succ` by `new_succ` where it appears. let mut num_edges = 0; - for s in basic_blocks[current].terminator_mut().successors_mut() { + basic_blocks[current].terminator_mut().successors_mut(|s| { if *s == succ { *s = new_succ; num_edges += 1; } - } + }); // Update predecessors with the new block. let _new_succ = self.predecessors.push(num_edges); diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 24f4c11a66d6..dc0eacd36130 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -701,8 +701,6 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' // Now, we need to shrink the generated MIR. &ref_prop::ReferencePropagation, &sroa::ScalarReplacementOfAggregates, - &match_branches::MatchBranchSimplification, - // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) &multiple_return_terminators::MultipleReturnTerminators, // After simplifycfg, it allows us to discover new opportunities for peephole // optimizations. @@ -711,6 +709,7 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' &dead_store_elimination::DeadStoreElimination::Initial, &gvn::GVN, &simplify::SimplifyLocals::AfterGVN, + &match_branches::MatchBranchSimplification, &dataflow_const_prop::DataflowConstProp, &single_use_consts::SingleUseConsts, &o1(simplify_branches::SimplifyConstCondition::AfterConstProp), diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index b8cb101f93c7..75f351f05c30 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -235,8 +235,9 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body< // When we encounter a DROP of some place P we only care // about the drop if `P` may be initialized. let move_data = MoveData::gather_moves(body, tcx, |_| true); - let maybe_init = MaybeInitializedPlaces::new(tcx, body, &move_data); - let mut maybe_init = maybe_init.iterate_to_fixpoint(tcx, body, None).into_results_cursor(body); + let mut maybe_init = MaybeInitializedPlaces::new(tcx, body, &move_data) + .iterate_to_fixpoint(tcx, body, None) + .into_results_cursor(body); let mut block_drop_value_info = IndexVec::from_elem_n(MovePathIndexAtBlock::Unknown, body.basic_blocks.len()); for (&block, candidates) in &bid_per_block { diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index b37241185c93..8c0c30968990 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -19,30 +19,32 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let typing_env = body.typing_env(tcx); - let mut should_cleanup = false; - for bb_idx in body.basic_blocks.indices() { - match &body.basic_blocks[bb_idx].terminator().kind { + let mut apply_patch = false; + let mut patch = MirPatch::new(body); + for (bb, bb_data) in body.basic_blocks.iter_enumerated() { + match &bb_data.terminator().kind { TerminatorKind::SwitchInt { discr: Operand::Copy(_) | Operand::Move(_), targets, .. // We require that the possible target blocks don't contain this block. - } if !targets.all_targets().contains(&bb_idx) => {} + } if !targets.all_targets().contains(&bb) => {} // Only optimize switch int statements _ => continue, }; - if SimplifyToIf.simplify(tcx, body, bb_idx, typing_env).is_some() { - should_cleanup = true; + if SimplifyToIf.simplify(tcx, body, &mut patch, bb, typing_env).is_some() { + apply_patch = true; continue; } - if SimplifyToExp::default().simplify(tcx, body, bb_idx, typing_env).is_some() { - should_cleanup = true; + if SimplifyToExp::default().simplify(tcx, body, &mut patch, bb, typing_env).is_some() { + apply_patch = true; continue; } } - if should_cleanup { + if apply_patch { + patch.apply(body); simplify_cfg(tcx, body); } } @@ -59,7 +61,8 @@ trait SimplifyMatch<'tcx> { fn simplify( &mut self, tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, + body: &Body<'tcx>, + patch: &mut MirPatch<'tcx>, switch_bb_idx: BasicBlock, typing_env: ty::TypingEnv<'tcx>, ) -> Option<()> { @@ -73,8 +76,6 @@ trait SimplifyMatch<'tcx> { let discr_ty = discr.ty(body.local_decls(), tcx); self.can_simplify(tcx, targets, typing_env, bbs, discr_ty)?; - let mut patch = MirPatch::new(body); - // Take ownership of items now that we know we can optimize. let discr = discr.clone(); @@ -87,19 +88,9 @@ trait SimplifyMatch<'tcx> { let parent_end = Location { block: switch_bb_idx, statement_index }; patch.add_statement(parent_end, StatementKind::StorageLive(discr_local)); patch.add_assign(parent_end, Place::from(discr_local), Rvalue::Use(discr)); - self.new_stmts( - tcx, - targets, - typing_env, - &mut patch, - parent_end, - bbs, - discr_local, - discr_ty, - ); + self.new_stmts(tcx, targets, typing_env, patch, parent_end, bbs, discr_local, discr_ty); patch.add_statement(parent_end, StatementKind::StorageDead(discr_local)); patch.patch_terminator(switch_bb_idx, bbs[first].terminator().kind.clone()); - patch.apply(body); Some(()) } diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs index 8ccfbe2f194b..8217feff24ec 100644 --- a/compiler/rustc_mir_transform/src/prettify.rs +++ b/compiler/rustc_mir_transform/src/prettify.rs @@ -115,9 +115,7 @@ impl<'tcx> MutVisitor<'tcx> for BasicBlockUpdater<'tcx> { } fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, _location: Location) { - for succ in terminator.successors_mut() { - *succ = self.map[*succ]; - } + terminator.successors_mut(|succ| *succ = self.map[*succ]); } } diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 1dd34005d664..797056ad52d4 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -58,13 +58,13 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { } } - for target in body[bb].terminator_mut().successors_mut() { + body[bb].terminator_mut().successors_mut(|target| { if *target != resume_block && nop_landing_pads.contains(*target) { debug!(" folding noop jump to {:?} to resume block", target); *target = resume_block; jumps_folded += 1; } - } + }); let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads); if is_nop_landing_pad { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 0d9a04b760a2..9688ac8ed2e2 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -298,10 +298,9 @@ fn local_decls_for_sig<'tcx>( fn dropee_emit_retag<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, - dropee_ptr: Place<'tcx>, + mut dropee_ptr: Place<'tcx>, span: Span, ) -> Place<'tcx> { - let mut dropee_ptr = dropee_ptr; if tcx.sess.opts.unstable_opts.mir_emit_retag { let source_info = SourceInfo::outermost(span); // We want to treat the function argument as if it was passed by `&mut`. As such, we @@ -365,8 +364,8 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); // The first argument (index 0), but add 1 for the return value. - let mut dropee_ptr = Place::from(Local::new(1 + 0)); - dropee_ptr = dropee_emit_retag(tcx, &mut body, dropee_ptr, span); + let dropee_ptr = Place::from(Local::new(1 + 0)); + let dropee_ptr = dropee_emit_retag(tcx, &mut body, dropee_ptr, span); if ty.is_some() { let patch = { diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 4f2cce8ac104..8f88228d9bbd 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -147,9 +147,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { let mut terminator = self.basic_blocks[bb].terminator.take().expect("invalid terminator state"); - for successor in terminator.successors_mut() { - self.collapse_goto_chain(successor, &mut changed); - } + terminator + .successors_mut(|successor| self.collapse_goto_chain(successor, &mut changed)); let mut inner_changed = true; merged_blocks.clear(); @@ -375,9 +374,7 @@ pub(super) fn remove_dead_blocks(body: &mut Body<'_>) { } for block in basic_blocks { - for target in block.terminator_mut().successors_mut() { - *target = replacements[target.index()]; - } + block.terminator_mut().successors_mut(|target| *target = replacements[target.index()]); } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 1e3744e19f54..c6a81e60b2b5 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -931,7 +931,7 @@ fn visit_instance_use<'tcx>( // We explicitly skip this otherwise to ensure we get a linker error // if anyone tries to call this intrinsic and the codegen backend did not // override the implementation. - let instance = ty::Instance::new(instance.def_id(), instance.args); + let instance = ty::Instance::new_raw(instance.def_id(), instance.args); if tcx.should_codegen_locally(instance) { output.push(create_fn_mono_item(tcx, instance, source)); } @@ -1520,7 +1520,7 @@ impl<'v> RootCollector<'_, 'v> { ty::Closure(def_id, args) | ty::Coroutine(def_id, args) | ty::CoroutineClosure(def_id, args) => { - Instance::new(def_id, self.tcx.erase_regions(args)) + Instance::new_raw(def_id, self.tcx.erase_regions(args)) } _ => unreachable!(), }; diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 25493970a0ce..90a7c2e9f787 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -39,10 +39,6 @@ pub trait SolverDelegate: Deref + Sized { term: ::Term, ) -> Option::Predicate>>>; - fn clone_opaque_types_for_query_response( - &self, - ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; - fn make_deduplicated_outlives_constraints( &self, ) -> Vec::GenericArg>>; @@ -61,14 +57,6 @@ pub trait SolverDelegate: Deref + Sized { span: ::Span, universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, ) -> ::GenericArg; - - fn register_hidden_type_in_storage( - &self, - opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: ::Ty, - span: ::Span, - ) -> Option<::Ty>; - fn add_item_bounds_for_hidden_type( &self, def_id: ::DefId, @@ -77,7 +65,6 @@ pub trait SolverDelegate: Deref + Sized { hidden_ty: ::Ty, goals: &mut Vec::Predicate>>, ); - fn reset_opaque_types(&self); fn fetch_eligible_assoc_item( &self, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 101129a231e7..345a272895d3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -2,21 +2,24 @@ pub(super) mod structural_traits; +use std::ops::ControlFlow; + use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::{ - self as ty, Interner, TypeFoldable, TypeVisitableExt as _, TypingMode, Upcast as _, elaborate, + self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _, + TypeVisitor, TypingMode, Upcast as _, elaborate, }; use tracing::{debug, instrument}; -use super::has_only_region_constraints; use super::trait_goals::TraitGoalProvenVia; +use super::{has_only_region_constraints, inspect}; use crate::delegate::SolverDelegate; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, - MaybeCause, NoSolution, QueryResult, + MaybeCause, NoSolution, ParamEnvSource, QueryResult, }; enum AliasBoundKind { @@ -49,18 +52,6 @@ where fn trait_def_id(self, cx: I) -> I::DefId; - /// Try equating an assumption predicate against a goal's predicate. If it - /// holds, then execute the `then` callback, which should do any additional - /// work, then produce a response (typically by executing - /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). - fn probe_and_match_goal_against_assumption( - ecx: &mut EvalCtxt<'_, D>, - source: CandidateSource, - goal: Goal, - assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, - ) -> Result, NoSolution>; - /// Consider a clause, which consists of a "assumption" and some "requirements", /// to satisfy a goal. If the requirements hold, then attempt to satisfy our /// goal by equating it with the assumption. @@ -119,6 +110,67 @@ where alias_ty: ty::AliasTy, ) -> Vec>; + fn probe_and_consider_param_env_candidate( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result, NoSolution> { + Self::fast_reject_assumption(ecx, goal, assumption)?; + + ecx.probe(|candidate: &Result, NoSolution>| match candidate { + Ok(candidate) => inspect::ProbeKind::TraitCandidate { + source: candidate.source, + result: Ok(candidate.result), + }, + Err(NoSolution) => inspect::ProbeKind::TraitCandidate { + source: CandidateSource::ParamEnv(ParamEnvSource::Global), + result: Err(NoSolution), + }, + }) + .enter(|ecx| { + Self::match_assumption(ecx, goal, assumption)?; + let source = ecx.characterize_param_env_assumption(goal.param_env, assumption)?; + Ok(Candidate { + source, + result: ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)?, + }) + }) + } + + /// Try equating an assumption predicate against a goal's predicate. If it + /// holds, then execute the `then` callback, which should do any additional + /// work, then produce a response (typically by executing + /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). + fn probe_and_match_goal_against_assumption( + ecx: &mut EvalCtxt<'_, D>, + source: CandidateSource, + goal: Goal, + assumption: I::Clause, + then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, + ) -> Result, NoSolution> { + Self::fast_reject_assumption(ecx, goal, assumption)?; + + ecx.probe_trait_candidate(source).enter(|ecx| { + Self::match_assumption(ecx, goal, assumption)?; + then(ecx) + }) + } + + /// Try to reject the assumption based off of simple heuristics, such as [`ty::ClauseKind`] + /// and `DefId`. + fn fast_reject_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution>; + + /// Relate the goal and assumption. + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution>; + fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, @@ -500,14 +552,8 @@ where goal: Goal, candidates: &mut Vec>, ) { - for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { - candidates.extend(G::probe_and_consider_implied_clause( - self, - CandidateSource::ParamEnv(i), - goal, - assumption, - [], - )); + for assumption in goal.param_env.caller_bounds().iter() { + candidates.extend(G::probe_and_consider_param_env_candidate(self, goal, assumption)); } } @@ -943,4 +989,88 @@ where } } } + + /// Compute whether a param-env assumption is global or non-global after normalizing it. + /// + /// This is necessary because, for example, given: + /// + /// ```ignore,rust + /// where + /// T: Trait, + /// i32: From, + /// ``` + /// + /// The `i32: From` bound is non-global before normalization, but is global after. + /// Since the old trait solver normalized param-envs eagerly, we want to emulate this + /// behavior lazily. + fn characterize_param_env_assumption( + &mut self, + param_env: I::ParamEnv, + assumption: I::Clause, + ) -> Result, NoSolution> { + // FIXME: This should be fixed, but it also requires changing the behavior + // in the old solver which is currently relied on. + if assumption.has_bound_vars() { + return Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)); + } + + match assumption.visit_with(&mut FindParamInClause { ecx: self, param_env }) { + ControlFlow::Break(Err(NoSolution)) => Err(NoSolution), + ControlFlow::Break(Ok(())) => Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)), + ControlFlow::Continue(()) => Ok(CandidateSource::ParamEnv(ParamEnvSource::Global)), + } + } +} + +struct FindParamInClause<'a, 'b, D: SolverDelegate, I: Interner> { + ecx: &'a mut EvalCtxt<'b, D>, + param_env: I::ParamEnv, +} + +impl TypeVisitor for FindParamInClause<'_, '_, D, I> +where + D: SolverDelegate, + I: Interner, +{ + type Result = ControlFlow>; + + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + self.ecx.enter_forall(t.clone(), |ecx, v| { + v.visit_with(&mut FindParamInClause { ecx, param_env: self.param_env }) + }) + } + + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + let Ok(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty) else { + return ControlFlow::Break(Err(NoSolution)); + }; + + if let ty::Placeholder(_) = ty.kind() { + ControlFlow::Break(Ok(())) + } else { + ty.super_visit_with(self) + } + } + + fn visit_const(&mut self, ct: I::Const) -> Self::Result { + let Ok(ct) = self.ecx.structurally_normalize_const(self.param_env, ct) else { + return ControlFlow::Break(Err(NoSolution)); + }; + + if let ty::ConstKind::Placeholder(_) = ct.kind() { + ControlFlow::Break(Ok(())) + } else { + ct.super_visit_with(self) + } + } + + fn visit_region(&mut self, r: I::Region) -> Self::Result { + match self.ecx.eager_resolve_region(r).kind() { + ty::ReStatic | ty::ReError(_) => ControlFlow::Continue(()), + ty::ReVar(_) | ty::RePlaceholder(_) => ControlFlow::Break(Ok(())), + ty::ReErased | ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReBound(..) => { + unreachable!() + } + } + } } diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 5edc777262b8..84a83d79cf04 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -36,39 +36,38 @@ where self.def_id() } - fn probe_and_match_goal_against_assumption( + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, - source: rustc_type_ir::solve::CandidateSource, goal: Goal, - assumption: ::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, - ) -> Result, NoSolution> { + assumption: I::Clause, + ) -> Result<(), NoSolution> { if let Some(host_clause) = assumption.as_host_effect_clause() { if host_clause.def_id() == goal.predicate.def_id() && host_clause.constness().satisfies(goal.predicate.constness) { - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.trait_ref.args, host_clause.skip_binder().trait_ref.args, ) { - return Err(NoSolution); + return Ok(()); } - - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); - ecx.eq( - goal.param_env, - goal.predicate.trait_ref, - assumption_trait_pred.trait_ref, - )?; - then(ecx) - }) - } else { - Err(NoSolution) } - } else { - Err(NoSolution) } + + Err(NoSolution) + } + + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + let host_clause = assumption.as_host_effect_clause().unwrap(); + + let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); + ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; + + Ok(()) } /// Register additional assumptions for aliases corresponding to `~const` item bounds. @@ -124,7 +123,7 @@ where fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, - impl_def_id: ::DefId, + impl_def_id: I::DefId, ) -> Result, NoSolution> { let cx = ecx.cx(); @@ -178,7 +177,7 @@ where fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, D>, - _guar: ::ErrorGuaranteed, + _guar: I::ErrorGuaranteed, ) -> Result, NoSolution> { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index dded84f67686..36f68808a2c8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -56,7 +56,10 @@ where &self, goal: Goal, ) -> (Vec, CanonicalInput) { - let opaque_types = self.delegate.clone_opaque_types_for_query_response(); + // We only care about one entry per `OpaqueTypeKey` here, + // so we only canonicalize the lookup table and ignore + // duplicate entries. + let opaque_types = self.delegate.clone_opaque_types_lookup_table(); let (goal, opaque_types) = (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate)); @@ -129,12 +132,14 @@ where (Certainty::Yes, NestedNormalizationGoals(goals)) } _ => { - let certainty = shallow_certainty.unify_with(goals_certainty); + let certainty = shallow_certainty.and(goals_certainty); (certainty, NestedNormalizationGoals::empty()) } }; - if let Certainty::Maybe(cause @ MaybeCause::Overflow { .. }) = certainty { + if let Certainty::Maybe(cause @ MaybeCause::Overflow { keep_constraints: false, .. }) = + certainty + { // If we have overflow, it's probable that we're substituting a type // into itself infinitely and any partial substitutions in the query // response are probably not useful anyways, so just return an empty @@ -190,6 +195,7 @@ where debug!(?num_non_region_vars, "too many inference variables -> overflow"); return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow { suggest_increasing_limit: true, + keep_constraints: false, })); } } @@ -241,19 +247,15 @@ where Default::default() }; - ExternalConstraintsData { - region_constraints, - opaque_types: self - .delegate - .clone_opaque_types_for_query_response() - .into_iter() - // Only return *newly defined* opaque types. - .filter(|(a, _)| { - self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a) - }) - .collect(), - normalization_nested_goals, - } + // We only return *newly defined* opaque types from canonical queries. + // + // Constraints for any existing opaque types are already tracked by changes + // to the `var_values`. + let opaque_types = self + .delegate + .clone_opaque_types_added_since(self.initial_opaque_types_storage_num_entries); + + ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } } /// After calling a canonical query, we apply the constraints returned @@ -432,7 +434,16 @@ where fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey, I::Ty)]) { for &(key, ty) in opaque_types { let prev = self.delegate.register_hidden_type_in_storage(key, ty, self.origin_span); - assert_eq!(prev, None); + // We eagerly resolve inference variables when computing the query response. + // This can cause previously distinct opaque type keys to now be structurally equal. + // + // To handle this, we store any duplicate entries in a separate list to check them + // at the end of typeck/borrowck. We could alternatively eagerly equate the hidden + // types here. However, doing so is difficult as it may result in nested goals and + // any errors may make it harder to track the control flow for diagnostics. + if let Some(prev) = prev { + self.delegate.add_duplicate_opaque_type(key, prev, self.origin_span); + } } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 6dd554299a69..fc5dad9a3edf 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -14,7 +14,7 @@ use rustc_type_ir::{ TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, }; -use tracing::{instrument, trace}; +use tracing::{debug, instrument, trace}; use super::has_only_region_constraints; use crate::coherence; @@ -23,8 +23,7 @@ use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, - HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryInput, - QueryResult, + HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, }; pub(super) mod canonical; @@ -99,8 +98,6 @@ where current_goal_kind: CurrentGoalKind, pub(super) var_values: CanonicalVarValues, - predefined_opaques_in_body: I::PredefinedOpaques, - /// The highest universe index nameable by the caller. /// /// When we enter a new binder inside of the query we create new universes @@ -111,6 +108,10 @@ where /// if we have a coinductive cycle and because that's the only way we can return /// new placeholders to the caller. pub(super) max_input_universe: ty::UniverseIndex, + /// The opaque types from the canonical input. We only need to return opaque types + /// which have been added to the storage while evaluating this goal. + pub(super) initial_opaque_types_storage_num_entries: + ::OpaqueTypeStorageEntries, pub(super) search_graph: &'a mut SearchGraph, @@ -305,10 +306,8 @@ where // Only relevant when canonicalizing the response, // which we don't do within this evaluation context. - predefined_opaques_in_body: delegate - .cx() - .mk_predefined_opaques_in_body(PredefinedOpaquesData::default()), max_input_universe: ty::UniverseIndex::ROOT, + initial_opaque_types_storage_num_entries: Default::default(), variables: Default::default(), var_values: CanonicalVarValues::dummy(), current_goal_kind: CurrentGoalKind::Misc, @@ -342,16 +341,34 @@ where canonical_goal_evaluation: &mut ProofTreeBuilder, f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal) -> R, ) -> R { - let (ref delegate, input, var_values) = - SolverDelegate::build_with_canonical(cx, &canonical_input); + let (ref delegate, input, var_values) = D::build_with_canonical(cx, &canonical_input); + for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { + let prev = delegate.register_hidden_type_in_storage(key, ty, I::Span::dummy()); + // It may be possible that two entries in the opaque type storage end up + // with the same key after resolving contained inference variables. + // + // We could put them in the duplicate list but don't have to. The opaques we + // encounter here are already tracked in the caller, so there's no need to + // also store them here. We'd take them out when computing the query response + // and then discard them, as they're already present in the input. + // + // Ideally we'd drop duplicate opaque type definitions when computing + // the canonical input. This is more annoying to implement and may cause a + // perf regression, so we do it inside of the query for now. + if let Some(prev) = prev { + debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`"); + } + } + + let initial_opaque_types_storage_num_entries = delegate.opaque_types_storage_num_entries(); let mut ecx = EvalCtxt { delegate, variables: canonical_input.canonical.variables, var_values, current_goal_kind: CurrentGoalKind::from_query_input(cx, input), - predefined_opaques_in_body: input.predefined_opaques_in_body, max_input_universe: canonical_input.canonical.max_universe, + initial_opaque_types_storage_num_entries, search_graph, nested_goals: Default::default(), origin_span: I::Span::dummy(), @@ -359,15 +376,6 @@ where inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values), }; - for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { - let prev = ecx.delegate.register_hidden_type_in_storage(key, ty, ecx.origin_span); - assert_eq!(prev, None); - } - - if !ecx.nested_goals.is_empty() { - panic!("prepopulating opaque types shouldn't add goals: {:?}", ecx.nested_goals); - } - let result = f(&mut ecx, input.goal); ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe); canonical_goal_evaluation.goal_evaluation_step(ecx.inspect); @@ -653,7 +661,7 @@ where Certainty::Yes => {} Certainty::Maybe(_) => { self.nested_goals.push((source, with_resolved_vars)); - unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty)); + unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } } else { @@ -667,7 +675,7 @@ where Certainty::Yes => {} Certainty::Maybe(_) => { self.nested_goals.push((source, goal)); - unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty)); + unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } } @@ -987,6 +995,14 @@ where self.delegate.resolve_vars_if_possible(value) } + pub(super) fn eager_resolve_region(&self, r: I::Region) -> I::Region { + if let ty::ReVar(vid) = r.kind() { + self.delegate.opportunistic_resolve_lt_var(vid) + } else { + r + } + } + pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs { let args = self.delegate.fresh_args_for_item(def_id); for arg in args.iter() { @@ -1065,14 +1081,17 @@ where &mut self, key: ty::OpaqueTypeKey, ) -> Option<(ty::OpaqueTypeKey, I::Ty)> { - let mut matching = - self.delegate.clone_opaque_types_for_query_response().into_iter().filter( - |(candidate_key, _)| { - candidate_key.def_id == key.def_id - && DeepRejectCtxt::relate_rigid_rigid(self.cx()) - .args_may_unify(candidate_key.args, key.args) - }, - ); + // We shouldn't have any duplicate entries when using + // this function during `TypingMode::Analysis`. + let duplicate_entries = self.delegate.clone_duplicate_opaque_types(); + assert!(duplicate_entries.is_empty(), "unexpected duplicates: {duplicate_entries:?}"); + let mut matching = self.delegate.clone_opaque_types_lookup_table().into_iter().filter( + |(candidate_key, _)| { + candidate_key.def_id == key.def_id + && DeepRejectCtxt::relate_rigid_rigid(self.cx()) + .args_may_unify(candidate_key.args, key.args) + }, + ); let first = matching.next(); let second = matching.next(); assert_eq!(second, None); diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs index 0a9e7fafaea6..ed0cedc40774 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs @@ -26,32 +26,33 @@ where I: Interner, { pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T) -> T { - let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self; + let ProbeCtxt { ecx: outer, probe_kind, _result } = self; - let delegate = outer_ecx.delegate; - let max_input_universe = outer_ecx.max_input_universe; - let mut nested_ecx = EvalCtxt { + let delegate = outer.delegate; + let max_input_universe = outer.max_input_universe; + let mut nested = EvalCtxt { delegate, - variables: outer_ecx.variables, - var_values: outer_ecx.var_values, - current_goal_kind: outer_ecx.current_goal_kind, - predefined_opaques_in_body: outer_ecx.predefined_opaques_in_body, + variables: outer.variables, + var_values: outer.var_values, + current_goal_kind: outer.current_goal_kind, max_input_universe, - search_graph: outer_ecx.search_graph, - nested_goals: outer_ecx.nested_goals.clone(), - origin_span: outer_ecx.origin_span, - tainted: outer_ecx.tainted, - inspect: outer_ecx.inspect.take_and_enter_probe(), + initial_opaque_types_storage_num_entries: outer + .initial_opaque_types_storage_num_entries, + search_graph: outer.search_graph, + nested_goals: outer.nested_goals.clone(), + origin_span: outer.origin_span, + tainted: outer.tainted, + inspect: outer.inspect.take_and_enter_probe(), }; - let r = nested_ecx.delegate.probe(|| { - let r = f(&mut nested_ecx); - nested_ecx.inspect.probe_final_state(delegate, max_input_universe); + let r = nested.delegate.probe(|| { + let r = f(&mut nested); + nested.inspect.probe_final_state(delegate, max_input_universe); r }); - if !nested_ecx.inspect.is_noop() { + if !nested.inspect.is_noop() { let probe_kind = probe_kind(&r); - nested_ecx.inspect.probe_kind(probe_kind); - outer_ecx.inspect = nested_ecx.inspect.finish_probe(); + nested.inspect.probe_kind(probe_kind); + outer.inspect = nested.inspect.finish_probe(); } r } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index c9f4fc649b52..8173146e2fe2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -253,16 +253,18 @@ where } fn bail_with_ambiguity(&mut self, responses: &[CanonicalResponse]) -> CanonicalResponse { - debug_assert!(!responses.is_empty()); - if let Certainty::Maybe(maybe_cause) = - responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| { - certainty.unify_with(response.value.certainty) - }) - { - self.make_ambiguous_response_no_constraints(maybe_cause) - } else { - panic!("expected flounder response to be ambiguous") - } + debug_assert!(responses.len() > 1); + let maybe_cause = responses.iter().fold(MaybeCause::Ambiguity, |maybe_cause, response| { + // Pull down the certainty of `Certainty::Yes` to ambiguity when combining + // these responses, b/c we're combining more than one response and this we + // don't know which one applies. + let candidate = match response.value.certainty { + Certainty::Yes => MaybeCause::Ambiguity, + Certainty::Maybe(candidate) => candidate, + }; + maybe_cause.or(candidate) + }); + self.make_ambiguous_response_no_constraints(maybe_cause) } /// If we fail to merge responses we flounder and return overflow or ambiguity. diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs index d077f8a9be8a..8aa6e4a3d711 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs @@ -19,19 +19,25 @@ where goal: Goal>, ) -> QueryResult { let cx = self.cx(); - let free_ty = goal.predicate.alias; + let free_alias = goal.predicate.alias; // Check where clauses self.add_goals( GoalSource::Misc, - cx.predicates_of(free_ty.def_id) - .iter_instantiated(cx, free_ty.args) + cx.predicates_of(free_alias.def_id) + .iter_instantiated(cx, free_alias.args) .map(|pred| goal.with(cx, pred)), ); - let actual = cx.type_of(free_ty.def_id).instantiate(cx, free_ty.args); - self.instantiate_normalizes_to_term(goal, actual.into()); + let actual = if free_alias.kind(cx).is_type() { + cx.type_of(free_alias.def_id).instantiate(cx, free_alias.args) + } else { + // FIXME(mgca): once const items are actual aliases defined as equal to type system consts + // this should instead return that. + panic!("normalizing free const aliases in the type system is unsupported"); + }; + self.instantiate_normalizes_to_term(goal, actual.into()); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 1d1ff09ee410..2640238f5a90 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -15,12 +15,12 @@ where D: SolverDelegate, I: Interner, { - pub(super) fn normalize_inherent_associated_type( + pub(super) fn normalize_inherent_associated_term( &mut self, goal: Goal>, ) -> QueryResult { let cx = self.cx(); - let inherent = goal.predicate.alias.expect_ty(cx); + let inherent = goal.predicate.alias; let impl_def_id = cx.parent(inherent.def_id); let impl_args = self.fresh_args_for_item(impl_def_id); @@ -48,8 +48,13 @@ where .map(|pred| goal.with(cx, pred)), ); - let normalized = cx.type_of(inherent.def_id).instantiate(cx, inherent_args); - self.instantiate_normalizes_to_term(goal, normalized.into()); + let normalized = if inherent.kind(cx).is_type() { + cx.type_of(inherent.def_id).instantiate(cx, inherent_args).into() + } else { + // FIXME(mgca): Properly handle IACs in the type system + panic!("normalizing inherent associated consts in the type system is unsupported"); + }; + self.instantiate_normalizes_to_term(goal, normalized); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index b030af483817..b90e34e78101 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -48,9 +48,13 @@ where }) }) } - ty::AliasTermKind::InherentTy => self.normalize_inherent_associated_type(goal), + ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => { + self.normalize_inherent_associated_term(goal) + } ty::AliasTermKind::OpaqueTy => self.normalize_opaque_type(goal), - ty::AliasTermKind::FreeTy => self.normalize_free_alias(goal), + ty::AliasTermKind::FreeTy | ty::AliasTermKind::FreeConst => { + self.normalize_free_alias(goal) + } ty::AliasTermKind::UnevaluatedConst => self.normalize_anon_const(goal), } } @@ -102,50 +106,48 @@ where self.trait_def_id(cx) } - fn probe_and_match_goal_against_assumption( + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, - source: CandidateSource, goal: Goal, assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, - ) -> Result, NoSolution> { + ) -> Result<(), NoSolution> { if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.item_def_id() == goal.predicate.def_id() { - let cx = ecx.cx(); - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.alias.args, projection_pred.skip_binder().projection_term.args, ) { - return Err(NoSolution); + return Ok(()); } - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_projection_pred = - ecx.instantiate_binder_with_infer(projection_pred); - ecx.eq( - goal.param_env, - goal.predicate.alias, - assumption_projection_pred.projection_term, - )?; - - ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); - - // Add GAT where clauses from the trait's definition - // FIXME: We don't need these, since these are the type's own WF obligations. - ecx.add_goals( - GoalSource::AliasWellFormed, - cx.own_predicates_of(goal.predicate.def_id()) - .iter_instantiated(cx, goal.predicate.alias.args) - .map(|pred| goal.with(cx, pred)), - ); - - then(ecx) - }) - } else { - Err(NoSolution) } - } else { - Err(NoSolution) } + + Err(NoSolution) + } + + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + let projection_pred = assumption.as_projection_clause().unwrap(); + + let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); + ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?; + + ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); + + // Add GAT where clauses from the trait's definition + // FIXME: We don't need these, since these are the type's own WF obligations. + let cx = ecx.cx(); + ecx.add_goals( + GoalSource::AliasWellFormed, + cx.own_predicates_of(goal.predicate.def_id()) + .iter_instantiated(cx, goal.predicate.alias.args) + .map(|pred| goal.with(cx, pred)), + ); + + Ok(()) } fn consider_additional_alias_assumptions( @@ -333,6 +335,8 @@ where cx.type_of(target_item_def_id).map_bound(|ty| ty.into()) } ty::AliasTermKind::ProjectionConst => { + // FIXME(mgca): once const items are actual aliases defined as equal to type system consts + // this should instead return that. if cx.features().associated_const_equality() { panic!("associated const projection is not supported yet") } else { diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index d19249df387c..e3addf8bf93f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -17,7 +17,7 @@ use crate::solve::assembly::{self, AllowInferenceConstraints, AssembleCandidates use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, - NoSolution, QueryResult, + NoSolution, ParamEnvSource, }; impl assembly::GoalKind for TraitPredicate @@ -125,39 +125,38 @@ where .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } - fn probe_and_match_goal_against_assumption( + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, - source: CandidateSource, goal: Goal, assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, - ) -> Result, NoSolution> { + ) -> Result<(), NoSolution> { if let Some(trait_clause) = assumption.as_trait_clause() { if trait_clause.def_id() == goal.predicate.def_id() && trait_clause.polarity() == goal.predicate.polarity { - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.trait_ref.args, trait_clause.skip_binder().trait_ref.args, ) { - return Err(NoSolution); + return Ok(()); } - - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); - ecx.eq( - goal.param_env, - goal.predicate.trait_ref, - assumption_trait_pred.trait_ref, - )?; - then(ecx) - }) - } else { - Err(NoSolution) } - } else { - Err(NoSolution) } + + Err(NoSolution) + } + + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + let trait_clause = assumption.as_trait_clause().unwrap(); + + let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); + ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; + + Ok(()) } fn consider_auto_trait_candidate( @@ -1253,10 +1252,9 @@ where D: SolverDelegate, I: Interner, { - #[instrument(level = "debug", skip(self, goal), ret)] + #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_trait_candidates( &mut self, - goal: Goal>, mut candidates: Vec>, ) -> Result<(CanonicalResponse, Option), NoSolution> { if let TypingMode::Coherence = self.typing_mode() { @@ -1284,21 +1282,9 @@ where // If there are non-global where-bounds, prefer where-bounds // (including global ones) over everything else. - let has_non_global_where_bounds = candidates.iter().any(|c| match c.source { - CandidateSource::ParamEnv(idx) => { - let where_bound = goal.param_env.caller_bounds().get(idx).unwrap(); - let ty::ClauseKind::Trait(trait_pred) = where_bound.kind().skip_binder() else { - unreachable!("expected trait-bound: {where_bound:?}"); - }; - - if trait_pred.has_bound_vars() || !trait_pred.is_global() { - return true; - } - - false - } - _ => false, - }); + let has_non_global_where_bounds = candidates + .iter() + .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal))); if has_non_global_where_bounds { let where_bounds: Vec<_> = candidates .iter() @@ -1331,13 +1317,16 @@ where // is still reported as being proven-via the param-env so that rigid projections // operate correctly. Otherwise, drop all global where-bounds before merging the // remaining candidates. - let proven_via = - if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) { - TraitGoalProvenVia::ParamEnv - } else { - candidates.retain(|c| !matches!(c.source, CandidateSource::ParamEnv(_))); - TraitGoalProvenVia::Misc - }; + let proven_via = if candidates + .iter() + .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))) + { + TraitGoalProvenVia::ParamEnv + } else { + candidates + .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))); + TraitGoalProvenVia::Misc + }; let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect(); if let Some(response) = self.try_merge_responses(&all_candidates) { @@ -1353,7 +1342,7 @@ where goal: Goal>, ) -> Result<(CanonicalResponse, Option), NoSolution> { let candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All); - self.merge_trait_candidates(goal, candidates) + self.merge_trait_candidates(candidates) } fn try_stall_coroutine_witness( diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index ac4f7ed64e22..3d7e0fcc3086 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -297,6 +297,19 @@ parse_forgot_paren = perhaps you forgot parentheses? parse_found_expr_would_be_stmt = expected expression, found `{$token}` .label = expected expression +parse_frontmatter_extra_characters_after_close = extra characters after frontmatter close are not allowed +parse_frontmatter_invalid_close_preceding_whitespace = invalid preceding whitespace for frontmatter close + .note = frontmatter close should not be preceded by whitespace +parse_frontmatter_invalid_infostring = invalid infostring for frontmatter + .note = frontmatter infostrings must be a single identifier immediately following the opening +parse_frontmatter_invalid_opening_preceding_whitespace = invalid preceding whitespace for frontmatter opening + .note = frontmatter opening should not be preceded by whitespace +parse_frontmatter_length_mismatch = frontmatter close does not match the opening + .label_opening = the opening here has {$len_opening} dashes... + .label_close = ...while the close has {$len_close} dashes +parse_frontmatter_unclosed = unclosed frontmatter + .note = frontmatter opening here was not closed + parse_function_body_equals_expr = function body cannot be `= expression;` .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;` @@ -702,6 +715,16 @@ parse_parenthesized_lifetime_suggestion = remove the parentheses parse_path_double_colon = path separator must be a double colon .suggestion = use a double colon instead + +parse_path_found_attribute_in_params = `Trait(...)` syntax does not support attributes in parameters + .suggestion = remove the attributes + +parse_path_found_c_variadic_params = `Trait(...)` syntax does not support c_variadic parameters + .suggestion = remove the `...` + +parse_path_found_named_params = `Trait(...)` syntax does not support named parameters + .suggestion = remove the parameter name + parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies .suggestion = give this argument a name or use an underscore to ignore it diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 6a6fb0eb9b5b..766baf6f80c7 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -735,6 +735,61 @@ pub(crate) struct FoundExprWouldBeStmt { pub suggestion: ExprParenthesesNeeded, } +#[derive(Diagnostic)] +#[diag(parse_frontmatter_extra_characters_after_close)] +pub(crate) struct FrontmatterExtraCharactersAfterClose { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_frontmatter_invalid_infostring)] +#[note] +pub(crate) struct FrontmatterInvalidInfostring { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_frontmatter_invalid_opening_preceding_whitespace)] +pub(crate) struct FrontmatterInvalidOpeningPrecedingWhitespace { + #[primary_span] + pub span: Span, + #[note] + pub note_span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_frontmatter_unclosed)] +pub(crate) struct FrontmatterUnclosed { + #[primary_span] + pub span: Span, + #[note] + pub note_span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_frontmatter_invalid_close_preceding_whitespace)] +pub(crate) struct FrontmatterInvalidClosingPrecedingWhitespace { + #[primary_span] + pub span: Span, + #[note] + pub note_span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_frontmatter_length_mismatch)] +pub(crate) struct FrontmatterLengthMismatch { + #[primary_span] + pub span: Span, + #[label(parse_label_opening)] + pub opening: Span, + #[label(parse_label_close)] + pub close: Span, + pub len_opening: usize, + pub len_close: usize, +} + #[derive(Diagnostic)] #[diag(parse_leading_plus_not_supported)] pub(crate) struct LeadingPlusNotSupported { @@ -1591,6 +1646,30 @@ pub(crate) struct ExpectedFnPathFoundFnKeyword { pub fn_token_span: Span, } +#[derive(Diagnostic)] +#[diag(parse_path_found_named_params)] +pub(crate) struct FnPathFoundNamedParams { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "")] + pub named_param_span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_path_found_c_variadic_params)] +pub(crate) struct PathFoundCVariadicParams { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_path_found_attribute_in_params)] +pub(crate) struct PathFoundAttributeInParams { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "")] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_path_double_colon)] pub(crate) struct PathSingleColon { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index e8a5cae54cf8..78c5742414b8 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,7 +7,9 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, StashKey}; -use rustc_lexer::{Base, Cursor, DocStyle, LiteralKind, RawStrError}; +use rustc_lexer::{ + Base, Cursor, DocStyle, FrontmatterAllowed, LiteralKind, RawStrError, is_whitespace, +}; use rustc_literal_escaper::{EscapeError, Mode, unescape_mixed, unescape_unicode}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ @@ -15,7 +17,7 @@ use rustc_session::lint::builtin::{ TEXT_DIRECTION_CODEPOINT_IN_COMMENT, }; use rustc_session::parse::ParseSess; -use rustc_span::{BytePos, Pos, Span, Symbol}; +use rustc_span::{BytePos, Pos, Span, Symbol, sym}; use tracing::debug; use crate::errors; @@ -56,7 +58,7 @@ pub(crate) fn lex_token_trees<'psess, 'src>( start_pos = start_pos + BytePos::from_usize(shebang_len); } - let cursor = Cursor::new(src); + let cursor = Cursor::new(src, FrontmatterAllowed::Yes); let mut lexer = Lexer { psess, start_pos, @@ -193,6 +195,11 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let content = self.str_from_to(content_start, content_end); self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style) } + rustc_lexer::TokenKind::Frontmatter { has_invalid_preceding_whitespace, invalid_infostring } => { + self.validate_frontmatter(start, has_invalid_preceding_whitespace, invalid_infostring); + preceded_by_whitespace = true; + continue; + } rustc_lexer::TokenKind::Whitespace => { preceded_by_whitespace = true; continue; @@ -256,7 +263,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { // was consumed. let lit_start = start + BytePos(prefix_len); self.pos = lit_start; - self.cursor = Cursor::new(&str_before[prefix_len as usize..]); + self.cursor = Cursor::new(&str_before[prefix_len as usize..], FrontmatterAllowed::No); self.report_unknown_prefix(start); let prefix_span = self.mk_sp(start, lit_start); return (Token::new(self.ident(start), prefix_span), preceded_by_whitespace); @@ -361,7 +368,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { // Reset the state so we just lex the `'r`. let lt_start = start + BytePos(2); self.pos = lt_start; - self.cursor = Cursor::new(&str_before[2 as usize..]); + self.cursor = Cursor::new(&str_before[2 as usize..], FrontmatterAllowed::No); let lifetime_name = self.str_from(start); let ident = Symbol::intern(lifetime_name); @@ -474,6 +481,91 @@ impl<'psess, 'src> Lexer<'psess, 'src> { } } + fn validate_frontmatter( + &self, + start: BytePos, + has_invalid_preceding_whitespace: bool, + invalid_infostring: bool, + ) { + let s = self.str_from(start); + let real_start = s.find("---").unwrap(); + let frontmatter_opening_pos = BytePos(real_start as u32) + start; + let s_new = &s[real_start..]; + let within = s_new.trim_start_matches('-'); + let len_opening = s_new.len() - within.len(); + + let frontmatter_opening_end_pos = frontmatter_opening_pos + BytePos(len_opening as u32); + if has_invalid_preceding_whitespace { + let line_start = + BytePos(s[..real_start].rfind("\n").map_or(0, |i| i as u32 + 1)) + start; + let span = self.mk_sp(line_start, frontmatter_opening_end_pos); + let label_span = self.mk_sp(line_start, frontmatter_opening_pos); + self.dcx().emit_err(errors::FrontmatterInvalidOpeningPrecedingWhitespace { + span, + note_span: label_span, + }); + } + + if invalid_infostring { + let line_end = s[real_start..].find('\n').unwrap_or(s[real_start..].len()); + let span = self.mk_sp( + frontmatter_opening_end_pos, + frontmatter_opening_pos + BytePos(line_end as u32), + ); + self.dcx().emit_err(errors::FrontmatterInvalidInfostring { span }); + } + + let last_line_start = within.rfind('\n').map_or(0, |i| i + 1); + let last_line = &within[last_line_start..]; + let last_line_trimmed = last_line.trim_start_matches(is_whitespace); + let last_line_start_pos = frontmatter_opening_end_pos + BytePos(last_line_start as u32); + + let frontmatter_span = self.mk_sp(frontmatter_opening_pos, self.pos); + self.psess.gated_spans.gate(sym::frontmatter, frontmatter_span); + + if !last_line_trimmed.starts_with("---") { + let label_span = self.mk_sp(frontmatter_opening_pos, frontmatter_opening_end_pos); + self.dcx().emit_err(errors::FrontmatterUnclosed { + span: frontmatter_span, + note_span: label_span, + }); + return; + } + + if last_line_trimmed.len() != last_line.len() { + let line_end = last_line_start_pos + BytePos(last_line.len() as u32); + let span = self.mk_sp(last_line_start_pos, line_end); + let whitespace_end = + last_line_start_pos + BytePos((last_line.len() - last_line_trimmed.len()) as u32); + let label_span = self.mk_sp(last_line_start_pos, whitespace_end); + self.dcx().emit_err(errors::FrontmatterInvalidClosingPrecedingWhitespace { + span, + note_span: label_span, + }); + } + + let rest = last_line_trimmed.trim_start_matches('-'); + let len_close = last_line_trimmed.len() - rest.len(); + if len_close != len_opening { + let span = self.mk_sp(frontmatter_opening_pos, self.pos); + let opening = self.mk_sp(frontmatter_opening_pos, frontmatter_opening_end_pos); + let last_line_close_pos = last_line_start_pos + BytePos(len_close as u32); + let close = self.mk_sp(last_line_start_pos, last_line_close_pos); + self.dcx().emit_err(errors::FrontmatterLengthMismatch { + span, + opening, + close, + len_opening, + len_close, + }); + } + + if !rest.trim_matches(is_whitespace).is_empty() { + let span = self.mk_sp(last_line_start_pos, self.pos); + self.dcx().emit_err(errors::FrontmatterExtraCharactersAfterClose { span }); + } + } + fn cook_doc_comment( &self, content_start: BytePos, @@ -839,7 +931,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let space_pos = start + BytePos(1); let space_span = self.mk_sp(space_pos, space_pos); - let mut cursor = Cursor::new(str_before); + let mut cursor = Cursor::new(str_before, FrontmatterAllowed::No); let (is_string, span, unterminated) = match cursor.guarded_double_quoted_string() { Some(rustc_lexer::GuardedStr { n_hashes, terminated, token_len }) => { @@ -905,7 +997,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { // For backwards compatibility, roll back to after just the first `#` // and return the `Pound` token. self.pos = start + BytePos(1); - self.cursor = Cursor::new(&str_before[1..]); + self.cursor = Cursor::new(&str_before[1..], FrontmatterAllowed::No); token::Pound } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f3b53971b295..2a7910a6af4d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3828,7 +3828,7 @@ impl<'a> Parser<'a> { // Convert `label` -> `'label`, // so that nameres doesn't complain about non-existing label let label = format!("'{}", ident.name); - let ident = Ident { name: Symbol::intern(&label), span: ident.span }; + let ident = Ident::new(Symbol::intern(&label), ident.span); self.dcx().emit_err(errors::ExpectedLabelFoundIdent { span: ident.span, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 4be8a90368d2..babc55ccc0f9 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2894,7 +2894,7 @@ impl<'a> Parser<'a> { let (mut params, _) = self.parse_paren_comma_seq(|p| { p.recover_vcs_conflict_marker(); let snapshot = p.create_snapshot_for_diagnostic(); - let param = p.parse_param_general(req_name, first_param).or_else(|e| { + let param = p.parse_param_general(req_name, first_param, true).or_else(|e| { let guar = e.emit(); // When parsing a param failed, we should check to make the span of the param // not contain '(' before it. @@ -2922,7 +2922,13 @@ impl<'a> Parser<'a> { /// Parses a single function parameter. /// /// - `self` is syntactically allowed when `first_param` holds. - fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResult<'a, Param> { + /// - `recover_arg_parse` is used to recover from a failed argument parse. + pub(super) fn parse_param_general( + &mut self, + req_name: ReqName, + first_param: bool, + recover_arg_parse: bool, + ) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { @@ -2990,12 +2996,13 @@ impl<'a> Parser<'a> { // If this is a C-variadic argument and we hit an error, return the error. Err(err) if this.token == token::DotDotDot => return Err(err), Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err), - // Recover from attempting to parse the argument as a type without pattern. - Err(err) => { + Err(err) if recover_arg_parse => { + // Recover from attempting to parse the argument as a type without pattern. err.cancel(); this.restore_snapshot(parser_snapshot_before_ty); this.recover_arg_parse()? } + Err(err) => return Err(err), } }; diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 1093e4f4af0a..9bce2fa74caa 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -15,7 +15,11 @@ use tracing::debug; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{Parser, Restrictions, TokenType}; -use crate::errors::{self, PathSingleColon, PathTripleColon}; +use crate::ast::{PatKind, TyKind}; +use crate::errors::{ + self, FnPathFoundNamedParams, PathFoundAttributeInParams, PathFoundCVariadicParams, + PathSingleColon, PathTripleColon, +}; use crate::exp; use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma}; @@ -396,7 +400,28 @@ impl<'a> Parser<'a> { snapshot = Some(self.create_snapshot_for_diagnostic()); } - let (inputs, _) = match self.parse_paren_comma_seq(|p| p.parse_ty()) { + let dcx = self.dcx(); + let parse_params_result = self.parse_paren_comma_seq(|p| { + let param = p.parse_param_general(|_| false, false, false); + param.map(move |param| { + if !matches!(param.pat.kind, PatKind::Missing) { + dcx.emit_err(FnPathFoundNamedParams { + named_param_span: param.pat.span, + }); + } + if matches!(param.ty.kind, TyKind::CVarArgs) { + dcx.emit_err(PathFoundCVariadicParams { span: param.pat.span }); + } + if !param.attrs.is_empty() { + dcx.emit_err(PathFoundAttributeInParams { + span: param.attrs[0].span, + }); + } + param.ty + }) + }); + + let (inputs, _) = match parse_params_result { Ok(output) => output, Err(mut error) if prev_token_before_parsing == token::PathSep => { error.span_label( diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 6a1c2af48ed5..378cbb846379 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -3,7 +3,8 @@ use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::{ - self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety, + self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, NodeId, + Safety, }; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::{AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; @@ -15,21 +16,19 @@ use rustc_span::{Span, Symbol, sym}; use crate::{errors, parse_in}; -pub fn check_attr(psess: &ParseSess, attr: &Attribute) { +pub fn check_attr(psess: &ParseSess, attr: &Attribute, id: NodeId) { if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) { return; } - let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); - let attr_item = attr.get_normal_item(); + let builtin_attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); - // All non-builtin attributes are considered safe - let safety = attr_info.map(|x| x.safety).unwrap_or(AttributeSafety::Normal); - check_attribute_safety(psess, safety, attr); + let builtin_attr_safety = builtin_attr_info.map(|x| x.safety); + check_attribute_safety(psess, builtin_attr_safety, attr, id); // Check input tokens for built-in and key-value attributes. - match attr_info { + match builtin_attr_info { // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => { match parse_meta(psess, attr) { @@ -43,6 +42,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { } } _ => { + let attr_item = attr.get_normal_item(); if let AttrArgs::Eq { .. } = attr_item.args { // All key-value attributes are restricted to meta-item syntax. match parse_meta(psess, attr) { @@ -154,11 +154,23 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte } } -pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: &Attribute) { +pub fn check_attribute_safety( + psess: &ParseSess, + builtin_attr_safety: Option, + attr: &Attribute, + id: NodeId, +) { let attr_item = attr.get_normal_item(); + match (builtin_attr_safety, attr_item.unsafety) { + // - Unsafe builtin attribute + // - User wrote `#[unsafe(..)]`, which is permitted on any edition + (Some(AttributeSafety::Unsafe { .. }), Safety::Unsafe(..)) => { + // OK + } - if let AttributeSafety::Unsafe { unsafe_since } = safety { - if let ast::Safety::Default = attr_item.unsafety { + // - Unsafe builtin attribute + // - User did not write `#[unsafe(..)]` + (Some(AttributeSafety::Unsafe { unsafe_since }), Safety::Default) => { let path_span = attr_item.path.span; // If the `attr_item`'s span is not from a macro, then just suggest @@ -185,7 +197,7 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: psess.buffer_lint( UNSAFE_ATTR_OUTSIDE_UNSAFE, path_span, - ast::CRATE_NODE_ID, + id, BuiltinLintDiag::UnsafeAttrOutsideUnsafe { attribute_name_span: path_span, sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), @@ -193,11 +205,38 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: ); } } - } else if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { - psess.dcx().emit_err(errors::InvalidAttrUnsafe { - span: unsafe_span, - name: attr_item.path.clone(), - }); + + // - Normal builtin attribute, or any non-builtin attribute + // - All non-builtin attributes are currently considered safe; writing `#[unsafe(..)]` is + // not permitted on non-builtin attributes or normal builtin attributes + (Some(AttributeSafety::Normal) | None, Safety::Unsafe(unsafe_span)) => { + psess.dcx().emit_err(errors::InvalidAttrUnsafe { + span: unsafe_span, + name: attr_item.path.clone(), + }); + } + + // - Normal builtin attribute + // - No explicit `#[unsafe(..)]` written. + (Some(AttributeSafety::Normal), Safety::Default) => { + // OK + } + + // - Non-builtin attribute + // - No explicit `#[unsafe(..)]` written. + (None, Safety::Default) => { + // OK + } + + ( + Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None, + Safety::Safe(..), + ) => { + psess.dcx().span_delayed_bug( + attr_item.span(), + "`check_attribute_safety` does not expect `Safety::Safe` on attributes", + ); + } } } diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index c59e6cb5c33f..9dd064aca662 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -15,50 +15,13 @@ )] // tidy-alphabetical-end +use std::ops::Range; + pub use Alignment::*; pub use Count::*; pub use Position::*; use rustc_literal_escaper::{Mode, unescape_unicode}; -// Note: copied from rustc_span -/// Range inside of a `Span` used for diagnostics when we only have access to relative positions. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct InnerSpan { - pub start: usize, - pub end: usize, -} - -impl InnerSpan { - pub fn new(start: usize, end: usize) -> InnerSpan { - InnerSpan { start, end } - } -} - -/// The location and before/after width of a character whose width has changed from its source code -/// representation -#[derive(Copy, Clone, PartialEq, Eq)] -pub struct InnerWidthMapping { - /// Index of the character in the source - pub position: usize, - /// The inner width in characters - pub before: usize, - /// The transformed width in characters - pub after: usize, -} - -impl InnerWidthMapping { - pub fn new(position: usize, before: usize, after: usize) -> InnerWidthMapping { - InnerWidthMapping { position, before, after } - } -} - -/// Whether the input string is a literal. If yes, it contains the inner width mappings. -#[derive(Clone, PartialEq, Eq)] -enum InputStringKind { - NotALiteral, - Literal { width_mappings: Vec }, -} - /// The type of format string that we are parsing. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ParseMode { @@ -68,15 +31,6 @@ pub enum ParseMode { InlineAsm, } -#[derive(Copy, Clone)] -struct InnerOffset(usize); - -impl InnerOffset { - fn to(self, end: InnerOffset) -> InnerSpan { - InnerSpan::new(self.0, end.0) - } -} - /// A piece is a portion of the format string which represents the next part /// to emit. These are emitted as a stream by the `Parser` class. #[derive(Clone, Debug, PartialEq)] @@ -89,24 +43,48 @@ pub enum Piece<'a> { } /// Representation of an argument specification. -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct Argument<'a> { /// Where to find this argument pub position: Position<'a>, /// The span of the position indicator. Includes any whitespace in implicit /// positions (`{ }`). - pub position_span: InnerSpan, + pub position_span: Range, /// How to format the argument pub format: FormatSpec<'a>, } +impl<'a> Argument<'a> { + pub fn is_identifier(&self) -> bool { + matches!(self.position, Position::ArgumentNamed(_)) + && matches!( + self.format, + FormatSpec { + fill: None, + fill_span: None, + align: AlignUnknown, + sign: None, + alternate: false, + zero_pad: false, + debug_hex: None, + precision: CountImplied, + precision_span: None, + width: CountImplied, + width_span: None, + ty: "", + ty_span: None, + }, + ) + } +} + /// Specification for the formatting of an argument in the format string. -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct FormatSpec<'a> { /// Optionally specified character to fill alignment with. pub fill: Option, /// Span of the optionally specified fill character. - pub fill_span: Option, + pub fill_span: Option>, /// Optionally specified alignment. pub align: Alignment, /// The `+` or `-` flag. @@ -120,21 +98,21 @@ pub struct FormatSpec<'a> { /// The integer precision to use. pub precision: Count<'a>, /// The span of the precision formatting flag (for diagnostics). - pub precision_span: Option, + pub precision_span: Option>, /// The string width requested for the resulting format. pub width: Count<'a>, /// The span of the width formatting flag (for diagnostics). - pub width_span: Option, + pub width_span: Option>, /// The descriptor string representing the name of the format desired for /// this argument, this can be empty or any number of characters, although /// it is required to be one word. pub ty: &'a str, /// The span of the descriptor string (for diagnostics). - pub ty_span: Option, + pub ty_span: Option>, } /// Enum describing where an argument for a format can be located. -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum Position<'a> { /// The argument is implied to be located at an index ArgumentImplicitlyIs(usize), @@ -186,12 +164,12 @@ pub enum DebugHex { /// A count is used for the precision and width parameters of an integer, and /// can reference either an argument or a literal integer. -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum Count<'a> { /// The count is specified explicitly. CountIs(u16), /// The count is specified by the argument with the given name. - CountIsName(&'a str, InnerSpan), + CountIsName(&'a str, Range), /// The count is specified by the argument at the given index. CountIsParam(usize), /// The count is specified by a star (like in `{:.*}`) that refers to the argument at the given index. @@ -204,8 +182,8 @@ pub struct ParseError { pub description: String, pub note: Option, pub label: String, - pub span: InnerSpan, - pub secondary_label: Option<(String, InnerSpan)>, + pub span: Range, + pub secondary_label: Option<(String, Range)>, pub suggestion: Suggestion, } @@ -216,12 +194,12 @@ pub enum Suggestion { UsePositional, /// Remove `r#` from identifier: /// `format!("{r#foo}")` -> `format!("{foo}")` - RemoveRawIdent(InnerSpan), + RemoveRawIdent(Range), /// Reorder format parameter: /// `format!("{foo:?#}")` -> `format!("{foo:#?}")` /// `format!("{foo:?x}")` -> `format!("{foo:x?}")` /// `format!("{foo:?X}")` -> `format!("{foo:X?}")` - ReorderFormatParameter(InnerSpan, String), + ReorderFormatParameter(Range, String), } /// The parser structure for interpreting the input format string. This is @@ -232,92 +210,94 @@ pub enum Suggestion { /// necessary there's probably lots of room for improvement performance-wise. pub struct Parser<'a> { mode: ParseMode, + /// Input to be parsed input: &'a str, - cur: std::iter::Peekable>, + /// Tuples of the span in the code snippet (input as written before being unescaped), the pos in input, and the char in input + input_vec: Vec<(Range, usize, char)>, + /// Index into input_vec + input_vec_index: usize, /// Error messages accumulated during parsing pub errors: Vec, /// Current position of implicit positional argument pointer pub curarg: usize, - /// `Some(raw count)` when the string is "raw", used to position spans correctly - style: Option, /// Start and end byte offset of every successfully parsed argument - pub arg_places: Vec, - /// Characters whose length has been changed from their in-code representation - width_map: Vec, + pub arg_places: Vec>, /// Span of the last opening brace seen, used for error reporting - last_opening_brace: Option, - /// Whether the source string is comes from `println!` as opposed to `format!` or `print!` - append_newline: bool, + last_open_brace: Option>, /// Whether this formatting string was written directly in the source. This controls whether we /// can use spans to refer into it and give better error messages. /// N.B: This does _not_ control whether implicit argument captures can be used. pub is_source_literal: bool, + /// Index to the end of the literal snippet + end_of_snippet: usize, /// Start position of the current line. cur_line_start: usize, /// Start and end byte offset of every line of the format string. Excludes /// newline characters and leading whitespace. - pub line_spans: Vec, + pub line_spans: Vec>, } impl<'a> Iterator for Parser<'a> { type Item = Piece<'a>; fn next(&mut self) -> Option> { - if let Some(&(pos, c)) = self.cur.peek() { - match c { + if let Some(&(Range { start, end }, idx, ch)) = self.input_vec.get(self.input_vec_index) { + match ch { '{' => { - let curr_last_brace = self.last_opening_brace; - let byte_pos = self.to_span_index(pos); - let lbrace_end = InnerOffset(byte_pos.0 + self.to_span_width(pos)); - self.last_opening_brace = Some(byte_pos.to(lbrace_end)); - self.cur.next(); - if self.consume('{') { - self.last_opening_brace = curr_last_brace; - - Some(Piece::Lit(self.string(pos + 1))) + self.input_vec_index += 1; + if let Some(&(_, i, '{')) = self.input_vec.get(self.input_vec_index) { + self.input_vec_index += 1; + // double open brace escape: "{{" + // next state after this is either end-of-input or seen-a-brace + Some(Piece::Lit(self.string(i))) } else { - let arg = self.argument(lbrace_end); - if let Some(rbrace_pos) = self.consume_closing_brace(&arg) { + // single open brace + self.last_open_brace = Some(start..end); + let arg = self.argument(); + if let Some(close_brace_range) = self.consume_closing_brace(&arg) { if self.is_source_literal { - let lbrace_byte_pos = self.to_span_index(pos); - let rbrace_byte_pos = self.to_span_index(rbrace_pos); - - let width = self.to_span_width(rbrace_pos); - - self.arg_places.push( - lbrace_byte_pos.to(InnerOffset(rbrace_byte_pos.0 + width)), - ); + self.arg_places.push(start..close_brace_range.end); } - } else if let Some(&(_, maybe)) = self.cur.peek() { - match maybe { + } else if let Some(&(_, _, c)) = self.input_vec.get(self.input_vec_index) { + match c { '?' => self.suggest_format_debug(), - '<' | '^' | '>' => self.suggest_format_align(maybe), - _ => self.suggest_positional_arg_instead_of_captured_arg(arg), + '<' | '^' | '>' => self.suggest_format_align(c), + _ => { + self.suggest_positional_arg_instead_of_captured_arg(arg.clone()) + } } } Some(Piece::NextArgument(Box::new(arg))) } } '}' => { - self.cur.next(); - if self.consume('}') { - Some(Piece::Lit(self.string(pos + 1))) + self.input_vec_index += 1; + if let Some(&(_, i, '}')) = self.input_vec.get(self.input_vec_index) { + self.input_vec_index += 1; + // double close brace escape: "}}" + // next state after this is either end-of-input or start + Some(Piece::Lit(self.string(i))) } else { - let err_pos = self.to_span_index(pos); - self.err_with_note( - "unmatched `}` found", - "unmatched `}`", - "if you intended to print `}`, you can escape it using `}}`", - err_pos.to(err_pos), - ); + // error: single close brace without corresponding open brace + self.errors.push(ParseError { + description: "unmatched `}` found".into(), + note: Some( + "if you intended to print `}`, you can escape it using `}}`".into(), + ), + label: "unmatched `}`".into(), + span: start..end, + secondary_label: None, + suggestion: Suggestion::None, + }); None } } - _ => Some(Piece::Lit(self.string(pos))), + _ => Some(Piece::Lit(self.string(idx))), } } else { + // end of input if self.is_source_literal { - let span = self.span(self.cur_line_start, self.input.len()); + let span = self.cur_line_start..self.end_of_snippet; if self.line_spans.last() != Some(&span) { self.line_spans.push(span); } @@ -328,71 +308,104 @@ impl<'a> Iterator for Parser<'a> { } impl<'a> Parser<'a> { - /// Creates a new parser for the given format string + /// Creates a new parser for the given unescaped input string and + /// optional code snippet (the input as written before being unescaped), + /// where `style` is `Some(nr_hashes)` when the snippet is a raw string with that many hashes. + /// If the input comes via `println` or `panic`, then it has a newline already appended, + /// which is reflected in the `appended_newline` parameter. pub fn new( - s: &'a str, + input: &'a str, style: Option, snippet: Option, - append_newline: bool, + appended_newline: bool, mode: ParseMode, - ) -> Parser<'a> { - let input_string_kind = find_width_map_from_snippet(s, snippet, style); - let (width_map, is_source_literal) = match input_string_kind { - InputStringKind::Literal { width_mappings } => (width_mappings, true), - InputStringKind::NotALiteral => (Vec::new(), false), + ) -> Self { + let quote_offset = style.map_or(1, |nr_hashes| nr_hashes + 2); + + let (is_source_literal, end_of_snippet, pre_input_vec) = if let Some(snippet) = snippet { + if let Some(nr_hashes) = style { + // snippet is a raw string, which starts with 'r', a number of hashes, and a quote + // and ends with a quote and the same number of hashes + (true, snippet.len() - nr_hashes - 1, vec![]) + } else { + // snippet is not a raw string + if snippet.starts_with('"') { + // snippet looks like an ordinary string literal + // check whether it is the escaped version of input + let without_quotes = &snippet[1..snippet.len() - 1]; + let (mut ok, mut vec) = (true, vec![]); + let mut chars = input.chars(); + unescape_unicode(without_quotes, Mode::Str, &mut |range, res| match res { + Ok(ch) if ok && chars.next().is_some_and(|c| ch == c) => { + vec.push((range, ch)); + } + _ => { + ok = false; + vec = vec![]; + } + }); + let end = vec.last().map(|(r, _)| r.end).unwrap_or(0); + if ok { + if appended_newline { + if chars.as_str() == "\n" { + vec.push((end..end + 1, '\n')); + (true, 1 + end, vec) + } else { + (false, snippet.len(), vec![]) + } + } else if chars.as_str() == "" { + (true, 1 + end, vec) + } else { + (false, snippet.len(), vec![]) + } + } else { + (false, snippet.len(), vec![]) + } + } else { + // snippet is not a raw string and does not start with '"' + (false, snippet.len(), vec![]) + } + } + } else { + // snippet is None + (false, input.len() - if appended_newline { 1 } else { 0 }, vec![]) + }; + + let input_vec: Vec<(Range, usize, char)> = if pre_input_vec.is_empty() { + // Snippet is *not* input before unescaping, so spans pointing at it will be incorrect. + // This can happen with proc macros that respan generated literals. + input + .char_indices() + .map(|(idx, c)| { + let i = idx + quote_offset; + (i..i + c.len_utf8(), idx, c) + }) + .collect() + } else { + // Snippet is input before unescaping + input + .char_indices() + .zip(pre_input_vec) + .map(|((i, c), (r, _))| (r.start + quote_offset..r.end + quote_offset, i, c)) + .collect() }; Parser { mode, - input: s, - cur: s.char_indices().peekable(), + input, + input_vec, + input_vec_index: 0, errors: vec![], curarg: 0, - style, arg_places: vec![], - width_map, - last_opening_brace: None, - append_newline, + last_open_brace: None, is_source_literal, - cur_line_start: 0, + end_of_snippet, + cur_line_start: quote_offset, line_spans: vec![], } } - /// Notifies of an error. The message doesn't actually need to be of type - /// String, but I think it does when this eventually uses conditions so it - /// might as well start using it now. - fn err(&mut self, description: impl Into, label: impl Into, span: InnerSpan) { - self.errors.push(ParseError { - description: description.into(), - note: None, - label: label.into(), - span, - secondary_label: None, - suggestion: Suggestion::None, - }); - } - - /// Notifies of an error. The message doesn't actually need to be of type - /// String, but I think it does when this eventually uses conditions so it - /// might as well start using it now. - fn err_with_note( - &mut self, - description: impl Into, - label: impl Into, - note: impl Into, - span: InnerSpan, - ) { - self.errors.push(ParseError { - description: description.into(), - note: Some(note.into()), - label: label.into(), - span, - secondary_label: None, - suggestion: Suggestion::None, - }); - } - /// Optionally consumes the specified character. If the character is not at /// the current position, then the current iterator isn't moved and `false` is /// returned, otherwise the character is consumed and `true` is returned. @@ -404,94 +417,56 @@ impl<'a> Parser<'a> { /// the current position, then the current iterator isn't moved and `None` is /// returned, otherwise the character is consumed and the current position is /// returned. - fn consume_pos(&mut self, c: char) -> Option { - if let Some(&(pos, maybe)) = self.cur.peek() { - if c == maybe { - self.cur.next(); - return Some(pos); + fn consume_pos(&mut self, ch: char) -> Option<(Range, usize)> { + if let Some((r, i, c)) = self.input_vec.get(self.input_vec_index) { + if ch == *c { + self.input_vec_index += 1; + return Some((r.clone(), *i)); } } None } - fn remap_pos(&self, mut pos: usize) -> InnerOffset { - for width in &self.width_map { - if pos > width.position { - pos += width.before - width.after; - } else if pos == width.position && width.after == 0 { - pos += width.before; - } else { - break; - } - } - - InnerOffset(pos) - } - - fn to_span_index(&self, pos: usize) -> InnerOffset { - // This handles the raw string case, the raw argument is the number of # - // in r###"..."### (we need to add one because of the `r`). - let raw = self.style.map_or(0, |raw| raw + 1); - let pos = self.remap_pos(pos); - InnerOffset(raw + pos.0 + 1) - } - - fn to_span_width(&self, pos: usize) -> usize { - let pos = self.remap_pos(pos); - match self.width_map.iter().find(|w| w.position == pos.0) { - Some(w) => w.before, - None => 1, - } - } - - fn span(&self, start_pos: usize, end_pos: usize) -> InnerSpan { - let start = self.to_span_index(start_pos); - let end = self.to_span_index(end_pos); - start.to(end) - } - /// Forces consumption of the specified character. If the character is not /// found, an error is emitted. - fn consume_closing_brace(&mut self, arg: &Argument<'_>) -> Option { + fn consume_closing_brace(&mut self, arg: &Argument<'_>) -> Option> { self.ws(); - let pos; - let description; - - if let Some(&(peek_pos, maybe)) = self.cur.peek() { - if maybe == '}' { - self.cur.next(); - return Some(peek_pos); + let (range, description) = if let Some((r, _, c)) = self.input_vec.get(self.input_vec_index) + { + if *c == '}' { + self.input_vec_index += 1; + return Some(r.clone()); } - - pos = peek_pos; - description = format!("expected `}}`, found `{}`", maybe.escape_debug()); + // or r.clone()? + (r.start..r.start, format!("expected `}}`, found `{}`", c.escape_debug())) } else { - description = "expected `}` but string was terminated".to_owned(); - // point at closing `"` - pos = self.input.len() - if self.append_newline { 1 } else { 0 }; - } + ( + // point at closing `"` + self.end_of_snippet..self.end_of_snippet, + "expected `}` but string was terminated".to_owned(), + ) + }; - let pos = self.to_span_index(pos); - - let label = "expected `}`".to_owned(); let (note, secondary_label) = if arg.format.fill == Some('}') { ( Some("the character `}` is interpreted as a fill character because of the `:` that precedes it".to_owned()), - arg.format.fill_span.map(|sp| ("this is not interpreted as a formatting closing brace".to_owned(), sp)), + arg.format.fill_span.clone().map(|sp| ("this is not interpreted as a formatting closing brace".to_owned(), sp)), ) } else { ( Some("if you intended to print `{`, you can escape it using `{{`".to_owned()), - self.last_opening_brace.map(|sp| ("because of this opening brace".to_owned(), sp)), + self.last_open_brace + .clone() + .map(|sp| ("because of this opening brace".to_owned(), sp)), ) }; self.errors.push(ParseError { description, note, - label, - span: pos.to(pos), + label: "expected `}`".to_owned(), + span: range.start..range.start, secondary_label, suggestion: Suggestion::None, }); @@ -501,28 +476,30 @@ impl<'a> Parser<'a> { /// Consumes all whitespace characters until the first non-whitespace character fn ws(&mut self) { - while let Some(_) = self.cur.next_if(|&(_, c)| c.is_whitespace()) {} + let rest = &self.input_vec[self.input_vec_index..]; + let step = rest.iter().position(|&(_, _, c)| !c.is_whitespace()).unwrap_or(rest.len()); + self.input_vec_index += step; } /// Parses all of a string which is to be considered a "raw literal" in a /// format string. This is everything outside of the braces. fn string(&mut self, start: usize) -> &'a str { - // we may not consume the character, peek the iterator - while let Some(&(pos, c)) = self.cur.peek() { + while let Some((r, i, c)) = self.input_vec.get(self.input_vec_index) { match c { '{' | '}' => { - return &self.input[start..pos]; + return &self.input[start..*i]; } '\n' if self.is_source_literal => { - self.line_spans.push(self.span(self.cur_line_start, pos)); - self.cur_line_start = pos + 1; - self.cur.next(); + self.input_vec_index += 1; + self.line_spans.push(self.cur_line_start..r.start); + self.cur_line_start = r.end; } _ => { - if self.is_source_literal && pos == self.cur_line_start && c.is_whitespace() { - self.cur_line_start = pos + c.len_utf8(); + self.input_vec_index += 1; + if self.is_source_literal && r.start == self.cur_line_start && c.is_whitespace() + { + self.cur_line_start = r.end; } - self.cur.next(); } } } @@ -530,15 +507,13 @@ impl<'a> Parser<'a> { } /// Parses an `Argument` structure, or what's contained within braces inside the format string. - fn argument(&mut self, start: InnerOffset) -> Argument<'a> { - let pos = self.position(); + fn argument(&mut self) -> Argument<'a> { + let start_idx = self.input_vec_index; - let end = self - .cur - .clone() - .find(|(_, ch)| !ch.is_whitespace()) - .map_or(start, |(end, _)| self.to_span_index(end)); - let position_span = start.to(end); + let position = self.position(); + self.ws(); + + let end_idx = self.input_vec_index; let format = match self.mode { ParseMode::Format => self.format(), @@ -546,16 +521,15 @@ impl<'a> Parser<'a> { }; // Resolve position after parsing format spec. - let pos = match pos { - Some(position) => position, - None => { - let i = self.curarg; - self.curarg += 1; - ArgumentImplicitlyIs(i) - } - }; + let position = position.unwrap_or_else(|| { + let i = self.curarg; + self.curarg += 1; + ArgumentImplicitlyIs(i) + }); - Argument { position: pos, position_span, format } + let position_span = + self.input_vec_index2range(start_idx).start..self.input_vec_index2range(end_idx).start; + Argument { position, position_span, format } } /// Parses a positional argument for a format. This could either be an @@ -566,23 +540,26 @@ impl<'a> Parser<'a> { if let Some(i) = self.integer() { Some(ArgumentIs(i.into())) } else { - match self.cur.peek() { - Some(&(lo, c)) if rustc_lexer::is_id_start(c) => { + match self.input_vec.get(self.input_vec_index) { + Some((range, _, c)) if rustc_lexer::is_id_start(*c) => { + let start = range.start; let word = self.word(); // Recover from `r#ident` in format strings. // FIXME: use a let chain if word == "r" { - if let Some((pos, '#')) = self.cur.peek() { - if self.input[pos + 1..] - .chars() - .next() - .is_some_and(rustc_lexer::is_id_start) + if let Some((r, _, '#')) = self.input_vec.get(self.input_vec_index) { + if self + .input_vec + .get(self.input_vec_index + 1) + .is_some_and(|(_, _, c)| rustc_lexer::is_id_start(*c)) { - self.cur.next(); + self.input_vec_index += 1; + let prefix_end = r.end; let word = self.word(); - let prefix_span = self.span(lo, lo + 2); - let full_span = self.span(lo, lo + 2 + word.len()); + let prefix_span = start..prefix_end; + let full_span = + start..self.input_vec_index2range(self.input_vec_index).start; self.errors.insert(0, ParseError { description: "raw identifiers are not supported".to_owned(), note: Some("identifiers in format strings can be keywords and don't need to be prefixed with `r#`".to_string()), @@ -598,7 +575,6 @@ impl<'a> Parser<'a> { Some(ArgumentNamed(word)) } - // This is an `ArgumentNext`. // Record the fact and do the resolution after parsing the // format spec, to make things like `{:.*}` work. @@ -607,8 +583,16 @@ impl<'a> Parser<'a> { } } - fn current_pos(&mut self) -> usize { - if let Some(&(pos, _)) = self.cur.peek() { pos } else { self.input.len() } + fn input_vec_index2pos(&self, index: usize) -> usize { + if let Some(&(_, pos, _)) = self.input_vec.get(index) { pos } else { self.input.len() } + } + + fn input_vec_index2range(&self, index: usize) -> Range { + if let Some((r, _, _)) = self.input_vec.get(index) { + r.clone() + } else { + self.end_of_snippet..self.end_of_snippet + } } /// Parses a format specifier at the current position, returning all of the @@ -634,11 +618,11 @@ impl<'a> Parser<'a> { } // fill character - if let Some(&(idx, c)) = self.cur.peek() { - if let Some((_, '>' | '<' | '^')) = self.cur.clone().nth(1) { + if let Some(&(ref r, _, c)) = self.input_vec.get(self.input_vec_index) { + if let Some((_, _, '>' | '<' | '^')) = self.input_vec.get(self.input_vec_index + 1) { + self.input_vec_index += 1; spec.fill = Some(c); - spec.fill_span = Some(self.span(idx, idx + 1)); - self.cur.next(); + spec.fill_span = Some(r.clone()); } } // Alignment @@ -662,14 +646,14 @@ impl<'a> Parser<'a> { // Width and precision let mut havewidth = false; - if self.consume('0') { + if let Some((range, _)) = self.consume_pos('0') { // small ambiguity with '0$' as a format string. In theory this is a // '0' flag and then an ill-formatted format string with just a '$' // and no count, but this is better if we instead interpret this as // no '0' flag and '0$' as the width instead. - if let Some(end) = self.consume_pos('$') { + if let Some((r, _)) = self.consume_pos('$') { spec.width = CountIsParam(0); - spec.width_span = Some(self.span(end - 1, end + 1)); + spec.width_span = Some(range.start..r.end); havewidth = true; } else { spec.zero_pad = true; @@ -677,15 +661,15 @@ impl<'a> Parser<'a> { } if !havewidth { - let start = self.current_pos(); - spec.width = self.count(start); + let start_idx = self.input_vec_index; + spec.width = self.count(); if spec.width != CountImplied { - let end = self.current_pos(); - spec.width_span = Some(self.span(start, end)); + let end = self.input_vec_index2range(self.input_vec_index).start; + spec.width_span = Some(self.input_vec_index2range(start_idx).start..end); } } - if let Some(start) = self.consume_pos('.') { + if let Some((range, _)) = self.consume_pos('.') { if self.consume('*') { // Resolve `CountIsNextParam`. // We can do this immediately as `position` is resolved later. @@ -693,13 +677,13 @@ impl<'a> Parser<'a> { self.curarg += 1; spec.precision = CountIsStar(i); } else { - spec.precision = self.count(start + 1); + spec.precision = self.count(); } - let end = self.current_pos(); - spec.precision_span = Some(self.span(start, end)); + spec.precision_span = + Some(range.start..self.input_vec_index2range(self.input_vec_index).start); } - let ty_span_start = self.current_pos(); + let start_idx = self.input_vec_index; // Optional radix followed by the actual format specifier if self.consume('x') { if self.consume('?') { @@ -715,19 +699,33 @@ impl<'a> Parser<'a> { } else { spec.ty = "X"; } - } else if self.consume('?') { + } else if let Some((range, _)) = self.consume_pos('?') { spec.ty = "?"; - if let Some(&(_, maybe)) = self.cur.peek() { - match maybe { - '#' | 'x' | 'X' => self.suggest_format_parameter(maybe), + if let Some((r, _, c)) = self.input_vec.get(self.input_vec_index) { + match c { + '#' | 'x' | 'X' => self.errors.insert( + 0, + ParseError { + description: format!("expected `}}`, found `{c}`"), + note: None, + label: "expected `'}'`".into(), + span: r.clone(), + secondary_label: None, + suggestion: Suggestion::ReorderFormatParameter( + range.start..r.end, + format!("{c}?"), + ), + }, + ), _ => (), } } } else { spec.ty = self.word(); if !spec.ty.is_empty() { - let ty_span_end = self.current_pos(); - spec.ty_span = Some(self.span(ty_span_start, ty_span_end)); + let start = self.input_vec_index2range(start_idx).start; + let end = self.input_vec_index2range(self.input_vec_index).start; + spec.ty_span = Some(start..end); } } spec @@ -755,11 +753,12 @@ impl<'a> Parser<'a> { return spec; } - let ty_span_start = self.current_pos(); + let start_idx = self.input_vec_index; spec.ty = self.word(); if !spec.ty.is_empty() { - let ty_span_end = self.current_pos(); - spec.ty_span = Some(self.span(ty_span_start, ty_span_end)); + let start = self.input_vec_index2range(start_idx).start; + let end = self.input_vec_index2range(self.input_vec_index).start; + spec.ty_span = Some(start..end); } spec @@ -768,55 +767,58 @@ impl<'a> Parser<'a> { /// Parses a `Count` parameter at the current position. This does not check /// for 'CountIsNextParam' because that is only used in precision, not /// width. - fn count(&mut self, start: usize) -> Count<'a> { + fn count(&mut self) -> Count<'a> { if let Some(i) = self.integer() { if self.consume('$') { CountIsParam(i.into()) } else { CountIs(i) } } else { - let tmp = self.cur.clone(); + let start_idx = self.input_vec_index; let word = self.word(); if word.is_empty() { - self.cur = tmp; CountImplied - } else if let Some(end) = self.consume_pos('$') { - let name_span = self.span(start, end); - CountIsName(word, name_span) + } else if let Some((r, _)) = self.consume_pos('$') { + CountIsName(word, self.input_vec_index2range(start_idx).start..r.start) } else { - self.cur = tmp; + self.input_vec_index = start_idx; CountImplied } } } - /// Parses a word starting at the current position. A word is the same as + /// Parses a word starting at the current position. A word is the same as a /// Rust identifier, except that it can't start with `_` character. fn word(&mut self) -> &'a str { - let start = match self.cur.peek() { - Some(&(pos, c)) if rustc_lexer::is_id_start(c) => { - self.cur.next(); - pos + let index = self.input_vec_index; + match self.input_vec.get(self.input_vec_index) { + Some(&(ref r, i, c)) if rustc_lexer::is_id_start(c) => { + self.input_vec_index += 1; + (r.start, i) } _ => { return ""; } }; - let mut end = None; - while let Some(&(pos, c)) = self.cur.peek() { - if rustc_lexer::is_id_continue(c) { - self.cur.next(); + let (err_end, end): (usize, usize) = loop { + if let Some(&(ref r, i, c)) = self.input_vec.get(self.input_vec_index) { + if rustc_lexer::is_id_continue(c) { + self.input_vec_index += 1; + } else { + break (r.start, i); + } } else { - end = Some(pos); - break; + break (self.end_of_snippet, self.input.len()); } - } - let end = end.unwrap_or(self.input.len()); - let word = &self.input[start..end]; + }; + + let word = &self.input[self.input_vec_index2pos(index)..end]; if word == "_" { - self.err_with_note( - "invalid argument name `_`", - "invalid argument name", - "argument name cannot be a single underscore", - self.span(start, end), - ); + self.errors.push(ParseError { + description: "invalid argument name `_`".into(), + note: Some("argument name cannot be a single underscore".into()), + label: "invalid argument name".into(), + span: self.input_vec_index2range(index).start..err_end, + secondary_label: None, + suggestion: Suggestion::None, + }); } word } @@ -825,9 +827,10 @@ impl<'a> Parser<'a> { let mut cur: u16 = 0; let mut found = false; let mut overflow = false; - let start = self.current_pos(); - while let Some(&(_, c)) = self.cur.peek() { + let start_index = self.input_vec_index; + while let Some(&(_, _, c)) = self.input_vec.get(self.input_vec_index) { if let Some(i) = c.to_digit(10) { + self.input_vec_index += 1; let (tmp, mul_overflow) = cur.overflowing_mul(10); let (tmp, add_overflow) = tmp.overflowing_add(i as u16); if mul_overflow || add_overflow { @@ -835,40 +838,42 @@ impl<'a> Parser<'a> { } cur = tmp; found = true; - self.cur.next(); } else { break; } } if overflow { - let end = self.current_pos(); - let overflowed_int = &self.input[start..end]; - self.err( - format!( + let overflowed_int = &self.input[self.input_vec_index2pos(start_index) + ..self.input_vec_index2pos(self.input_vec_index)]; + self.errors.push(ParseError { + description: format!( "integer `{}` does not fit into the type `u16` whose range is `0..={}`", overflowed_int, u16::MAX ), - "integer out of range for `u16`", - self.span(start, end), - ); + note: None, + label: "integer out of range for `u16`".into(), + span: self.input_vec_index2range(start_index).start + ..self.input_vec_index2range(self.input_vec_index).end, + secondary_label: None, + suggestion: Suggestion::None, + }); } found.then_some(cur) } fn suggest_format_debug(&mut self) { - if let (Some(pos), Some(_)) = (self.consume_pos('?'), self.consume_pos(':')) { + if let (Some((range, _)), Some(_)) = (self.consume_pos('?'), self.consume_pos(':')) { let word = self.word(); - let pos = self.to_span_index(pos); self.errors.insert( 0, ParseError { description: "expected format parameter to occur after `:`".to_owned(), note: Some(format!("`?` comes after `:`, try `{}:{}` instead", word, "?")), label: "expected `?` to occur after `:`".to_owned(), - span: pos.to(pos), + span: range, secondary_label: None, suggestion: Suggestion::None, }, @@ -877,15 +882,14 @@ impl<'a> Parser<'a> { } fn suggest_format_align(&mut self, alignment: char) { - if let Some(pos) = self.consume_pos(alignment) { - let pos = self.to_span_index(pos); + if let Some((range, _)) = self.consume_pos(alignment) { self.errors.insert( 0, ParseError { description: "expected format parameter to occur after `:`".to_owned(), note: None, label: format!("expected `{}` to occur after `:`", alignment), - span: pos.to(pos), + span: range, secondary_label: None, suggestion: Suggestion::None, }, @@ -894,10 +898,13 @@ impl<'a> Parser<'a> { } fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) { - if let Some(end) = self.consume_pos('.') { - let byte_pos = self.to_span_index(end); - let start = InnerOffset(byte_pos.0 + 1); - let field = self.argument(start); + // If the argument is not an identifier, it is not a field access. + if !arg.is_identifier() { + return; + } + + if let Some((_range, _pos)) = self.consume_pos('.') { + let field = self.argument(); // We can only parse simple `foo.bar` field access or `foo.0` tuple index access, any // deeper nesting, or another type of expression, like method calls, are not supported if !self.consume('}') { @@ -912,10 +919,7 @@ impl<'a> Parser<'a> { description: "field access isn't supported".to_string(), note: None, label: "not supported".to_string(), - span: InnerSpan::new( - arg.position_span.start, - field.position_span.end, - ), + span: arg.position_span.start..field.position_span.end, secondary_label: None, suggestion: Suggestion::UsePositional, }, @@ -928,10 +932,7 @@ impl<'a> Parser<'a> { description: "tuple index access isn't supported".to_string(), note: None, label: "not supported".to_string(), - span: InnerSpan::new( - arg.position_span.start, - field.position_span.end, - ), + span: arg.position_span.start..field.position_span.end, secondary_label: None, suggestion: Suggestion::UsePositional, }, @@ -942,164 +943,6 @@ impl<'a> Parser<'a> { } } } - - fn suggest_format_parameter(&mut self, c: char) { - let replacement = match c { - '#' => "#?", - 'x' => "x?", - 'X' => "X?", - _ => return, - }; - let Some(pos) = self.consume_pos(c) else { - return; - }; - - let span = self.span(pos - 1, pos + 1); - let pos = self.to_span_index(pos); - - self.errors.insert( - 0, - ParseError { - description: format!("expected `}}`, found `{c}`"), - note: None, - label: "expected `'}'`".into(), - span: pos.to(pos), - secondary_label: None, - suggestion: Suggestion::ReorderFormatParameter(span, format!("{replacement}")), - }, - ) - } -} - -/// Finds the indices of all characters that have been processed and differ between the actual -/// written code (code snippet) and the `InternedString` that gets processed in the `Parser` -/// in order to properly synthesise the intra-string `Span`s for error diagnostics. -fn find_width_map_from_snippet( - input: &str, - snippet: Option, - str_style: Option, -) -> InputStringKind { - let snippet = match snippet { - Some(ref s) if s.starts_with('"') || s.starts_with("r\"") || s.starts_with("r#") => s, - _ => return InputStringKind::NotALiteral, - }; - - if str_style.is_some() { - return InputStringKind::Literal { width_mappings: Vec::new() }; - } - - // Strip quotes. - let snippet = &snippet[1..snippet.len() - 1]; - - // Macros like `println` add a newline at the end. That technically doesn't make them "literals" anymore, but it's fine - // since we will never need to point our spans there, so we lie about it here by ignoring it. - // Since there might actually be newlines in the source code, we need to normalize away all trailing newlines. - // If we only trimmed it off the input, `format!("\n")` would cause a mismatch as here we they actually match up. - // Alternatively, we could just count the trailing newlines and only trim one from the input if they don't match up. - let input_no_nl = input.trim_end_matches('\n'); - let Some(unescaped) = unescape_string(snippet) else { - return InputStringKind::NotALiteral; - }; - - let unescaped_no_nl = unescaped.trim_end_matches('\n'); - - if unescaped_no_nl != input_no_nl { - // The source string that we're pointing at isn't our input, so spans pointing at it will be incorrect. - // This can for example happen with proc macros that respan generated literals. - return InputStringKind::NotALiteral; - } - - let mut s = snippet.char_indices(); - let mut width_mappings = vec![]; - while let Some((pos, c)) = s.next() { - match (c, s.clone().next()) { - // skip whitespace and empty lines ending in '\\' - ('\\', Some((_, '\n'))) => { - let _ = s.next(); - let mut width = 2; - - while let Some((_, c)) = s.clone().next() { - if matches!(c, ' ' | '\n' | '\t') { - width += 1; - let _ = s.next(); - } else { - break; - } - } - - width_mappings.push(InnerWidthMapping::new(pos, width, 0)); - } - ('\\', Some((_, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => { - width_mappings.push(InnerWidthMapping::new(pos, 2, 1)); - let _ = s.next(); - } - ('\\', Some((_, 'x'))) => { - // consume `\xAB` literal - s.nth(2); - width_mappings.push(InnerWidthMapping::new(pos, 4, 1)); - } - ('\\', Some((_, 'u'))) => { - let mut width = 2; - let _ = s.next(); - - if let Some((_, next_c)) = s.next() { - if next_c == '{' { - // consume up to 6 hexanumeric chars - let digits_len = - s.clone().take(6).take_while(|(_, c)| c.is_ascii_hexdigit()).count(); - - let len_utf8 = s - .as_str() - .get(..digits_len) - .and_then(|digits| u32::from_str_radix(digits, 16).ok()) - .and_then(char::from_u32) - .map_or(1, char::len_utf8); - - // Skip the digits, for chars that encode to more than 1 utf-8 byte - // exclude as many digits as it is greater than 1 byte - // - // So for a 3 byte character, exclude 2 digits - let required_skips = digits_len.saturating_sub(len_utf8.saturating_sub(1)); - - // skip '{' and '}' also - width += required_skips + 2; - - s.nth(digits_len); - } else if next_c.is_ascii_hexdigit() { - width += 1; - - // We suggest adding `{` and `}` when appropriate, accept it here as if - // it were correct - let mut i = 0; // consume up to 6 hexanumeric chars - while let (Some((_, c)), _) = (s.next(), i < 6) { - if c.is_ascii_hexdigit() { - width += 1; - } else { - break; - } - i += 1; - } - } - } - - width_mappings.push(InnerWidthMapping::new(pos, width, 1)); - } - _ => {} - } - } - - InputStringKind::Literal { width_mappings } -} - -fn unescape_string(string: &str) -> Option { - let mut buf = String::new(); - let mut ok = true; - unescape_unicode(string, Mode::Str, &mut |_, unescaped_char| match unescaped_char { - Ok(c) => buf.push(c), - Err(_) => ok = false, - }); - - ok.then_some(buf) } // Assert a reasonable size for `Piece` diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs index cc8a0069c4ec..e6a7f24034ad 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -41,7 +41,6 @@ fn simple() { same("}}", &[Lit("}")]); same("\\}}", &[Lit("\\"), Lit("}")]); } - #[test] fn invalid01() { musterr("{") @@ -79,23 +78,48 @@ fn invalid_precision() { } #[test] -fn format_nothing() { +fn format_empty() { same( "{}", &[NextArgument(Box::new(Argument { position: ArgumentImplicitlyIs(0), - position_span: InnerSpan { start: 2, end: 2 }, + position_span: 2..2, format: fmtdflt(), }))], ); } #[test] +fn format_tab_empty() { + let fmt_pre = r###""\t{}""###; + let fmt = "\t{}"; + let parser = Parser::new(fmt, None, Some(fmt_pre.into()), false, ParseMode::Format); + assert_eq!( + parser.collect::>>(), + &[ + Lit("\t"), + NextArgument(Box::new(Argument { + position: ArgumentImplicitlyIs(0), + position_span: 4..4, + format: fmtdflt(), + })) + ], + ); +} +#[test] +fn format_open_brace_tab() { + let fmt_pre = r###""{\t""###; + let fmt = "{\t"; + let mut parser = Parser::new(fmt, None, Some(fmt_pre.into()), false, ParseMode::Format); + let _ = parser.by_ref().collect::>>(); + assert_eq!(parser.errors[0].span, 4..4); +} +#[test] fn format_position() { same( "{3}", &[NextArgument(Box::new(Argument { position: ArgumentIs(3), - position_span: InnerSpan { start: 2, end: 3 }, + position_span: 2..3, format: fmtdflt(), }))], ); @@ -106,7 +130,7 @@ fn format_position_nothing_else() { "{3:}", &[NextArgument(Box::new(Argument { position: ArgumentIs(3), - position_span: InnerSpan { start: 2, end: 3 }, + position_span: 2..3, format: fmtdflt(), }))], ); @@ -117,18 +141,54 @@ fn format_named() { "{name}", &[NextArgument(Box::new(Argument { position: ArgumentNamed("name"), - position_span: InnerSpan { start: 2, end: 6 }, + position_span: 2..6, format: fmtdflt(), }))], ) } #[test] +fn format_named_space_nothing() { + same( + "{name} {}", + &[ + NextArgument(Box::new(Argument { + position: ArgumentNamed("name"), + position_span: 2..6, + format: fmtdflt(), + })), + Lit(" "), + NextArgument(Box::new(Argument { + position: ArgumentImplicitlyIs(0), + position_span: 9..9, + format: fmtdflt(), + })), + ], + ) +} +#[test] +fn format_raw() { + let snippet = r###"r#"assertion `left {op} right` failed"#"###.into(); + let source = r#"assertion `left {op} right` failed"#; + + let parser = Parser::new(source, Some(1), Some(snippet), true, ParseMode::Format); + let expected = &[ + Lit("assertion `left "), + NextArgument(Box::new(Argument { + position: ArgumentNamed("op"), + position_span: 20..22, + format: fmtdflt(), + })), + Lit(" right` failed"), + ]; + assert_eq!(parser.collect::>>(), expected); +} +#[test] fn format_type() { same( "{3:x}", &[NextArgument(Box::new(Argument { position: ArgumentIs(3), - position_span: InnerSpan { start: 2, end: 3 }, + position_span: 2..3, format: FormatSpec { fill: None, fill_span: None, @@ -153,7 +213,7 @@ fn format_align_fill() { "{3:>}", &[NextArgument(Box::new(Argument { position: ArgumentIs(3), - position_span: InnerSpan { start: 2, end: 3 }, + position_span: 2..3, format: FormatSpec { fill: None, fill_span: None, @@ -175,10 +235,10 @@ fn format_align_fill() { "{3:0<}", &[NextArgument(Box::new(Argument { position: ArgumentIs(3), - position_span: InnerSpan { start: 2, end: 3 }, + position_span: 2..3, format: FormatSpec { fill: Some('0'), - fill_span: Some(InnerSpan::new(4, 5)), + fill_span: Some(4..5), align: AlignLeft, sign: None, alternate: false, @@ -197,10 +257,10 @@ fn format_align_fill() { "{3:*>>(), + &[Lit("\n .intel_syntax noprefix\n nop")] + ); + assert_eq!(parser.line_spans, &[2..2, 11..33, 42..45]); +} +#[test] +fn asm_concat() { + let asm_pre = r###"concat!("invalid", "_", "instruction")"###; + let asm = "invalid_instruction"; + let mut parser = Parser::new(asm, None, Some(asm_pre.into()), false, ParseMode::InlineAsm); + assert!(!parser.is_source_literal); + assert_eq!(parser.by_ref().collect::>>(), &[Lit(asm)]); + assert_eq!(parser.line_spans, &[]); +} diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 413726ddd82d..6d815e510ea2 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -356,6 +356,8 @@ passes_ignored_derived_impls = passes_implied_feature_not_exist = feature `{$implied_by}` implying `{$feature}` does not exist +passes_incorrect_crate_type = lang items are not allowed in stable dylibs + passes_incorrect_do_not_recommend_args = `#[diagnostic::do_not_recommend]` does not expect any arguments @@ -742,6 +744,23 @@ passes_trait_impl_const_stable = passes_transparent_incompatible = transparent {$target} cannot have other repr hints +passes_unexportable_adt_with_private_fields = ADT types with private fields are not exportable + .note = `{$field_name}` is private + +passes_unexportable_fn_abi = only functions with "C" ABI are exportable + +passes_unexportable_generic_fn = generic functions are not exportable + +passes_unexportable_item = {$descr}'s are not exportable + +passes_unexportable_priv_item = private items are not exportable + .note = is only usable at visibility `{$vis_descr}` + +passes_unexportable_type_in_interface = {$desc} with `#[export_stable]` attribute uses type `{$ty}`, which is not exportable + .label = not exportable + +passes_unexportable_type_repr = types with unstable layout are not exportable + passes_unknown_external_lang_item = unknown external lang item: `{$lang_item}` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f04b167889f1..c68f8df49fc7 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -277,6 +277,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::cfg_attr | sym::cfg_trace | sym::cfg_attr_trace + | sym::export_stable // handled in `check_export` // need to be fixed | sym::cfi_encoding // FIXME(cfi_encoding) | sym::pointee // FIXME(derive_coerce_pointee) @@ -683,7 +684,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - if !other_attr.has_any_name(ALLOW_LIST) { + if !other_attr.has_any_name(ALLOW_LIST) + && !matches!(other_attr.path().as_slice(), [sym::rustfmt, ..]) + { let path = other_attr.path(); let path: Vec<_> = path.iter().map(|s| s.as_str()).collect(); let other_attr_name = path.join("::"); diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs new file mode 100644 index 000000000000..2bb698689bee --- /dev/null +++ b/compiler/rustc_passes/src/check_export.rs @@ -0,0 +1,398 @@ +use std::iter; +use std::ops::ControlFlow; + +use rustc_abi::ExternAbi; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_hir as hir; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::intravisit::{self, Visitor}; +use rustc_middle::hir::nested_filter; +use rustc_middle::middle::privacy::{EffectiveVisibility, Level}; +use rustc_middle::query::{LocalCrate, Providers}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Visibility, +}; +use rustc_session::config::CrateType; +use rustc_span::{Span, sym}; + +use crate::errors::UnexportableItem; + +struct ExportableItemCollector<'tcx> { + tcx: TyCtxt<'tcx>, + exportable_items: FxIndexSet, + in_exportable_mod: bool, + seen_exportable_in_mod: bool, +} + +impl<'tcx> ExportableItemCollector<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> ExportableItemCollector<'tcx> { + ExportableItemCollector { + tcx, + exportable_items: Default::default(), + in_exportable_mod: false, + seen_exportable_in_mod: false, + } + } + + fn report_wrong_site(&self, def_id: LocalDefId) { + let def_descr = self.tcx.def_descr(def_id.to_def_id()); + self.tcx.dcx().emit_err(UnexportableItem::Item { + descr: &format!("{}", def_descr), + span: self.tcx.def_span(def_id), + }); + } + + fn item_is_exportable(&self, def_id: LocalDefId) -> bool { + let has_attr = self.tcx.has_attr(def_id, sym::export_stable); + if !self.in_exportable_mod && !has_attr { + return false; + } + + let visibilities = self.tcx.effective_visibilities(()); + let is_pub = visibilities.is_directly_public(def_id); + + if has_attr && !is_pub { + let vis = visibilities.effective_vis(def_id).cloned().unwrap_or( + EffectiveVisibility::from_vis(Visibility::Restricted( + self.tcx.parent_module_from_def_id(def_id).to_local_def_id(), + )), + ); + let vis = vis.at_level(Level::Direct); + let span = self.tcx.def_span(def_id); + + self.tcx.dcx().emit_err(UnexportableItem::PrivItem { + vis_note: span, + vis_descr: &vis.to_string(def_id, self.tcx), + span, + }); + return false; + } + + is_pub && (has_attr || self.in_exportable_mod) + } + + fn add_exportable(&mut self, def_id: LocalDefId) { + self.seen_exportable_in_mod = true; + self.exportable_items.insert(def_id.to_def_id()); + } + + fn walk_item_with_mod(&mut self, item: &'tcx hir::Item<'tcx>) { + let def_id = item.hir_id().owner.def_id; + let old_exportable_mod = self.in_exportable_mod; + if self.tcx.get_attr(def_id, sym::export_stable).is_some() { + self.in_exportable_mod = true; + } + let old_seen_exportable_in_mod = std::mem::replace(&mut self.seen_exportable_in_mod, false); + + intravisit::walk_item(self, item); + + if self.seen_exportable_in_mod || self.in_exportable_mod { + self.exportable_items.insert(def_id.to_def_id()); + } + + self.seen_exportable_in_mod = old_seen_exportable_in_mod; + self.in_exportable_mod = old_exportable_mod; + } +} + +impl<'tcx> Visitor<'tcx> for ExportableItemCollector<'tcx> { + type NestedFilter = nested_filter::All; + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx + } + + fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + let def_id = item.hir_id().owner.def_id; + // Applying #[extern] attribute to modules is simply equivalent to + // applying the attribute to every public item within it. + match item.kind { + hir::ItemKind::Mod(..) => { + self.walk_item_with_mod(item); + return; + } + hir::ItemKind::Impl(impl_) if impl_.of_trait.is_none() => { + self.walk_item_with_mod(item); + return; + } + _ => {} + } + + if !self.item_is_exportable(def_id) { + return; + } + + match item.kind { + hir::ItemKind::Fn { .. } + | hir::ItemKind::Struct(..) + | hir::ItemKind::Enum(..) + | hir::ItemKind::Union(..) + | hir::ItemKind::TyAlias(..) => { + self.add_exportable(def_id); + } + hir::ItemKind::Use(path, _) => { + for res in &path.res { + // Only local items are exportable. + if let Some(res_id) = res.opt_def_id() + && let Some(res_id) = res_id.as_local() + { + self.add_exportable(res_id); + } + } + } + // handled above + hir::ItemKind::Mod(..) => unreachable!(), + hir::ItemKind::Impl(impl_) if impl_.of_trait.is_none() => { + unreachable!(); + } + _ => self.report_wrong_site(def_id), + } + } + + fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) { + let def_id = item.hir_id().owner.def_id; + if !self.item_is_exportable(def_id) { + return; + } + match item.kind { + hir::ImplItemKind::Fn(..) | hir::ImplItemKind::Type(..) => { + self.add_exportable(def_id); + } + _ => self.report_wrong_site(def_id), + } + } + + fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { + let def_id = item.hir_id().owner.def_id; + if !self.item_is_exportable(def_id) { + self.report_wrong_site(def_id); + } + } + + fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) { + let def_id = item.hir_id().owner.def_id; + if !self.item_is_exportable(def_id) { + self.report_wrong_site(def_id); + } + } +} + +struct ExportableItemsChecker<'tcx, 'a> { + tcx: TyCtxt<'tcx>, + exportable_items: &'a FxIndexSet, + item_id: DefId, +} + +impl<'tcx, 'a> ExportableItemsChecker<'tcx, 'a> { + fn check(&mut self) { + match self.tcx.def_kind(self.item_id) { + DefKind::Fn | DefKind::AssocFn => self.check_fn(), + DefKind::Enum | DefKind::Struct | DefKind::Union => self.check_ty(), + _ => {} + } + } + + fn check_fn(&mut self) { + let def_id = self.item_id.expect_local(); + let span = self.tcx.def_span(def_id); + + if self.tcx.generics_of(def_id).requires_monomorphization(self.tcx) { + self.tcx.dcx().emit_err(UnexportableItem::GenericFn(span)); + return; + } + + let sig = self.tcx.fn_sig(def_id).instantiate_identity().skip_binder(); + if !matches!(sig.abi, ExternAbi::C { .. }) { + self.tcx.dcx().emit_err(UnexportableItem::FnAbi(span)); + return; + } + + let sig = self + .tcx + .try_normalize_erasing_regions(ty::TypingEnv::non_body_analysis(self.tcx, def_id), sig) + .unwrap_or(sig); + + let hir_id = self.tcx.local_def_id_to_hir_id(def_id); + let decl = self.tcx.hir_fn_decl_by_hir_id(hir_id).unwrap(); + + for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { + self.check_nested_types_are_exportable(*input_ty, input_hir.span); + } + + if let hir::FnRetTy::Return(ret_hir) = decl.output { + self.check_nested_types_are_exportable(sig.output(), ret_hir.span); + } + } + + fn check_ty(&mut self) { + let ty = self.tcx.type_of(self.item_id).skip_binder(); + if let ty::Adt(adt_def, _) = ty.kind() { + if !adt_def.repr().inhibit_struct_field_reordering() { + self.tcx + .dcx() + .emit_err(UnexportableItem::TypeRepr(self.tcx.def_span(self.item_id))); + } + + // FIXME: support `#[export(unsafe_stable_abi = "hash")]` syntax + for variant in adt_def.variants() { + for field in &variant.fields { + if !field.vis.is_public() { + self.tcx.dcx().emit_err(UnexportableItem::AdtWithPrivFields { + span: self.tcx.def_span(self.item_id), + vis_note: self.tcx.def_span(field.did), + field_name: field.name.as_str(), + }); + } + } + } + } + } + + fn check_nested_types_are_exportable(&mut self, ty: Ty<'tcx>, ty_span: Span) { + let res = ty.visit_with(self); + if let Some(err_cause) = res.break_value() { + self.tcx.dcx().emit_err(UnexportableItem::TypeInInterface { + span: self.tcx.def_span(self.item_id), + desc: self.tcx.def_descr(self.item_id), + ty: &format!("{}", err_cause), + ty_span, + }); + } + } +} + +impl<'tcx, 'a> TypeVisitor> for ExportableItemsChecker<'tcx, 'a> { + type Result = ControlFlow>; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + match ty.kind() { + ty::Adt(adt_def, _) => { + let did = adt_def.did(); + let exportable = if did.is_local() { + self.exportable_items.contains(&did) + } else { + self.tcx.is_exportable(did) + }; + if !exportable { + return ControlFlow::Break(ty); + } + for variant in adt_def.variants() { + for field in &variant.fields { + let field_ty = self.tcx.type_of(field.did).instantiate_identity(); + field_ty.visit_with(self)?; + } + } + + return ty.super_visit_with(self); + } + + ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Bool | ty::Char | ty::Error(_) => {} + + ty::Array(_, _) + | ty::Ref(_, _, _) + | ty::Param(_) + | ty::Closure(_, _) + | ty::Dynamic(_, _, _) + | ty::Coroutine(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Tuple(_) + | ty::Pat(..) + | ty::Slice(_) + | ty::RawPtr(_, _) + | ty::FnDef(_, _) + | ty::FnPtr(_, _) + | ty::CoroutineClosure(_, _) + | ty::CoroutineWitness(_, _) + | ty::Never + | ty::UnsafeBinder(_) + | ty::Alias(ty::AliasTyKind::Opaque, _) => { + return ControlFlow::Break(ty); + } + + ty::Alias(..) | ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => unreachable!(), + } + ControlFlow::Continue(()) + } +} + +/// Exportable items: +/// +/// 1. Structs/enums/unions with a stable representation (e.g. repr(i32) or repr(C)). +/// 2. Primitive types. +/// 3. Non-generic functions with a stable ABI (e.g. extern "C") for which every user +/// defined type used in the signature is also marked as `#[export]`. +fn exportable_items_provider_local<'tcx>(tcx: TyCtxt<'tcx>, _: LocalCrate) -> &'tcx [DefId] { + if !tcx.crate_types().contains(&CrateType::Sdylib) && !tcx.is_sdylib_interface_build() { + return &[]; + } + + let mut visitor = ExportableItemCollector::new(tcx); + tcx.hir_walk_toplevel_module(&mut visitor); + let exportable_items = visitor.exportable_items; + for item_id in exportable_items.iter() { + let mut validator = + ExportableItemsChecker { tcx, exportable_items: &exportable_items, item_id: *item_id }; + validator.check(); + } + + tcx.arena.alloc_from_iter(exportable_items.into_iter()) +} + +struct ImplsOrderVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + order: FxIndexMap, +} + +impl<'tcx> ImplsOrderVisitor<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> ImplsOrderVisitor<'tcx> { + ImplsOrderVisitor { tcx, order: Default::default() } + } +} + +impl<'tcx> Visitor<'tcx> for ImplsOrderVisitor<'tcx> { + type NestedFilter = nested_filter::All; + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx + } + + fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + if let hir::ItemKind::Impl(impl_) = item.kind + && impl_.of_trait.is_none() + && self.tcx.is_exportable(item.owner_id.def_id.to_def_id()) + { + self.order.insert(item.owner_id.def_id.to_def_id(), self.order.len()); + } + intravisit::walk_item(self, item); + } +} + +/// During symbol mangling rustc uses a special index to distinguish between two impls of +/// the same type in the same module(See `DisambiguatedDefPathData`). For exportable items +/// we cannot use the current approach because it is dependent on the compiler's +/// implementation. +/// +/// In order to make disambiguation independent of the compiler version we can assign an +/// id to each impl according to the relative order of elements in the source code. +fn stable_order_of_exportable_impls<'tcx>( + tcx: TyCtxt<'tcx>, + _: LocalCrate, +) -> &'tcx FxIndexMap { + if !tcx.crate_types().contains(&CrateType::Sdylib) && !tcx.is_sdylib_interface_build() { + return tcx.arena.alloc(FxIndexMap::::default()); + } + + let mut vis = ImplsOrderVisitor::new(tcx); + tcx.hir_walk_toplevel_module(&mut vis); + tcx.arena.alloc(vis.order) +} + +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { + exportable_items: exportable_items_provider_local, + stable_order_of_exportable_impls, + ..*providers + }; +} diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index b1b4b9ee9276..00682a9c7a79 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1422,6 +1422,13 @@ pub(crate) struct IncorrectTarget<'a> { pub at_least: bool, } +#[derive(Diagnostic)] +#[diag(passes_incorrect_crate_type)] +pub(crate) struct IncorrectCrateType { + #[primary_span] + pub span: Span, +} + #[derive(LintDiagnostic)] #[diag(passes_useless_assignment)] pub(crate) struct UselessAssignment<'a> { @@ -1919,3 +1926,50 @@ pub(crate) struct UnsupportedAttributesInWhere { #[primary_span] pub span: MultiSpan, } + +#[derive(Diagnostic)] +pub(crate) enum UnexportableItem<'a> { + #[diag(passes_unexportable_item)] + Item { + #[primary_span] + span: Span, + descr: &'a str, + }, + + #[diag(passes_unexportable_generic_fn)] + GenericFn(#[primary_span] Span), + + #[diag(passes_unexportable_fn_abi)] + FnAbi(#[primary_span] Span), + + #[diag(passes_unexportable_type_repr)] + TypeRepr(#[primary_span] Span), + + #[diag(passes_unexportable_type_in_interface)] + TypeInInterface { + #[primary_span] + span: Span, + desc: &'a str, + ty: &'a str, + #[label] + ty_span: Span, + }, + + #[diag(passes_unexportable_priv_item)] + PrivItem { + #[primary_span] + span: Span, + #[note] + vis_note: Span, + vis_descr: &'a str, + }, + + #[diag(passes_unexportable_adt_with_private_fields)] + AdtWithPrivFields { + #[primary_span] + span: Span, + #[note] + vis_note: Span, + field_name: &'a str, + }, +} diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 664bd4ad0a25..275714c2d0e4 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -19,7 +19,8 @@ use rustc_session::cstore::ExternCrate; use rustc_span::Span; use crate::errors::{ - DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem, + DuplicateLangItem, IncorrectCrateType, IncorrectTarget, LangItemOnIncorrectTarget, + UnknownLangItem, }; use crate::weak_lang_items; @@ -236,6 +237,10 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { } } + if self.tcx.crate_types().contains(&rustc_session::config::CrateType::Sdylib) { + self.tcx.dcx().emit_err(IncorrectCrateType { span: attr_span }); + } + self.collect_item(lang_item, item_def_id.to_def_id(), Some(item_span)); } } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 424bce9d4d47..001725e28827 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -19,6 +19,7 @@ use rustc_middle::query::Providers; pub mod abi_test; mod check_attr; +mod check_export; pub mod dead; mod debugger_visualizer; mod diagnostic_items; @@ -54,4 +55,5 @@ pub fn provide(providers: &mut Providers) { reachable::provide(providers); stability::provide(providers); upvars::provide(providers); + check_export::provide(providers); } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 321e5729b727..f0e8fa986fea 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -435,10 +435,12 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet { let effective_visibilities = &tcx.effective_visibilities(()); - let any_library = tcx - .crate_types() - .iter() - .any(|ty| *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro); + let any_library = tcx.crate_types().iter().any(|ty| { + *ty == CrateType::Rlib + || *ty == CrateType::Dylib + || *ty == CrateType::ProcMacro + || *ty == CrateType::Sdylib + }); let mut reachable_context = ReachableContext { tcx, maybe_typeck_results: None, diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 701f500e4f60..93d164e7d01f 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -67,7 +67,8 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { | CrateType::ProcMacro | CrateType::Cdylib | CrateType::Executable - | CrateType::Staticlib => true, + | CrateType::Staticlib + | CrateType::Sdylib => true, CrateType::Rlib => false, }); if !needs_check { diff --git a/compiler/rustc_pattern_analysis/messages.ftl b/compiler/rustc_pattern_analysis/messages.ftl index 41a1d958f109..d3a3107f8e89 100644 --- a/compiler/rustc_pattern_analysis/messages.ftl +++ b/compiler/rustc_pattern_analysis/messages.ftl @@ -6,6 +6,10 @@ pattern_analysis_excluside_range_missing_max = exclusive range missing `{$max}` .label = this range doesn't match `{$max}` because `..` is an exclusive range .suggestion = use an inclusive range instead +pattern_analysis_mixed_deref_pattern_constructors = mix of deref patterns and normal constructors + .deref_pattern_label = matches on the result of dereferencing `{$smart_pointer_ty}` + .normal_constructor_label = matches directly on `{$smart_pointer_ty}` + pattern_analysis_non_exhaustive_omitted_pattern = some variants are not matched explicitly .help = ensure that all variants are matched explicitly by adding the suggested match arms .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 4ce868f014f4..f7a4931c1114 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -696,6 +696,10 @@ pub enum Constructor { F128Range(IeeeFloat, IeeeFloat, RangeEnd), /// String literals. Strings are not quite the same as `&[u8]` so we treat them separately. Str(Cx::StrLit), + /// Deref patterns (enabled by the `deref_patterns` feature) provide a way of matching on a + /// smart pointer ADT through its pointee. They don't directly correspond to ADT constructors, + /// and currently are not supported alongside them. Carries the type of the pointee. + DerefPattern(Cx::Ty), /// Constants that must not be matched structurally. They are treated as black boxes for the /// purposes of exhaustiveness: we must not inspect them, and they don't count towards making a /// match exhaustive. @@ -740,6 +744,7 @@ impl Clone for Constructor { Constructor::F64Range(lo, hi, end) => Constructor::F64Range(*lo, *hi, *end), Constructor::F128Range(lo, hi, end) => Constructor::F128Range(*lo, *hi, *end), Constructor::Str(value) => Constructor::Str(value.clone()), + Constructor::DerefPattern(ty) => Constructor::DerefPattern(ty.clone()), Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()), Constructor::Or => Constructor::Or, Constructor::Never => Constructor::Never, @@ -856,6 +861,10 @@ impl Constructor { } (Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice), + // Deref patterns only interact with other deref patterns. Prior to usefulness analysis, + // we ensure they don't appear alongside any other non-wild non-opaque constructors. + (DerefPattern(_), DerefPattern(_)) => true, + // Opaque constructors don't interact with anything unless they come from the // syntactically identical pattern. (Opaque(self_id), Opaque(other_id)) => self_id == other_id, @@ -932,6 +941,7 @@ impl Constructor { F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?, F128Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?, Str(value) => write!(f, "{value:?}")?, + DerefPattern(_) => write!(f, "deref!({:?})", fields.next().unwrap())?, Opaque(..) => write!(f, "")?, Or => { for pat in fields { @@ -1039,8 +1049,17 @@ impl ConstructorSet { let mut missing = Vec::new(); // Constructors in `ctors`, except wildcards and opaques. let mut seen = Vec::new(); + // If we see a deref pattern, it must be the only non-wildcard non-opaque constructor; we + // ensure this prior to analysis. + let mut deref_pat_present = false; for ctor in ctors.cloned() { match ctor { + DerefPattern(..) => { + if !deref_pat_present { + deref_pat_present = true; + present.push(ctor); + } + } Opaque(..) => present.push(ctor), Wildcard => {} // discard wildcards _ => seen.push(ctor), @@ -1048,6 +1067,9 @@ impl ConstructorSet { } match self { + _ if deref_pat_present => { + // Deref patterns are the only constructor; nothing is missing. + } ConstructorSet::Struct { empty } => { if !seen.is_empty() { present.push(Struct); diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index e60930d6cd21..156ba9737673 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -1,5 +1,5 @@ use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic}; -use rustc_macros::{LintDiagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::Span; @@ -133,3 +133,15 @@ pub(crate) struct NonExhaustiveOmittedPatternLintOnArm { pub lint_level: &'static str, pub lint_name: &'static str, } + +#[derive(Diagnostic)] +#[diag(pattern_analysis_mixed_deref_pattern_constructors)] +pub(crate) struct MixedDerefPatternConstructors<'tcx> { + #[primary_span] + pub spans: Vec, + pub smart_pointer_ty: Ty<'tcx>, + #[label(pattern_analysis_deref_pattern_label)] + pub deref_pattern_label: Span, + #[label(pattern_analysis_normal_constructor_label)] + pub normal_constructor_label: Span, +} diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 7c12f69f14c1..a89d01dcbbe4 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -269,6 +269,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } _ => bug!("bad slice pattern {:?} {:?}", ctor, ty), }, + DerefPattern(pointee_ty) => reveal_and_alloc(cx, once(pointee_ty.inner())), Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => &[], @@ -296,7 +297,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } _ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"), }, - Ref => 1, + Ref | DerefPattern(_) => 1, Slice(slice) => slice.arity(), Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing @@ -493,11 +494,15 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { ), }; } - PatKind::DerefPattern { .. } => { - // FIXME(deref_patterns): At least detect that `box _` is irrefutable. - fields = vec![]; - arity = 0; - ctor = Opaque(OpaqueId::new()); + PatKind::DerefPattern { subpattern, .. } => { + // NB(deref_patterns): This assumes the deref pattern is matching on a trusted + // `DerefPure` type. If the `Deref` impl isn't trusted, exhaustiveness must take + // into account that multiple calls to deref may return different results. Hence + // multiple deref! patterns cannot be exhaustive together unless each is exhaustive + // by itself. + fields = vec![self.lower_pat(subpattern).at_index(0)]; + arity = 1; + ctor = DerefPattern(cx.reveal_opaque_ty(subpattern.ty)); } PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => { match ty.kind() { @@ -874,6 +879,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { print::write_ref_like(&mut s, pat.ty().inner(), &print(&pat.fields[0])).unwrap(); s } + DerefPattern(_) => format!("deref!({})", print(&pat.fields[0])), Slice(slice) => { let (prefix_len, has_dot_dot) = match slice.kind { SliceKind::FixedLen(len) => (len, false), @@ -1100,6 +1106,14 @@ pub fn analyze_match<'p, 'tcx>( scrut_ty: Ty<'tcx>, ) -> Result, ErrorGuaranteed> { let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); + + // The analysis doesn't support deref patterns mixed with normal constructors; error if present. + // FIXME(deref_patterns): This only needs to run when a deref pattern was found during lowering. + if tycx.tcx.features().deref_patterns() { + let pat_column = PatternColumn::new(arms); + detect_mixed_deref_pat_ctors(tycx, &pat_column)?; + } + let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee); let report = compute_match_usefulness( tycx, @@ -1119,6 +1133,51 @@ pub fn analyze_match<'p, 'tcx>( Ok(report) } +// FIXME(deref_patterns): Currently it's the responsibility of the frontend (rustc or rust-analyzer) +// to ensure that deref patterns don't appear in the same column as normal constructors. Deref +// patterns aren't currently implemented in rust-analyzer, but should they be, the columnwise check +// here could be made generic and shared between frontends. +fn detect_mixed_deref_pat_ctors<'p, 'tcx>( + cx: &RustcPatCtxt<'p, 'tcx>, + column: &PatternColumn<'p, RustcPatCtxt<'p, 'tcx>>, +) -> Result<(), ErrorGuaranteed> { + let Some(&ty) = column.head_ty() else { + return Ok(()); + }; + + // Check for a mix of deref patterns and normal constructors. + let mut normal_ctor_span = None; + let mut deref_pat_span = None; + for pat in column.iter() { + match pat.ctor() { + // The analysis can handle mixing deref patterns with wildcards and opaque patterns. + Wildcard | Opaque(_) => {} + DerefPattern(_) => deref_pat_span = Some(pat.data().span), + // Nothing else can be compared to deref patterns in `Constructor::is_covered_by`. + _ => normal_ctor_span = Some(pat.data().span), + } + } + if let Some(normal_constructor_label) = normal_ctor_span + && let Some(deref_pattern_label) = deref_pat_span + { + return Err(cx.tcx.dcx().emit_err(errors::MixedDerefPatternConstructors { + spans: vec![deref_pattern_label, normal_constructor_label], + smart_pointer_ty: ty.inner(), + deref_pattern_label, + normal_constructor_label, + })); + } + + // Specialize and recurse into the patterns' fields. + let set = column.analyze_ctors(cx, &ty)?; + for ctor in set.present { + for specialized_column in column.specialize(cx, &ty, &ctor).iter() { + detect_mixed_deref_pat_ctors(cx, specialized_column)?; + } + } + Ok(()) +} + struct RecursiveOpaque { def_id: DefId, } diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 11ebbea07fa4..53638f2a57dd 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -702,6 +702,7 @@ //! - `ui/consts/const_in_pattern` //! - `ui/rfc-2008-non-exhaustive` //! - `ui/half-open-range-patterns` +//! - `ui/pattern/deref-patterns` //! - probably many others //! //! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific @@ -866,7 +867,8 @@ impl PlaceValidity { /// inside `&` and union fields where validity is reset to `MaybeInvalid`. fn specialize(self, ctor: &Constructor) -> Self { // We preserve validity except when we go inside a reference or a union field. - if matches!(ctor, Constructor::Ref | Constructor::UnionField) { + if matches!(ctor, Constructor::Ref | Constructor::DerefPattern(_) | Constructor::UnionField) + { // Validity of `x: &T` does not imply validity of `*x: T`. MaybeInvalid } else { diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 0d56db160996..3ae56cef2c42 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -11,7 +11,7 @@ use rustc_data_structures::outline; use rustc_data_structures::profiling::QueryInvocationId; use rustc_data_structures::sharded::{self, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::{AtomicU64, Lock}; +use rustc_data_structures::sync::{AtomicU64, Lock, is_dyn_thread_safe}; use rustc_data_structures::unord::UnordMap; use rustc_errors::DiagInner; use rustc_index::IndexVec; @@ -124,19 +124,11 @@ impl DepGraph { prev_graph: Arc, prev_work_products: WorkProductMap, encoder: FileEncoder, - record_graph: bool, - record_stats: bool, ) -> DepGraph { let prev_graph_node_count = prev_graph.node_count(); - let current = CurrentDepGraph::new( - session, - prev_graph_node_count, - encoder, - record_graph, - record_stats, - Arc::clone(&prev_graph), - ); + let current = + CurrentDepGraph::new(session, prev_graph_node_count, encoder, Arc::clone(&prev_graph)); let colors = DepNodeColorMap::new(prev_graph_node_count); @@ -1052,17 +1044,8 @@ impl DepGraph { } } - pub fn print_incremental_info(&self) { - if let Some(data) = &self.data { - data.current.encoder.print_incremental_info( - data.current.total_read_count.load(Ordering::Relaxed), - data.current.total_duplicate_read_count.load(Ordering::Relaxed), - ) - } - } - pub fn finish_encoding(&self) -> FileEncodeResult { - if let Some(data) = &self.data { data.current.encoder.finish() } else { Ok(0) } + if let Some(data) = &self.data { data.current.encoder.finish(&data.current) } else { Ok(0) } } pub(crate) fn next_virtual_depnode_index(&self) -> DepNodeIndex { @@ -1179,8 +1162,8 @@ pub(super) struct CurrentDepGraph { /// These are simple counters that are for profiling and /// debugging and only active with `debug_assertions`. - total_read_count: AtomicU64, - total_duplicate_read_count: AtomicU64, + pub(super) total_read_count: AtomicU64, + pub(super) total_duplicate_read_count: AtomicU64, } impl CurrentDepGraph { @@ -1188,8 +1171,6 @@ impl CurrentDepGraph { session: &Session, prev_graph_node_count: usize, encoder: FileEncoder, - record_graph: bool, - record_stats: bool, previous: Arc, ) -> Self { let mut stable_hasher = StableHasher::new(); @@ -1211,14 +1192,7 @@ impl CurrentDepGraph { session.opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions); CurrentDepGraph { - encoder: GraphEncoder::new( - encoder, - prev_graph_node_count, - record_graph, - record_stats, - &session.prof, - previous, - ), + encoder: GraphEncoder::new(session, encoder, prev_graph_node_count, previous), anon_node_to_index: ShardedHashMap::with_capacity( // FIXME: The count estimate is off as anon nodes are only a portion of the nodes. new_node_count_estimate / sharded::shards(), @@ -1345,6 +1319,7 @@ impl Default for TaskDeps { // array, using one u32 per entry. pub(super) struct DepNodeColorMap { values: IndexVec, + sync: bool, } const COMPRESSED_NONE: u32 = u32::MAX; @@ -1353,7 +1328,10 @@ const COMPRESSED_RED: u32 = u32::MAX - 1; impl DepNodeColorMap { fn new(size: usize) -> DepNodeColorMap { debug_assert!(COMPRESSED_RED > DepNodeIndex::MAX_AS_U32); - DepNodeColorMap { values: (0..size).map(|_| AtomicU32::new(COMPRESSED_NONE)).collect() } + DepNodeColorMap { + values: (0..size).map(|_| AtomicU32::new(COMPRESSED_NONE)).collect(), + sync: is_dyn_thread_safe(), + } } #[inline] @@ -1362,6 +1340,37 @@ impl DepNodeColorMap { if value <= DepNodeIndex::MAX_AS_U32 { Some(DepNodeIndex::from_u32(value)) } else { None } } + /// This tries to atomically mark a node green and assign `index` as the new + /// index. This returns `Ok` if `index` gets assigned, otherwise it returns + /// the alreadly allocated index in `Err`. + #[inline] + pub(super) fn try_mark_green( + &self, + prev_index: SerializedDepNodeIndex, + index: DepNodeIndex, + ) -> Result<(), DepNodeIndex> { + let value = &self.values[prev_index]; + if self.sync { + match value.compare_exchange( + COMPRESSED_NONE, + index.as_u32(), + Ordering::Relaxed, + Ordering::Relaxed, + ) { + Ok(_) => Ok(()), + Err(v) => Err(DepNodeIndex::from_u32(v)), + } + } else { + let v = value.load(Ordering::Relaxed); + if v == COMPRESSED_NONE { + value.store(index.as_u32(), Ordering::Relaxed); + Ok(()) + } else { + Err(DepNodeIndex::from_u32(v)) + } + } + } + #[inline] pub(super) fn get(&self, index: SerializedDepNodeIndex) -> Option { match self.values[index].load(Ordering::Acquire) { diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 3a80835afad5..89d1db878095 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -12,6 +12,7 @@ pub(crate) use graph::DepGraphData; pub use graph::{DepGraph, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result}; pub use query::DepGraphQuery; use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_data_structures::sync::DynSync; use rustc_session::Session; pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; use tracing::instrument; @@ -89,7 +90,7 @@ pub trait DepContext: Copy { } } -pub trait Deps { +pub trait Deps: DynSync { /// Execute the operation with provided dependencies. fn with_deps(deps: TaskDepsRef<'_>, op: OP) -> R where diff --git a/compiler/rustc_query_system/src/dep_graph/query.rs b/compiler/rustc_query_system/src/dep_graph/query.rs index 624f4e4578ed..724a01327aba 100644 --- a/compiler/rustc_query_system/src/dep_graph/query.rs +++ b/compiler/rustc_query_system/src/dep_graph/query.rs @@ -1,11 +1,11 @@ use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::graph::implementation::{Direction, Graph, INCOMING, NodeIndex}; +use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, LinkedGraph, NodeIndex}; use rustc_index::IndexVec; use super::{DepNode, DepNodeIndex}; pub struct DepGraphQuery { - pub graph: Graph, + pub graph: LinkedGraph, pub indices: FxHashMap, pub dep_index_to_index: IndexVec>, } @@ -15,7 +15,7 @@ impl DepGraphQuery { let node_count = prev_node_count + prev_node_count / 4; let edge_count = 6 * node_count; - let graph = Graph::with_capacity(node_count, edge_count); + let graph = LinkedGraph::with_capacity(node_count, edge_count); let indices = FxHashMap::default(); let dep_index_to_index = IndexVec::new(); diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index d2bcde143835..f1b609a3ca90 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -12,7 +12,7 @@ //! node and edge count are stored at the end of the file, all the arrays can be //! pre-allocated with the right length. //! -//! The encoding of the de-pgraph is generally designed around the fact that fixed-size +//! The encoding of the dep-graph is generally designed around the fact that fixed-size //! reads of encoded data are generally faster than variable-sized reads. Ergo we adopt //! essentially the same varint encoding scheme used in the rmeta format; the edge lists //! for each node on the graph store a 2-bit integer which is the number of bytes per edge @@ -34,24 +34,32 @@ //! [`DepKind`], number of edges, and bytes per edge are all bit-packed together, if they fit. //! If the number of edges in this node does not fit in the bits available in the header, we //! store it directly after the header with leb128. +//! +//! Dep-graph indices are bulk allocated to threads inside `LocalEncoderState`. Having threads +//! own these indices helps avoid races when they are conditionally used when marking nodes green. +//! It also reduces congestion on the shared index count. -use std::iter; +use std::cell::RefCell; +use std::cmp::max; use std::marker::PhantomData; use std::sync::Arc; +use std::sync::atomic::Ordering; +use std::{iter, mem, u64}; use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::outline; use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_data_structures::sync::Lock; +use rustc_data_structures::sync::{AtomicU64, Lock, WorkerLocal, broadcast}; use rustc_data_structures::unhash::UnhashMap; -use rustc_index::{Idx, IndexVec}; +use rustc_index::IndexVec; use rustc_serialize::opaque::mem_encoder::MemEncoder; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use rustc_session::Session; use tracing::{debug, instrument}; -use super::graph::{DepNodeColor, DepNodeColorMap}; +use super::graph::{CurrentDepGraph, DepNodeColor, DepNodeColorMap}; use super::query::DepGraphQuery; use super::{DepKind, DepNode, DepNodeIndex, Deps}; use crate::dep_graph::edges::EdgesVec; @@ -76,6 +84,9 @@ const DEP_NODE_PAD: usize = DEP_NODE_SIZE - 1; const DEP_NODE_WIDTH_BITS: usize = DEP_NODE_SIZE / 2; /// Data for use when recompiling the **current crate**. +/// +/// There may be unused indices with DEP_KIND_NULL in this graph due to batch allocation of +/// indices to threads. #[derive(Debug, Default)] pub struct SerializedDepGraph { /// The set of all DepNodes in the graph @@ -184,26 +195,30 @@ impl SerializedDepGraph { pub fn decode(d: &mut MemDecoder<'_>, deps: &D) -> Arc { // The last 16 bytes are the node count and edge count. debug!("position: {:?}", d.position()); - let (node_count, edge_count) = - d.with_position(d.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { + + // `node_max` is the number of indices including empty nodes while `node_count` + // is the number of actually encoded nodes. + let (node_max, node_count, edge_count) = + d.with_position(d.len() - 3 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { debug!("position: {:?}", d.position()); + let node_max = IntEncodedWithFixedSize::decode(d).0 as usize; let node_count = IntEncodedWithFixedSize::decode(d).0 as usize; let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize; - (node_count, edge_count) + (node_max, node_count, edge_count) }); debug!("position: {:?}", d.position()); debug!(?node_count, ?edge_count); - let graph_bytes = d.len() - (2 * IntEncodedWithFixedSize::ENCODED_SIZE) - d.position(); + let graph_bytes = d.len() - (3 * IntEncodedWithFixedSize::ENCODED_SIZE) - d.position(); let mut nodes = IndexVec::from_elem_n( DepNode { kind: D::DEP_KIND_NULL, hash: PackedFingerprint::from(Fingerprint::ZERO) }, - node_count, + node_max, ); - let mut fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO, node_count); + let mut fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO, node_max); let mut edge_list_indices = - IndexVec::from_elem_n(EdgeHeader { repr: 0, num_edges: 0 }, node_count); + IndexVec::from_elem_n(EdgeHeader { repr: 0, num_edges: 0 }, node_max); // This estimation assumes that all of the encoded bytes are for the edge lists or for the // fixed-size node headers. But that's not necessarily true; if any edge list has a length @@ -217,7 +232,7 @@ impl SerializedDepGraph { let mut edge_list_data = Vec::with_capacity(graph_bytes - node_count * size_of::>()); - for _index in 0..node_count { + for _ in 0..node_count { // Decode the header for this edge; the header packs together as many of the fixed-size // fields as possible to limit the number of times we update decoder state. let node_header = @@ -263,8 +278,8 @@ impl SerializedDepGraph { for (idx, node) in nodes.iter_enumerated() { if index[node.kind.as_usize()].insert(node.hash, idx).is_some() { - // Side effect nodes can have duplicates - if node.kind != D::DEP_KIND_SIDE_EFFECT { + // Empty nodes and side effect nodes can have duplicates + if node.kind != D::DEP_KIND_NULL && node.kind != D::DEP_KIND_SIDE_EFFECT { let name = deps.name(node.kind); panic!( "Error: A dep graph node ({name}) does not have an unique index. \ @@ -508,17 +523,32 @@ struct Stat { edge_counter: u64, } -struct EncoderState { - previous: Arc, - encoder: FileEncoder, - total_node_count: usize, - total_edge_count: usize, - stats: Option>, - - mem_encoder: MemEncoder, +struct LocalEncoderState { + next_node_index: u32, + remaining_node_index: u32, + encoder: MemEncoder, + node_count: usize, + edge_count: usize, /// Stores the number of times we've encoded each dep kind. kind_stats: Vec, +} + +struct LocalEncoderResult { + node_max: u32, + node_count: usize, + edge_count: usize, + + /// Stores the number of times we've encoded each dep kind. + kind_stats: Vec, +} + +struct EncoderState { + next_node_index: AtomicU64, + previous: Arc, + file: Lock>, + local: WorkerLocal>, + stats: Option>>, marker: PhantomData, } @@ -526,34 +556,63 @@ impl EncoderState { fn new(encoder: FileEncoder, record_stats: bool, previous: Arc) -> Self { Self { previous, - encoder, - total_edge_count: 0, - total_node_count: 0, - stats: record_stats.then(FxHashMap::default), - mem_encoder: MemEncoder::new(), - kind_stats: iter::repeat(0).take(D::DEP_KIND_MAX as usize + 1).collect(), + next_node_index: AtomicU64::new(0), + stats: record_stats.then(|| Lock::new(FxHashMap::default())), + file: Lock::new(Some(encoder)), + local: WorkerLocal::new(|_| { + RefCell::new(LocalEncoderState { + next_node_index: 0, + remaining_node_index: 0, + edge_count: 0, + node_count: 0, + encoder: MemEncoder::new(), + kind_stats: iter::repeat(0).take(D::DEP_KIND_MAX as usize + 1).collect(), + }) + }), marker: PhantomData, } } #[inline] - fn alloc_index(&mut self) -> DepNodeIndex { - let index = DepNodeIndex::new(self.total_node_count); - self.total_node_count += 1; - index + fn next_index(&self, local: &mut LocalEncoderState) -> DepNodeIndex { + if local.remaining_node_index == 0 { + const COUNT: u32 = 256; + + // We assume that there won't be enough active threads to overflow `u64` from `u32::MAX` here. + // This can exceed u32::MAX by at most `N` * `COUNT` where `N` is the thread pool count since + // `try_into().unwrap()` will make threads panic when `self.next_node_index` exceeds u32::MAX. + local.next_node_index = + self.next_node_index.fetch_add(COUNT as u64, Ordering::Relaxed).try_into().unwrap(); + + // Check that we'll stay within `u32` + local.next_node_index.checked_add(COUNT).unwrap(); + + local.remaining_node_index = COUNT; + } + + DepNodeIndex::from_u32(local.next_node_index) + } + + /// Marks the index previously returned by `next_index` as used. + #[inline] + fn bump_index(&self, local: &mut LocalEncoderState) { + local.remaining_node_index -= 1; + local.next_node_index += 1; + local.node_count += 1; } #[inline] fn record( - &mut self, + &self, node: DepNode, index: DepNodeIndex, edge_count: usize, - edges: impl FnOnce(&mut Self) -> Vec, + edges: impl FnOnce(&Self) -> Vec, record_graph: &Option>, - ) -> DepNodeIndex { - self.kind_stats[node.kind.as_usize()] += 1; - self.total_edge_count += edge_count; + local: &mut LocalEncoderState, + ) { + local.kind_stats[node.kind.as_usize()] += 1; + local.edge_count += edge_count; if let Some(record_graph) = &record_graph { // Call `edges` before the outlined code to allow the closure to be optimized out. @@ -568,40 +627,47 @@ impl EncoderState { }); } - if let Some(stats) = &mut self.stats { + if let Some(stats) = &self.stats { let kind = node.kind; // Outline the stats code as it's typically disabled and cold. outline(move || { + let mut stats = stats.lock(); let stat = stats.entry(kind).or_insert(Stat { kind, node_counter: 0, edge_counter: 0 }); stat.node_counter += 1; stat.edge_counter += edge_count as u64; }); } - - index } #[inline] - fn flush_mem_encoder(&mut self) { - let data = &mut self.mem_encoder.data; + fn flush_mem_encoder(&self, local: &mut LocalEncoderState) { + let data = &mut local.encoder.data; if data.len() > 64 * 1024 { - self.encoder.emit_raw_bytes(&data[..]); + self.file.lock().as_mut().unwrap().emit_raw_bytes(&data[..]); data.clear(); } } /// Encodes a node to the current graph. fn encode_node( - &mut self, + &self, + index: DepNodeIndex, node: &NodeInfo, record_graph: &Option>, - ) -> DepNodeIndex { - let index = self.alloc_index(); - node.encode::(&mut self.mem_encoder, index); - self.flush_mem_encoder(); - self.record(node.node, index, node.edges.len(), |_| node.edges[..].to_vec(), record_graph) + local: &mut LocalEncoderState, + ) { + node.encode::(&mut local.encoder, index); + self.flush_mem_encoder(&mut *local); + self.record( + node.node, + index, + node.edges.len(), + |_| node.edges[..].to_vec(), + record_graph, + &mut *local, + ); } /// Encodes a node that was promoted from the previous graph. It reads the information directly from @@ -612,16 +678,17 @@ impl EncoderState { /// It expects all edges to already have a new dep node index assigned. #[inline] fn encode_promoted_node( - &mut self, + &self, + index: DepNodeIndex, prev_index: SerializedDepNodeIndex, record_graph: &Option>, colors: &DepNodeColorMap, - ) -> DepNodeIndex { - let index = self.alloc_index(); + local: &mut LocalEncoderState, + ) { let node = self.previous.index_to_node(prev_index); let fingerprint = self.previous.fingerprint_by_index(prev_index); let edge_count = NodeInfo::encode_promoted::( - &mut self.mem_encoder, + &mut local.encoder, node, index, fingerprint, @@ -629,7 +696,7 @@ impl EncoderState { colors, &self.previous, ); - self.flush_mem_encoder(); + self.flush_mem_encoder(&mut *local); self.record( node, index, @@ -641,38 +708,60 @@ impl EncoderState { .collect() }, record_graph, + &mut *local, ); - index } - fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { - let Self { - mut encoder, - mem_encoder, - total_node_count, - total_edge_count, - stats: _, - kind_stats, - marker: _, - previous, - } = self; + fn finish(&self, profiler: &SelfProfilerRef, current: &CurrentDepGraph) -> FileEncodeResult { + // Prevent more indices from being allocated. + self.next_node_index.store(u32::MAX as u64 + 1, Ordering::SeqCst); - encoder.emit_raw_bytes(&mem_encoder.data); + let results = broadcast(|_| { + let mut local = self.local.borrow_mut(); - let node_count = total_node_count.try_into().unwrap(); - let edge_count = total_edge_count.try_into().unwrap(); + // Prevent more indices from being allocated on this thread. + local.remaining_node_index = 0; + + let data = mem::replace(&mut local.encoder.data, Vec::new()); + self.file.lock().as_mut().unwrap().emit_raw_bytes(&data); + + LocalEncoderResult { + kind_stats: local.kind_stats.clone(), + node_max: local.next_node_index, + node_count: local.node_count, + edge_count: local.edge_count, + } + }); + + let mut encoder = self.file.lock().take().unwrap(); + + let mut kind_stats: Vec = iter::repeat(0).take(D::DEP_KIND_MAX as usize + 1).collect(); + + let mut node_max = 0; + let mut node_count = 0; + let mut edge_count = 0; + + for result in results { + node_max = max(node_max, result.node_max); + node_count += result.node_count; + edge_count += result.edge_count; + for (i, stat) in result.kind_stats.iter().enumerate() { + kind_stats[i] += stat; + } + } // Encode the number of each dep kind encountered for count in kind_stats.iter() { count.encode(&mut encoder); } - previous.session_count.checked_add(1).unwrap().encode(&mut encoder); + self.previous.session_count.checked_add(1).unwrap().encode(&mut encoder); - debug!(?node_count, ?edge_count); + debug!(?node_max, ?node_count, ?edge_count); debug!("position: {:?}", encoder.position()); - IntEncodedWithFixedSize(node_count).encode(&mut encoder); - IntEncodedWithFixedSize(edge_count).encode(&mut encoder); + IntEncodedWithFixedSize(node_max.try_into().unwrap()).encode(&mut encoder); + IntEncodedWithFixedSize(node_count.try_into().unwrap()).encode(&mut encoder); + IntEncodedWithFixedSize(edge_count.try_into().unwrap()).encode(&mut encoder); debug!("position: {:?}", encoder.position()); // Drop the encoder so that nothing is written after the counts. let result = encoder.finish(); @@ -681,44 +770,20 @@ impl EncoderState { // don't need a dependency on rustc_incremental just for that. profiler.artifact_size("dep_graph", "dep-graph.bin", position as u64); } + + self.print_incremental_info(current, node_count, edge_count); + result } -} -pub(crate) struct GraphEncoder { - profiler: SelfProfilerRef, - status: Lock>>, - record_graph: Option>, -} - -impl GraphEncoder { - pub(crate) fn new( - encoder: FileEncoder, - prev_node_count: usize, - record_graph: bool, - record_stats: bool, - profiler: &SelfProfilerRef, - previous: Arc, - ) -> Self { - let record_graph = record_graph.then(|| Lock::new(DepGraphQuery::new(prev_node_count))); - let status = Lock::new(Some(EncoderState::new(encoder, record_stats, previous))); - GraphEncoder { status, record_graph, profiler: profiler.clone() } - } - - pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery)) { - if let Some(record_graph) = &self.record_graph { - f(&record_graph.lock()) - } - } - - pub(crate) fn print_incremental_info( + fn print_incremental_info( &self, - total_read_count: u64, - total_duplicate_read_count: u64, + current: &CurrentDepGraph, + total_node_count: usize, + total_edge_count: usize, ) { - let mut status = self.status.lock(); - let status = status.as_mut().unwrap(); - if let Some(record_stats) = &status.stats { + if let Some(record_stats) = &self.stats { + let record_stats = record_stats.lock(); let mut stats: Vec<_> = record_stats.values().collect(); stats.sort_by_key(|s| -(s.node_counter as i64)); @@ -730,10 +795,13 @@ impl GraphEncoder { eprintln!("[incremental] DepGraph Statistics"); eprintln!("{SEPARATOR}"); eprintln!("[incremental]"); - eprintln!("[incremental] Total Node Count: {}", status.total_node_count); - eprintln!("[incremental] Total Edge Count: {}", status.total_edge_count); + eprintln!("[incremental] Total Node Count: {}", total_node_count); + eprintln!("[incremental] Total Edge Count: {}", total_edge_count); if cfg!(debug_assertions) { + let total_read_count = current.total_read_count.load(Ordering::Relaxed); + let total_duplicate_read_count = + current.total_duplicate_read_count.load(Ordering::Relaxed); eprintln!("[incremental] Total Edge Reads: {total_read_count}"); eprintln!("[incremental] Total Duplicate Edge Reads: {total_duplicate_read_count}"); } @@ -747,7 +815,7 @@ impl GraphEncoder { for stat in stats { let node_kind_ratio = - (100.0 * (stat.node_counter as f64)) / (status.total_node_count as f64); + (100.0 * (stat.node_counter as f64)) / (total_node_count as f64); let node_kind_avg_edges = (stat.edge_counter as f64) / (stat.node_counter as f64); eprintln!( @@ -763,6 +831,35 @@ impl GraphEncoder { eprintln!("[incremental]"); } } +} + +pub(crate) struct GraphEncoder { + profiler: SelfProfilerRef, + status: EncoderState, + record_graph: Option>, +} + +impl GraphEncoder { + pub(crate) fn new( + sess: &Session, + encoder: FileEncoder, + prev_node_count: usize, + previous: Arc, + ) -> Self { + let record_graph = sess + .opts + .unstable_opts + .query_dep_graph + .then(|| Lock::new(DepGraphQuery::new(prev_node_count))); + let status = EncoderState::new(encoder, sess.opts.unstable_opts.incremental_info, previous); + GraphEncoder { status, record_graph, profiler: sess.prof.clone() } + } + + pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery)) { + if let Some(record_graph) = &self.record_graph { + f(&record_graph.lock()) + } + } /// Encodes a node that does not exists in the previous graph. pub(crate) fn send_new( @@ -773,7 +870,11 @@ impl GraphEncoder { ) -> DepNodeIndex { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph"); let node = NodeInfo { node, fingerprint, edges }; - self.status.lock().as_mut().unwrap().encode_node(&node, &self.record_graph) + let mut local = self.status.local.borrow_mut(); + let index = self.status.next_index(&mut *local); + self.status.bump_index(&mut *local); + self.status.encode_node(index, &node, &self.record_graph, &mut *local); + index } /// Encodes a node that exists in the previous graph, but was re-executed. @@ -791,23 +892,24 @@ impl GraphEncoder { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph"); let node = NodeInfo { node, fingerprint, edges }; - let mut status = self.status.lock(); - let status = status.as_mut().unwrap(); + let mut local = self.status.local.borrow_mut(); - // Check colors inside the lock to avoid racing when `send_promoted` is called concurrently - // on the same index. - match colors.get(prev_index) { - None => { - let dep_node_index = status.encode_node(&node, &self.record_graph); - colors.insert( - prev_index, - if is_green { DepNodeColor::Green(dep_node_index) } else { DepNodeColor::Red }, - ); - dep_node_index + let index = self.status.next_index(&mut *local); + + if is_green { + // Use `try_mark_green` to avoid racing when `send_promoted` is called concurrently + // on the same index. + match colors.try_mark_green(prev_index, index) { + Ok(()) => (), + Err(dep_node_index) => return dep_node_index, } - Some(DepNodeColor::Green(dep_node_index)) => dep_node_index, - Some(DepNodeColor::Red) => panic!(), + } else { + colors.insert(prev_index, DepNodeColor::Red); } + + self.status.bump_index(&mut *local); + self.status.encode_node(index, &node, &self.record_graph, &mut *local); + index } /// Encodes a node that was promoted from the previous graph. It reads the information directly from @@ -822,26 +924,30 @@ impl GraphEncoder { ) -> DepNodeIndex { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph"); - let mut status = self.status.lock(); - let status = status.as_mut().unwrap(); + let mut local = self.status.local.borrow_mut(); + let index = self.status.next_index(&mut *local); - // Check colors inside the lock to avoid racing when `send_promoted` or `send_and_color` + // Use `try_mark_green` to avoid racing when `send_promoted` or `send_and_color` // is called concurrently on the same index. - match colors.get(prev_index) { - None => { - let dep_node_index = - status.encode_promoted_node(prev_index, &self.record_graph, colors); - colors.insert(prev_index, DepNodeColor::Green(dep_node_index)); - dep_node_index + match colors.try_mark_green(prev_index, index) { + Ok(()) => { + self.status.bump_index(&mut *local); + self.status.encode_promoted_node( + index, + prev_index, + &self.record_graph, + colors, + &mut *local, + ); + index } - Some(DepNodeColor::Green(dep_node_index)) => dep_node_index, - Some(DepNodeColor::Red) => panic!(), + Err(dep_node_index) => dep_node_index, } } - pub(crate) fn finish(&self) -> FileEncodeResult { + pub(crate) fn finish(&self, current: &CurrentDepGraph) -> FileEncodeResult { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph_finish"); - self.status.lock().take().unwrap().finish(&self.profiler) + self.status.finish(&self.profiler, current) } } diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 558a01713dc7..38cdfa72a14d 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -218,10 +218,6 @@ resolve_invalid_asm_sym = .label = is a local variable .help = `sym` operands must refer to either a function or a static -resolve_is_not_directly_importable = - `{$target}` is not directly importable - .label = cannot be imported directly - resolve_is_private = {$ident_descr} `{$ident}` is private .label = private {$ident_descr} @@ -231,9 +227,6 @@ resolve_item_was_behind_feature = resolve_item_was_cfg_out = the item is gated here -resolve_items_in_traits_are_not_importable = - items in traits are not importable - resolve_label_with_similar_name_reachable = a label with a similar name is reachable diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index cb328022c76d..3460c53782f3 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -549,7 +549,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { source = module_path.pop().unwrap(); if rename.is_none() { // Keep the span of `self`, but the name of `foo` - ident = Ident { name: source.ident.name, span: self_span }; + ident = Ident::new(source.ident.name, self_span); } } } else { @@ -597,7 +597,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { if let Some(crate_name) = crate_name { // `crate_name` should not be interpreted as relative. module_path.push(Segment::from_ident_and_id( - Ident { name: kw::PathRoot, span: source.ident.span }, + Ident::new(kw::PathRoot, source.ident.span), self.r.next_node_id(), )); source.ident.name = crate_name; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 363a75911ad4..74daad083946 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1181,11 +1181,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } { let in_module_is_extern = !in_module.def_id().is_local(); in_module.for_each_child(self, |this, ident, ns, name_binding| { - // avoid non-importable candidates - if !name_binding.is_importable() - // FIXME(import_trait_associated_functions): remove this when `import_trait_associated_functions` is stable - || name_binding.is_assoc_const_or_fn() - && !this.tcx.features().import_trait_associated_functions() + // Avoid non-importable candidates. + if name_binding.is_assoc_item() + && !this.tcx.features().import_trait_associated_functions() { return; } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index e26b300f13ef..7fe74378b674 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -781,22 +781,6 @@ pub(crate) struct CannotGlobImportAllCrates { pub(crate) span: Span, } -#[derive(Diagnostic)] -#[diag(resolve_items_in_traits_are_not_importable)] -pub(crate) struct ItemsInTraitsAreNotImportable { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(resolve_is_not_directly_importable, code = E0253)] -pub(crate) struct IsNotDirectlyImportable { - #[primary_span] - #[label] - pub(crate) span: Span, - pub(crate) target: Ident, -} - #[derive(Subdiagnostic)] #[suggestion( resolve_unexpected_res_change_ty_to_const_param_sugg, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 762e08b2be5f..816efd0d5fa2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -30,8 +30,7 @@ use crate::diagnostics::{DiagMode, Suggestion, import_candidates}; use crate::errors::{ CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate, CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates, - ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable, - ItemsInTraitsAreNotImportable, + ConsiderAddingMacroExport, ConsiderMarkingAsPub, }; use crate::{ AmbiguityError, AmbiguityKind, BindingKey, Finalize, ImportSuggestion, Module, @@ -835,11 +834,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let parent = import.parent_scope.module; match source_bindings[ns].get() { - Err(Undetermined) => indeterminate_count += 1, - // Don't update the resolution, because it was never added. - Err(Determined) if target.name == kw::Underscore => {} - Ok(binding) if binding.is_importable() => { - if binding.is_assoc_const_or_fn() + Ok(binding) => { + if binding.is_assoc_item() && !this.tcx.features().import_trait_associated_functions() { feature_err( @@ -850,21 +846,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) .emit(); } + let imported_binding = this.import(binding, import); target_bindings[ns].set(Some(imported_binding)); this.define(parent, target, ns, imported_binding); } - source_binding @ (Ok(..) | Err(Determined)) => { - if source_binding.is_ok() { - this.dcx() - .create_err(IsNotDirectlyImportable { span: import.span, target }) - .emit(); + Err(Determined) => { + // Don't update the resolution for underscores, because it was never added. + if target.name != kw::Underscore { + let key = BindingKey::new(target, ns); + this.update_resolution(parent, key, false, |_, resolution| { + resolution.single_imports.swap_remove(&import); + }); } - let key = BindingKey::new(target, ns); - this.update_resolution(parent, key, false, |_, resolution| { - resolution.single_imports.swap_remove(&import); - }); } + Err(Undetermined) => indeterminate_count += 1, } } }); @@ -1428,10 +1424,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return; }; - if module.is_trait() { - self.dcx().emit_err(ItemsInTraitsAreNotImportable { span: import.span }); - return; - } else if module == import.parent_scope.module { + if module.is_trait() && !self.tcx.features().import_trait_associated_functions() { + feature_err( + self.tcx.sess, + sym::import_trait_associated_functions, + import.span, + "`use` associated items of traits is unstable", + ) + .emit(); + } + + if module == import.parent_scope.module { return; } else if is_prelude { self.prelude = Some(module); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index d2da3ac7d86f..4c47e9ed6992 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -56,6 +56,7 @@ use rustc_hir::def::{ self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS, }; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; +use rustc_hir::definitions::DisambiguatorState; use rustc_hir::{PrimTy, TraitCandidate}; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; @@ -949,14 +950,8 @@ impl<'ra> NameBindingData<'ra> { } } - fn is_importable(&self) -> bool { - !matches!(self.res(), Res::Def(DefKind::AssocTy, _)) - } - - // FIXME(import_trait_associated_functions): associate `const` or `fn` are not importable unless - // the feature `import_trait_associated_functions` is enable - fn is_assoc_const_or_fn(&self) -> bool { - matches!(self.res(), Res::Def(DefKind::AssocConst | DefKind::AssocFn, _)) + fn is_assoc_item(&self) -> bool { + matches!(self.res(), Res::Def(DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, _)) } fn macro_kind(&self) -> Option { @@ -1104,7 +1099,7 @@ pub struct Resolver<'ra, 'tcx> { underscore_disambiguator: u32, /// Maps glob imports to the names of items actually imported. - glob_map: FxHashMap>, + glob_map: FxIndexMap>, glob_error: Option, visibilities_for_hashing: Vec<(LocalDefId, ty::Visibility)>, used_imports: FxHashSet, @@ -1185,6 +1180,8 @@ pub struct Resolver<'ra, 'tcx> { node_id_to_def_id: NodeMap>, + disambiguator: DisambiguatorState, + /// Indices of unnamed struct or variant fields with unresolved attributes. placeholder_field_indices: FxHashMap, /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId` @@ -1348,7 +1345,7 @@ impl<'tcx> Resolver<'_, 'tcx> { ); // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()` - let feed = self.tcx.create_def(parent, name, def_kind); + let feed = self.tcx.create_def(parent, name, def_kind, None, &mut self.disambiguator); let def_id = feed.def_id(); // Create the definition. @@ -1562,6 +1559,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lint_buffer: LintBuffer::default(), next_node_id: CRATE_NODE_ID, node_id_to_def_id, + disambiguator: DisambiguatorState::new(), placeholder_field_indices: Default::default(), invocation_parents, legacy_const_generic_args: Default::default(), @@ -1691,6 +1689,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .into_items() .map(|(k, f)| (k, f.key())) .collect(), + disambiguator: self.disambiguator, trait_map: self.trait_map, lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), @@ -2158,13 +2157,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ns: Namespace, parent_scope: ParentScope<'ra>, ) -> Option { - let mut segments = - Vec::from_iter(path_str.split("::").map(Ident::from_str).map(Segment::from_ident)); - if let Some(segment) = segments.first_mut() { - if segment.ident.name == kw::Empty { - segment.ident.name = kw::PathRoot; - } - } + let segments: Result, ()> = path_str + .split("::") + .enumerate() + .map(|(i, s)| { + let sym = if s.is_empty() { + if i == 0 { + // For a path like `::a::b`, use `kw::PathRoot` as the leading segment. + kw::PathRoot + } else { + return Err(()); // occurs in cases like `String::` + } + } else { + Symbol::intern(s) + }; + Ok(Segment::from_ident(Ident::with_dummy_span(sym))) + }) + .collect(); + let Ok(segments) = segments else { return None }; match self.maybe_resolve_path(&segments, Some(ns), &parent_scope, None) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()), diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 4b1b3903e403..47831f2f4180 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -717,12 +717,14 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { hir::definitions::DefPathData::AnonConst => "k", hir::definitions::DefPathData::OpaqueTy => "i", hir::definitions::DefPathData::SyntheticCoroutineBody => "s", + hir::definitions::DefPathData::NestedStatic => "n", hir::definitions::DefPathData::CrateRoot | hir::definitions::DefPathData::Use | hir::definitions::DefPathData::GlobalAsm | hir::definitions::DefPathData::MacroNs(..) + | hir::definitions::DefPathData::OpaqueLifetime(..) | hir::definitions::DefPathData::LifetimeNs(..) - | hir::definitions::DefPathData::AnonAssocTy => { + | hir::definitions::DefPathData::AnonAssocTy(..) => { bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data); } }); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index e2d36f6a4e2f..60e1b465ba96 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -24,7 +24,8 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION}; use rustc_span::source_map::FilePathMapping; use rustc_span::{ - FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm, Symbol, sym, + FileName, FileNameDisplayPreference, FileNameEmbeddablePreference, RealFileName, + SourceFileHashAlgorithm, Symbol, sym, }; use rustc_target::spec::{ FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTuple, @@ -1169,6 +1170,10 @@ impl OutputFilenames { .unwrap_or_else(|| OutFileName::Real(self.output_path(flavor))) } + pub fn interface_path(&self) -> PathBuf { + self.out_directory.join(format!("lib{}.rs", self.crate_stem)) + } + /// Gets the output path where a compilation artifact of the given type /// should be placed on disk. fn output_path(&self, flavor: OutputType) -> PathBuf { @@ -1316,6 +1321,11 @@ fn file_path_mapping( } else { FileNameDisplayPreference::Local }, + if unstable_opts.remap_path_scope.is_all() { + FileNameEmbeddablePreference::RemappedOnly + } else { + FileNameEmbeddablePreference::LocalAndRemapped + }, ) } @@ -1452,13 +1462,17 @@ pub enum CrateType { Staticlib, Cdylib, ProcMacro, + Sdylib, } impl CrateType { pub fn has_metadata(self) -> bool { match self { CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true, - CrateType::Executable | CrateType::Cdylib | CrateType::Staticlib => false, + CrateType::Executable + | CrateType::Cdylib + | CrateType::Staticlib + | CrateType::Sdylib => false, } } } @@ -2818,6 +2832,7 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result CrateType::Cdylib, "bin" => CrateType::Executable, "proc-macro" => CrateType::ProcMacro, + "sdylib" => CrateType::Sdylib, _ => { return Err(format!( "unknown crate type: `{part}`, expected one of: \ @@ -2915,6 +2930,7 @@ impl fmt::Display for CrateType { CrateType::Staticlib => "staticlib".fmt(f), CrateType::Cdylib => "cdylib".fmt(f), CrateType::ProcMacro => "proc-macro".fmt(f), + CrateType::Sdylib => "sdylib".fmt(f), } } } diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index c8a5c22ad123..4cfc745dec28 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -27,6 +27,7 @@ pub struct CrateSource { pub dylib: Option<(PathBuf, PathKind)>, pub rlib: Option<(PathBuf, PathKind)>, pub rmeta: Option<(PathBuf, PathKind)>, + pub sdylib_interface: Option<(PathBuf, PathKind)>, } impl CrateSource { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 5f4695fb1841..b95ebfbe89f2 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2113,6 +2113,8 @@ options! { "emit noalias metadata for box (default: yes)"), branch_protection: Option = (None, parse_branch_protection, [TRACKED], "set options for branch target identification and pointer authentication on AArch64"), + build_sdylib_interface: bool = (false, parse_bool, [UNTRACKED], + "whether the stable interface is being built"), cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED], "instrument control-flow architecture protection"), check_cfg_all_expected: bool = (false, parse_bool, [UNTRACKED], @@ -2208,7 +2210,7 @@ options! { fewer_names: Option = (None, parse_opt_bool, [TRACKED], "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \ (default: no)"), - fixed_x18: bool = (false, parse_bool, [TRACKED], + fixed_x18: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER], "make the x18 register reserved on AArch64 (default: no)"), flatten_format_args: bool = (true, parse_bool, [TRACKED], "flatten nested format_args!() and literals into a simplified format_args!() call \ diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 46dae9144cd4..cba70b5bd5d1 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -98,7 +98,7 @@ pub fn filename_for_input( CrateType::Rlib => { OutFileName::Real(outputs.out_directory.join(&format!("lib{libname}.rlib"))) } - CrateType::Cdylib | CrateType::ProcMacro | CrateType::Dylib => { + CrateType::Cdylib | CrateType::ProcMacro | CrateType::Dylib | CrateType::Sdylib => { let (prefix, suffix) = (&sess.target.dll_prefix, &sess.target.dll_suffix); OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}"))) } @@ -167,6 +167,7 @@ pub const CRATE_TYPES: &[(Symbol, CrateType)] = &[ (sym::staticlib, CrateType::Staticlib), (sym::proc_dash_macro, CrateType::ProcMacro), (sym::bin, CrateType::Executable), + (sym::sdylib, CrateType::Sdylib), ]; pub fn categorize_crate_type(s: Symbol) -> Option { @@ -187,6 +188,11 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec BodyBuilder<'tcx> { pub(crate) fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self { let instance = match instance.def { // To get the fallback body of an intrinsic, we need to convert it to an item. - ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args), + ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new_raw(def_id, instance.args), _ => instance, }; BodyBuilder { tcx, instance } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index ab0a802dc7f7..b621920d62ba 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -41,6 +41,7 @@ use tracing::{debug, trace}; use crate::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, StableCrateId}; use crate::edition::Edition; +use crate::source_map::SourceMap; use crate::symbol::{Symbol, kw, sym}; use crate::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, with_session_globals}; @@ -907,6 +908,30 @@ impl SyntaxContext { pub fn edition(self) -> Edition { HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition) } + + /// Returns whether this context originates in a foreign crate's external macro. + /// + /// This is used to test whether a lint should not even begin to figure out whether it should + /// be reported on the current node. + pub fn in_external_macro(self, sm: &SourceMap) -> bool { + let expn_data = self.outer_expn_data(); + match expn_data.kind { + ExpnKind::Root + | ExpnKind::Desugaring( + DesugaringKind::ForLoop + | DesugaringKind::WhileLoop + | DesugaringKind::OpaqueTy + | DesugaringKind::Async + | DesugaringKind::Await, + ) => false, + ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" + ExpnKind::Macro(MacroKind::Bang, _) => { + // Dummy span for the `def_site` means it's an external macro. + expn_data.def_site.is_dummy() || sm.is_imported(expn_data.def_site) + } + ExpnKind::Macro { .. } => true, // definitely a plugin + } + } } impl fmt::Debug for SyntaxContext { diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 9722031f209b..61c96e67c17f 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -224,7 +224,7 @@ pub fn with_metavar_spans(f: impl FnOnce(&MetavarSpansMap) -> R) -> R { // FIXME: We should use this enum or something like it to get rid of the // use of magic `/rust/1.x/...` paths across the board. -#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable)] +#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable)] pub enum RealFileName { LocalPath(PathBuf), /// For remapped paths (namely paths into libstd that have been mapped @@ -250,28 +250,6 @@ impl Hash for RealFileName { } } -// This is functionally identical to #[derive(Encodable)], with the exception of -// an added assert statement -impl Encodable for RealFileName { - fn encode(&self, encoder: &mut S) { - match *self { - RealFileName::LocalPath(ref local_path) => { - encoder.emit_u8(0); - local_path.encode(encoder); - } - - RealFileName::Remapped { ref local_path, ref virtual_name } => { - encoder.emit_u8(1); - // For privacy and build reproducibility, we must not embed host-dependant path - // in artifacts if they have been remapped by --remap-path-prefix - assert!(local_path.is_none()); - local_path.encode(encoder); - virtual_name.encode(encoder); - } - } - } -} - impl RealFileName { /// Returns the path suitable for reading from the file system on the local host, /// if this information exists. @@ -368,6 +346,16 @@ impl From for FileName { } } +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub enum FileNameEmbeddablePreference { + /// If a remapped path is available, only embed the `virtual_path` and omit the `local_path`. + /// + /// Otherwise embed the local-path into the `virtual_path`. + RemappedOnly, + /// Embed the original path as well as its remapped `virtual_path` component if available. + LocalAndRemapped, +} + #[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] pub enum FileNameDisplayPreference { /// Display the path after the application of rewrite rules provided via `--remap-path-prefix`. @@ -606,28 +594,13 @@ impl Span { !self.is_dummy() && sm.is_span_accessible(self) } - /// Returns whether `span` originates in a foreign crate's external macro. + /// Returns whether this span originates in a foreign crate's external macro. /// /// This is used to test whether a lint should not even begin to figure out whether it should /// be reported on the current node. + #[inline] pub fn in_external_macro(self, sm: &SourceMap) -> bool { - let expn_data = self.ctxt().outer_expn_data(); - match expn_data.kind { - ExpnKind::Root - | ExpnKind::Desugaring( - DesugaringKind::ForLoop - | DesugaringKind::WhileLoop - | DesugaringKind::OpaqueTy - | DesugaringKind::Async - | DesugaringKind::Await, - ) => false, - ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" - ExpnKind::Macro(MacroKind::Bang, _) => { - // Dummy span for the `def_site` means it's an external macro. - expn_data.def_site.is_dummy() || sm.is_imported(expn_data.def_site) - } - ExpnKind::Macro { .. } => true, // definitely a plugin - } + self.ctxt().in_external_macro(sm) } /// Returns `true` if `span` originates in a derive-macro's expansion. diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 0273bb040f43..8a3644163caf 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -1108,18 +1108,28 @@ pub fn get_source_map() -> Option> { pub struct FilePathMapping { mapping: Vec<(PathBuf, PathBuf)>, filename_display_for_diagnostics: FileNameDisplayPreference, + filename_embeddable_preference: FileNameEmbeddablePreference, } impl FilePathMapping { pub fn empty() -> FilePathMapping { - FilePathMapping::new(Vec::new(), FileNameDisplayPreference::Local) + FilePathMapping::new( + Vec::new(), + FileNameDisplayPreference::Local, + FileNameEmbeddablePreference::RemappedOnly, + ) } pub fn new( mapping: Vec<(PathBuf, PathBuf)>, filename_display_for_diagnostics: FileNameDisplayPreference, + filename_embeddable_preference: FileNameEmbeddablePreference, ) -> FilePathMapping { - FilePathMapping { mapping, filename_display_for_diagnostics } + FilePathMapping { + mapping, + filename_display_for_diagnostics, + filename_embeddable_preference, + } } /// Applies any path prefix substitution as defined by the mapping. @@ -1217,11 +1227,13 @@ impl FilePathMapping { ) -> RealFileName { match file_path { // Anything that's already remapped we don't modify, except for erasing - // the `local_path` portion. - RealFileName::Remapped { local_path: _, virtual_name } => { + // the `local_path` portion (if desired). + RealFileName::Remapped { local_path, virtual_name } => { RealFileName::Remapped { - // We do not want any local path to be exported into metadata - local_path: None, + local_path: match self.filename_embeddable_preference { + FileNameEmbeddablePreference::RemappedOnly => None, + FileNameEmbeddablePreference::LocalAndRemapped => local_path, + }, // We use the remapped name verbatim, even if it looks like a relative // path. The assumption is that the user doesn't want us to further // process paths that have gone through remapping. @@ -1231,12 +1243,18 @@ impl FilePathMapping { RealFileName::LocalPath(unmapped_file_path) => { // If no remapping has been applied yet, try to do so - let (new_path, was_remapped) = self.map_prefix(unmapped_file_path); + let (new_path, was_remapped) = self.map_prefix(&unmapped_file_path); if was_remapped { // It was remapped, so don't modify further return RealFileName::Remapped { - local_path: None, virtual_name: new_path.into_owned(), + // But still provide the local path if desired + local_path: match self.filename_embeddable_preference { + FileNameEmbeddablePreference::RemappedOnly => None, + FileNameEmbeddablePreference::LocalAndRemapped => { + Some(unmapped_file_path) + } + }, }; } @@ -1252,17 +1270,23 @@ impl FilePathMapping { match working_directory { RealFileName::LocalPath(unmapped_working_dir_abs) => { - let file_path_abs = unmapped_working_dir_abs.join(unmapped_file_path_rel); + let unmapped_file_path_abs = + unmapped_working_dir_abs.join(unmapped_file_path_rel); // Although neither `working_directory` nor the file name were subject // to path remapping, the concatenation between the two may be. Hence // we need to do a remapping here. - let (file_path_abs, was_remapped) = self.map_prefix(file_path_abs); + let (file_path_abs, was_remapped) = + self.map_prefix(&unmapped_file_path_abs); if was_remapped { RealFileName::Remapped { - // Erase the actual path - local_path: None, virtual_name: file_path_abs.into_owned(), + local_path: match self.filename_embeddable_preference { + FileNameEmbeddablePreference::RemappedOnly => None, + FileNameEmbeddablePreference::LocalAndRemapped => { + Some(unmapped_file_path_abs) + } + }, } } else { // No kind of remapping applied to this path, so @@ -1271,15 +1295,20 @@ impl FilePathMapping { } } RealFileName::Remapped { - local_path: _, + local_path, virtual_name: remapped_working_dir_abs, } => { // If working_directory has been remapped, then we emit // Remapped variant as the expanded path won't be valid RealFileName::Remapped { - local_path: None, virtual_name: Path::new(remapped_working_dir_abs) - .join(unmapped_file_path_rel), + .join(&unmapped_file_path_rel), + local_path: match self.filename_embeddable_preference { + FileNameEmbeddablePreference::RemappedOnly => None, + FileNameEmbeddablePreference::LocalAndRemapped => local_path + .as_ref() + .map(|local_path| local_path.join(unmapped_file_path_rel)), + }, } } } @@ -1287,27 +1316,6 @@ impl FilePathMapping { } } - /// Expand a relative path to an absolute path **without** remapping taken into account. - /// - /// The resulting `RealFileName` will have its `virtual_path` portion erased if - /// possible (i.e. if there's also a remapped path). - pub fn to_local_embeddable_absolute_path( - &self, - file_path: RealFileName, - working_directory: &RealFileName, - ) -> RealFileName { - let file_path = file_path.local_path_if_available(); - if file_path.is_absolute() { - // No remapping has applied to this path and it is absolute, - // so the working directory cannot influence it either, so - // we are done. - return RealFileName::LocalPath(file_path.to_path_buf()); - } - debug_assert!(file_path.is_relative()); - let working_directory = working_directory.local_path_if_available(); - RealFileName::LocalPath(Path::new(working_directory).join(file_path)) - } - /// Attempts to (heuristically) reverse a prefix mapping. /// /// Returns [`Some`] if there is exactly one mapping where the "to" part is diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 957f55e39138..589c2a363548 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -305,6 +305,7 @@ fn path_prefix_remapping() { let mapping = &FilePathMapping::new( vec![(path("abc/def"), path("foo"))], FileNameDisplayPreference::Remapped, + FileNameEmbeddablePreference::RemappedOnly, ); assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("foo/src/main.rs")); @@ -316,6 +317,7 @@ fn path_prefix_remapping() { let mapping = &FilePathMapping::new( vec![(path("abc/def"), path("/foo"))], FileNameDisplayPreference::Remapped, + FileNameEmbeddablePreference::RemappedOnly, ); assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("/foo/src/main.rs")); @@ -327,6 +329,7 @@ fn path_prefix_remapping() { let mapping = &FilePathMapping::new( vec![(path("/abc/def"), path("foo"))], FileNameDisplayPreference::Remapped, + FileNameEmbeddablePreference::RemappedOnly, ); assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("foo/src/main.rs")); @@ -338,6 +341,7 @@ fn path_prefix_remapping() { let mapping = &FilePathMapping::new( vec![(path("/abc/def"), path("/foo"))], FileNameDisplayPreference::Remapped, + FileNameEmbeddablePreference::RemappedOnly, ); assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("/foo/src/main.rs")); @@ -351,6 +355,7 @@ fn path_prefix_remapping_expand_to_absolute() { let mapping = &FilePathMapping::new( vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))], FileNameDisplayPreference::Remapped, + FileNameEmbeddablePreference::RemappedOnly, ); let working_directory = path("/foo"); let working_directory = RealFileName::Remapped { @@ -448,6 +453,71 @@ fn path_prefix_remapping_expand_to_absolute() { ); } +#[test] +fn path_prefix_remapping_expand_to_absolute_and_local() { + // "virtual" working directory is relative path + let mapping = &FilePathMapping::new( + vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))], + FileNameDisplayPreference::Remapped, + FileNameEmbeddablePreference::LocalAndRemapped, + ); + let working_directory = path("/foo"); + let working_directory = RealFileName::Remapped { + local_path: Some(working_directory.clone()), + virtual_name: mapping.map_prefix(working_directory).0.into_owned(), + }; + + assert_eq!(working_directory.remapped_path_if_available(), path("FOO")); + + // Unmapped absolute path + assert_eq!( + mapping.to_embeddable_absolute_path( + RealFileName::LocalPath(path("/foo/src/main.rs")), + &working_directory + ), + RealFileName::Remapped { + local_path: Some(path("/foo/src/main.rs")), + virtual_name: path("FOO/src/main.rs") + } + ); + + // Unmapped absolute path with unrelated working directory + assert_eq!( + mapping.to_embeddable_absolute_path( + RealFileName::LocalPath(path("/bar/src/main.rs")), + &working_directory + ), + RealFileName::Remapped { + local_path: Some(path("/bar/src/main.rs")), + virtual_name: path("BAR/src/main.rs") + } + ); + + // Already remapped absolute path, with unrelated working directory + assert_eq!( + mapping.to_embeddable_absolute_path( + RealFileName::Remapped { + local_path: Some(path("/bar/src/main.rs")), + virtual_name: path("BAR/src/main.rs"), + }, + &working_directory + ), + RealFileName::Remapped { + local_path: Some(path("/bar/src/main.rs")), + virtual_name: path("BAR/src/main.rs") + } + ); + + // Already remapped relative path + assert_eq!( + mapping.to_embeddable_absolute_path( + RealFileName::Remapped { local_path: None, virtual_name: path("XYZ/src/main.rs") }, + &working_directory + ), + RealFileName::Remapped { local_path: None, virtual_name: path("XYZ/src/main.rs") } + ); +} + #[test] fn path_prefix_remapping_reverse() { // Ignores options without alphanumeric chars. @@ -455,6 +525,7 @@ fn path_prefix_remapping_reverse() { let mapping = &FilePathMapping::new( vec![(path("abc"), path("/")), (path("def"), path("."))], FileNameDisplayPreference::Remapped, + FileNameEmbeddablePreference::RemappedOnly, ); assert_eq!(reverse_map_prefix(mapping, "/hello.rs"), None); @@ -466,6 +537,7 @@ fn path_prefix_remapping_reverse() { let mapping = &FilePathMapping::new( vec![(path("abc"), path("/redacted")), (path("def"), path("/redacted"))], FileNameDisplayPreference::Remapped, + FileNameEmbeddablePreference::RemappedOnly, ); assert_eq!(reverse_map_prefix(mapping, "/redacted/hello.rs"), None); @@ -476,6 +548,7 @@ fn path_prefix_remapping_reverse() { let mapping = &FilePathMapping::new( vec![(path("abc"), path("/redacted")), (path("def/ghi"), path("/fake/dir"))], FileNameDisplayPreference::Remapped, + FileNameEmbeddablePreference::RemappedOnly, ); assert_eq!( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7a1fb36324bf..b6cb6113f9fc 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -459,6 +459,7 @@ symbols! { anonymous_lifetime_in_impl_trait, any, append_const_msg, + apx_target_feature, arbitrary_enum_discriminant, arbitrary_self_types, arbitrary_self_types_pointers, @@ -531,6 +532,7 @@ symbols! { autodiff, automatically_derived, avx, + avx10_target_feature, avx512_target_feature, avx512bw, avx512f, @@ -913,6 +915,7 @@ symbols! { explicit_generic_args_with_impl_trait, explicit_tail_calls, export_name, + export_stable, expr, expr_2021, expr_fragment_specifier_2024, @@ -1047,6 +1050,7 @@ symbols! { from_u16, from_usize, from_yeet, + frontmatter, fs_create_dir, fsub_algebraic, fsub_fast, @@ -1877,6 +1881,7 @@ symbols! { saturating_add, saturating_div, saturating_sub, + sdylib, search_unbox, select_unpredictable, self_in_typedefs, @@ -2094,7 +2099,6 @@ symbols! { three_way_compare, thumb2, thumb_mode: "thumb-mode", - time, tmm_reg, to_owned_method, to_string, @@ -2337,6 +2341,9 @@ pub const STDLIB_STABLE_CRATES: &[Symbol] = &[sym::std, sym::core, sym::alloc, s #[derive(Copy, Clone, Eq, HashStable_Generic, Encodable, Decodable)] pub struct Ident { + // `name` should never be the empty symbol. If you are considering that, + // you are probably conflating "empty identifer with "no identifier" and + // you should use `Option` instead. pub name: Symbol, pub span: Span, } @@ -2344,28 +2351,21 @@ pub struct Ident { impl Ident { #[inline] /// Constructs a new identifier from a symbol and a span. - pub const fn new(name: Symbol, span: Span) -> Ident { + pub fn new(name: Symbol, span: Span) -> Ident { + assert_ne!(name, kw::Empty); Ident { name, span } } /// Constructs a new identifier with a dummy span. #[inline] - pub const fn with_dummy_span(name: Symbol) -> Ident { + pub fn with_dummy_span(name: Symbol) -> Ident { Ident::new(name, DUMMY_SP) } - /// This is best avoided, because it blurs the lines between "empty - /// identifier" and "no identifier". Using `Option` is preferable, - /// where possible, because that is unambiguous. - #[inline] - pub fn empty() -> Ident { - Ident::with_dummy_span(kw::Empty) - } - // For dummy identifiers that are never used and absolutely must be - // present, it's better to use `Ident::dummy` than `Ident::Empty`, because - // it's clearer that it's intended as a dummy value, and more likely to be - // detected if it accidentally does get used. + // present. Note that this does *not* use the empty symbol; `sym::dummy` + // makes it clear that it's intended as a dummy value, and is more likely + // to be detected if it accidentally does get used. #[inline] pub fn dummy() -> Ident { Ident::with_dummy_span(sym::dummy) diff --git a/compiler/rustc_symbol_mangling/src/export.rs b/compiler/rustc_symbol_mangling/src/export.rs new file mode 100644 index 000000000000..770401fc8cfe --- /dev/null +++ b/compiler/rustc_symbol_mangling/src/export.rs @@ -0,0 +1,181 @@ +use std::assert_matches::debug_assert_matches; + +use rustc_abi::IntegerType; +use rustc_data_structures::stable_hasher::StableHasher; +use rustc_hashes::Hash128; +use rustc_hir::def::DefKind; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_span::symbol::{Symbol, sym}; + +trait AbiHashStable<'tcx> { + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher); +} +macro_rules! default_hash_impl { + ($($t:ty,)+) => { + $(impl<'tcx> AbiHashStable<'tcx> for $t { + #[inline] + fn abi_hash(&self, _tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + ::std::hash::Hash::hash(self, hasher); + } + })* + }; +} + +default_hash_impl! { i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, } + +impl<'tcx> AbiHashStable<'tcx> for bool { + #[inline] + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + (if *self { 1u8 } else { 0u8 }).abi_hash(tcx, hasher); + } +} + +impl<'tcx> AbiHashStable<'tcx> for str { + #[inline] + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + self.as_bytes().abi_hash(tcx, hasher); + } +} + +impl<'tcx> AbiHashStable<'tcx> for String { + #[inline] + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + self[..].abi_hash(tcx, hasher); + } +} + +impl<'tcx> AbiHashStable<'tcx> for Symbol { + #[inline] + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + self.as_str().abi_hash(tcx, hasher); + } +} + +impl<'tcx, T: AbiHashStable<'tcx>> AbiHashStable<'tcx> for [T] { + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + self.len().abi_hash(tcx, hasher); + for item in self { + item.abi_hash(tcx, hasher); + } + } +} + +impl<'tcx> AbiHashStable<'tcx> for Ty<'tcx> { + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + match self.kind() { + ty::Bool => sym::bool.abi_hash(tcx, hasher), + ty::Char => sym::char.abi_hash(tcx, hasher), + ty::Int(int_ty) => int_ty.name_str().abi_hash(tcx, hasher), + ty::Uint(uint_ty) => uint_ty.name_str().abi_hash(tcx, hasher), + ty::Float(float_ty) => float_ty.name_str().abi_hash(tcx, hasher), + + ty::Adt(adt_def, args) => { + adt_def.is_struct().abi_hash(tcx, hasher); + adt_def.is_enum().abi_hash(tcx, hasher); + adt_def.is_union().abi_hash(tcx, hasher); + + if let Some(align) = adt_def.repr().align { + align.bits().abi_hash(tcx, hasher); + } + + if let Some(integer) = adt_def.repr().int { + match integer { + IntegerType::Pointer(sign) => sign.abi_hash(tcx, hasher), + IntegerType::Fixed(integer, sign) => { + integer.int_ty_str().abi_hash(tcx, hasher); + sign.abi_hash(tcx, hasher); + } + } + } + + if let Some(pack) = adt_def.repr().pack { + pack.bits().abi_hash(tcx, hasher); + } + + adt_def.repr().c().abi_hash(tcx, hasher); + + for variant in adt_def.variants() { + variant.name.abi_hash(tcx, hasher); + for field in &variant.fields { + field.name.abi_hash(tcx, hasher); + let field_ty = tcx.type_of(field.did).instantiate_identity(); + field_ty.abi_hash(tcx, hasher); + } + } + args.abi_hash(tcx, hasher); + } + + ty::Tuple(args) if args.len() == 0 => {} + + // FIXME: Not yet supported. + ty::Foreign(_) + | ty::Ref(_, _, _) + | ty::Str + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::Slice(_) + | ty::RawPtr(_, _) + | ty::FnDef(_, _) + | ty::FnPtr(_, _) + | ty::Dynamic(_, _, _) + | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(_, _) + | ty::Never + | ty::Tuple(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Placeholder(_) + | ty::Infer(_) + | ty::UnsafeBinder(_) => unreachable!(), + + ty::Error(_) => {} + } + } +} + +impl<'tcx> AbiHashStable<'tcx> for ty::FnSig<'tcx> { + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + for ty in self.inputs_and_output { + ty.abi_hash(tcx, hasher); + } + self.safety.is_safe().abi_hash(tcx, hasher); + } +} + +impl<'tcx> AbiHashStable<'tcx> for ty::GenericArg<'tcx> { + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + self.unpack().abi_hash(tcx, hasher); + } +} + +impl<'tcx> AbiHashStable<'tcx> for ty::GenericArgKind<'tcx> { + fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) { + match self { + ty::GenericArgKind::Type(t) => t.abi_hash(tcx, hasher), + ty::GenericArgKind::Lifetime(_) | ty::GenericArgKind::Const(_) => unimplemented!(), + } + } +} + +pub(crate) fn compute_hash_of_export_fn<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, +) -> String { + let def_id = instance.def_id(); + debug_assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn); + + let args = instance.args; + let sig_ty = tcx.fn_sig(def_id).instantiate(tcx, args); + let sig_ty = tcx.instantiate_bound_regions_with_erased(sig_ty); + + let hash = { + let mut hasher = StableHasher::new(); + sig_ty.abi_hash(tcx, &mut hasher); + hasher.finish::() + }; + + hash.as_u128().to_string() +} diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index ca8918e06aaf..a51d7da878a2 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -92,6 +92,7 @@ #![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] +#![feature(assert_matches)] #![feature(rustdoc_internals)] // tidy-alphabetical-end @@ -104,6 +105,7 @@ use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_session::config::SymbolManglingVersion; use tracing::debug; +mod export; mod hashed; mod legacy; mod v0; @@ -296,12 +298,21 @@ fn compute_symbol_name<'tcx>( tcx.symbol_mangling_version(mangling_version_crate) }; - let symbol = match mangling_version { - SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate), - SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate), - SymbolManglingVersion::Hashed => hashed::mangle(tcx, instance, instantiating_crate, || { - v0::mangle(tcx, instance, instantiating_crate) - }), + let symbol = match tcx.is_exportable(def_id) { + true => format!( + "{}.{}", + v0::mangle(tcx, instance, instantiating_crate, true), + export::compute_hash_of_export_fn(tcx, instance) + ), + false => match mangling_version { + SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate), + SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate, false), + SymbolManglingVersion::Hashed => { + hashed::mangle(tcx, instance, instantiating_crate, || { + v0::mangle(tcx, instance, instantiating_crate, false) + }) + } + }, }; debug_assert!( diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index ddeeadff13d1..0c6d1495e39c 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -56,7 +56,7 @@ impl SymbolNamesTest<'_> { // some subset. for attr in tcx.get_attrs(def_id, SYMBOL_NAME) { let def_id = def_id.to_def_id(); - let instance = Instance::new( + let instance = Instance::new_raw( def_id, tcx.erase_regions(GenericArgs::identity_for_item(tcx, def_id)), ); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index f8f2714ee42d..4a99ce09b39a 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -26,6 +26,7 @@ pub(super) fn mangle<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, instantiating_crate: Option, + is_exportable: bool, ) -> String { let def_id = instance.def_id(); // FIXME(eddyb) this should ideally not be needed. @@ -35,6 +36,7 @@ pub(super) fn mangle<'tcx>( let mut cx: SymbolMangler<'_> = SymbolMangler { tcx, start_offset: prefix.len(), + is_exportable, paths: FxHashMap::default(), types: FxHashMap::default(), consts: FxHashMap::default(), @@ -93,6 +95,7 @@ pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> Strin let mut cx: SymbolMangler<'_> = SymbolMangler { tcx, start_offset: prefix.len(), + is_exportable: false, paths: FxHashMap::default(), types: FxHashMap::default(), consts: FxHashMap::default(), @@ -135,6 +138,7 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>( let mut cx = SymbolMangler { tcx, start_offset: 0, + is_exportable: false, paths: FxHashMap::default(), types: FxHashMap::default(), consts: FxHashMap::default(), @@ -163,6 +167,7 @@ struct SymbolMangler<'tcx> { tcx: TyCtxt<'tcx>, binders: Vec, out: String, + is_exportable: bool, /// The length of the prefix in `out` (e.g. 2 for `_R`). start_offset: usize, @@ -376,7 +381,14 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { args, )?; } else { - self.push_disambiguator(key.disambiguated_data.disambiguator as u64); + let exported_impl_order = self.tcx.stable_order_of_exportable_impls(impl_def_id.krate); + let disambiguator = match self.is_exportable { + true => exported_impl_order[&impl_def_id] as u64, + false => { + exported_impl_order.len() as u64 + key.disambiguated_data.disambiguator as u64 + } + }; + self.push_disambiguator(disambiguator); self.print_def_path(parent_def_id, &[])?; } @@ -818,8 +830,10 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> { self.push("C"); - let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); - self.push_disambiguator(stable_crate_id.as_u64()); + if !self.is_exportable { + let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); + self.push_disambiguator(stable_crate_id.as_u64()); + } let name = self.tcx.crate_name(cnum); self.push_ident(name.as_str()); Ok(()) @@ -867,6 +881,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { DefPathData::AnonConst => 'k', DefPathData::OpaqueTy => 'i', DefPathData::SyntheticCoroutineBody => 's', + DefPathData::NestedStatic => 'n', // These should never show up as `path_append` arguments. DefPathData::CrateRoot @@ -875,7 +890,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | DefPathData::Impl | DefPathData::MacroNs(_) | DefPathData::LifetimeNs(_) - | DefPathData::AnonAssocTy => { + | DefPathData::OpaqueLifetime(_) + | DefPathData::AnonAssocTy(..) => { bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data) } }; diff --git a/compiler/rustc_target/src/spec/base/msvc.rs b/compiler/rustc_target/src/spec/base/msvc.rs index 486d7158723f..bd59678d2366 100644 --- a/compiler/rustc_target/src/spec/base/msvc.rs +++ b/compiler/rustc_target/src/spec/base/msvc.rs @@ -5,7 +5,19 @@ use crate::spec::{BinaryFormat, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo pub(crate) fn opts() -> TargetOptions { // Suppress the verbose logo and authorship debugging output, which would needlessly // clog any log files. - let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/NOLOGO"]); + let pre_link_args = TargetOptions::link_args( + LinkerFlavor::Msvc(Lld::No), + &[ + "/NOLOGO", + // "Symbol is marked as dllimport, but defined in an object file" + // Harmless warning that flags a potential performance improvement: marking a symbol as + // dllimport indirects usage via the `__imp_` symbol, which isn't required if the symbol + // is in the current binary. This is tripped by __rust_no_alloc_shim_is_unstable as it + // is generated by the compiler, but marked as a foreign item (hence the dllimport) in + // the standard library. + "/IGNORE:4286", + ], + ); TargetOptions { linker_flavor: LinkerFlavor::Msvc(Lld::No), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 37ea0d6e7b58..303be54a6d78 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3567,7 +3567,19 @@ impl Target { "x86" => (Architecture::I386, None), "s390x" => (Architecture::S390x, None), "mips" | "mips32r6" => (Architecture::Mips, None), - "mips64" | "mips64r6" => (Architecture::Mips64, None), + "mips64" | "mips64r6" => ( + // While there are currently no builtin targets + // using the N32 ABI, it is possible to specify + // it using a custom target specification. N32 + // is an ILP32 ABI like the Aarch64_Ilp32 + // and X86_64_X32 cases above and below this one. + if self.options.llvm_abiname.as_ref() == "n32" { + Architecture::Mips64_N32 + } else { + Architecture::Mips64 + }, + None, + ), "x86_64" => ( if self.pointer_width == 32 { Architecture::X86_64_X32 diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index 98d78520c983..c5704c574483 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -1,10 +1,21 @@ -use crate::spec::{Target, TargetMetadata, base}; +use crate::spec::{FramePointer, LinkerFlavor, Lld, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); + // Microsoft recommends enabling frame pointers on Arm64 Windows. + // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers + // "The frame pointer (x29) is required for compatibility with fast stack walking used by ETW + // and other services. It must point to the previous {x29, x30} pair on the stack." + base.frame_pointer = FramePointer::NonLeaf; + + // MSVC emits a warning about code that may trip "Cortex-A53 MPCore processor bug #843419" (see + // https://developer.arm.com/documentation/epm048406/latest) which is sometimes emitted by LLVM. + // Since Arm64 Windows 10+ isn't supported on that processor, it's safe to disable the warning. + base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/arm64hazardfree"]); + Target { llvm_target: "aarch64-pc-windows-msvc".into(), metadata: TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs index bb3e3e544cba..8f93523909e3 100644 --- a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, Lld, Target, TargetMetadata, add_link_args, base}; +use crate::spec::{FramePointer, LinkerFlavor, Lld, Target, TargetMetadata, add_link_args, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); @@ -10,6 +10,12 @@ pub(crate) fn target() -> Target { &["/machine:arm64ec", "softintrin.lib"], ); + // Microsoft recommends enabling frame pointers on Arm64 Windows. + // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers + // "The frame pointer (x29) is required for compatibility with fast stack walking used by ETW + // and other services. It must point to the previous {x29, x30} pair on the stack." + base.frame_pointer = FramePointer::NonLeaf; + Target { llvm_target: "arm64ec-pc-windows-msvc".into(), metadata: TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index 71b3fbe00b2f..508abc010184 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -27,6 +27,7 @@ pub(crate) fn target() -> Target { abi: "abi64".into(), endian: Endian::Big, mcount: "_mcount".into(), + llvm_abiname: "n64".into(), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs index b130ca29c7f0..a26350ff2250 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs @@ -22,6 +22,7 @@ pub(crate) fn target() -> Target { features: "+mips64r2,+xgot".into(), max_atomic_width: Some(64), mcount: "_mcount".into(), + llvm_abiname: "n64".into(), ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs index 4ea7c7bff44a..fd5095030530 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs @@ -25,6 +25,7 @@ pub(crate) fn target() -> Target { mcount: "_mcount".into(), // FIXME(compiler-team#422): musl targets should be dynamically linked by default. crt_static_default: true, + llvm_abiname: "n64".into(), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs index a9afea27ef34..19bceadc6223 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs @@ -19,6 +19,7 @@ pub(crate) fn target() -> Target { features: "+mips64r2,+xgot".into(), max_atomic_width: Some(64), mcount: "_mcount".into(), + llvm_abiname: "n64".into(), ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs index 7bdd9edda70c..aa087b1a35af 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs @@ -19,6 +19,11 @@ pub(crate) fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), - options: TargetOptions { abi: "abi64".into(), mcount: "_mcount".into(), ..base }, + options: TargetOptions { + abi: "abi64".into(), + mcount: "_mcount".into(), + llvm_abiname: "n64".into(), + ..base + }, } } diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs index 3eefa27ea04b..cdd5f6b84365 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -22,6 +22,7 @@ pub(crate) fn target() -> Target { features: "+mips64r6".into(), max_atomic_width: Some(64), mcount: "_mcount".into(), + llvm_abiname: "n64".into(), ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs index 0887180791c7..88879a25818b 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs @@ -19,6 +19,7 @@ pub(crate) fn target() -> Target { features: "+mips64r6".into(), max_atomic_width: Some(64), mcount: "_mcount".into(), + llvm_abiname: "n64".into(), ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index f856d3efc1c9..5a21925ba04e 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -393,7 +393,28 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("amx-tf32", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]), ("amx-transpose", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("apxf", Unstable(sym::apx_target_feature), &[]), ("avx", Stable, &["sse4.2"]), + ( + "avx10.1", + Unstable(sym::avx10_target_feature), + &[ + "avx512bf16", + "avx512bitalg", + "avx512bw", + "avx512cd", + "avx512dq", + "avx512f", + "avx512fp16", + "avx512ifma", + "avx512vbmi", + "avx512vbmi2", + "avx512vl", + "avx512vnni", + "avx512vpopcntdq", + ], + ), + ("avx10.2", Unstable(sym::avx10_target_feature), &["avx10.1"]), ("avx2", Stable, &["avx"]), ("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]), ("avx512bitalg", Unstable(sym::avx512_target_feature), &["avx512bw"]), diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index a5cc8d9ea012..1071105522d1 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -8,7 +8,6 @@ edition = "2024" itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } -rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 74e38f525c8e..00922c6038ee 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -148,9 +148,6 @@ trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement -trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]` - .label = empty on-clause here - trait_selection_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}` trait_selection_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type @@ -187,9 +184,6 @@ trait_selection_inherent_projection_normalization_overflow = overflow evaluating trait_selection_invalid_format_specifier = invalid format specifier .help = no format specifier are supported in this position -trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]` - .label = invalid on-clause here - trait_selection_label_bad = {$bad_kind -> *[other] cannot infer type [more_info] cannot infer {$prefix_kind -> @@ -237,10 +231,6 @@ trait_selection_negative_positive_conflict = found both positive and negative im .positive_implementation_here = positive implementation here .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}` -trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value - .label = expected value here - .note = eg `#[rustc_on_unimplemented(message="foo")]` - trait_selection_nothing = {""} trait_selection_oc_cant_coerce_force_inline = @@ -339,6 +329,22 @@ trait_selection_ril_introduced_by = requirement introduced by this return type trait_selection_ril_introduced_here = `'static` requirement introduced here trait_selection_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type +trait_selection_rustc_on_unimplemented_empty_on_clause = empty `on`-clause in `#[rustc_on_unimplemented]` + .label = empty `on`-clause here +trait_selection_rustc_on_unimplemented_expected_identifier = expected an identifier inside this `on`-clause + .label = expected an identifier here, not `{$path}` +trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not = expected a single predicate in `not(..)` + .label = unexpected quantity of predicates here +trait_selection_rustc_on_unimplemented_invalid_flag = invalid flag in `on`-clause + .label = expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}` +trait_selection_rustc_on_unimplemented_invalid_predicate = this predicate is invalid + .label = expected one of `any`, `all` or `not` here, not `{$invalid_pred}` +trait_selection_rustc_on_unimplemented_missing_value = this attribute must have a value + .label = expected value here + .note = e.g. `#[rustc_on_unimplemented(message="foo")]` +trait_selection_rustc_on_unimplemented_unsupported_literal_in_on = literals inside `on`-clauses are not supported + .label = unexpected literal here + trait_selection_source_kind_closure_return = try giving this closure an explicit return type @@ -446,8 +452,6 @@ trait_selection_type_annotations_needed = {$source_kind -> } .label = type must be known at this point -trait_selection_type_annotations_needed_error_time = this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` - trait_selection_types_declared_different = these two types are declared with different lifetimes... trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index de9a50f19623..cb1c9c753690 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -6,7 +6,7 @@ use rustc_errors::codes::*; use rustc_errors::{Diag, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource}; use rustc_middle::bug; @@ -17,7 +17,7 @@ use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypeckResults, }; -use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym}; +use rustc_span::{BytePos, DUMMY_SP, Ident, Span, sym}; use tracing::{debug, instrument, warn}; use super::nice_region_error::placeholder_error::Highlighted; @@ -438,7 +438,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label, was_written: false, path: Default::default(), - time_version: false, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -630,10 +629,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } - - let time_version = - self.detect_old_time_crate_version(failure_span, &kind, &mut infer_subdiags); - match error_code { TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired { span, @@ -645,7 +640,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label: None, was_written: path.is_some(), path: path.unwrap_or_default(), - time_version, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -671,42 +665,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }), } } - - /// Detect the inference regression on crate `time` <= 0.3.35 and emit a more targeted error. - /// - // FIXME: we should figure out a more generic version of doing this, ideally in cargo itself. - fn detect_old_time_crate_version( - &self, - span: Option, - kind: &InferSourceKind<'_>, - // We will clear the non-actionable suggestion from the error to reduce noise. - infer_subdiags: &mut Vec>, - ) -> bool { - // FIXME(#129461): We are time-boxing this code in the compiler. It'll start failing - // compilation once we promote 1.89 to beta, which will happen in 9 months from now. - #[cfg(not(version("1.89")))] - const fn version_check() {} - #[cfg(version("1.89"))] - const fn version_check() { - panic!("remove this check as presumably the ecosystem has moved from needing it"); - } - const { version_check() }; - // Only relevant when building the `time` crate. - if self.infcx.tcx.crate_name(LOCAL_CRATE) == sym::time - && let Some(span) = span - && let InferSourceKind::LetBinding { pattern_name, .. } = kind - && let Some(name) = pattern_name - && name.as_str() == "items" - && let FileName::Real(file) = self.infcx.tcx.sess.source_map().span_to_filename(span) - { - let path = file.local_path_if_available().to_string_lossy(); - if path.contains("format_description") && path.contains("parse") { - infer_subdiags.clear(); - return true; - } - } - false - } } #[derive(Debug)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 4c4491269b75..d5ee6e2123a1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -4,6 +4,7 @@ use std::path::PathBuf; use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit}; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; +use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{AttrArgs, Attribute}; use rustc_macros::LintDiagnostic; @@ -13,17 +14,16 @@ use rustc_middle::ty::{self, GenericArgsRef, GenericParamDef, GenericParamDefKin use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::{Span, Symbol, sym}; use tracing::{debug, info}; -use {rustc_attr_parsing as attr, rustc_hir as hir}; use super::{ObligationCauseCode, PredicateObligation}; use crate::error_reporting::TypeErrCtxt; -use crate::error_reporting::traits::on_unimplemented_condition::{Condition, ConditionOptions}; +use crate::error_reporting::traits::on_unimplemented_condition::{ + ConditionOptions, OnUnimplementedCondition, +}; use crate::error_reporting::traits::on_unimplemented_format::{ Ctx, FormatArgs, FormatString, FormatWarning, }; -use crate::errors::{ - EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented, -}; +use crate::errors::{InvalidOnClause, NoValueInOnUnimplemented}; use crate::infer::InferCtxtExt; impl<'tcx> TypeErrCtxt<'_, 'tcx> { @@ -306,21 +306,21 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { #[derive(Clone, Debug)] pub struct OnUnimplementedFormatString { /// Symbol of the format string, i.e. `"content"` - pub symbol: Symbol, + symbol: Symbol, ///The span of the format string, i.e. `"content"` - pub span: Span, - pub is_diagnostic_namespace_variant: bool, + span: Span, + is_diagnostic_namespace_variant: bool, } #[derive(Debug)] pub struct OnUnimplementedDirective { - pub condition: Option, - pub subcommands: Vec, - pub message: Option<(Span, OnUnimplementedFormatString)>, - pub label: Option<(Span, OnUnimplementedFormatString)>, - pub notes: Vec, - pub parent_label: Option, - pub append_const_msg: Option, + condition: Option, + subcommands: Vec, + message: Option<(Span, OnUnimplementedFormatString)>, + label: Option<(Span, OnUnimplementedFormatString)>, + notes: Vec, + parent_label: Option, + append_const_msg: Option, } /// For the `#[rustc_on_unimplemented]` attribute @@ -427,18 +427,12 @@ impl<'tcx> OnUnimplementedDirective { } else { let cond = item_iter .next() - .ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))? - .meta_item_or_bool() - .ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?; - attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| { - if let Some(value) = cfg.value - && let Err(guar) = parse_value(value, cfg.span) - { - errored = Some(guar); - } - true - }); - Some(Condition { inner: cond.clone() }) + .ok_or_else(|| tcx.dcx().emit_err(InvalidOnClause::Empty { span }))?; + + match OnUnimplementedCondition::parse(cond) { + Ok(condition) => Some(condition), + Err(e) => return Err(tcx.dcx().emit_err(e)), + } }; let mut message = None; @@ -724,7 +718,7 @@ impl<'tcx> OnUnimplementedDirective { result } - pub fn evaluate( + pub(crate) fn evaluate( &self, tcx: TyCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, @@ -744,7 +738,7 @@ impl<'tcx> OnUnimplementedDirective { for command in self.subcommands.iter().chain(Some(self)).rev() { debug!(?command); if let Some(ref condition) = command.condition - && !condition.matches_predicate(tcx, condition_options) + && !condition.matches_predicate(condition_options) { debug!("evaluate: skipping {:?} due to condition", command); continue; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_condition.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_condition.rs index 116cfb01cb63..13753761f092 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_condition.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_condition.rs @@ -1,52 +1,251 @@ -use rustc_ast::MetaItemInner; -use rustc_attr_parsing as attr; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_ast::{MetaItemInner, MetaItemKind, MetaItemLit}; use rustc_parse_format::{ParseMode, Parser, Piece, Position}; -use rustc_span::{DesugaringKind, Span, Symbol, kw, sym}; +use rustc_span::{DesugaringKind, Ident, Span, Symbol, kw, sym}; -/// A predicate in an attribute using on, all, any, -/// similar to a cfg predicate. +use crate::errors::InvalidOnClause; + +/// Represents the `on` filter in `#[rustc_on_unimplemented]`. #[derive(Debug)] -pub struct Condition { - pub inner: MetaItemInner, +pub(crate) struct OnUnimplementedCondition { + span: Span, + pred: Predicate, } -impl Condition { - pub fn span(&self) -> Span { - self.inner.span() +impl OnUnimplementedCondition { + pub(crate) fn span(&self) -> Span { + self.span } - pub fn matches_predicate<'tcx>(&self, tcx: TyCtxt<'tcx>, options: &ConditionOptions) -> bool { - attr::eval_condition(&self.inner, tcx.sess, Some(tcx.features()), &mut |cfg| { - let value = cfg.value.map(|v| { - // `with_no_visible_paths` is also used when generating the options, - // so we need to match it here. - ty::print::with_no_visible_paths!({ - Parser::new(v.as_str(), None, None, false, ParseMode::Format) - .map(|p| match p { - Piece::Lit(s) => s.to_owned(), - Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(arg) => { - let s = Symbol::intern(arg); - match options.generic_args.iter().find(|(k, _)| *k == s) { - Some((_, val)) => val.to_string(), - None => format!("{{{arg}}}"), - } - } - Position::ArgumentImplicitlyIs(_) => String::from("{}"), - Position::ArgumentIs(idx) => format!("{{{idx}}}"), - }, - }) - .collect() - }) - }); - - options.contains(cfg.name, &value) + pub(crate) fn matches_predicate(&self, options: &ConditionOptions) -> bool { + self.pred.eval(&mut |p| match p { + FlagOrNv::Flag(b) => options.has_flag(*b), + FlagOrNv::NameValue(NameValue { name, value }) => { + let value = value.format(&options.generic_args); + options.contains(*name, value) + } }) } + + pub(crate) fn parse(input: &MetaItemInner) -> Result { + let span = input.span(); + let pred = Predicate::parse(input)?; + Ok(OnUnimplementedCondition { span, pred }) + } } -/// Used with `Condition::matches_predicate` to test whether the condition applies +/// Predicate(s) in `#[rustc_on_unimplemented]`'s `on` filter. See [`OnUnimplementedCondition`]. +/// +/// It is similar to the predicate in the `cfg` attribute, +/// and may contain nested predicates. +#[derive(Debug)] +enum Predicate { + /// A condition like `on(crate_local)`. + Flag(Flag), + /// A match, like `on(Rhs = "Whatever")`. + Match(NameValue), + /// Negation, like `on(not($pred))`. + Not(Box), + /// True if all predicates are true, like `on(all($a, $b, $c))`. + All(Vec), + /// True if any predicate is true, like `on(any($a, $b, $c))`. + Any(Vec), +} + +impl Predicate { + fn parse(input: &MetaItemInner) -> Result { + let meta_item = match input { + MetaItemInner::MetaItem(meta_item) => meta_item, + MetaItemInner::Lit(lit) => { + return Err(InvalidOnClause::UnsupportedLiteral { span: lit.span }); + } + }; + + let Some(predicate) = meta_item.ident() else { + return Err(InvalidOnClause::ExpectedIdentifier { + span: meta_item.path.span, + path: meta_item.path.clone(), + }); + }; + + match meta_item.kind { + MetaItemKind::List(ref mis) => match predicate.name { + sym::any => Ok(Predicate::Any(Predicate::parse_sequence(mis)?)), + sym::all => Ok(Predicate::All(Predicate::parse_sequence(mis)?)), + sym::not => match &**mis { + [one] => Ok(Predicate::Not(Box::new(Predicate::parse(one)?))), + [first, .., last] => Err(InvalidOnClause::ExpectedOnePredInNot { + span: first.span().to(last.span()), + }), + [] => Err(InvalidOnClause::ExpectedOnePredInNot { span: meta_item.span }), + }, + invalid_pred => { + Err(InvalidOnClause::InvalidPredicate { span: predicate.span, invalid_pred }) + } + }, + MetaItemKind::NameValue(MetaItemLit { symbol, .. }) => { + let name = Name::parse(predicate); + let value = FilterFormatString::parse(symbol); + let kv = NameValue { name, value }; + Ok(Predicate::Match(kv)) + } + MetaItemKind::Word => { + let flag = Flag::parse(predicate)?; + Ok(Predicate::Flag(flag)) + } + } + } + + fn parse_sequence(sequence: &[MetaItemInner]) -> Result, InvalidOnClause> { + sequence.iter().map(Predicate::parse).collect() + } + + fn eval(&self, eval: &mut impl FnMut(FlagOrNv<'_>) -> bool) -> bool { + match self { + Predicate::Flag(flag) => eval(FlagOrNv::Flag(flag)), + Predicate::Match(nv) => eval(FlagOrNv::NameValue(nv)), + Predicate::Not(not) => !not.eval(eval), + Predicate::All(preds) => preds.into_iter().all(|pred| pred.eval(eval)), + Predicate::Any(preds) => preds.into_iter().any(|pred| pred.eval(eval)), + } + } +} + +/// Represents a `MetaWord` in an `on`-filter. +#[derive(Debug, Clone, Copy)] +enum Flag { + /// Whether the code causing the trait bound to not be fulfilled + /// is part of the user's crate. + CrateLocal, + /// Whether the obligation is user-specified rather than derived. + Direct, + /// Whether we are in some kind of desugaring like + /// `?` or `try { .. }`. + FromDesugaring, +} + +impl Flag { + fn parse(Ident { name, span }: Ident) -> Result { + match name { + sym::crate_local => Ok(Flag::CrateLocal), + sym::direct => Ok(Flag::Direct), + sym::from_desugaring => Ok(Flag::FromDesugaring), + invalid_flag => Err(InvalidOnClause::InvalidFlag { invalid_flag, span }), + } + } +} + +/// A `MetaNameValueStr` in an `on`-filter. +/// +/// For example, `#[rustc_on_unimplemented(on(name = "value", message = "hello"))]`. +#[derive(Debug, Clone)] +struct NameValue { + name: Name, + /// Something like `"&str"` or `"alloc::string::String"`, + /// in which case it just contains a single string piece. + /// But if it is something like `"&[{A}]"` then it must be formatted later. + value: FilterFormatString, +} + +/// The valid names of the `on` filter. +#[derive(Debug, Clone, Copy)] +enum Name { + Cause, + FromDesugaring, + SelfUpper, + GenericArg(Symbol), +} + +impl Name { + fn parse(Ident { name, .. }: Ident) -> Self { + match name { + sym::_Self | kw::SelfUpper => Name::SelfUpper, + sym::from_desugaring => Name::FromDesugaring, + sym::cause => Name::Cause, + // FIXME(mejrs) Perhaps we should start checking that + // this actually is a valid generic parameter? + generic => Name::GenericArg(generic), + } + } +} + +#[derive(Debug, Clone)] +enum FlagOrNv<'p> { + Flag(&'p Flag), + NameValue(&'p NameValue), +} + +/// Represents a value inside an `on` filter. +/// +/// For example, `#[rustc_on_unimplemented(on(name = "value", message = "hello"))]`. +/// If it is a simple literal like this then `pieces` will be `[LitOrArg::Lit("value")]`. +/// The `Arg` variant is used when it contains formatting like +/// `#[rustc_on_unimplemented(on(Self = "&[{A}]", message = "hello"))]`. +#[derive(Debug, Clone)] +struct FilterFormatString { + pieces: Vec, +} + +#[derive(Debug, Clone)] +enum LitOrArg { + Lit(String), + Arg(String), +} + +impl FilterFormatString { + fn parse(input: Symbol) -> Self { + let pieces = Parser::new(input.as_str(), None, None, false, ParseMode::Format) + .map(|p| match p { + Piece::Lit(s) => LitOrArg::Lit(s.to_owned()), + // We just ignore formatspecs here + Piece::NextArgument(a) => match a.position { + // In `TypeErrCtxt::on_unimplemented_note` we substitute `"{integral}"` even + // if the integer type has been resolved, to allow targeting all integers. + // `"{integer}"` and `"{float}"` come from numerics that haven't been inferred yet, + // from the `Display` impl of `InferTy` to be precise. + // + // Don't try to format these later! + Position::ArgumentNamed(arg @ "integer" | arg @ "integral" | arg @ "float") => { + LitOrArg::Lit(format!("{{{arg}}}")) + } + + // FIXME(mejrs) We should check if these correspond to a generic of the trait. + Position::ArgumentNamed(arg) => LitOrArg::Arg(arg.to_owned()), + + // FIXME(mejrs) These should really be warnings/errors + Position::ArgumentImplicitlyIs(_) => LitOrArg::Lit(String::from("{}")), + Position::ArgumentIs(idx) => LitOrArg::Lit(format!("{{{idx}}}")), + }, + }) + .collect(); + Self { pieces } + } + + fn format(&self, generic_args: &[(Symbol, String)]) -> String { + let mut ret = String::new(); + + for piece in &self.pieces { + match piece { + LitOrArg::Lit(s) => ret.push_str(s), + LitOrArg::Arg(arg) => { + let s = Symbol::intern(arg); + match generic_args.iter().find(|(k, _)| *k == s) { + Some((_, val)) => ret.push_str(val), + None => { + // FIXME(mejrs) If we start checking as mentioned in + // FilterFormatString::parse then this shouldn't happen + let _ = std::fmt::write(&mut ret, format_args!("{{{s}}}")); + } + } + } + } + } + + ret + } +} + +/// Used with `OnUnimplementedCondition::matches_predicate` to evaluate the +/// [`OnUnimplementedCondition`]. /// /// For example, given a /// ```rust,ignore (just an example) @@ -85,36 +284,34 @@ impl Condition { /// } /// ``` #[derive(Debug)] -pub struct ConditionOptions { +pub(crate) struct ConditionOptions { /// All the self types that may apply. - /// for example - pub self_types: Vec, + pub(crate) self_types: Vec, // The kind of compiler desugaring. - pub from_desugaring: Option, - /// Match on a variant of [rustc_infer::traits::ObligationCauseCode] - pub cause: Option, - pub crate_local: bool, + pub(crate) from_desugaring: Option, + /// Match on a variant of [rustc_infer::traits::ObligationCauseCode]. + pub(crate) cause: Option, + pub(crate) crate_local: bool, /// Is the obligation "directly" user-specified, rather than derived? - pub direct: bool, - // A list of the generic arguments and their reified types - pub generic_args: Vec<(Symbol, String)>, + pub(crate) direct: bool, + // A list of the generic arguments and their reified types. + pub(crate) generic_args: Vec<(Symbol, String)>, } impl ConditionOptions { - pub fn contains(&self, key: Symbol, value: &Option) -> bool { - match (key, value) { - (sym::_Self | kw::SelfUpper, Some(value)) => self.self_types.contains(&value), - // from_desugaring as a flag - (sym::from_desugaring, None) => self.from_desugaring.is_some(), - // from_desugaring as key == value - (sym::from_desugaring, Some(v)) if let Some(ds) = self.from_desugaring => ds.matches(v), - (sym::cause, Some(value)) => self.cause.as_deref() == Some(value), - (sym::crate_local, None) => self.crate_local, - (sym::direct, None) => self.direct, - (other, Some(value)) => { - self.generic_args.iter().any(|(k, v)| *k == other && v == value) - } - _ => false, + fn has_flag(&self, name: Flag) -> bool { + match name { + Flag::CrateLocal => self.crate_local, + Flag::Direct => self.direct, + Flag::FromDesugaring => self.from_desugaring.is_some(), + } + } + fn contains(&self, name: Name, value: String) -> bool { + match name { + Name::SelfUpper => self.self_types.contains(&value), + Name::FromDesugaring => self.from_desugaring.is_some_and(|ds| ds.matches(&value)), + Name::Cause => self.cause == Some(value), + Name::GenericArg(arg) => self.generic_args.contains(&(arg, value)), } } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs index f835406122b8..d8b90844b7d2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs @@ -1,11 +1,12 @@ use std::fmt; +use std::ops::Range; use errors::*; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::print::TraitRefPrintSugared; use rustc_parse_format::{ - Alignment, Argument, Count, FormatSpec, InnerSpan, ParseError, ParseMode, Parser, - Piece as RpfPiece, Position, + Alignment, Argument, Count, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece, + Position, }; use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::def_id::DefId; @@ -173,7 +174,7 @@ impl FormatString { pieces.push(Piece::Lit(lit.into())); } RpfPiece::NextArgument(arg) => { - warn_on_format_spec(arg.format, &mut warnings, span); + warn_on_format_spec(arg.format.clone(), &mut warnings, span); let arg = parse_arg(&arg, ctx, &mut warnings, span); pieces.push(Piece::Arg(arg)); } @@ -233,7 +234,7 @@ fn parse_arg<'tcx>( | Ctx::DiagnosticOnUnimplemented { tcx, trait_def_id }) = ctx; let trait_name = tcx.item_ident(*trait_def_id); let generics = tcx.generics_of(trait_def_id); - let span = slice_span(input_span, arg.position_span); + let span = slice_span(input_span, arg.position_span.clone()); match arg.position { // Something like "hello {name}" @@ -335,14 +336,12 @@ fn warn_on_format_spec(spec: FormatSpec<'_>, warnings: &mut Vec, } } -/// Helper function because `Span` and `rustc_parse_format::InnerSpan` don't know about each other -fn slice_span(input: Span, inner: InnerSpan) -> Span { - let InnerSpan { start, end } = inner; +fn slice_span(input: Span, range: Range) -> Span { let span = input.data(); Span::new( - span.lo + BytePos::from_usize(start), - span.lo + BytePos::from_usize(end), + span.lo + BytePos::from_usize(range.start), + span.lo + BytePos::from_usize(range.end), span.ctxt, span.parent, ) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index de251ae2893c..8801397b7754 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1516,6 +1516,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } else { expr.span.with_hi(expr.span.lo() + BytePos(1)) }; + + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(snippet) if snippet.starts_with("&") => {} + _ => break 'outer, + } + suggestions.push((span, String::new())); let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else { diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 1063115ed237..8ab4d795c459 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; +use rustc_ast::Path; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ @@ -31,23 +32,50 @@ pub struct UnableToConstructConstantValue<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = E0232)] -pub struct EmptyOnClauseInOnUnimplemented { - #[primary_span] - #[label] - pub span: Span, +pub enum InvalidOnClause { + #[diag(trait_selection_rustc_on_unimplemented_empty_on_clause, code = E0232)] + Empty { + #[primary_span] + #[label] + span: Span, + }, + #[diag(trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not, code = E0232)] + ExpectedOnePredInNot { + #[primary_span] + #[label] + span: Span, + }, + #[diag(trait_selection_rustc_on_unimplemented_unsupported_literal_in_on, code = E0232)] + UnsupportedLiteral { + #[primary_span] + #[label] + span: Span, + }, + #[diag(trait_selection_rustc_on_unimplemented_expected_identifier, code = E0232)] + ExpectedIdentifier { + #[primary_span] + #[label] + span: Span, + path: Path, + }, + #[diag(trait_selection_rustc_on_unimplemented_invalid_predicate, code = E0232)] + InvalidPredicate { + #[primary_span] + #[label] + span: Span, + invalid_pred: Symbol, + }, + #[diag(trait_selection_rustc_on_unimplemented_invalid_flag, code = E0232)] + InvalidFlag { + #[primary_span] + #[label] + span: Span, + invalid_flag: Symbol, + }, } #[derive(Diagnostic)] -#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = E0232)] -pub struct InvalidOnClauseInOnUnimplemented { - #[primary_span] - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = E0232)] +#[diag(trait_selection_rustc_on_unimplemented_missing_value, code = E0232)] #[note] pub struct NoValueInOnUnimplemented { #[primary_span] @@ -191,8 +219,6 @@ pub struct AnnotationRequired<'a> { #[note(trait_selection_full_type_written)] pub was_written: bool, pub path: PathBuf, - #[note(trait_selection_type_annotations_needed_error_time)] - pub time_version: bool, } // Copy of `AnnotationRequired` for E0283 diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index cce67b066dde..332204a0c5f0 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -13,6 +13,49 @@ use crate::errors::NonGenericOpaqueTypeParam; use crate::regions::OutlivesEnvironmentBuildExt; use crate::traits::ObligationCtxt; +pub enum InvalidOpaqueTypeArgs<'tcx> { + AlreadyReported(ErrorGuaranteed), + NotAParam { opaque_type_key: OpaqueTypeKey<'tcx>, param_index: usize, span: Span }, + DuplicateParam { opaque_type_key: OpaqueTypeKey<'tcx>, param_indices: Vec, span: Span }, +} +impl From for InvalidOpaqueTypeArgs<'_> { + fn from(guar: ErrorGuaranteed) -> Self { + InvalidOpaqueTypeArgs::AlreadyReported(guar) + } +} +impl<'tcx> InvalidOpaqueTypeArgs<'tcx> { + pub fn report(self, infcx: &InferCtxt<'tcx>) -> ErrorGuaranteed { + let tcx = infcx.tcx; + match self { + InvalidOpaqueTypeArgs::AlreadyReported(guar) => guar, + InvalidOpaqueTypeArgs::NotAParam { opaque_type_key, param_index, span } => { + let opaque_generics = tcx.generics_of(opaque_type_key.def_id); + let opaque_param = opaque_generics.param_at(param_index, tcx); + let kind = opaque_param.kind.descr(); + infcx.dcx().emit_err(NonGenericOpaqueTypeParam { + arg: opaque_type_key.args[param_index], + kind, + span, + param_span: tcx.def_span(opaque_param.def_id), + }) + } + InvalidOpaqueTypeArgs::DuplicateParam { opaque_type_key, param_indices, span } => { + let opaque_generics = tcx.generics_of(opaque_type_key.def_id); + let descr = opaque_generics.param_at(param_indices[0], tcx).kind.descr(); + let spans: Vec<_> = param_indices + .into_iter() + .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) + .collect(); + infcx + .dcx() + .struct_span_err(span, "non-defining opaque type use in defining scope") + .with_span_note(spans, format!("{descr} used multiple times")) + .emit() + } + } + } +} + /// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter]. /// /// [rustc-dev-guide chapter]: @@ -22,23 +65,19 @@ pub fn check_opaque_type_parameter_valid<'tcx>( opaque_type_key: OpaqueTypeKey<'tcx>, span: Span, defining_scope_kind: DefiningScopeKind, -) -> Result<(), ErrorGuaranteed> { +) -> Result<(), InvalidOpaqueTypeArgs<'tcx>> { let tcx = infcx.tcx; - let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); // Avoid duplicate errors in case the opaque has already been malformed in // HIR typeck. if let DefiningScopeKind::MirBorrowck = defining_scope_kind { - if let Err(guar) = infcx + infcx .tcx .type_of_opaque_hir_typeck(opaque_type_key.def_id) .instantiate_identity() - .error_reported() - { - return Err(guar); - } + .error_reported()?; } for (i, arg) in opaque_type_key.iter_captured_args(tcx) { @@ -64,32 +103,18 @@ pub fn check_opaque_type_parameter_valid<'tcx>( } } else { // Prevent `fn foo() -> Foo` from being defining. - let opaque_param = opaque_generics.param_at(i, tcx); - let kind = opaque_param.kind.descr(); - opaque_env.param_is_error(i)?; - - return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam { - arg, - kind, - span, - param_span: tcx.def_span(opaque_param.def_id), - })); + return Err(InvalidOpaqueTypeArgs::NotAParam { opaque_type_key, param_index: i, span }); } } - for (_, indices) in seen_params { - if indices.len() > 1 { - let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); - let spans: Vec<_> = indices - .into_iter() - .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) - .collect(); - return Err(infcx - .dcx() - .struct_span_err(span, "non-defining opaque type use in defining scope") - .with_span_note(spans, format!("{descr} used multiple times")) - .emit()); + for (_, param_indices) in seen_params { + if param_indices.len() > 1 { + return Err(InvalidOpaqueTypeArgs::DuplicateParam { + opaque_type_key, + param_indices, + span, + }); } } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index ef64da131891..3601c2cba9b5 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -104,10 +104,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< .map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect()) } - fn clone_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { - self.0.clone_opaque_types_for_query_response() - } - fn make_deduplicated_outlives_constraints( &self, ) -> Vec>> { @@ -153,18 +149,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.instantiate_canonical_var(span, cv_info, universe_map) } - fn register_hidden_type_in_storage( - &self, - opaque_type_key: ty::OpaqueTypeKey<'tcx>, - hidden_ty: ::Ty, - span: ::Span, - ) -> Option<::Ty> { - self.0.register_hidden_type_in_storage( - opaque_type_key, - ty::OpaqueHiddenType { span, ty: hidden_ty }, - ) - } - fn add_item_bounds_for_hidden_type( &self, def_id: DefId, @@ -176,10 +160,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.add_item_bounds_for_hidden_type(def_id, args, param_env, hidden_ty, goals); } - fn reset_opaque_types(&self) { - let _ = self.take_opaque_types(); - } - fn fetch_eligible_assoc_item( &self, goal_trait_ref: ty::TraitRef<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 2d445dd07900..f64cd5ffebe3 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -99,7 +99,13 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { (FulfillmentErrorCode::Ambiguity { overflow: None }, true) } - Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( + Ok(( + _, + Certainty::Maybe(MaybeCause::Overflow { + suggest_increasing_limit, + keep_constraints: _, + }), + )) => ( FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, // Don't look into overflows because we treat overflows weirdly anyways. // We discard the inference constraints from overflowing goals, so diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 24b87000e32b..9795655e8422 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -382,7 +382,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { if let Some(term_hack) = normalizes_to_term_hack { infcx .probe(|_| term_hack.constrain(infcx, DUMMY_SP, uncanonicalized_goal.param_env)) - .map(|certainty| ok.value.certainty.unify_with(certainty)) + .map(|certainty| ok.value.certainty.and(certainty)) } else { Ok(ok.value.certainty) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 0987c5b42d88..5b938456e03b 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -51,7 +51,7 @@ pub use self::dyn_compatibility::{ pub use self::engine::{ObligationCtxt, TraitEngineExt}; pub use self::fulfill::{FulfillmentContext, OldSolverError, PendingPredicateObligation}; pub use self::normalize::NormalizeExt; -pub use self::project::{normalize_inherent_projection, normalize_projection_ty}; +pub use self::project::{normalize_inherent_projection, normalize_projection_term}; pub use self::select::{ EvaluationCache, EvaluationResult, IntercrateAmbiguityCause, OverflowError, SelectionCache, SelectionContext, diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 5f0acd46f86a..88a0c402702e 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -1,6 +1,7 @@ //! Deeply normalize types using the old trait solver. use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_hir::def::DefKind; use rustc_infer::infer::at::At; use rustc_infer::infer::{InferCtxt, InferOk}; use rustc_infer::traits::{ @@ -10,15 +11,12 @@ use rustc_macros::extension; use rustc_middle::span_bug; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, - TypingMode, + self, AliasTerm, Term, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, + TypeVisitableExt, TypingMode, }; use tracing::{debug, instrument}; -use super::{ - BoundVarReplacer, PlaceholderReplacer, SelectionContext, project, - with_replaced_escaping_bound_vars, -}; +use super::{BoundVarReplacer, PlaceholderReplacer, SelectionContext, project}; use crate::error_reporting::InferCtxtErrorExt; use crate::error_reporting::traits::OverflowCause; use crate::solve::NextSolverError; @@ -178,6 +176,163 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { if !needs_normalization(self.selcx.infcx, &value) { value } else { value.fold_with(self) } } + + // FIXME(mgca): While this supports constants, it is only used for types by default right now + #[instrument(level = "debug", skip(self), ret)] + fn normalize_trait_projection(&mut self, proj: AliasTerm<'tcx>) -> Term<'tcx> { + if !proj.has_escaping_bound_vars() { + // When we don't have escaping bound vars we can normalize ambig aliases + // to inference variables (done in `normalize_projection_ty`). This would + // be wrong if there were escaping bound vars as even if we instantiated + // the bound vars with placeholders, we wouldn't be able to map them back + // after normalization succeeded. + // + // Also, as an optimization: when we don't have escaping bound vars, we don't + // need to replace them with placeholders (see branch below). + let proj = proj.fold_with(self); + project::normalize_projection_term( + self.selcx, + self.param_env, + proj, + self.cause.clone(), + self.depth, + self.obligations, + ) + } else { + // If there are escaping bound vars, we temporarily replace the + // bound vars with placeholders. Note though, that in the case + // that we still can't project for whatever reason (e.g. self + // type isn't known enough), we *can't* register an obligation + // and return an inference variable (since then that obligation + // would have bound vars and that's a can of worms). Instead, + // we just give up and fall back to pretending like we never tried! + // + // Note: this isn't necessarily the final approach here; we may + // want to figure out how to register obligations with escaping vars + // or handle this some other way. + let infcx = self.selcx.infcx; + let (proj, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, proj); + let proj = proj.fold_with(self); + let normalized_term = project::opt_normalize_projection_term( + self.selcx, + self.param_env, + proj, + self.cause.clone(), + self.depth, + self.obligations, + ) + .ok() + .flatten() + .unwrap_or(proj.to_term(infcx.tcx)); + + PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + normalized_term, + ) + } + } + + // FIXME(mgca): While this supports constants, it is only used for types by default right now + #[instrument(level = "debug", skip(self), ret)] + fn normalize_inherent_projection(&mut self, inherent: AliasTerm<'tcx>) -> Term<'tcx> { + if !inherent.has_escaping_bound_vars() { + // When we don't have escaping bound vars we can normalize ambig aliases + // to inference variables (done in `normalize_projection_ty`). This would + // be wrong if there were escaping bound vars as even if we instantiated + // the bound vars with placeholders, we wouldn't be able to map them back + // after normalization succeeded. + // + // Also, as an optimization: when we don't have escaping bound vars, we don't + // need to replace them with placeholders (see branch below). + + let inherent = inherent.fold_with(self); + project::normalize_inherent_projection( + self.selcx, + self.param_env, + inherent, + self.cause.clone(), + self.depth, + self.obligations, + ) + } else { + let infcx = self.selcx.infcx; + let (inherent, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, inherent); + let inherent = inherent.fold_with(self); + let inherent = project::normalize_inherent_projection( + self.selcx, + self.param_env, + inherent, + self.cause.clone(), + self.depth, + self.obligations, + ); + + PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + inherent, + ) + } + } + + // FIXME(mgca): While this supports constants, it is only used for types by default right now + #[instrument(level = "debug", skip(self), ret)] + fn normalize_free_alias(&mut self, free: AliasTerm<'tcx>) -> Term<'tcx> { + let recursion_limit = self.cx().recursion_limit(); + if !recursion_limit.value_within_limit(self.depth) { + self.selcx.infcx.err_ctxt().report_overflow_error( + OverflowCause::DeeplyNormalize(free.into()), + self.cause.span, + false, + |diag| { + diag.note(crate::fluent_generated::trait_selection_ty_alias_overflow); + }, + ); + } + + let infcx = self.selcx.infcx; + self.obligations.extend( + // FIXME(BoxyUwU): + // FIXME(lazy_type_alias): + // It seems suspicious to instantiate the predicates with arguments that might be bound vars, + // we might wind up instantiating one of these bound vars underneath a hrtb. + infcx.tcx.predicates_of(free.def_id).instantiate_own(infcx.tcx, free.args).map( + |(mut predicate, span)| { + if free.has_escaping_bound_vars() { + (predicate, ..) = BoundVarReplacer::replace_bound_vars( + infcx, + &mut self.universes, + predicate, + ); + } + let mut cause = self.cause.clone(); + cause.map_code(|code| ObligationCauseCode::TypeAlias(code, span, free.def_id)); + Obligation::new(infcx.tcx, cause, self.param_env, predicate) + }, + ), + ); + self.depth += 1; + let res = if free.kind(infcx.tcx).is_type() { + infcx.tcx.type_of(free.def_id).instantiate(infcx.tcx, free.args).fold_with(self).into() + } else { + // FIXME(mgca): once const items are actual aliases defined as equal to type system consts + // this should instead use that rather than evaluating. + super::evaluate_const(infcx, free.to_term(infcx.tcx).expect_const(), self.param_env) + .super_fold_with(self) + .into() + }; + self.depth -= 1; + res + } } impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx> { @@ -259,186 +414,63 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx } } - ty::Projection if !data.has_escaping_bound_vars() => { - // When we don't have escaping bound vars we can normalize ambig aliases - // to inference variables (done in `normalize_projection_ty`). This would - // be wrong if there were escaping bound vars as even if we instantiated - // the bound vars with placeholders, we wouldn't be able to map them back - // after normalization succeeded. - // - // Also, as an optimization: when we don't have escaping bound vars, we don't - // need to replace them with placeholders (see branch below). - let data = data.fold_with(self); - let normalized_ty = project::normalize_projection_ty( - self.selcx, - self.param_env, - data, - self.cause.clone(), - self.depth, - self.obligations, - ); - debug!( - ?self.depth, - ?ty, - ?normalized_ty, - obligations.len = ?self.obligations.len(), - "AssocTypeNormalizer: normalized type" - ); - normalized_ty.expect_type() - } - - ty::Projection => { - // If there are escaping bound vars, we temporarily replace the - // bound vars with placeholders. Note though, that in the case - // that we still can't project for whatever reason (e.g. self - // type isn't known enough), we *can't* register an obligation - // and return an inference variable (since then that obligation - // would have bound vars and that's a can of worms). Instead, - // we just give up and fall back to pretending like we never tried! - // - // Note: this isn't necessarily the final approach here; we may - // want to figure out how to register obligations with escaping vars - // or handle this some other way. - - let infcx = self.selcx.infcx; - let (data, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); - let data = data.fold_with(self); - let normalized_ty = project::opt_normalize_projection_term( - self.selcx, - self.param_env, - data.into(), - self.cause.clone(), - self.depth, - self.obligations, - ) - .ok() - .flatten() - .map(|term| term.expect_type()) - .map(|normalized_ty| { - PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - normalized_ty, - ) - }) - .unwrap_or_else(|| ty.super_fold_with(self)); - - debug!( - ?self.depth, - ?ty, - ?normalized_ty, - obligations.len = ?self.obligations.len(), - "AssocTypeNormalizer: normalized type" - ); - normalized_ty - } - ty::Free => { - let recursion_limit = self.cx().recursion_limit(); - if !recursion_limit.value_within_limit(self.depth) { - self.selcx.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(data.into()), - self.cause.span, - false, - |diag| { - diag.note(crate::fluent_generated::trait_selection_ty_alias_overflow); - }, - ); - } - - let infcx = self.selcx.infcx; - self.obligations.extend( - infcx.tcx.predicates_of(data.def_id).instantiate_own(infcx.tcx, data.args).map( - |(mut predicate, span)| { - if data.has_escaping_bound_vars() { - (predicate, ..) = BoundVarReplacer::replace_bound_vars( - infcx, - &mut self.universes, - predicate, - ); - } - let mut cause = self.cause.clone(); - cause.map_code(|code| { - ObligationCauseCode::TypeAlias(code, span, data.def_id) - }); - Obligation::new(infcx.tcx, cause, self.param_env, predicate) - }, - ), - ); - self.depth += 1; - let res = infcx - .tcx - .type_of(data.def_id) - .instantiate(infcx.tcx, data.args) - .fold_with(self); - self.depth -= 1; - res - } - - ty::Inherent if !data.has_escaping_bound_vars() => { - // This branch is *mostly* just an optimization: when we don't - // have escaping bound vars, we don't need to replace them with - // placeholders (see branch below). *Also*, we know that we can - // register an obligation to *later* project, since we know - // there won't be bound vars there. - - let data = data.fold_with(self); - - project::normalize_inherent_projection( - self.selcx, - self.param_env, - data, - self.cause.clone(), - self.depth, - self.obligations, - ) - } - - ty::Inherent => { - let infcx = self.selcx.infcx; - let (data, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); - let data = data.fold_with(self); - let ty = project::normalize_inherent_projection( - self.selcx, - self.param_env, - data, - self.cause.clone(), - self.depth, - self.obligations, - ); - - PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - ty, - ) - } + ty::Projection => self.normalize_trait_projection(data.into()).expect_type(), + ty::Inherent => self.normalize_inherent_projection(data.into()).expect_type(), + ty::Free => self.normalize_free_alias(data.into()).expect_type(), } } #[instrument(skip(self), level = "debug")] - fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> { + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { let tcx = self.selcx.tcx(); - if tcx.features().generic_const_exprs() || !needs_normalization(self.selcx.infcx, &constant) - { - constant + if tcx.features().generic_const_exprs() || !needs_normalization(self.selcx.infcx, &ct) { + return ct; + } + + // Doing "proper" normalization of const aliases is inherently cyclic until const items + // are real aliases instead of having bodies. We gate proper const alias handling behind + // mgca to avoid breaking stable code, though this should become the "main" codepath long + // before mgca is stabilized. + // + // FIXME(BoxyUwU): Enabling this by default is blocked on a refactoring to how const items + // are represented. + if tcx.features().min_generic_const_args() { + let uv = match ct.kind() { + ty::ConstKind::Unevaluated(uv) => uv, + _ => return ct.super_fold_with(self), + }; + + let ct = match tcx.def_kind(uv.def) { + DefKind::AssocConst => match tcx.def_kind(tcx.parent(uv.def)) { + DefKind::Trait => self.normalize_trait_projection(uv.into()), + DefKind::Impl { of_trait: false } => { + self.normalize_inherent_projection(uv.into()) + } + kind => unreachable!( + "unexpected `DefKind` for const alias' resolution's parent def: {:?}", + kind + ), + }, + DefKind::Const | DefKind::AnonConst => self.normalize_free_alias(uv.into()), + kind => { + unreachable!("unexpected `DefKind` for const alias to resolve to: {:?}", kind) + } + }; + + // We re-fold the normalized const as the `ty` field on `ConstKind::Value` may be + // unnormalized after const evaluation returns. + ct.expect_const().super_fold_with(self) } else { - let constant = constant.super_fold_with(self); - debug!(?constant, ?self.param_env); - with_replaced_escaping_bound_vars( + let ct = ct.super_fold_with(self); + return super::with_replaced_escaping_bound_vars( self.selcx.infcx, &mut self.universes, - constant, - |constant| super::evaluate_const(self.selcx.infcx, constant, self.param_env), + ct, + |ct| super::evaluate_const(self.selcx.infcx, ct, self.param_env), ) - .super_fold_with(self) + .super_fold_with(self); + // We re-fold the normalized const as the `ty` field on `ConstKind::Value` may be + // unnormalized after const evaluation returns. } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index dd868c9d40ea..ca58da5ca6d5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -5,7 +5,6 @@ use std::ops::ControlFlow; use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::resolve::OpportunisticRegionResolver; @@ -172,6 +171,7 @@ pub(super) enum ProjectAndUnifyResult<'tcx> { /// ``` /// If successful, this may result in additional obligations. Also returns /// the projection cache key used to track these additional obligations. +// FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "debug", skip(selcx))] pub(super) fn poly_project_and_unify_term<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, @@ -201,6 +201,7 @@ pub(super) fn poly_project_and_unify_term<'cx, 'tcx>( /// If successful, this may result in additional obligations. /// /// See [poly_project_and_unify_term] for an explanation of the return value. +// FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "debug", skip(selcx))] fn project_and_unify_term<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, @@ -258,34 +259,28 @@ fn project_and_unify_term<'cx, 'tcx>( /// there are unresolved type variables in the projection, we will /// instantiate it with a fresh type variable `$X` and generate a new /// obligation `::Item == $X` for later. -pub fn normalize_projection_ty<'a, 'b, 'tcx>( +// FIXME(mgca): While this supports constants, it is only used for types by default right now +pub fn normalize_projection_term<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::AliasTy<'tcx>, + alias_term: ty::AliasTerm<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &mut PredicateObligations<'tcx>, ) -> Term<'tcx> { - opt_normalize_projection_term( - selcx, - param_env, - projection_ty.into(), - cause.clone(), - depth, - obligations, - ) - .ok() - .flatten() - .unwrap_or_else(move || { - // if we bottom out in ambiguity, create a type variable - // and a deferred predicate to resolve this when more type - // information is available. + opt_normalize_projection_term(selcx, param_env, alias_term, cause.clone(), depth, obligations) + .ok() + .flatten() + .unwrap_or_else(move || { + // if we bottom out in ambiguity, create a type variable + // and a deferred predicate to resolve this when more type + // information is available. - selcx - .infcx - .projection_ty_to_infer(param_env, projection_ty, cause, depth + 1, obligations) - .into() - }) + selcx + .infcx + .projection_term_to_infer(param_env, alias_term, cause, depth + 1, obligations) + .into() + }) } /// The guts of `normalize`: normalize a specific projection like `( /// often immediately appended to another obligations vector. So now this /// function takes an obligations vector and appends to it directly, which is /// slightly uglier but avoids the need for an extra short-lived allocation. +// FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, @@ -456,6 +452,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( /// an error for this obligation, but we legitimately should not, /// because it contains `[type error]`. Yuck! (See issue #29857 for /// one case where this arose.) +// FIXME(mgca): While this supports constants, it is only used for types by default right now fn normalize_to_error<'a, 'tcx>( selcx: &SelectionContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -469,9 +466,10 @@ fn normalize_to_error<'a, 'tcx>( | ty::AliasTermKind::InherentTy | ty::AliasTermKind::OpaqueTy | ty::AliasTermKind::FreeTy => selcx.infcx.next_ty_var(cause.span).into(), - ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => { - selcx.infcx.next_const_var(cause.span).into() - } + ty::AliasTermKind::FreeConst + | ty::AliasTermKind::InherentConst + | ty::AliasTermKind::UnevaluatedConst + | ty::AliasTermKind::ProjectionConst => selcx.infcx.next_const_var(cause.span).into(), }; let mut obligations = PredicateObligations::new(); obligations.push(Obligation { @@ -484,36 +482,37 @@ fn normalize_to_error<'a, 'tcx>( } /// Confirm and normalize the given inherent projection. +// FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] pub fn normalize_inherent_projection<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, - alias_ty: ty::AliasTy<'tcx>, + alias_term: ty::AliasTerm<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &mut PredicateObligations<'tcx>, -) -> Ty<'tcx> { +) -> ty::Term<'tcx> { let tcx = selcx.tcx(); if !tcx.recursion_limit().value_within_limit(depth) { // Halt compilation because it is important that overflows never be masked. tcx.dcx().emit_fatal(InherentProjectionNormalizationOverflow { span: cause.span, - ty: alias_ty.to_string(), + ty: alias_term.to_string(), }); } - let args = compute_inherent_assoc_ty_args( + let args = compute_inherent_assoc_term_args( selcx, param_env, - alias_ty, + alias_term, cause.clone(), depth, obligations, ); // Register the obligations arising from the impl and from the associated type itself. - let predicates = tcx.predicates_of(alias_ty.def_id).instantiate(tcx, args); + let predicates = tcx.predicates_of(alias_term.def_id).instantiate(tcx, args); for (predicate, span) in predicates { let predicate = normalize_with_depth_to( selcx, @@ -531,7 +530,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( // cause code, inherent projections will be printed with identity instantiation in // diagnostics which is not ideal. // Consider creating separate cause codes for this specific situation. - ObligationCauseCode::WhereClause(alias_ty.def_id, span), + ObligationCauseCode::WhereClause(alias_term.def_id, span), ); obligations.push(Obligation::with_depth( @@ -543,27 +542,33 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( )); } - let ty = tcx.type_of(alias_ty.def_id).instantiate(tcx, args); + let term: Term<'tcx> = if alias_term.kind(tcx).is_type() { + tcx.type_of(alias_term.def_id).instantiate(tcx, args).into() + } else { + get_associated_const_value(selcx, alias_term.to_term(tcx).expect_const(), param_env).into() + }; - let mut ty = selcx.infcx.resolve_vars_if_possible(ty); - if ty.has_aliases() { - ty = normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, ty, obligations); + let mut term = selcx.infcx.resolve_vars_if_possible(term); + if term.has_aliases() { + term = + normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, term, obligations); } - ty + term } -pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>( +// FIXME(mgca): While this supports constants, it is only used for types by default right now +pub fn compute_inherent_assoc_term_args<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, - alias_ty: ty::AliasTy<'tcx>, + alias_term: ty::AliasTerm<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &mut PredicateObligations<'tcx>, ) -> ty::GenericArgsRef<'tcx> { let tcx = selcx.tcx(); - let impl_def_id = tcx.parent(alias_ty.def_id); + let impl_def_id = tcx.parent(alias_term.def_id); let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id); let mut impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args); @@ -580,7 +585,7 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>( // Infer the generic parameters of the impl by unifying the // impl type with the self type of the projection. - let mut self_ty = alias_ty.self_ty(); + let mut self_ty = alias_term.self_ty(); if !selcx.infcx.next_trait_solver() { self_ty = normalize_with_depth_to( selcx, @@ -602,7 +607,7 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>( } } - alias_ty.rebase_inherent_args_onto_impl(impl_args, tcx) + alias_term.rebase_inherent_args_onto_impl(impl_args, tcx) } enum Projected<'tcx> { @@ -630,6 +635,7 @@ impl<'tcx> Progress<'tcx> { /// /// IMPORTANT: /// - `obligation` must be fully normalized +// FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "info", skip(selcx))] fn project<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, @@ -896,7 +902,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( ImplSource::UserDefined(impl_data) => { // We have to be careful when projecting out of an // impl because of specialization. If we are not in - // codegen (i.e., projection mode is not "any"), and the + // codegen (i.e., `TypingMode` is not `PostAnalysis`), and the // impl's type is declared as default, then we disable // projection (even if the trait ref is fully // monomorphic). In the case where trait ref is not @@ -1189,6 +1195,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( }); } +// FIXME(mgca): While this supports constants, it is only used for types by default right now fn confirm_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, @@ -1222,6 +1229,7 @@ fn confirm_candidate<'cx, 'tcx>( result } +// FIXME(mgca): While this supports constants, it is only used for types by default right now fn confirm_select_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, @@ -1873,6 +1881,7 @@ fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>( .with_addl_obligations(nested) } +// FIXME(mgca): While this supports constants, it is only used for types by default right now fn confirm_param_env_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, @@ -1926,9 +1935,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ) { Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); - assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); - // FIXME(associated_const_equality): Handle consts here as well? Maybe this progress type should just take - // a term instead. + assoc_term_own_obligations(selcx, obligation, &mut nested_obligations); Progress { term: cache_entry.term, obligations: nested_obligations } } Err(e) => { @@ -1942,6 +1949,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( } } +// FIXME(mgca): While this supports constants, it is only used for types by default right now fn confirm_impl_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, @@ -1955,8 +1963,8 @@ fn confirm_impl_candidate<'cx, 'tcx>( let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); let param_env = obligation.param_env; - let assoc_ty = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) { - Ok(assoc_ty) => assoc_ty, + let assoc_term = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) { + Ok(assoc_term) => assoc_term, Err(guar) => return Ok(Projected::Progress(Progress::error(tcx, guar))), }; @@ -1965,10 +1973,10 @@ fn confirm_impl_candidate<'cx, 'tcx>( // has impossible-to-satisfy predicates (since those were // allowed in ), // or because the impl is literally missing the definition. - if !assoc_ty.item.defaultness(tcx).has_value() { + if !assoc_term.item.defaultness(tcx).has_value() { debug!( "confirm_impl_candidate: no associated type {:?} for {:?}", - assoc_ty.item.name(), + assoc_term.item.name(), obligation.predicate ); if tcx.impl_self_is_guaranteed_unsized(impl_def_id) { @@ -1979,7 +1987,11 @@ fn confirm_impl_candidate<'cx, 'tcx>( return Ok(Projected::NoProgress(obligation.predicate.to_term(tcx))); } else { return Ok(Projected::Progress(Progress { - term: Ty::new_misc_error(tcx).into(), + term: if obligation.predicate.kind(tcx).is_type() { + Ty::new_misc_error(tcx).into() + } else { + ty::Const::new_misc_error(tcx).into() + }, obligations: nested, })); } @@ -1992,27 +2004,32 @@ fn confirm_impl_candidate<'cx, 'tcx>( // * `args` is `[u32]` // * `args` ends up as `[u32, S]` let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args); - let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node); - let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst); + let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_term.defining_node); - let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const { - let did = assoc_ty.item.def_id; - let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did); - let uv = ty::UnevaluatedConst::new(did, identity_args); - ty::EarlyBinder::bind(ty::Const::new_unevaluated(tcx, uv).into()) + let term = if obligation.predicate.kind(tcx).is_type() { + tcx.type_of(assoc_term.item.def_id).map_bound(|ty| ty.into()) } else { - tcx.type_of(assoc_ty.item.def_id).map_bound(|ty| ty.into()) + ty::EarlyBinder::bind( + get_associated_const_value( + selcx, + obligation.predicate.to_term(tcx).expect_const(), + param_env, + ) + .into(), + ) }; - let progress = if !tcx.check_args_compatible(assoc_ty.item.def_id, args) { - let err = Ty::new_error_with_message( - tcx, - obligation.cause.span, - "impl item and trait item have different parameters", - ); - Progress { term: err.into(), obligations: nested } + let progress = if !tcx.check_args_compatible(assoc_term.item.def_id, args) { + let msg = "impl item and trait item have different parameters"; + let span = obligation.cause.span; + let err = if obligation.predicate.kind(tcx).is_type() { + Ty::new_error_with_message(tcx, span, msg).into() + } else { + ty::Const::new_error_with_message(tcx, span, msg).into() + }; + Progress { term: err, obligations: nested } } else { - assoc_ty_own_obligations(selcx, obligation, &mut nested); + assoc_term_own_obligations(selcx, obligation, &mut nested); Progress { term: term.instantiate(tcx, args), obligations: nested } }; Ok(Projected::Progress(progress)) @@ -2020,7 +2037,8 @@ fn confirm_impl_candidate<'cx, 'tcx>( // Get obligations corresponding to the predicates from the where-clause of the // associated type itself. -fn assoc_ty_own_obligations<'cx, 'tcx>( +// FIXME(mgca): While this supports constants, it is only used for types by default right now +fn assoc_term_own_obligations<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, nested: &mut PredicateObligations<'tcx>, @@ -2090,3 +2108,15 @@ impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> { }) } } + +fn get_associated_const_value<'tcx>( + selcx: &mut SelectionContext<'_, 'tcx>, + alias_ct: ty::Const<'tcx>, + param_env: ty::ParamEnv<'tcx>, +) -> ty::Const<'tcx> { + // FIXME(mgca): We shouldn't be invoking ctfe here, instead const items should be aliases to type + // system consts that we can retrieve with some `query const_arg_of_alias` query. Evaluating the + // constant is "close enough" to getting the actual rhs of the const item for now even if it might + // lead to some cycles + super::evaluate_const(selcx.infcx, alias_ct, param_env) +} diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index a54eb80fedc2..eb34cb10c68d 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -9,7 +9,7 @@ use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; use rustc_middle::ty::{ self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + TypeVisitableExt, TypeVisitor, TypingMode, }; use rustc_span::DUMMY_SP; use tracing::{debug, info, instrument}; @@ -127,7 +127,7 @@ struct MaxEscapingBoundVarVisitor { } impl<'tcx> TypeVisitor> for MaxEscapingBoundVarVisitor { - fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { self.outer_index.shift_in(1); t.super_visit_with(self); self.outer_index.shift_out(1); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 8008c7e4d342..94190cd3ae33 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -406,7 +406,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let mut assume = predicate.trait_ref.args.const_at(2); - // FIXME(mgca): We should shallowly normalize this. if self.tcx().features().generic_const_exprs() { assume = crate::traits::evaluate_const(self.infcx, assume, obligation.param_env) } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 2e32cda7602e..08d3b92e9b5e 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -6,6 +6,7 @@ use std::iter; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_middle::bug; @@ -486,7 +487,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// Pushes the obligations required for an inherent alias to be WF /// into `self.out`. // FIXME(inherent_associated_types): Merge this function with `fn compute_alias`. - fn add_wf_preds_for_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) { + fn add_wf_preds_for_inherent_projection(&mut self, data: ty::AliasTerm<'tcx>) { // An inherent projection is well-formed if // // (a) its predicates hold (*) @@ -498,7 +499,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { if !data.self_ty().has_escaping_bound_vars() { // FIXME(inherent_associated_types): Should this happen inside of a snapshot? // FIXME(inherent_associated_types): This is incompatible with the new solver and lazy norm! - let args = traits::project::compute_inherent_assoc_ty_args( + let args = traits::project::compute_inherent_assoc_term_args( &mut traits::SelectionContext::new(self.infcx), self.param_env, data, @@ -776,7 +777,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { self.out.extend(obligations); } ty::Alias(ty::Inherent, data) => { - self.add_wf_preds_for_inherent_projection(data); + self.add_wf_preds_for_inherent_projection(data.into()); return; // Subtree handled by compute_inherent_projection. } @@ -961,9 +962,6 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { match c.kind() { ty::ConstKind::Unevaluated(uv) => { if !c.has_escaping_bound_vars() { - let obligations = self.nominal_obligations(uv.def, uv.args); - self.out.extend(obligations); - let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::ConstEvaluatable(c), )); @@ -975,6 +973,16 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { self.param_env, predicate, )); + + if tcx.def_kind(uv.def) == DefKind::AssocConst + && tcx.def_kind(tcx.parent(uv.def)) == (DefKind::Impl { of_trait: false }) + { + self.add_wf_preds_for_inherent_projection(uv.into()); + return; // Subtree is handled by above function + } else { + let obligations = self.nominal_obligations(uv.def, uv.args); + self.out.extend(obligations); + } } } ty::ConstKind::Infer(_) => { diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 14a92ebb9f96..e52898cc6e24 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -32,8 +32,14 @@ fn normalize_canonicalized_projection_ty<'tcx>( let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); let mut obligations = PredicateObligations::new(); - let answer = - traits::normalize_projection_ty(selcx, param_env, goal, cause, 0, &mut obligations); + let answer = traits::normalize_projection_term( + selcx, + param_env, + goal.into(), + cause, + 0, + &mut obligations, + ); ocx.register_obligations(obligations); // #112047: With projections and opaques, we are able to create opaques that // are recursive (given some generic parameters of the opaque's type variables). @@ -104,14 +110,14 @@ fn normalize_canonicalized_inherent_projection_ty<'tcx>( let answer = traits::normalize_inherent_projection( selcx, param_env, - goal, + goal.into(), cause, 0, &mut obligations, ); ocx.register_obligations(obligations); - Ok(NormalizationResult { normalized_ty: answer }) + Ok(NormalizationResult { normalized_ty: answer.expect_type() }) }, ) } diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 6cb9fdc6f931..f14a45aa1e3b 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -1,6 +1,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; +use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, AmbigArg}; use rustc_middle::query::Providers; @@ -159,6 +160,22 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A container: ty::AssocItemContainer::Impl, } } +struct RPITVisitor { + rpits: FxIndexSet, +} + +impl<'tcx> Visitor<'tcx> for RPITVisitor { + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { + if let hir::TyKind::OpaqueDef(opaq) = ty.kind + && self.rpits.insert(opaq.def_id) + { + for bound in opaq.bounds { + intravisit::walk_param_bound(self, bound); + } + } + intravisit::walk_ty(self, ty) + } +} /// Given an `fn_def_id` of a trait or a trait implementation: /// @@ -177,23 +194,6 @@ fn associated_types_for_impl_traits_in_associated_fn( match tcx.def_kind(parent_def_id) { DefKind::Trait => { - struct RPITVisitor { - rpits: FxIndexSet, - } - - impl<'tcx> Visitor<'tcx> for RPITVisitor { - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { - if let hir::TyKind::OpaqueDef(opaq) = ty.kind - && self.rpits.insert(opaq.def_id) - { - for bound in opaq.bounds { - intravisit::walk_param_bound(self, bound); - } - } - intravisit::walk_ty(self, ty) - } - } - let mut visitor = RPITVisitor { rpits: FxIndexSet::default() }; if let Some(output) = tcx.hir_get_fn_output(fn_def_id) { @@ -246,9 +246,23 @@ fn associated_type_for_impl_trait_in_trait( let trait_def_id = tcx.local_parent(fn_def_id); assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait); + // Collect all opaque types in return position for the method and use + // the index as the disambiguator to make an unique def path. + let mut visitor = RPITVisitor { rpits: FxIndexSet::default() }; + visitor.visit_fn_ret_ty(tcx.hir_get_fn_output(fn_def_id).unwrap()); + let disambiguator = visitor.rpits.get_index_of(&opaque_ty_def_id).unwrap().try_into().unwrap(); + let span = tcx.def_span(opaque_ty_def_id); - // No name because this is an anonymous associated type. - let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, None, DefKind::AssocTy); + // Also use the method name to create an unique def path. + let data = DefPathData::AnonAssocTy(tcx.item_name(fn_def_id.to_def_id())); + let trait_assoc_ty = tcx.at(span).create_def( + trait_def_id, + // No name because this is an anonymous associated type. + None, + DefKind::AssocTy, + Some(data), + &mut DisambiguatorState::with(trait_def_id, data, disambiguator), + ); let local_def_id = trait_assoc_ty.def_id(); let def_id = local_def_id.to_def_id(); @@ -299,8 +313,22 @@ fn associated_type_for_impl_trait_in_impl( hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id), hir::FnRetTy::Return(ty) => ty.span, }; - // No name because this is an anonymous associated type. - let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, None, DefKind::AssocTy); + + // Use the same disambiguator and method name as the anon associated type in the trait. + let disambiguated_data = tcx.def_key(trait_assoc_def_id).disambiguated_data; + let DefPathData::AnonAssocTy(name) = disambiguated_data.data else { + bug!("expected anon associated type") + }; + let data = DefPathData::AnonAssocTy(name); + + let impl_assoc_ty = tcx.at(span).create_def( + impl_local_def_id, + // No name because this is an anonymous associated type. + None, + DefKind::AssocTy, + Some(data), + &mut DisambiguatorState::with(impl_local_def_id, data, disambiguated_data.disambiguator), + ); let local_def_id = impl_assoc_ty.def_id(); let def_id = local_def_id.to_def_id(); diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index da83566dad02..166e8f193429 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -235,7 +235,7 @@ fn resolve_associated_item<'tcx>( tcx.ensure_ok().compare_impl_item(leaf_def_item)?; } - Some(ty::Instance::new(leaf_def.item.def_id, args)) + Some(ty::Instance::new_raw(leaf_def.item.def_id, args)) } traits::ImplSource::Builtin(BuiltinImplSource::Object(_), _) => { let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_args); @@ -280,7 +280,7 @@ fn resolve_associated_item<'tcx>( // Use the default `fn clone_from` from `trait Clone`. let args = tcx.erase_regions(rcvr_args); - Some(ty::Instance::new(trait_item_id, args)) + Some(ty::Instance::new_raw(trait_item_id, args)) } } else if tcx.is_lang_item(trait_ref.def_id, LangItem::FnPtrTrait) { if tcx.is_lang_item(trait_item_id, LangItem::FnPtrAddr) { @@ -329,7 +329,7 @@ fn resolve_associated_item<'tcx>( // sync with the built-in trait implementations (since all of the // implementations return `FnOnce::Output`). if ty::ClosureKind::FnOnce == args.as_coroutine_closure().kind() { - Some(Instance::new(coroutine_closure_def_id, args)) + Some(Instance::new_raw(coroutine_closure_def_id, args)) } else { Some(Instance { def: ty::InstanceKind::ConstructCoroutineInClosureShim { @@ -362,7 +362,7 @@ fn resolve_associated_item<'tcx>( args, }) } else { - Some(Instance::new(coroutine_closure_def_id, args)) + Some(Instance::new_raw(coroutine_closure_def_id, args)) } } ty::Closure(closure_def_id, args) => { @@ -381,7 +381,7 @@ fn resolve_associated_item<'tcx>( let name = tcx.item_name(trait_item_id); assert_eq!(name, sym::transmute); let args = tcx.erase_regions(rcvr_args); - Some(ty::Instance::new(trait_item_id, args)) + Some(ty::Instance::new_raw(trait_item_id, args)) } else { Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args) } diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index ea0f6b8dfba7..f79b6d44bfdf 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -29,10 +29,10 @@ mod implied_bounds; mod instance; mod layout; mod needs_drop; +mod nested_bodies; mod opaque_types; mod representability; pub mod sig_types; -mod stalled_generators; mod structural_match; mod ty; @@ -51,5 +51,5 @@ pub fn provide(providers: &mut Providers) { ty::provide(providers); instance::provide(providers); structural_match::provide(providers); - stalled_generators::provide(providers); + nested_bodies::provide(providers); } diff --git a/compiler/rustc_ty_utils/src/nested_bodies.rs b/compiler/rustc_ty_utils/src/nested_bodies.rs new file mode 100644 index 000000000000..7c74d8eb6351 --- /dev/null +++ b/compiler/rustc_ty_utils/src/nested_bodies.rs @@ -0,0 +1,34 @@ +use rustc_hir as hir; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::intravisit::Visitor; +use rustc_middle::query::Providers; +use rustc_middle::ty::{self, TyCtxt}; + +fn nested_bodies_within<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx ty::List { + let body = tcx.hir_body_owned_by(item); + let mut collector = + NestedBodiesVisitor { tcx, root_def_id: item.to_def_id(), nested_bodies: vec![] }; + collector.visit_body(body); + tcx.mk_local_def_ids(&collector.nested_bodies) +} + +struct NestedBodiesVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + root_def_id: DefId, + nested_bodies: Vec, +} + +impl<'tcx> Visitor<'tcx> for NestedBodiesVisitor<'tcx> { + fn visit_nested_body(&mut self, id: hir::BodyId) { + let body_def_id = self.tcx.hir_body_owner_def_id(id); + if self.tcx.typeck_root_def_id(body_def_id.to_def_id()) == self.root_def_id { + self.nested_bodies.push(body_def_id); + let body = self.tcx.hir_body(id); + self.visit_body(body); + } + } +} + +pub(super) fn provide(providers: &mut Providers) { + *providers = Providers { nested_bodies_within, ..*providers }; +} diff --git a/compiler/rustc_ty_utils/src/stalled_generators.rs b/compiler/rustc_ty_utils/src/stalled_generators.rs deleted file mode 100644 index 8b45e8b0f6f9..000000000000 --- a/compiler/rustc_ty_utils/src/stalled_generators.rs +++ /dev/null @@ -1,54 +0,0 @@ -use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit; -use rustc_hir::intravisit::Visitor; -use rustc_middle::query::Providers; -use rustc_middle::ty::{self, TyCtxt}; - -fn stalled_generators_within<'tcx>( - tcx: TyCtxt<'tcx>, - item: LocalDefId, -) -> &'tcx ty::List { - if !tcx.next_trait_solver_globally() { - return ty::List::empty(); - } - - let body = tcx.hir_body_owned_by(item); - let mut collector = - StalledGeneratorVisitor { tcx, root_def_id: item.to_def_id(), stalled_coroutines: vec![] }; - collector.visit_body(body); - tcx.mk_local_def_ids(&collector.stalled_coroutines) -} - -struct StalledGeneratorVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - root_def_id: DefId, - stalled_coroutines: Vec, -} - -impl<'tcx> Visitor<'tcx> for StalledGeneratorVisitor<'tcx> { - fn visit_nested_body(&mut self, id: hir::BodyId) { - if self.tcx.typeck_root_def_id(self.tcx.hir_body_owner_def_id(id).to_def_id()) - == self.root_def_id - { - let body = self.tcx.hir_body(id); - self.visit_body(body); - } - } - - fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { - if let hir::ExprKind::Closure(&hir::Closure { - def_id, - kind: hir::ClosureKind::Coroutine(_), - .. - }) = ex.kind - { - self.stalled_coroutines.push(def_id); - } - intravisit::walk_expr(self, ex); - } -} - -pub(super) fn provide(providers: &mut Providers) { - *providers = Providers { stalled_generators_within, ..*providers }; -} diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 31d69eef5ecf..0c49ddff39bc 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -7,7 +7,8 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, fold_regions, + self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, + fold_regions, }; use rustc_span::DUMMY_SP; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; @@ -185,7 +186,7 @@ struct ImplTraitInTraitFinder<'a, 'tcx> { } impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { - fn visit_binder>>(&mut self, binder: &ty::Binder<'tcx, T>) { + fn visit_binder>>(&mut self, binder: &ty::Binder<'tcx, T>) { self.depth.shift_in(1); binder.super_visit_with(self); self.depth.shift_out(1); diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 27ea4e211fef..000cf1e1fd8b 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -128,7 +128,7 @@ impl> TypeFoldable for Binder { } } -impl> TypeVisitable for Binder { +impl> TypeVisitable for Binder { fn visit_with>(&self, visitor: &mut V) -> V::Result { visitor.visit_binder(self) } @@ -147,7 +147,7 @@ impl> TypeSuperFoldable for Binder { } } -impl> TypeSuperVisitable for Binder { +impl> TypeSuperVisitable for Binder { fn super_visit_with>(&self, visitor: &mut V) -> V::Result { self.as_ref().skip_binder().visit_with(visitor) } @@ -292,7 +292,7 @@ impl ValidateBoundVars { impl TypeVisitor for ValidateBoundVars { type Result = ControlFlow<()>; - fn visit_binder>(&mut self, t: &Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &Binder) -> Self::Result { self.binder_index.shift_in(1); let result = t.super_visit_with(self); self.binder_index.shift_out(1); diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 8fa56c359996..c14907621173 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,3 +1,5 @@ +use std::fmt::Debug; + use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; @@ -100,7 +102,7 @@ impl TypingMode { pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode { TypingMode::Analysis { defining_opaque_types_and_generators: cx - .opaque_types_and_generators_defined_by(body_def_id), + .opaque_types_and_coroutines_defined_by(body_def_id), } } @@ -245,4 +247,32 @@ pub trait InferCtxtLike: Sized { r: ::Region, span: ::Span, ); + + type OpaqueTypeStorageEntries: Debug + Copy + Default; + fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries; + fn clone_opaque_types_lookup_table( + &self, + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + fn clone_duplicate_opaque_types( + &self, + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + fn clone_opaque_types_added_since( + &self, + prev_entries: Self::OpaqueTypeStorageEntries, + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + + fn register_hidden_type_in_storage( + &self, + opaque_type_key: ty::OpaqueTypeKey, + hidden_ty: ::Ty, + span: ::Span, + ) -> Option<::Ty>; + fn add_duplicate_opaque_type( + &self, + opaque_type_key: ty::OpaqueTypeKey, + hidden_ty: ::Ty, + span: ::Span, + ); + + fn reset_opaque_types(&self); } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 6410da1f7409..0fd2d9f3ad38 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -341,7 +341,7 @@ pub trait Interner: fn opaque_types_defined_by(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds; - fn opaque_types_and_generators_defined_by( + fn opaque_types_and_coroutines_defined_by( self, defining_anchor: Self::LocalDefId, ) -> Self::LocalDefIds; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 0411c5c2325e..b59495b93c83 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -474,10 +474,15 @@ pub enum AliasTermKind { /// Currently only used if the type alias references opaque types. /// Can always be normalized away. FreeTy, - /// An unevaluated const coming from a generic const expression. + + /// An unevaluated anonymous constants. UnevaluatedConst, /// An unevaluated const coming from an associated const. ProjectionConst, + /// A top level const item not part of a trait or impl. + FreeConst, + /// An associated const in an inherent `impl` + InherentConst, } impl AliasTermKind { @@ -486,11 +491,27 @@ impl AliasTermKind { AliasTermKind::ProjectionTy => "associated type", AliasTermKind::ProjectionConst => "associated const", AliasTermKind::InherentTy => "inherent associated type", + AliasTermKind::InherentConst => "inherent associated const", AliasTermKind::OpaqueTy => "opaque type", AliasTermKind::FreeTy => "type alias", + AliasTermKind::FreeConst => "unevaluated constant", AliasTermKind::UnevaluatedConst => "unevaluated constant", } } + + pub fn is_type(self) -> bool { + match self { + AliasTermKind::ProjectionTy + | AliasTermKind::InherentTy + | AliasTermKind::OpaqueTy + | AliasTermKind::FreeTy => true, + + AliasTermKind::UnevaluatedConst + | AliasTermKind::ProjectionConst + | AliasTermKind::InherentConst + | AliasTermKind::FreeConst => false, + } + } } impl From for AliasTermKind { @@ -566,7 +587,10 @@ impl AliasTerm { | AliasTermKind::InherentTy | AliasTermKind::OpaqueTy | AliasTermKind::FreeTy => {} - AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => { + AliasTermKind::InherentConst + | AliasTermKind::FreeConst + | AliasTermKind::UnevaluatedConst + | AliasTermKind::ProjectionConst => { panic!("Cannot turn `UnevaluatedConst` into `AliasTy`") } } @@ -603,18 +627,19 @@ impl AliasTerm { ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, ) .into(), - AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => { - I::Const::new_unevaluated( - interner, - ty::UnevaluatedConst::new(self.def_id, self.args), - ) - .into() - } + AliasTermKind::FreeConst + | AliasTermKind::InherentConst + | AliasTermKind::UnevaluatedConst + | AliasTermKind::ProjectionConst => I::Const::new_unevaluated( + interner, + ty::UnevaluatedConst::new(self.def_id, self.args), + ) + .into(), } } } -/// The following methods work only with (trait) associated type projections. +/// The following methods work only with (trait) associated term projections. impl AliasTerm { pub fn self_ty(self) -> I::Ty { self.args.type_at(0) @@ -659,6 +684,31 @@ impl AliasTerm { } } +/// The following methods work only with inherent associated term projections. +impl AliasTerm { + /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that. + /// + /// Does the following transformation: + /// + /// ```text + /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m] + /// + /// I_i impl args + /// P_j GAT args + /// ``` + pub fn rebase_inherent_args_onto_impl( + self, + impl_args: I::GenericArgs, + interner: I, + ) -> I::GenericArgs { + debug_assert!(matches!( + self.kind(interner), + AliasTermKind::InherentTy | AliasTermKind::InherentConst + )); + interner.mk_args_from_iter(impl_args.iter().chain(self.args.iter().skip(1))) + } +} + impl From> for AliasTerm { fn from(ty: ty::AliasTy) -> Self { AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () } diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index c80a567117c6..e3c4a793b37f 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -273,8 +273,10 @@ impl Relate for ty::AliasTerm { false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle )?, ty::AliasTermKind::ProjectionTy + | ty::AliasTermKind::FreeConst | ty::AliasTermKind::FreeTy | ty::AliasTermKind::InherentTy + | ty::AliasTermKind::InherentConst | ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => { relate_args_invariantly(relation, a.args, b.args)? diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 4e9b87fdf74d..2e05c23a6458 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -147,9 +147,8 @@ pub enum CandidateSource { /// For a list of all traits with builtin impls, check out the /// `EvalCtxt::assemble_builtin_impl_candidates` method. BuiltinImpl(BuiltinImplSource), - /// An assumption from the environment. - /// - /// More precisely we've used the `n-th` assumption in the `param_env`. + /// An assumption from the environment. Stores a [`ParamEnvSource`], since we + /// prefer non-global param-env candidates in candidate assembly. /// /// ## Examples /// @@ -160,7 +159,7 @@ pub enum CandidateSource { /// (x.clone(), x) /// } /// ``` - ParamEnv(usize), + ParamEnv(ParamEnvSource), /// If the self type is an alias type, e.g. an opaque type or a projection, /// we know the bounds on that alias to hold even without knowing its concrete /// underlying type. @@ -189,6 +188,14 @@ pub enum CandidateSource { CoherenceUnknowable, } +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +pub enum ParamEnvSource { + /// Preferred eagerly. + NonGlobal, + // Not considered unless there are non-global param-env candidates too. + Global, +} + #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] #[cfg_attr( feature = "nightly", @@ -266,17 +273,17 @@ impl Certainty { /// however matter for diagnostics. If `T: Foo` resulted in overflow and `T: Bar` /// in ambiguity without changing the inference state, we still want to tell the /// user that `T: Baz` results in overflow. - pub fn unify_with(self, other: Certainty) -> Certainty { + pub fn and(self, other: Certainty) -> Certainty { match (self, other) { (Certainty::Yes, Certainty::Yes) => Certainty::Yes, (Certainty::Yes, Certainty::Maybe(_)) => other, (Certainty::Maybe(_), Certainty::Yes) => self, - (Certainty::Maybe(a), Certainty::Maybe(b)) => Certainty::Maybe(a.unify_with(b)), + (Certainty::Maybe(a), Certainty::Maybe(b)) => Certainty::Maybe(a.and(b)), } } pub const fn overflow(suggest_increasing_limit: bool) -> Certainty { - Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }) + Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: false }) } } @@ -289,19 +296,58 @@ pub enum MaybeCause { /// or we hit a case where we just don't bother, e.g. `?x: Trait` goals. Ambiguity, /// We gave up due to an overflow, most often by hitting the recursion limit. - Overflow { suggest_increasing_limit: bool }, + Overflow { suggest_increasing_limit: bool, keep_constraints: bool }, } impl MaybeCause { - fn unify_with(self, other: MaybeCause) -> MaybeCause { + fn and(self, other: MaybeCause) -> MaybeCause { match (self, other) { (MaybeCause::Ambiguity, MaybeCause::Ambiguity) => MaybeCause::Ambiguity, (MaybeCause::Ambiguity, MaybeCause::Overflow { .. }) => other, (MaybeCause::Overflow { .. }, MaybeCause::Ambiguity) => self, ( - MaybeCause::Overflow { suggest_increasing_limit: a }, - MaybeCause::Overflow { suggest_increasing_limit: b }, - ) => MaybeCause::Overflow { suggest_increasing_limit: a || b }, + MaybeCause::Overflow { + suggest_increasing_limit: limit_a, + keep_constraints: keep_a, + }, + MaybeCause::Overflow { + suggest_increasing_limit: limit_b, + keep_constraints: keep_b, + }, + ) => MaybeCause::Overflow { + suggest_increasing_limit: limit_a && limit_b, + keep_constraints: keep_a && keep_b, + }, + } + } + + pub fn or(self, other: MaybeCause) -> MaybeCause { + match (self, other) { + (MaybeCause::Ambiguity, MaybeCause::Ambiguity) => MaybeCause::Ambiguity, + + // When combining ambiguity + overflow, we can keep constraints. + ( + MaybeCause::Ambiguity, + MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ }, + ) => MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: true }, + ( + MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ }, + MaybeCause::Ambiguity, + ) => MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: true }, + + ( + MaybeCause::Overflow { + suggest_increasing_limit: limit_a, + keep_constraints: keep_a, + }, + MaybeCause::Overflow { + suggest_increasing_limit: limit_b, + keep_constraints: keep_b, + }, + ) => MaybeCause::Overflow { + suggest_increasing_limit: limit_a || limit_b, + keep_constraints: keep_a || keep_b, + }, } } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 21adbffc0274..cf2e4284d10d 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -514,28 +514,6 @@ impl AliasTy { } } -/// The following methods work only with inherent associated type projections. -impl AliasTy { - /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that. - /// - /// Does the following transformation: - /// - /// ```text - /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m] - /// - /// I_i impl args - /// P_j GAT args - /// ``` - pub fn rebase_inherent_args_onto_impl( - self, - impl_args: I::GenericArgs, - interner: I, - ) -> I::GenericArgs { - debug_assert_eq!(self.kind(interner), AliasTyKind::Inherent); - interner.mk_args_from_iter(impl_args.iter().chain(self.args.iter().skip(1))) - } -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr( feature = "nightly", diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index d1ca9bdb7fbd..8ba985d2d193 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -342,7 +342,7 @@ struct HasRegionsBoundAt { // FIXME: Could be optimized to not walk into components with no escaping bound vars. impl TypeVisitor for HasRegionsBoundAt { type Result = ControlFlow<()>; - fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { self.binder.shift_in(1); t.super_visit_with(self)?; self.binder.shift_out(1); diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 2285e0e75de0..ccb84e259112 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -52,7 +52,7 @@ use smallvec::SmallVec; use thin_vec::ThinVec; use crate::inherent::*; -use crate::{self as ty, Interner, TypeFlags}; +use crate::{self as ty, Interner, TypeFlags, TypeFoldable}; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -94,7 +94,7 @@ pub trait TypeVisitor: Sized { #[cfg(not(feature = "nightly"))] type Result: VisitorResult; - fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { t.super_visit_with(self) } @@ -401,7 +401,7 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { impl TypeVisitor for HasTypeFlagsVisitor { type Result = ControlFlow; - fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { // If we're looking for the HAS_BINDER_VARS flag, check if the // binder has vars. This won't be present in the binder's bound // value, so we need to check here too. @@ -510,7 +510,7 @@ struct HasEscapingVarsVisitor { impl TypeVisitor for HasEscapingVarsVisitor { type Result = ControlFlow; - fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); diff --git a/compiler/stable_mir/Cargo.toml b/compiler/stable_mir/Cargo.toml index 3a01ee5783ee..516c8e9c718b 100644 --- a/compiler/stable_mir/Cargo.toml +++ b/compiler/stable_mir/Cargo.toml @@ -5,3 +5,9 @@ edition = "2024" [dependencies] rustc_smir = { path = "../rustc_smir" } + +[features] +# Provides access to APIs that expose internals of the rust compiler. +# APIs enabled by this feature are unstable. They can be removed or modified +# at any point and they are not included in the crate's semantic versioning. +rustc_internal = [] diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index cc0fb52433d9..688f3936b26c 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -4,4 +4,8 @@ //! This is a transitional measure as described in [PR #139319](https://github.com/rust-lang/rust/pull/139319). //! Once the refactoring is complete, the `stable_mir` implementation will be moved back here. +/// Export the rustc_internal APIs. Note that this module has no stability +/// guarantees and it is not taken into account for semver. +#[cfg(feature = "rustc_internal")] +pub use rustc_smir::rustc_internal; pub use rustc_smir::stable_mir::*; diff --git a/library/Cargo.lock b/library/Cargo.lock index f5c04a3bf48c..5100b4d8176d 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -32,12 +32,6 @@ dependencies = [ "core", ] -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - [[package]] name = "alloctests" version = "0.0.0" @@ -67,9 +61,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.156" +version = "0.1.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ffbd2789fe5bb95b96a2e22cbe3128239dc46ff0374e0d38e9f102062d7055" +checksum = "164cdc689e4c6d69417f77a5f48be240c291e84fbef0b1281755dc754b19c809" dependencies = [ "cc", "rustc-std-workspace-core", @@ -134,11 +128,10 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" dependencies = [ - "allocator-api2", "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", @@ -221,15 +214,6 @@ dependencies = [ "unwind", ] -[[package]] -name = "proc-macro2" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" -dependencies = [ - "unicode-ident", -] - [[package]] name = "proc_macro" version = "0.0.0" @@ -246,15 +230,6 @@ dependencies = [ "cc", ] -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - [[package]] name = "r-efi" version = "5.2.0" @@ -278,12 +253,11 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_core", - "zerocopy", ] [[package]] @@ -387,17 +361,6 @@ dependencies = [ "rustc-std-workspace-core", ] -[[package]] -name = "syn" -version = "2.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "sysroot" version = "0.0.0" @@ -418,12 +381,6 @@ dependencies = [ "std", ] -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - [[package]] name = "unicode-width" version = "0.1.14" @@ -544,23 +501,3 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "zerocopy" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 994221de8663..51ddc9bf9fc9 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -16,7 +16,7 @@ bench = false [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.156", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.158", features = ['rustc-dep-of-std'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 78b7da9d6b3e..5ca32ed741af 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1917,14 +1917,13 @@ pub struct ExtractIf< V, F, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, -> where - F: 'a + FnMut(&K, &mut V) -> bool, -{ +> { pred: F, inner: ExtractIfInner<'a, K, V>, /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. alloc: A, } + /// Most of the implementation of ExtractIf are generic over the type /// of the predicate, thus also serving for BTreeSet::ExtractIf. pub(super) struct ExtractIfInner<'a, K, V> { @@ -1940,14 +1939,14 @@ pub(super) struct ExtractIfInner<'a, K, V> { } #[unstable(feature = "btree_extract_if", issue = "70530")] -impl fmt::Debug for ExtractIf<'_, K, V, F> +impl fmt::Debug for ExtractIf<'_, K, V, F, A> where K: fmt::Debug, V: fmt::Debug, - F: FnMut(&K, &mut V) -> bool, + A: Allocator + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("ExtractIf").field(&self.inner.peek()).finish() + f.debug_struct("ExtractIf").field("peek", &self.inner.peek()).finish_non_exhaustive() } } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 7ad9e59dfede..343934680b87 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1556,10 +1556,7 @@ pub struct ExtractIf< T, F, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, -> where - T: 'a, - F: 'a + FnMut(&T) -> bool, -{ +> { pred: F, inner: super::map::ExtractIfInner<'a, T, SetValZST>, /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. @@ -1567,13 +1564,15 @@ pub struct ExtractIf< } #[unstable(feature = "btree_extract_if", issue = "70530")] -impl fmt::Debug for ExtractIf<'_, T, F, A> +impl fmt::Debug for ExtractIf<'_, T, F, A> where T: fmt::Debug, - F: FnMut(&T) -> bool, + A: Allocator + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("ExtractIf").field(&self.inner.peek().map(|(k, _)| k)).finish() + f.debug_struct("ExtractIf") + .field("peek", &self.inner.peek().map(|(k, _)| k)) + .finish_non_exhaustive() } } diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index cc42a120e4fa..00e2805d11f6 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1976,9 +1976,14 @@ where } #[stable(feature = "extract_if", since = "1.87.0")] -impl fmt::Debug for ExtractIf<'_, T, F> { +impl fmt::Debug for ExtractIf<'_, T, F, A> +where + T: fmt::Debug, + A: Allocator, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("ExtractIf").field(&self.list).finish() + let peek = self.it.map(|node| unsafe { &node.as_ref().element }); + f.debug_struct("ExtractIf").field("peek", &peek).finish_non_exhaustive() } } diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index f8844e2d3a5c..712f38a76c01 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1188,6 +1188,73 @@ impl VecDeque { } } + /// Shortens the deque, keeping the last `len` elements and dropping + /// the rest. + /// + /// If `len` is greater or equal to the deque's current length, this has + /// no effect. + /// + /// # Examples + /// + /// ``` + /// # #![feature(vec_deque_truncate_front)] + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_front(5); + /// buf.push_front(10); + /// buf.push_front(15); + /// assert_eq!(buf, [15, 10, 5]); + /// assert_eq!(buf.as_slices(), (&[15, 10, 5][..], &[][..])); + /// buf.truncate_front(1); + /// assert_eq!(buf.as_slices(), (&[5][..], &[][..])); + /// ``` + #[unstable(feature = "vec_deque_truncate_front", issue = "140667")] + pub fn truncate_front(&mut self, len: usize) { + /// Runs the destructor for all items in the slice when it gets dropped (normally or + /// during unwinding). + struct Dropper<'a, T>(&'a mut [T]); + + impl<'a, T> Drop for Dropper<'a, T> { + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(self.0); + } + } + } + + unsafe { + if len >= self.len { + // No action is taken + return; + } + + let (front, back) = self.as_mut_slices(); + if len > back.len() { + // The 'back' slice remains unchanged. + // front.len() + back.len() == self.len, so 'end' is non-negative + // and end < front.len() + let end = front.len() - (len - back.len()); + let drop_front = front.get_unchecked_mut(..end) as *mut _; + self.head += end; + self.len = len; + ptr::drop_in_place(drop_front); + } else { + let drop_front = front as *mut _; + // 'end' is non-negative by the condition above + let end = back.len() - len; + let drop_back = back.get_unchecked_mut(..end) as *mut _; + self.head = self.to_physical_idx(self.len - len); + self.len = len; + + // Make sure the second half is dropped even when a destructor + // in the first one panics. + let _back_dropper = Dropper(&mut *drop_back); + ptr::drop_in_place(drop_front); + } + } + } + /// Returns a reference to the underlying allocator. #[unstable(feature = "allocator_api", issue = "32838")] #[inline] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 619d9f258e34..4b8ea708e7e5 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -3536,11 +3536,11 @@ impl Default for Weak { } } -// NOTE: We checked_add here to deal with mem::forget safely. In particular -// if you mem::forget Rcs (or Weaks), the ref-count can overflow, and then -// you can free the allocation while outstanding Rcs (or Weaks) exist. -// We abort because this is such a degenerate scenario that we don't care about -// what happens -- no real program should ever experience this. +// NOTE: If you mem::forget Rcs (or Weaks), drop is skipped and the ref-count +// is not decremented, meaning the ref-count can overflow, and then you can +// free the allocation while outstanding Rcs (or Weaks) exist, which would be +// unsound. We abort because this is such a degenerate scenario that we don't +// care about what happens -- no real program should ever experience this. // // This should have negligible overhead since you don't actually need to // clone these much in Rust thanks to ownership and move-semantics. diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index 8a591a877964..a456d3d9e602 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -1,5 +1,5 @@ use core::ops::{Range, RangeBounds}; -use core::{ptr, slice}; +use core::{fmt, ptr, slice}; use super::Vec; use crate::alloc::{Allocator, Global}; @@ -16,7 +16,6 @@ use crate::alloc::{Allocator, Global}; /// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(.., |x| *x % 2 == 0); /// ``` #[stable(feature = "extract_if", since = "1.87.0")] -#[derive(Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ExtractIf< 'a, @@ -108,3 +107,15 @@ impl Drop for ExtractIf<'_, T, F, A> { } } } + +#[stable(feature = "extract_if", since = "1.87.0")] +impl fmt::Debug for ExtractIf<'_, T, F, A> +where + T: fmt::Debug, + A: Allocator, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let peek = if self.idx < self.end { self.vec.get(self.idx) } else { None }; + f.debug_struct("ExtractIf").field("peek", &peek).finish_non_exhaustive() + } +} diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 1af110691ba6..37df928228d9 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -258,6 +258,11 @@ impl Iterator for IntoIter { self.len() } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } + #[inline] fn next_chunk(&mut self) -> Result<[T; N], core::array::IntoIter> { let mut raw_ary = [const { MaybeUninit::uninit() }; N]; diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 65a83cb98ba6..a97912304c89 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3659,28 +3659,34 @@ impl Vec { /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating /// or the iteration short-circuits, then the remaining elements will be retained. - /// Use [`retain`] with a negated predicate if you do not need the returned iterator. + /// Use [`retain_mut`] with a negated predicate if you do not need the returned iterator. /// - /// [`retain`]: Vec::retain + /// [`retain_mut`]: Vec::retain_mut /// /// Using this method is equivalent to the following code: /// /// ``` - /// # use std::cmp::min; - /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; - /// # let mut vec = vec![1, 2, 3, 4, 5, 6]; - /// # let range = 1..4; + /// # let some_predicate = |x: &mut i32| { *x % 2 == 1 }; + /// # let mut vec = vec![0, 1, 2, 3, 4, 5, 6]; + /// # let mut vec2 = vec.clone(); + /// # let range = 1..5; /// let mut i = range.start; - /// while i < min(vec.len(), range.end) { + /// let end_items = vec.len() - range.end; + /// # let mut extracted = vec![]; + /// + /// while i < vec.len() - end_items { /// if some_predicate(&mut vec[i]) { /// let val = vec.remove(i); + /// # extracted.push(val); /// // your code here /// } else { /// i += 1; /// } /// } /// - /// # assert_eq!(vec, vec![1, 4, 5]); + /// # let extracted2: Vec<_> = vec2.extract_if(range, some_predicate).collect(); + /// # assert_eq!(vec, vec2); + /// # assert_eq!(extracted, extracted2); /// ``` /// /// But `extract_if` is easier to use. `extract_if` is also more efficient, diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index f1f4cc6f93bb..38309585fad6 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -37,6 +37,7 @@ #![feature(str_as_str)] #![feature(strict_provenance_lints)] #![feature(vec_deque_pop_if)] +#![feature(vec_deque_truncate_front)] #![feature(unique_rc_arc)] #![feature(macro_metavar_expr_concat)] #![allow(internal_features)] diff --git a/library/alloctests/tests/vec_deque.rs b/library/alloctests/tests/vec_deque.rs index 1b03c29e5bda..b77ea3a312be 100644 --- a/library/alloctests/tests/vec_deque.rs +++ b/library/alloctests/tests/vec_deque.rs @@ -1686,6 +1686,40 @@ fn truncate_leak() { assert_eq!(unsafe { DROPS }, 7); } +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn truncate_front_leak() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = VecDeque::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(true)); + q.push_front(D(false)); + q.push_front(D(false)); + + catch_unwind(AssertUnwindSafe(|| q.truncate_front(1))).ok(); + + assert_eq!(unsafe { DROPS }, 7); +} + #[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_drain_leak() { @@ -1863,3 +1897,38 @@ fn test_collect_from_into_iter_keeps_allocation() { assert_eq!(v.capacity(), 13); } } + +#[test] +fn test_truncate_front() { + let mut v = VecDeque::with_capacity(13); + v.extend(0..7); + assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); + v.truncate_front(10); + assert_eq!(v.len(), 7); + assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); + v.truncate_front(7); + assert_eq!(v.len(), 7); + assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); + v.truncate_front(3); + assert_eq!(v.as_slices(), ([4, 5, 6].as_slice(), [].as_slice())); + assert_eq!(v.len(), 3); + v.truncate_front(0); + assert_eq!(v.as_slices(), ([].as_slice(), [].as_slice())); + assert_eq!(v.len(), 0); + + v.clear(); + v.extend(0..7); + assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); + v.push_front(9); + v.push_front(8); + v.push_front(7); + assert_eq!(v.as_slices(), ([7, 8, 9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice())); + v.truncate_front(12); + assert_eq!(v.as_slices(), ([7, 8, 9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice())); + v.truncate_front(10); + assert_eq!(v.as_slices(), ([7, 8, 9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice())); + v.truncate_front(8); + assert_eq!(v.as_slices(), ([9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice())); + v.truncate_front(5); + assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice())); +} diff --git a/library/backtrace b/library/backtrace index 9d2c34e7e63a..6c882eb11984 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit 9d2c34e7e63afe1e71c333b247065e3b7ba4d883 +Subproject commit 6c882eb11984d737f62e85f36703effaf34c2453 diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 394a3ea67783..cb83540c4eaf 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -320,6 +320,10 @@ pub fn spin_loop() { /// This also means that this function does not offer any guarantees for cryptographic or security /// purposes. /// +/// This limitation is not specific to `black_box`; there is no mechanism in the entire Rust +/// language that can provide the guarantees required for constant-time cryptography. +/// (There is also no such mechanism in LLVM, so the same is true for every other LLVM-based compiler.) +/// /// /// /// [`std::convert::identity`]: crate::convert::identity diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index c5d5bc000f1c..5649736e4049 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3320,7 +3320,6 @@ pub const fn is_val_statically_known(_arg: T) -> bool { #[inline] #[rustc_intrinsic] #[rustc_intrinsic_const_stable_indirect] -#[rustc_allow_const_fn_unstable(const_swap_nonoverlapping)] // this is anyway not called since CTFE implements the intrinsic pub const unsafe fn typed_swap_nonoverlapping(x: *mut T, y: *mut T) { // SAFETY: The caller provided single non-overlapping items behind // pointers, so swapping them with `count: 1` is fine. diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs index 72d746289711..aea6d64281ae 100644 --- a/library/core/src/iter/adapters/cloned.rs +++ b/library/core/src/iter/adapters/cloned.rs @@ -1,6 +1,5 @@ use core::num::NonZero; -use crate::cmp::Ordering; use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator}; @@ -42,31 +41,13 @@ where self.it.next().cloned() } - #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } - #[inline] - fn count(self) -> usize { - self.it.count() - } - - fn last(self) -> Option { - self.it.last().cloned() - } - - #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { - self.it.advance_by(n) - } - - fn nth(&mut self, n: usize) -> Option { - self.it.nth(n).cloned() - } - fn try_fold(&mut self, init: B, f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try, { @@ -80,58 +61,6 @@ where self.it.map(T::clone).fold(init, f) } - fn find

(&mut self, mut predicate: P) -> Option - where - P: FnMut(&Self::Item) -> bool, - { - self.it.find(move |x| predicate(&x)).cloned() - } - - fn max_by(self, mut compare: F) -> Option - where - F: FnMut(&Self::Item, &Self::Item) -> Ordering, - { - self.it.max_by(move |&x, &y| compare(x, y)).cloned() - } - - fn min_by(self, mut compare: F) -> Option - where - F: FnMut(&Self::Item, &Self::Item) -> Ordering, - { - self.it.min_by(move |&x, &y| compare(x, y)).cloned() - } - - fn cmp(self, other: O) -> Ordering - where - O: IntoIterator, - Self::Item: Ord, - { - self.it.cmp_by(other, |x, y| x.cmp(&y)) - } - - fn partial_cmp(self, other: O) -> Option - where - O: IntoIterator, - Self::Item: PartialOrd, - { - self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) - } - - fn eq(self, other: O) -> bool - where - O: IntoIterator, - Self::Item: PartialEq, - { - self.it.eq_by(other, |x, y| x == &y) - } - - fn is_sorted_by(self, mut compare: F) -> bool - where - F: FnMut(&Self::Item, &Self::Item) -> bool, - { - self.it.is_sorted_by(move |&x, &y| compare(x, y)) - } - unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T where Self: TrustedRandomAccessNoCoerce, @@ -152,13 +81,9 @@ where self.it.next_back().cloned() } - #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { - self.it.advance_back_by(n) - } - fn try_rfold(&mut self, init: B, f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try, { @@ -171,13 +96,6 @@ where { self.it.map(T::clone).rfold(init, f) } - - fn rfind

(&mut self, mut predicate: P) -> Option - where - P: FnMut(&Self::Item) -> bool, - { - self.it.rfind(move |x| predicate(&x)).cloned() - } } #[stable(feature = "iter_cloned", since = "1.1.0")] @@ -186,12 +104,10 @@ where I: ExactSizeIterator, T: Clone, { - #[inline] fn len(&self) -> usize { self.it.len() } - #[inline] fn is_empty(&self) -> bool { self.it.is_empty() } diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index 73913aa34a9e..23e4e25ab538 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -1,4 +1,3 @@ -use crate::cmp::Ordering; use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; @@ -49,35 +48,20 @@ where fn next_chunk( &mut self, - ) -> Result<[Self::Item; N], array::IntoIter> { + ) -> Result<[Self::Item; N], array::IntoIter> + where + Self: Sized, + { >::spec_next_chunk(&mut self.it) } - #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } - #[inline] - fn count(self) -> usize { - self.it.count() - } - - fn last(self) -> Option { - self.it.last().copied() - } - - #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { - self.it.advance_by(n) - } - - fn nth(&mut self, n: usize) -> Option { - self.it.nth(n).copied() - } - fn try_fold(&mut self, init: B, f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try, { @@ -91,56 +75,21 @@ where self.it.fold(init, copy_fold(f)) } - fn find

(&mut self, mut predicate: P) -> Option - where - P: FnMut(&Self::Item) -> bool, - { - self.it.find(move |x| predicate(&x)).copied() + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n).copied() } - fn max_by(self, mut compare: F) -> Option - where - F: FnMut(&Self::Item, &Self::Item) -> Ordering, - { - self.it.max_by(move |&x, &y| compare(x, y)).copied() + fn last(self) -> Option { + self.it.last().copied() } - fn min_by(self, mut compare: F) -> Option - where - F: FnMut(&Self::Item, &Self::Item) -> Ordering, - { - self.it.min_by(move |&x, &y| compare(x, y)).copied() + fn count(self) -> usize { + self.it.count() } - fn cmp(self, other: O) -> Ordering - where - O: IntoIterator, - Self::Item: Ord, - { - self.it.cmp_by(other, |x, y| x.cmp(&y)) - } - - fn partial_cmp(self, other: O) -> Option - where - O: IntoIterator, - Self::Item: PartialOrd, - { - self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) - } - - fn eq(self, other: O) -> bool - where - O: IntoIterator, - Self::Item: PartialEq, - { - self.it.eq_by(other, |x, y| x == &y) - } - - fn is_sorted_by(self, mut compare: F) -> bool - where - F: FnMut(&Self::Item, &Self::Item) -> bool, - { - self.it.is_sorted_by(move |&x, &y| compare(x, y)) + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.it.advance_by(n) } unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T @@ -163,13 +112,9 @@ where self.it.next_back().copied() } - #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { - self.it.advance_back_by(n) - } - fn try_rfold(&mut self, init: B, f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try, { @@ -183,11 +128,9 @@ where self.it.rfold(init, copy_fold(f)) } - fn rfind

(&mut self, mut predicate: P) -> Option - where - P: FnMut(&Self::Item) -> bool, - { - self.it.rfind(move |x| predicate(&x)).copied() + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.it.advance_back_by(n) } } @@ -197,12 +140,10 @@ where I: ExactSizeIterator, T: Copy, { - #[inline] fn len(&self) -> usize { self.it.len() } - #[inline] fn is_empty(&self) -> bool { self.it.is_empty() } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index c68fd2115d68..d1e71f0e60f2 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -56,12 +56,12 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// /// // A call to next() returns the next value... - /// assert_eq!(Some(&1), iter.next()); - /// assert_eq!(Some(&2), iter.next()); - /// assert_eq!(Some(&3), iter.next()); + /// assert_eq!(Some(1), iter.next()); + /// assert_eq!(Some(2), iter.next()); + /// assert_eq!(Some(3), iter.next()); /// /// // ... and then None once it's over. /// assert_eq!(None, iter.next()); @@ -239,10 +239,10 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3]; - /// assert_eq!(a.iter().last(), Some(&3)); + /// assert_eq!(a.into_iter().last(), Some(3)); /// /// let a = [1, 2, 3, 4, 5]; - /// assert_eq!(a.iter().last(), Some(&5)); + /// assert_eq!(a.into_iter().last(), Some(5)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -284,12 +284,12 @@ pub trait Iterator { /// use std::num::NonZero; /// /// let a = [1, 2, 3, 4]; - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// /// assert_eq!(iter.advance_by(2), Ok(())); - /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), Some(3)); /// assert_eq!(iter.advance_by(0), Ok(())); - /// assert_eq!(iter.advance_by(100), Err(NonZero::new(99).unwrap())); // only `&4` was skipped + /// assert_eq!(iter.advance_by(100), Err(NonZero::new(99).unwrap())); // only `4` was skipped /// ``` #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] @@ -322,7 +322,7 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3]; - /// assert_eq!(a.iter().nth(1), Some(&2)); + /// assert_eq!(a.into_iter().nth(1), Some(2)); /// ``` /// /// Calling `nth()` multiple times doesn't rewind the iterator: @@ -330,9 +330,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// - /// assert_eq!(iter.nth(1), Some(&2)); + /// assert_eq!(iter.nth(1), Some(2)); /// assert_eq!(iter.nth(1), None); /// ``` /// @@ -340,7 +340,7 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3]; - /// assert_eq!(a.iter().nth(10), None); + /// assert_eq!(a.into_iter().nth(10), None); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -385,11 +385,11 @@ pub trait Iterator { /// /// ``` /// let a = [0, 1, 2, 3, 4, 5]; - /// let mut iter = a.iter().step_by(2); + /// let mut iter = a.into_iter().step_by(2); /// - /// assert_eq!(iter.next(), Some(&0)); - /// assert_eq!(iter.next(), Some(&2)); - /// assert_eq!(iter.next(), Some(&4)); + /// assert_eq!(iter.next(), Some(0)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), Some(4)); /// assert_eq!(iter.next(), None); /// ``` #[inline] @@ -417,37 +417,37 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// let a1 = [1, 2, 3]; - /// let a2 = [4, 5, 6]; + /// let s1 = "abc".chars(); + /// let s2 = "def".chars(); /// - /// let mut iter = a1.iter().chain(a2.iter()); + /// let mut iter = s1.chain(s2); /// - /// assert_eq!(iter.next(), Some(&1)); - /// assert_eq!(iter.next(), Some(&2)); - /// assert_eq!(iter.next(), Some(&3)); - /// assert_eq!(iter.next(), Some(&4)); - /// assert_eq!(iter.next(), Some(&5)); - /// assert_eq!(iter.next(), Some(&6)); + /// assert_eq!(iter.next(), Some('a')); + /// assert_eq!(iter.next(), Some('b')); + /// assert_eq!(iter.next(), Some('c')); + /// assert_eq!(iter.next(), Some('d')); + /// assert_eq!(iter.next(), Some('e')); + /// assert_eq!(iter.next(), Some('f')); /// assert_eq!(iter.next(), None); /// ``` /// /// Since the argument to `chain()` uses [`IntoIterator`], we can pass /// anything that can be converted into an [`Iterator`], not just an - /// [`Iterator`] itself. For example, slices (`&[T]`) implement + /// [`Iterator`] itself. For example, arrays (`[T]`) implement /// [`IntoIterator`], and so can be passed to `chain()` directly: /// /// ``` - /// let s1 = &[1, 2, 3]; - /// let s2 = &[4, 5, 6]; + /// let a1 = [1, 2, 3]; + /// let a2 = [4, 5, 6]; /// - /// let mut iter = s1.iter().chain(s2); + /// let mut iter = a1.into_iter().chain(a2); /// - /// assert_eq!(iter.next(), Some(&1)); - /// assert_eq!(iter.next(), Some(&2)); - /// assert_eq!(iter.next(), Some(&3)); - /// assert_eq!(iter.next(), Some(&4)); - /// assert_eq!(iter.next(), Some(&5)); - /// assert_eq!(iter.next(), Some(&6)); + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), Some(3)); + /// assert_eq!(iter.next(), Some(4)); + /// assert_eq!(iter.next(), Some(5)); + /// assert_eq!(iter.next(), Some(6)); /// assert_eq!(iter.next(), None); /// ``` /// @@ -496,31 +496,31 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// let a1 = [1, 2, 3]; - /// let a2 = [4, 5, 6]; + /// let s1 = "abc".chars(); + /// let s2 = "def".chars(); /// - /// let mut iter = a1.iter().zip(a2.iter()); + /// let mut iter = s1.zip(s2); /// - /// assert_eq!(iter.next(), Some((&1, &4))); - /// assert_eq!(iter.next(), Some((&2, &5))); - /// assert_eq!(iter.next(), Some((&3, &6))); + /// assert_eq!(iter.next(), Some(('a', 'd'))); + /// assert_eq!(iter.next(), Some(('b', 'e'))); + /// assert_eq!(iter.next(), Some(('c', 'f'))); /// assert_eq!(iter.next(), None); /// ``` /// /// Since the argument to `zip()` uses [`IntoIterator`], we can pass /// anything that can be converted into an [`Iterator`], not just an - /// [`Iterator`] itself. For example, slices (`&[T]`) implement + /// [`Iterator`] itself. For example, arrays (`[T]`) implement /// [`IntoIterator`], and so can be passed to `zip()` directly: /// /// ``` - /// let s1 = &[1, 2, 3]; - /// let s2 = &[4, 5, 6]; + /// let a1 = [1, 2, 3]; + /// let a2 = [4, 5, 6]; /// - /// let mut iter = s1.iter().zip(s2); + /// let mut iter = a1.into_iter().zip(a2); /// - /// assert_eq!(iter.next(), Some((&1, &4))); - /// assert_eq!(iter.next(), Some((&2, &5))); - /// assert_eq!(iter.next(), Some((&3, &6))); + /// assert_eq!(iter.next(), Some((1, 4))); + /// assert_eq!(iter.next(), Some((2, 5))); + /// assert_eq!(iter.next(), Some((3, 6))); /// assert_eq!(iter.next(), None); /// ``` /// @@ -604,12 +604,12 @@ pub trait Iterator { /// ``` /// #![feature(iter_intersperse)] /// - /// let mut a = [0, 1, 2].iter().intersperse(&100); - /// assert_eq!(a.next(), Some(&0)); // The first element from `a`. - /// assert_eq!(a.next(), Some(&100)); // The separator. - /// assert_eq!(a.next(), Some(&1)); // The next element from `a`. - /// assert_eq!(a.next(), Some(&100)); // The separator. - /// assert_eq!(a.next(), Some(&2)); // The last element from `a`. + /// let mut a = [0, 1, 2].into_iter().intersperse(100); + /// assert_eq!(a.next(), Some(0)); // The first element from `a`. + /// assert_eq!(a.next(), Some(100)); // The separator. + /// assert_eq!(a.next(), Some(1)); // The next element from `a`. + /// assert_eq!(a.next(), Some(100)); // The separator. + /// assert_eq!(a.next(), Some(2)); // The last element from `a`. /// assert_eq!(a.next(), None); // The iterator is finished. /// ``` /// @@ -617,7 +617,8 @@ pub trait Iterator { /// ``` /// #![feature(iter_intersperse)] /// - /// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::(); + /// let words = ["Hello", "World", "!"]; + /// let hello: String = words.into_iter().intersperse(" ").collect(); /// assert_eq!(hello, "Hello World !"); /// ``` /// @@ -673,7 +674,7 @@ pub trait Iterator { /// let src = ["Hello", "to", "all", "people", "!!"].iter().copied(); /// /// // The closure mutably borrows its context to generate an item. - /// let mut happy_emojis = [" ❤️ ", " 😀 "].iter().copied(); + /// let mut happy_emojis = [" ❤️ ", " 😀 "].into_iter(); /// let separator = || happy_emojis.next().unwrap_or(" 🦀 "); /// /// let result = src.intersperse_with(separator).collect::(); @@ -734,7 +735,7 @@ pub trait Iterator { /// /// // it won't even execute, as it is lazy. Rust will warn you about this. /// - /// // Instead, use for: + /// // Instead, use a for-loop: /// for x in 0..5 { /// println!("{x}"); /// } @@ -814,10 +815,10 @@ pub trait Iterator { /// ``` /// let a = [0i32, 1, 2]; /// - /// let mut iter = a.iter().filter(|x| x.is_positive()); + /// let mut iter = a.into_iter().filter(|x| x.is_positive()); /// - /// assert_eq!(iter.next(), Some(&1)); - /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); /// assert_eq!(iter.next(), None); /// ``` /// @@ -826,21 +827,20 @@ pub trait Iterator { /// situation, where the type of the closure is a double reference: /// /// ``` - /// let a = [0, 1, 2]; + /// let s = &[0, 1, 2]; /// - /// let mut iter = a.iter().filter(|x| **x > 1); // need two *s! + /// let mut iter = s.iter().filter(|x| **x > 1); // needs two *s! /// /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), None); /// ``` /// - /// It's common to instead use destructuring on the argument to strip away - /// one: + /// It's common to instead use destructuring on the argument to strip away one: /// /// ``` - /// let a = [0, 1, 2]; + /// let s = &[0, 1, 2]; /// - /// let mut iter = a.iter().filter(|&x| *x > 1); // both & and * + /// let mut iter = s.iter().filter(|&x| *x > 1); // both & and * /// /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), None); @@ -849,9 +849,9 @@ pub trait Iterator { /// or both: /// /// ``` - /// let a = [0, 1, 2]; + /// let s = &[0, 1, 2]; /// - /// let mut iter = a.iter().filter(|&&x| x > 1); // two &s + /// let mut iter = s.iter().filter(|&&x| x > 1); // two &s /// /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), None); @@ -945,11 +945,11 @@ pub trait Iterator { /// ``` /// let a = ['a', 'b', 'c']; /// - /// let mut iter = a.iter().enumerate(); + /// let mut iter = a.into_iter().enumerate(); /// - /// assert_eq!(iter.next(), Some((0, &'a'))); - /// assert_eq!(iter.next(), Some((1, &'b'))); - /// assert_eq!(iter.next(), Some((2, &'c'))); + /// assert_eq!(iter.next(), Some((0, 'a'))); + /// assert_eq!(iter.next(), Some((1, 'b'))); + /// assert_eq!(iter.next(), Some((2, 'c'))); /// assert_eq!(iter.next(), None); /// ``` #[inline] @@ -980,19 +980,19 @@ pub trait Iterator { /// ``` /// let xs = [1, 2, 3]; /// - /// let mut iter = xs.iter().peekable(); + /// let mut iter = xs.into_iter().peekable(); /// /// // peek() lets us see into the future - /// assert_eq!(iter.peek(), Some(&&1)); - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.peek(), Some(&1)); + /// assert_eq!(iter.next(), Some(1)); /// - /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), Some(2)); /// /// // we can peek() multiple times, the iterator won't advance - /// assert_eq!(iter.peek(), Some(&&3)); - /// assert_eq!(iter.peek(), Some(&&3)); + /// assert_eq!(iter.peek(), Some(&3)); + /// assert_eq!(iter.peek(), Some(&3)); /// - /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), Some(3)); /// /// // after the iterator is finished, so is peek() /// assert_eq!(iter.peek(), None); @@ -1005,21 +1005,21 @@ pub trait Iterator { /// ``` /// let xs = [1, 2, 3]; /// - /// let mut iter = xs.iter().peekable(); + /// let mut iter = xs.into_iter().peekable(); /// /// // `peek_mut()` lets us see into the future - /// assert_eq!(iter.peek_mut(), Some(&mut &1)); - /// assert_eq!(iter.peek_mut(), Some(&mut &1)); - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.peek_mut(), Some(&mut 1)); + /// assert_eq!(iter.peek_mut(), Some(&mut 1)); + /// assert_eq!(iter.next(), Some(1)); /// - /// if let Some(mut p) = iter.peek_mut() { - /// assert_eq!(*p, &2); + /// if let Some(p) = iter.peek_mut() { + /// assert_eq!(*p, 2); /// // put a value into the iterator - /// *p = &1000; + /// *p = 1000; /// } /// /// // The value reappears as the iterator continues - /// assert_eq!(iter.collect::>(), vec![&1000, &3]); + /// assert_eq!(iter.collect::>(), vec![1000, 3]); /// ``` /// [`peek`]: Peekable::peek /// [`peek_mut`]: Peekable::peek_mut @@ -1051,10 +1051,10 @@ pub trait Iterator { /// ``` /// let a = [-1i32, 0, 1]; /// - /// let mut iter = a.iter().skip_while(|x| x.is_negative()); + /// let mut iter = a.into_iter().skip_while(|x| x.is_negative()); /// - /// assert_eq!(iter.next(), Some(&0)); - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(0)); + /// assert_eq!(iter.next(), Some(1)); /// assert_eq!(iter.next(), None); /// ``` /// @@ -1063,9 +1063,9 @@ pub trait Iterator { /// situation, where the type of the closure argument is a double reference: /// /// ``` - /// let a = [-1, 0, 1]; + /// let s = &[-1, 0, 1]; /// - /// let mut iter = a.iter().skip_while(|x| **x < 0); // need two *s! + /// let mut iter = s.iter().skip_while(|x| **x < 0); // need two *s! /// /// assert_eq!(iter.next(), Some(&0)); /// assert_eq!(iter.next(), Some(&1)); @@ -1077,14 +1077,14 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1, -2]; /// - /// let mut iter = a.iter().skip_while(|x| **x < 0); + /// let mut iter = a.into_iter().skip_while(|&x| x < 0); /// - /// assert_eq!(iter.next(), Some(&0)); - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(0)); + /// assert_eq!(iter.next(), Some(1)); /// /// // while this would have been false, since we already got a false, /// // skip_while() isn't used any more - /// assert_eq!(iter.next(), Some(&-2)); + /// assert_eq!(iter.next(), Some(-2)); /// /// assert_eq!(iter.next(), None); /// ``` @@ -1115,9 +1115,9 @@ pub trait Iterator { /// ``` /// let a = [-1i32, 0, 1]; /// - /// let mut iter = a.iter().take_while(|x| x.is_negative()); + /// let mut iter = a.into_iter().take_while(|x| x.is_negative()); /// - /// assert_eq!(iter.next(), Some(&-1)); + /// assert_eq!(iter.next(), Some(-1)); /// assert_eq!(iter.next(), None); /// ``` /// @@ -1126,9 +1126,9 @@ pub trait Iterator { /// situation, where the type of the closure is a double reference: /// /// ``` - /// let a = [-1, 0, 1]; + /// let s = &[-1, 0, 1]; /// - /// let mut iter = a.iter().take_while(|x| **x < 0); // need two *s! + /// let mut iter = s.iter().take_while(|x| **x < 0); // need two *s! /// /// assert_eq!(iter.next(), Some(&-1)); /// assert_eq!(iter.next(), None); @@ -1139,12 +1139,12 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1, -2]; /// - /// let mut iter = a.iter().take_while(|x| **x < 0); + /// let mut iter = a.into_iter().take_while(|&x| x < 0); /// - /// assert_eq!(iter.next(), Some(&-1)); + /// assert_eq!(iter.next(), Some(-1)); /// /// // We have more elements that are less than zero, but since we already - /// // got a false, take_while() isn't used any more + /// // got a false, take_while() ignores the remaining elements. /// assert_eq!(iter.next(), None); /// ``` /// @@ -1154,18 +1154,15 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3, 4]; - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// - /// let result: Vec = iter.by_ref() - /// .take_while(|n| **n != 3) - /// .cloned() - /// .collect(); + /// let result: Vec = iter.by_ref().take_while(|&n| n != 3).collect(); /// - /// assert_eq!(result, &[1, 2]); + /// assert_eq!(result, [1, 2]); /// - /// let result: Vec = iter.cloned().collect(); + /// let result: Vec = iter.collect(); /// - /// assert_eq!(result, &[4]); + /// assert_eq!(result, [4]); /// ``` /// /// The `3` is no longer there, because it was consumed in order to see if @@ -1193,7 +1190,7 @@ pub trait Iterator { /// ``` /// let a = [-1i32, 4, 0, 1]; /// - /// let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x)); + /// let mut iter = a.into_iter().map_while(|x| 16i32.checked_div(x)); /// /// assert_eq!(iter.next(), Some(-16)); /// assert_eq!(iter.next(), Some(4)); @@ -1208,8 +1205,8 @@ pub trait Iterator { /// ``` /// let a = [-1i32, 4, 0, 1]; /// - /// let mut iter = a.iter() - /// .map(|x| 16i32.checked_div(*x)) + /// let mut iter = a.into_iter() + /// .map(|x| 16i32.checked_div(x)) /// .take_while(|x| x.is_some()) /// .map(|x| x.unwrap()); /// @@ -1223,12 +1220,12 @@ pub trait Iterator { /// ``` /// let a = [0, 1, 2, -3, 4, 5, -6]; /// - /// let iter = a.iter().map_while(|x| u32::try_from(*x).ok()); - /// let vec = iter.collect::>(); + /// let iter = a.into_iter().map_while(|x| u32::try_from(x).ok()); + /// let vec: Vec<_> = iter.collect(); /// - /// // We have more elements which could fit in u32 (4, 5), but `map_while` returned `None` for `-3` + /// // We have more elements that could fit in u32 (such as 4, 5), but `map_while` returned `None` for `-3` /// // (as the `predicate` returned `None`) and `collect` stops at the first `None` encountered. - /// assert_eq!(vec, vec![0, 1, 2]); + /// assert_eq!(vec, [0, 1, 2]); /// ``` /// /// Because `map_while()` needs to look at the value in order to see if it @@ -1237,17 +1234,17 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, -3, 4]; - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// /// let result: Vec = iter.by_ref() - /// .map_while(|n| u32::try_from(*n).ok()) + /// .map_while(|n| u32::try_from(n).ok()) /// .collect(); /// - /// assert_eq!(result, &[1, 2]); + /// assert_eq!(result, [1, 2]); /// - /// let result: Vec = iter.cloned().collect(); + /// let result: Vec = iter.collect(); /// - /// assert_eq!(result, &[4]); + /// assert_eq!(result, [4]); /// ``` /// /// The `-3` is no longer there, because it was consumed in order to see if @@ -1255,7 +1252,7 @@ pub trait Iterator { /// /// Note that unlike [`take_while`] this iterator is **not** fused. /// It is also not specified what this iterator returns after the first [`None`] is returned. - /// If you need fused iterator, use [`fuse`]. + /// If you need a fused iterator, use [`fuse`]. /// /// [`fuse`]: Iterator::fuse #[inline] @@ -1282,9 +1279,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.iter().skip(2); + /// let mut iter = a.into_iter().skip(2); /// - /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), Some(3)); /// assert_eq!(iter.next(), None); /// ``` #[inline] @@ -1312,10 +1309,10 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.iter().take(2); + /// let mut iter = a.into_iter().take(2); /// - /// assert_eq!(iter.next(), Some(&1)); - /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); /// assert_eq!(iter.next(), None); /// ``` /// @@ -1358,6 +1355,7 @@ pub trait Iterator { /// ``` /// /// [`by_ref`]: Iterator::by_ref + #[doc(alias = "limit")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn take(self, n: usize) -> Take @@ -1388,7 +1386,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3, 4]; /// - /// let mut iter = a.iter().scan(1, |state, &x| { + /// let mut iter = a.into_iter().scan(1, |state, x| { /// // each iteration, we'll multiply the state by the element ... /// *state = *state * x; /// @@ -1466,8 +1464,8 @@ pub trait Iterator { /// /// ``` /// let data = vec![vec![1, 2, 3, 4], vec![5, 6]]; - /// let flattened = data.into_iter().flatten().collect::>(); - /// assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]); + /// let flattened: Vec<_> = data.into_iter().flatten().collect(); + /// assert_eq!(flattened, [1, 2, 3, 4, 5, 6]); /// ``` /// /// Mapping and then flattening: @@ -1501,11 +1499,11 @@ pub trait Iterator { /// ``` /// let options = vec![Some(123), Some(321), None, Some(231)]; /// let flattened_options: Vec<_> = options.into_iter().flatten().collect(); - /// assert_eq!(flattened_options, vec![123, 321, 231]); + /// assert_eq!(flattened_options, [123, 321, 231]); /// /// let results = vec![Ok(123), Ok(321), Err(456), Ok(231)]; /// let flattened_results: Vec<_> = results.into_iter().flatten().collect(); - /// assert_eq!(flattened_results, vec![123, 321, 231]); + /// assert_eq!(flattened_results, [123, 321, 231]); /// ``` /// /// Flattening only removes one level of nesting at a time: @@ -1513,11 +1511,11 @@ pub trait Iterator { /// ``` /// let d3 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]; /// - /// let d2 = d3.iter().flatten().collect::>(); - /// assert_eq!(d2, [&[1, 2], &[3, 4], &[5, 6], &[7, 8]]); + /// let d2: Vec<_> = d3.into_iter().flatten().collect(); + /// assert_eq!(d2, [[1, 2], [3, 4], [5, 6], [7, 8]]); /// - /// let d1 = d3.iter().flatten().flatten().collect::>(); - /// assert_eq!(d1, [&1, &2, &3, &4, &5, &6, &7, &8]); + /// let d1: Vec<_> = d3.into_iter().flatten().flatten().collect(); + /// assert_eq!(d1, [1, 2, 3, 4, 5, 6, 7, 8]); /// ``` /// /// Here we see that `flatten()` does not perform a "deep" flatten. @@ -1904,7 +1902,7 @@ pub trait Iterator { /// let a = [1, 2, 3]; /// /// let doubled: Vec = a.iter() - /// .map(|&x| x * 2) + /// .map(|x| x * 2) /// .collect(); /// /// assert_eq!(vec![2, 4, 6], doubled); @@ -1920,7 +1918,7 @@ pub trait Iterator { /// /// let a = [1, 2, 3]; /// - /// let doubled: VecDeque = a.iter().map(|&x| x * 2).collect(); + /// let doubled: VecDeque = a.iter().map(|x| x * 2).collect(); /// /// assert_eq!(2, doubled[0]); /// assert_eq!(4, doubled[1]); @@ -1953,8 +1951,8 @@ pub trait Iterator { /// ``` /// let chars = ['g', 'd', 'k', 'k', 'n']; /// - /// let hello: String = chars.iter() - /// .map(|&x| x as u8) + /// let hello: String = chars.into_iter() + /// .map(|x| x as u8) /// .map(|x| (x + 1) as char) /// .collect(); /// @@ -1967,14 +1965,14 @@ pub trait Iterator { /// ``` /// let results = [Ok(1), Err("nope"), Ok(3), Err("bad")]; /// - /// let result: Result, &str> = results.iter().cloned().collect(); + /// let result: Result, &str> = results.into_iter().collect(); /// /// // gives us the first error /// assert_eq!(Err("nope"), result); /// /// let results = [Ok(1), Ok(3)]; /// - /// let result: Result, &str> = results.iter().cloned().collect(); + /// let result: Result, &str> = results.into_iter().collect(); /// /// // gives us the list of answers /// assert_eq!(Ok(vec![1, 3]), result); @@ -2105,8 +2103,8 @@ pub trait Iterator { /// let a = [1, 2, 3]; /// let mut vec: Vec:: = vec![0, 1]; /// - /// a.iter().map(|&x| x * 2).collect_into(&mut vec); - /// a.iter().map(|&x| x * 10).collect_into(&mut vec); + /// a.iter().map(|x| x * 2).collect_into(&mut vec); + /// a.iter().map(|x| x * 10).collect_into(&mut vec); /// /// assert_eq!(vec, vec![0, 1, 2, 4, 6, 10, 20, 30]); /// ``` @@ -2119,8 +2117,8 @@ pub trait Iterator { /// let a = [1, 2, 3]; /// let mut vec: Vec:: = Vec::with_capacity(6); /// - /// a.iter().map(|&x| x * 2).collect_into(&mut vec); - /// a.iter().map(|&x| x * 10).collect_into(&mut vec); + /// a.iter().map(|x| x * 2).collect_into(&mut vec); + /// a.iter().map(|x| x * 10).collect_into(&mut vec); /// /// assert_eq!(6, vec.capacity()); /// assert_eq!(vec, vec![2, 4, 6, 10, 20, 30]); @@ -2174,8 +2172,8 @@ pub trait Iterator { /// .into_iter() /// .partition(|n| n % 2 == 0); /// - /// assert_eq!(even, vec![2]); - /// assert_eq!(odd, vec![1, 3]); + /// assert_eq!(even, [2]); + /// assert_eq!(odd, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn partition(self, f: F) -> (B, B) @@ -2233,11 +2231,11 @@ pub trait Iterator { /// let mut a = [1, 2, 3, 4, 5, 6, 7]; /// /// // Partition in-place between evens and odds - /// let i = a.iter_mut().partition_in_place(|&n| n % 2 == 0); + /// let i = a.iter_mut().partition_in_place(|n| n % 2 == 0); /// /// assert_eq!(i, 3); - /// assert!(a[..i].iter().all(|&n| n % 2 == 0)); // evens - /// assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds + /// assert!(a[..i].iter().all(|n| n % 2 == 0)); // evens + /// assert!(a[i..].iter().all(|n| n % 2 == 1)); // odds /// ``` #[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")] fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize @@ -2344,7 +2342,7 @@ pub trait Iterator { /// let a = [1, 2, 3]; /// /// // the checked sum of all of the elements of the array - /// let sum = a.iter().try_fold(0i8, |acc, &x| acc.checked_add(x)); + /// let sum = a.into_iter().try_fold(0i8, |acc, x| acc.checked_add(x)); /// /// assert_eq!(sum, Some(6)); /// ``` @@ -2353,16 +2351,16 @@ pub trait Iterator { /// /// ``` /// let a = [10, 20, 30, 100, 40, 50]; - /// let mut it = a.iter(); + /// let mut iter = a.into_iter(); /// /// // This sum overflows when adding the 100 element - /// let sum = it.try_fold(0i8, |acc, &x| acc.checked_add(x)); + /// let sum = iter.try_fold(0i8, |acc, x| acc.checked_add(x)); /// assert_eq!(sum, None); /// /// // Because it short-circuited, the remaining elements are still /// // available through the iterator. - /// assert_eq!(it.len(), 2); - /// assert_eq!(it.next(), Some(&40)); + /// assert_eq!(iter.len(), 2); + /// assert_eq!(iter.next(), Some(40)); /// ``` /// /// While you cannot `break` from a closure, the [`ControlFlow`] type allows @@ -2715,9 +2713,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// assert!(a.iter().all(|&x| x > 0)); + /// assert!(a.into_iter().all(|x| x > 0)); /// - /// assert!(!a.iter().all(|&x| x > 2)); + /// assert!(!a.into_iter().all(|x| x > 2)); /// ``` /// /// Stopping at the first `false`: @@ -2725,12 +2723,12 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// - /// assert!(!iter.all(|&x| x != 2)); + /// assert!(!iter.all(|x| x != 2)); /// /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), Some(3)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -2768,9 +2766,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// assert!(a.iter().any(|&x| x > 0)); + /// assert!(a.into_iter().any(|x| x > 0)); /// - /// assert!(!a.iter().any(|&x| x > 5)); + /// assert!(!a.into_iter().any(|x| x > 5)); /// ``` /// /// Stopping at the first `true`: @@ -2778,12 +2776,12 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// - /// assert!(iter.any(|&x| x != 2)); + /// assert!(iter.any(|x| x != 2)); /// /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), Some(2)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -2829,9 +2827,8 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// assert_eq!(a.iter().find(|&&x| x == 2), Some(&2)); - /// - /// assert_eq!(a.iter().find(|&&x| x == 5), None); + /// assert_eq!(a.into_iter().find(|&x| x == 2), Some(2)); + /// assert_eq!(a.into_iter().find(|&x| x == 5), None); /// ``` /// /// Stopping at the first `true`: @@ -2839,12 +2836,12 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// - /// assert_eq!(iter.find(|&&x| x == 2), Some(&2)); + /// assert_eq!(iter.find(|&x| x == 2), Some(2)); /// /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), Some(3)); /// ``` /// /// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`. @@ -2912,13 +2909,13 @@ pub trait Iterator { /// let a = ["1", "2", "lol", "NaN", "5"]; /// /// let is_my_num = |s: &str, search: i32| -> Result { - /// Ok(s.parse::()? == search) + /// Ok(s.parse::()? == search) /// }; /// - /// let result = a.iter().try_find(|&&s| is_my_num(s, 2)); - /// assert_eq!(result, Ok(Some(&"2"))); + /// let result = a.into_iter().try_find(|&s| is_my_num(s, 2)); + /// assert_eq!(result, Ok(Some("2"))); /// - /// let result = a.iter().try_find(|&&s| is_my_num(s, 5)); + /// let result = a.into_iter().try_find(|&s| is_my_num(s, 5)); /// assert!(result.is_err()); /// ``` /// @@ -2930,11 +2927,11 @@ pub trait Iterator { /// use std::num::NonZero; /// /// let a = [3, 5, 7, 4, 9, 0, 11u32]; - /// let result = a.iter().try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); - /// assert_eq!(result, Some(Some(&4))); - /// let result = a.iter().take(3).try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); + /// let result = a.into_iter().try_find(|&x| NonZero::new(x).map(|y| y.is_power_of_two())); + /// assert_eq!(result, Some(Some(4))); + /// let result = a.into_iter().take(3).try_find(|&x| NonZero::new(x).map(|y| y.is_power_of_two())); /// assert_eq!(result, Some(None)); - /// let result = a.iter().rev().try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); + /// let result = a.into_iter().rev().try_find(|&x| NonZero::new(x).map(|y| y.is_power_of_two())); /// assert_eq!(result, None); /// ``` #[inline] @@ -2999,9 +2996,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// assert_eq!(a.iter().position(|&x| x == 2), Some(1)); + /// assert_eq!(a.into_iter().position(|x| x == 2), Some(1)); /// - /// assert_eq!(a.iter().position(|&x| x == 5), None); + /// assert_eq!(a.into_iter().position(|x| x == 5), None); /// ``` /// /// Stopping at the first `true`: @@ -3009,15 +3006,15 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3, 4]; /// - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// - /// assert_eq!(iter.position(|&x| x >= 2), Some(1)); + /// assert_eq!(iter.position(|x| x >= 2), Some(1)); /// /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), Some(3)); /// /// // The returned index depends on iterator state - /// assert_eq!(iter.position(|&x| x == 4), Some(0)); + /// assert_eq!(iter.position(|x| x == 4), Some(0)); /// /// ``` #[inline] @@ -3067,9 +3064,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// assert_eq!(a.iter().rposition(|&x| x == 3), Some(2)); + /// assert_eq!(a.into_iter().rposition(|x| x == 3), Some(2)); /// - /// assert_eq!(a.iter().rposition(|&x| x == 5), None); + /// assert_eq!(a.into_iter().rposition(|x| x == 5), None); /// ``` /// /// Stopping at the first `true`: @@ -3077,13 +3074,13 @@ pub trait Iterator { /// ``` /// let a = [-1, 2, 3, 4]; /// - /// let mut iter = a.iter(); + /// let mut iter = a.into_iter(); /// - /// assert_eq!(iter.rposition(|&x| x >= 2), Some(3)); + /// assert_eq!(iter.rposition(|x| x >= 2), Some(3)); /// /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next(), Some(&-1)); - /// assert_eq!(iter.next_back(), Some(&3)); + /// assert_eq!(iter.next(), Some(-1)); + /// assert_eq!(iter.next_back(), Some(3)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -3129,10 +3126,10 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3]; - /// let b: Vec = Vec::new(); + /// let b: [u32; 0] = []; /// - /// assert_eq!(a.iter().max(), Some(&3)); - /// assert_eq!(b.iter().max(), None); + /// assert_eq!(a.into_iter().max(), Some(3)); + /// assert_eq!(b.into_iter().max(), None); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -3165,10 +3162,10 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3]; - /// let b: Vec = Vec::new(); + /// let b: [u32; 0] = []; /// - /// assert_eq!(a.iter().min(), Some(&1)); - /// assert_eq!(b.iter().min(), None); + /// assert_eq!(a.into_iter().min(), Some(1)); + /// assert_eq!(b.into_iter().min(), None); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -3190,7 +3187,7 @@ pub trait Iterator { /// /// ``` /// let a = [-3_i32, 0, 1, 5, -10]; - /// assert_eq!(*a.iter().max_by_key(|x| x.abs()).unwrap(), -10); + /// assert_eq!(a.into_iter().max_by_key(|x| x.abs()).unwrap(), -10); /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] @@ -3223,7 +3220,7 @@ pub trait Iterator { /// /// ``` /// let a = [-3_i32, 0, 1, 5, -10]; - /// assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5); + /// assert_eq!(a.into_iter().max_by(|x, y| x.cmp(y)).unwrap(), 5); /// ``` #[inline] #[stable(feature = "iter_max_by", since = "1.15.0")] @@ -3250,7 +3247,7 @@ pub trait Iterator { /// /// ``` /// let a = [-3_i32, 0, 1, 5, -10]; - /// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0); + /// assert_eq!(a.into_iter().min_by_key(|x| x.abs()).unwrap(), 0); /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] @@ -3283,7 +3280,7 @@ pub trait Iterator { /// /// ``` /// let a = [-3_i32, 0, 1, 5, -10]; - /// assert_eq!(*a.iter().min_by(|x, y| x.cmp(y)).unwrap(), -10); + /// assert_eq!(a.into_iter().min_by(|x, y| x.cmp(y)).unwrap(), -10); /// ``` #[inline] #[stable(feature = "iter_min_by", since = "1.15.0")] @@ -3313,11 +3310,11 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.iter().rev(); + /// let mut iter = a.into_iter().rev(); /// - /// assert_eq!(iter.next(), Some(&3)); - /// assert_eq!(iter.next(), Some(&2)); - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(3)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), Some(1)); /// /// assert_eq!(iter.next(), None); /// ``` @@ -3346,7 +3343,7 @@ pub trait Iterator { /// ``` /// let a = [(1, 2), (3, 4), (5, 6)]; /// - /// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip(); + /// let (left, right): (Vec<_>, Vec<_>) = a.into_iter().unzip(); /// /// assert_eq!(left, [1, 3, 5]); /// assert_eq!(right, [2, 4, 6]); @@ -3354,7 +3351,7 @@ pub trait Iterator { /// // you can also unzip multiple nested tuples at once /// let a = [(1, (2, 3)), (4, (5, 6))]; /// - /// let (x, (y, z)): (Vec<_>, (Vec<_>, Vec<_>)) = a.iter().cloned().unzip(); + /// let (x, (y, z)): (Vec<_>, (Vec<_>, Vec<_>)) = a.into_iter().unzip(); /// assert_eq!(x, [1, 4]); /// assert_eq!(y, [2, 5]); /// assert_eq!(z, [3, 6]); @@ -3386,8 +3383,8 @@ pub trait Iterator { /// // copied is the same as .map(|&x| x) /// let v_map: Vec<_> = a.iter().map(|&x| x).collect(); /// - /// assert_eq!(v_copied, vec![1, 2, 3]); - /// assert_eq!(v_map, vec![1, 2, 3]); + /// assert_eq!(v_copied, [1, 2, 3]); + /// assert_eq!(v_map, [1, 2, 3]); /// ``` #[stable(feature = "iter_copied", since = "1.36.0")] #[rustc_diagnostic_item = "iter_copied"] @@ -3422,8 +3419,8 @@ pub trait Iterator { /// // cloned is the same as .map(|&x| x), for integers /// let v_map: Vec<_> = a.iter().map(|&x| x).collect(); /// - /// assert_eq!(v_cloned, vec![1, 2, 3]); - /// assert_eq!(v_map, vec![1, 2, 3]); + /// assert_eq!(v_cloned, [1, 2, 3]); + /// assert_eq!(v_map, [1, 2, 3]); /// ``` /// /// To get the best performance, try to clone late: @@ -3459,15 +3456,14 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut it = a.iter().cycle(); + /// let mut iter = a.into_iter().cycle(); /// - /// assert_eq!(it.next(), Some(&1)); - /// assert_eq!(it.next(), Some(&2)); - /// assert_eq!(it.next(), Some(&3)); - /// assert_eq!(it.next(), Some(&1)); - /// assert_eq!(it.next(), Some(&2)); - /// assert_eq!(it.next(), Some(&3)); - /// assert_eq!(it.next(), Some(&1)); + /// loop { + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), Some(3)); + /// # break; + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -3625,9 +3621,9 @@ pub trait Iterator { /// let xs = [1, 2, 3, 4]; /// let ys = [1, 4, 9, 16]; /// - /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| x.cmp(&y)), Ordering::Less); - /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (x * x).cmp(&y)), Ordering::Equal); - /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); + /// assert_eq!(xs.into_iter().cmp_by(ys, |x, y| x.cmp(&y)), Ordering::Less); + /// assert_eq!(xs.into_iter().cmp_by(ys, |x, y| (x * x).cmp(&y)), Ordering::Equal); + /// assert_eq!(xs.into_iter().cmp_by(ys, |x, y| (2 * x).cmp(&y)), Ordering::Greater); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] fn cmp_by(self, other: I, cmp: F) -> Ordering @@ -3709,15 +3705,15 @@ pub trait Iterator { /// let ys = [1.0, 4.0, 9.0, 16.0]; /// /// assert_eq!( - /// xs.iter().partial_cmp_by(&ys, |&x, &y| x.partial_cmp(&y)), + /// xs.iter().partial_cmp_by(ys, |x, y| x.partial_cmp(&y)), /// Some(Ordering::Less) /// ); /// assert_eq!( - /// xs.iter().partial_cmp_by(&ys, |&x, &y| (x * x).partial_cmp(&y)), + /// xs.iter().partial_cmp_by(ys, |x, y| (x * x).partial_cmp(&y)), /// Some(Ordering::Equal) /// ); /// assert_eq!( - /// xs.iter().partial_cmp_by(&ys, |&x, &y| (2.0 * x).partial_cmp(&y)), + /// xs.iter().partial_cmp_by(ys, |x, y| (2.0 * x).partial_cmp(&y)), /// Some(Ordering::Greater) /// ); /// ``` @@ -3775,7 +3771,7 @@ pub trait Iterator { /// let xs = [1, 2, 3, 4]; /// let ys = [1, 4, 9, 16]; /// - /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); + /// assert!(xs.iter().eq_by(ys, |x, y| x * x == y)); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] fn eq_by(self, other: I, eq: F) -> bool diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3ad6662bdd7f..7dc8c060cd5b 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1661,7 +1661,6 @@ pub(crate) mod builtin { #[unstable( feature = "test", issue = "50297", - soft, reason = "`bench` is a part of custom test frameworks which are unstable" )] #[allow_internal_unstable(test, rustc_attrs, coverage_attribute)] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 445c789a7de2..aa103af93ffc 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1065,10 +1065,45 @@ pub const unsafe fn swap(x: *mut T, y: *mut T) { /// assert_eq!(x, [7, 8, 3, 4]); /// assert_eq!(y, [1, 2, 9]); /// ``` +/// +/// # Const evaluation limitations +/// +/// If this function is invoked during const-evaluation, the current implementation has a small (and +/// rarely relevant) limitation: if `count` is at least 2 and the data pointed to by `x` or `y` +/// contains a pointer that crosses the boundary of two `T`-sized chunks of memory, the function may +/// fail to evaluate (similar to a panic during const-evaluation). This behavior may change in the +/// future. +/// +/// The limitation is illustrated by the following example: +/// +/// ``` +/// use std::mem::size_of; +/// use std::ptr; +/// +/// const { unsafe { +/// const PTR_SIZE: usize = size_of::<*const i32>(); +/// let mut data1 = [0u8; PTR_SIZE]; +/// let mut data2 = [0u8; PTR_SIZE]; +/// // Store a pointer in `data1`. +/// data1.as_mut_ptr().cast::<*const i32>().write_unaligned(&42); +/// // Swap the contents of `data1` and `data2` by swapping `PTR_SIZE` many `u8`-sized chunks. +/// // This call will fail, because the pointer in `data1` crosses the boundary +/// // between several of the 1-byte chunks that are being swapped here. +/// //ptr::swap_nonoverlapping(data1.as_mut_ptr(), data2.as_mut_ptr(), PTR_SIZE); +/// // Swap the contents of `data1` and `data2` by swapping a single chunk of size +/// // `[u8; PTR_SIZE]`. That works, as there is no pointer crossing the boundary between +/// // two chunks. +/// ptr::swap_nonoverlapping(&mut data1, &mut data2, 1); +/// // Read the pointer from `data2` and dereference it. +/// let ptr = data2.as_ptr().cast::<*const i32>().read_unaligned(); +/// assert!(*ptr == 42); +/// } } +/// ``` #[inline] #[stable(feature = "swap_nonoverlapping", since = "1.27.0")] -#[rustc_const_unstable(feature = "const_swap_nonoverlapping", issue = "133668")] +#[rustc_const_stable(feature = "const_swap_nonoverlapping", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_swap_nonoverlapping"] +#[rustc_allow_const_fn_unstable(const_eval_select)] // both implementations behave the same pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { ub_checks::assert_unsafe_precondition!( check_library_ub, diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index ed2cefc59a51..8d4210c80827 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -147,12 +147,14 @@ impl fmt::Debug for Debug<'_> { /// An iterator used to decode a slice of mostly UTF-8 bytes to string slices /// ([`&str`]) and byte slices ([`&[u8]`][byteslice]). /// +/// This struct is created by the [`utf8_chunks`] method on bytes slices. /// If you want a simple conversion from UTF-8 byte slices to string slices, /// [`from_utf8`] is easier to use. /// /// See the [`Utf8Chunk`] type for documentation of the items yielded by this iterator. /// /// [byteslice]: slice +/// [`utf8_chunks`]: slice::utf8_chunks /// [`from_utf8`]: super::from_utf8 /// /// # Examples diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index f52e338a0850..a71c4139308a 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -15,7 +15,6 @@ #![feature(char_max_len)] #![feature(clone_to_uninit)] #![feature(const_eval_select)] -#![feature(const_swap_nonoverlapping)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] #![feature(core_intrinsics_fallbacks)] diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs index 7d6e4eac1e21..bb60fb07468f 100644 --- a/library/coretests/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs @@ -949,6 +949,10 @@ fn test_const_swap_ptr() { // Make sure they still work. assert!(*s1.0.ptr == 1); assert!(*s2.0.ptr == 666); + + // This is where we'd swap again using a `u8` type and a `count` of `size_of::()` if it + // were not for the limitation of `swap_nonoverlapping` around pointers crossing multiple + // elements. }; } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 36a1c57b0201..79e9b8430b8d 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -543,18 +543,18 @@ impl Span { /// The path to the source file in which this span occurs, for display purposes. /// /// This might not correspond to a valid file system path. - /// It might be remapped, or might be an artificial path such as `""`. - #[unstable(feature = "proc_macro_span", issue = "54725")] + /// It might be remapped (e.g. `"/src/lib.rs"`) or an artificial path (e.g. `""`). + #[stable(feature = "proc_macro_span_file", since = "CURRENT_RUSTC_VERSION")] pub fn file(&self) -> String { self.0.file() } - /// The path to the source file in which this span occurs on disk. + /// The path to the source file in which this span occurs on the local file system. /// /// This is the actual path on disk. It is unaffected by path remapping. /// /// This path should not be embedded in the output of the macro; prefer `file()` instead. - #[unstable(feature = "proc_macro_span", issue = "54725")] + #[stable(feature = "proc_macro_span_file", since = "CURRENT_RUSTC_VERSION")] pub fn local_file(&self) -> Option { self.0.local_file().map(|s| PathBuf::from(s)) } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index d7bd28b5279d..7915196e8e89 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.156" } +compiler_builtins = { version = "=0.1.158" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', @@ -57,7 +57,7 @@ object = { version = "0.36.0", default-features = false, optional = true, featur 'archive', ] } -[target.'cfg(windows)'.dependencies.windows-targets] +[target.'cfg(any(windows, target_os = "cygwin"))'.dependencies.windows-targets] path = "../windows_targets" [dev-dependencies] diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 9ad26e5d28ec..961d6ee0665c 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -683,7 +683,7 @@ impl HashMap { /// ``` #[inline] #[rustc_lint_query_instability] - #[stable(feature = "hash_extract_if", since = "1.87.0")] + #[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] pub fn extract_if(&mut self, pred: F) -> ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool, @@ -1680,12 +1680,9 @@ impl<'a, K, V> Drain<'a, K, V> { /// ]); /// let iter = map.extract_if(|_k, v| *v % 2 == 0); /// ``` -#[stable(feature = "hash_extract_if", since = "1.87.0")] +#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] #[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct ExtractIf<'a, K, V, F> -where - F: FnMut(&K, &mut V) -> bool, -{ +pub struct ExtractIf<'a, K, V, F> { base: base::ExtractIf<'a, K, V, F>, } @@ -2297,7 +2294,7 @@ where } } -#[stable(feature = "hash_extract_if", since = "1.87.0")] +#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] impl Iterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool, @@ -2314,13 +2311,14 @@ where } } -#[stable(feature = "hash_extract_if", since = "1.87.0")] +#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] impl FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {} -#[stable(feature = "hash_extract_if", since = "1.87.0")] -impl<'a, K, V, F> fmt::Debug for ExtractIf<'a, K, V, F> +#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +impl fmt::Debug for ExtractIf<'_, K, V, F> where - F: FnMut(&K, &mut V) -> bool, + K: fmt::Debug, + V: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ExtractIf").finish_non_exhaustive() diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 7be000594bc5..fa2f4f0a58fe 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -308,7 +308,7 @@ impl HashSet { /// ``` #[inline] #[rustc_lint_query_instability] - #[stable(feature = "hash_extract_if", since = "1.87.0")] + #[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] pub fn extract_if(&mut self, pred: F) -> ExtractIf<'_, T, F> where F: FnMut(&T) -> bool, @@ -1390,11 +1390,8 @@ pub struct Drain<'a, K: 'a> { /// /// let mut extract_ifed = a.extract_if(|v| v % 2 == 0); /// ``` -#[stable(feature = "hash_extract_if", since = "1.87.0")] -pub struct ExtractIf<'a, K, F> -where - F: FnMut(&K) -> bool, -{ +#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +pub struct ExtractIf<'a, K, F> { base: base::ExtractIf<'a, K, F>, } @@ -1673,7 +1670,7 @@ impl fmt::Debug for Drain<'_, K> { } } -#[stable(feature = "hash_extract_if", since = "1.87.0")] +#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] impl Iterator for ExtractIf<'_, K, F> where F: FnMut(&K) -> bool, @@ -1690,13 +1687,13 @@ where } } -#[stable(feature = "hash_extract_if", since = "1.87.0")] +#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] impl FusedIterator for ExtractIf<'_, K, F> where F: FnMut(&K) -> bool {} -#[stable(feature = "hash_extract_if", since = "1.87.0")] -impl<'a, K, F> fmt::Debug for ExtractIf<'a, K, F> +#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +impl fmt::Debug for ExtractIf<'_, K, F> where - F: FnMut(&K) -> bool, + K: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ExtractIf").finish_non_exhaustive() diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 462c06dcea26..11f439b9996d 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -21,7 +21,6 @@ mod tests; use crate::ffi::OsString; -use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; use crate::sealed::Sealed; @@ -29,6 +28,7 @@ use crate::sync::Arc; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::time::SystemTime; +use crate::{error, fmt}; /// An object providing access to an open file on the filesystem. /// @@ -116,6 +116,22 @@ pub struct File { inner: fs_imp::File, } +/// An enumeration of possible errors which can occur while trying to acquire a lock +/// from the [`try_lock`] method and [`try_lock_shared`] method on a [`File`]. +/// +/// [`try_lock`]: File::try_lock +/// [`try_lock_shared`]: File::try_lock_shared +#[unstable(feature = "file_lock", issue = "130994")] +pub enum TryLockError { + /// The lock could not be acquired due to an I/O error on the file. The standard library will + /// not return an [`ErrorKind::WouldBlock`] error inside [`TryLockError::Error`] + /// + /// [`ErrorKind::WouldBlock`]: io::ErrorKind::WouldBlock + Error(io::Error), + /// The lock could not be acquired at this time because it is held by another handle/process. + WouldBlock, +} + /// Metadata information about a file. /// /// This structure is returned from the [`metadata`] or @@ -352,6 +368,30 @@ pub fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result inner(path.as_ref(), contents.as_ref()) } +#[unstable(feature = "file_lock", issue = "130994")] +impl error::Error for TryLockError {} + +#[unstable(feature = "file_lock", issue = "130994")] +impl fmt::Debug for TryLockError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + TryLockError::Error(err) => err.fmt(f), + TryLockError::WouldBlock => "WouldBlock".fmt(f), + } + } +} + +#[unstable(feature = "file_lock", issue = "130994")] +impl fmt::Display for TryLockError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + TryLockError::Error(_) => "lock acquisition failed due to I/O error", + TryLockError::WouldBlock => "lock acquisition failed because the operation would block", + } + .fmt(f) + } +} + impl File { /// Attempts to open a file in read-only mode. /// @@ -734,8 +774,8 @@ impl File { /// Try to acquire an exclusive lock on the file. /// - /// Returns `Ok(false)` if a different lock is already held on this file (via another - /// handle/descriptor). + /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file + /// (via another handle/descriptor). /// /// This acquires an exclusive lock; no other file handle to this file may acquire another lock. /// @@ -777,23 +817,27 @@ impl File { /// /// ```no_run /// #![feature(file_lock)] - /// use std::fs::File; + /// use std::fs::{File, TryLockError}; /// /// fn main() -> std::io::Result<()> { /// let f = File::create("foo.txt")?; - /// f.try_lock()?; + /// match f.try_lock() { + /// Ok(_) => (), + /// Err(TryLockError::WouldBlock) => (), // Lock not acquired + /// Err(TryLockError::Error(err)) => return Err(err), + /// } /// Ok(()) /// } /// ``` #[unstable(feature = "file_lock", issue = "130994")] - pub fn try_lock(&self) -> io::Result { + pub fn try_lock(&self) -> Result<(), TryLockError> { self.inner.try_lock() } /// Try to acquire a shared (non-exclusive) lock on the file. /// - /// Returns `Ok(false)` if an exclusive lock is already held on this file (via another - /// handle/descriptor). + /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file + /// (via another handle/descriptor). /// /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may /// hold an exclusive lock at the same time. @@ -834,16 +878,21 @@ impl File { /// /// ```no_run /// #![feature(file_lock)] - /// use std::fs::File; + /// use std::fs::{File, TryLockError}; /// /// fn main() -> std::io::Result<()> { /// let f = File::open("foo.txt")?; - /// f.try_lock_shared()?; + /// match f.try_lock_shared() { + /// Ok(_) => (), + /// Err(TryLockError::WouldBlock) => (), // Lock not acquired + /// Err(TryLockError::Error(err)) => return Err(err), + /// } + /// /// Ok(()) /// } /// ``` #[unstable(feature = "file_lock", issue = "130994")] - pub fn try_lock_shared(&self) -> io::Result { + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { self.inner.try_lock_shared() } @@ -2994,7 +3043,7 @@ pub fn read_dir>(path: P) -> io::Result { /// When possible, permissions should be set at creation time instead. /// /// # Rationale -/// POSIX does not specify an `lchown` function, +/// POSIX does not specify an `lchmod` function, /// and symlinks can be followed regardless of what permission bits are set. /// /// # Errors diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 4712e58980cc..c81a5ff4d96e 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1,6 +1,22 @@ use rand::RngCore; +#[cfg(any( + windows, + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", +))] +use crate::assert_matches::assert_matches; use crate::char::MAX_LEN_UTF8; +#[cfg(any( + windows, + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", +))] +use crate::fs::TryLockError; use crate::fs::{self, File, FileTimes, OpenOptions}; use crate::io::prelude::*; use crate::io::{BorrowedBuf, ErrorKind, SeekFrom}; @@ -223,8 +239,8 @@ fn file_lock_multiple_shared() { check!(f2.lock_shared()); check!(f1.unlock()); check!(f2.unlock()); - assert!(check!(f1.try_lock_shared())); - assert!(check!(f2.try_lock_shared())); + check!(f1.try_lock_shared()); + check!(f2.try_lock_shared()); } #[test] @@ -243,12 +259,12 @@ fn file_lock_blocking() { // Check that shared locks block exclusive locks check!(f1.lock_shared()); - assert!(!check!(f2.try_lock())); + assert_matches!(f2.try_lock(), Err(TryLockError::WouldBlock)); check!(f1.unlock()); // Check that exclusive locks block shared locks check!(f1.lock()); - assert!(!check!(f2.try_lock_shared())); + assert_matches!(f2.try_lock_shared(), Err(TryLockError::WouldBlock)); } #[test] @@ -267,9 +283,9 @@ fn file_lock_drop() { // Check that locks are released when the File is dropped check!(f1.lock_shared()); - assert!(!check!(f2.try_lock())); + assert_matches!(f2.try_lock(), Err(TryLockError::WouldBlock)); drop(f1); - assert!(check!(f2.try_lock())); + check!(f2.try_lock()); } #[test] @@ -288,10 +304,10 @@ fn file_lock_dup() { // Check that locks are not dropped if the File has been cloned check!(f1.lock_shared()); - assert!(!check!(f2.try_lock())); + assert_matches!(f2.try_lock(), Err(TryLockError::WouldBlock)); let cloned = check!(f1.try_clone()); drop(f1); - assert!(!check!(f2.try_lock())); + assert_matches!(f2.try_lock(), Err(TryLockError::WouldBlock)); drop(cloned) } @@ -307,9 +323,9 @@ fn file_lock_double_unlock() { // Check that both are released by unlock() check!(f1.lock()); check!(f1.lock_shared()); - assert!(!check!(f2.try_lock())); + assert_matches!(f2.try_lock(), Err(TryLockError::WouldBlock)); check!(f1.unlock()); - assert!(check!(f2.try_lock())); + check!(f2.try_lock()); } #[test] @@ -714,6 +730,10 @@ fn recursive_mkdir_empty() { } #[test] +#[cfg_attr( + all(windows, target_arch = "aarch64"), + ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" +)] fn recursive_rmdir() { let tmpdir = tmpdir(); let d1 = tmpdir.join("d1"); @@ -733,6 +753,10 @@ fn recursive_rmdir() { } #[test] +#[cfg_attr( + all(windows, target_arch = "aarch64"), + ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" +)] fn recursive_rmdir_of_symlink() { // test we do not recursively delete a symlink but only dirs. let tmpdir = tmpdir(); @@ -1517,6 +1541,10 @@ fn file_open_not_found() { } #[test] +#[cfg_attr( + all(windows, target_arch = "aarch64"), + ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" +)] fn create_dir_all_with_junctions() { let tmpdir = tmpdir(); let target = tmpdir.join("target"); @@ -1995,6 +2023,10 @@ fn test_rename_symlink() { #[test] #[cfg(windows)] +#[cfg_attr( + all(windows, target_arch = "aarch64"), + ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" +)] fn test_rename_junction() { let tmpdir = tmpdir(); let original = tmpdir.join("original"); diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs index c6b7b49a351e..47243806cd2d 100644 --- a/library/std/src/io/pipe.rs +++ b/library/std/src/io/pipe.rs @@ -2,7 +2,7 @@ use crate::io; use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; use crate::sys_common::{FromInner, IntoInner}; -/// Create an anonymous pipe. +/// Creates an anonymous pipe. /// /// # Behavior /// @@ -108,7 +108,7 @@ impl IntoInner for PipeWriter { } impl PipeReader { - /// Create a new [`PipeReader`] instance that shares the same underlying file description. + /// Creates a new [`PipeReader`] instance that shares the same underlying file description. /// /// # Examples /// @@ -167,7 +167,7 @@ impl PipeReader { } impl PipeWriter { - /// Create a new [`PipeWriter`] instance that shares the same underlying file description. + /// Creates a new [`PipeWriter`] instance that shares the same underlying file description. /// /// # Examples /// diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 76ce7bce81b1..df6b9a6e563c 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -168,8 +168,6 @@ use crate::num::NonZero; use crate::path::Path; use crate::sys::pipe::{AnonPipe, read2}; use crate::sys::process as imp; -#[stable(feature = "command_access", since = "1.57.0")] -pub use crate::sys_common::process::CommandEnvs; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::{fmt, fs, str}; @@ -1073,7 +1071,7 @@ impl Command { /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn output(&mut self) -> io::Result { - let (status, stdout, stderr) = self.inner.output()?; + let (status, stdout, stderr) = imp::output(&mut self.inner)?; Ok(Output { status: ExitStatus(status), stdout, stderr }) } @@ -1174,7 +1172,7 @@ impl Command { /// ``` #[stable(feature = "command_access", since = "1.57.0")] pub fn get_envs(&self) -> CommandEnvs<'_> { - self.inner.get_envs() + CommandEnvs { iter: self.inner.get_envs() } } /// Returns the working directory for the child process. @@ -1264,6 +1262,48 @@ impl<'a> ExactSizeIterator for CommandArgs<'a> { } } +/// An iterator over the command environment variables. +/// +/// This struct is created by +/// [`Command::get_envs`][crate::process::Command::get_envs]. See its +/// documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "command_access", since = "1.57.0")] +pub struct CommandEnvs<'a> { + iter: imp::CommandEnvs<'a>, +} + +#[stable(feature = "command_access", since = "1.57.0")] +impl<'a> Iterator for CommandEnvs<'a> { + type Item = (&'a OsStr, Option<&'a OsStr>); + + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "command_access", since = "1.57.0")] +impl<'a> ExactSizeIterator for CommandEnvs<'a> { + fn len(&self) -> usize { + self.iter.len() + } + + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "command_access", since = "1.57.0")] +impl<'a> fmt::Debug for CommandEnvs<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.fmt(f) + } +} + /// The output of a finished process. /// /// This is returned in a Result by either the [`output`] method of a diff --git a/library/std/src/sys/args/common.rs b/library/std/src/sys/args/common.rs index 303b373ccf90..e787105a05a7 100644 --- a/library/std/src/sys/args/common.rs +++ b/library/std/src/sys/args/common.rs @@ -49,8 +49,8 @@ impl Iterator for Args { } #[inline] - fn last(mut self) -> Option { - self.iter.next_back() + fn last(self) -> Option { + self.iter.last() } #[inline] diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index 99690abe8ed2..a9774bef9e33 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs @@ -1,4 +1,5 @@ use crate::ffi::{CStr, OsStr, OsString, c_char}; +use crate::fs::TryLockError; use crate::io::{self, BorrowedCursor, Error, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; use crate::os::hermit::ffi::OsStringExt; use crate::os::hermit::hermit_abi::{ @@ -12,7 +13,7 @@ use crate::sys::common::small_c_string::run_path_with_cstr; use crate::sys::fd::FileDesc; pub use crate::sys::fs::common::{copy, exists}; use crate::sys::time::SystemTime; -use crate::sys::{cvt, unsupported}; +use crate::sys::{cvt, unsupported, unsupported_err}; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::{fmt, mem}; @@ -366,12 +367,12 @@ impl File { unsupported() } - pub fn try_lock(&self) -> io::Result { - unsupported() + pub fn try_lock(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(unsupported_err())) } - pub fn try_lock_shared(&self) -> io::Result { - unsupported() + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(unsupported_err())) } pub fn unlock(&self) -> io::Result<()> { diff --git a/library/std/src/sys/fs/solid.rs b/library/std/src/sys/fs/solid.rs index 39de933b7248..3bfb39bac95b 100644 --- a/library/std/src/sys/fs/solid.rs +++ b/library/std/src/sys/fs/solid.rs @@ -2,6 +2,7 @@ use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; +use crate::fs::TryLockError; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::mem::MaybeUninit; use crate::os::raw::{c_int, c_short}; @@ -11,7 +12,7 @@ use crate::sync::Arc; pub use crate::sys::fs::common::exists; use crate::sys::pal::{abi, error}; use crate::sys::time::SystemTime; -use crate::sys::unsupported; +use crate::sys::{unsupported, unsupported_err}; use crate::sys_common::ignore_notfound; type CIntNotMinusOne = core::num::niche_types::NotAllOnes; @@ -352,12 +353,12 @@ impl File { unsupported() } - pub fn try_lock(&self) -> io::Result { - unsupported() + pub fn try_lock(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(unsupported_err())) } - pub fn try_lock_shared(&self) -> io::Result { - unsupported() + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(unsupported_err())) } pub fn unlock(&self) -> io::Result<()> { diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index d6ae86bd3d26..416c90b98b6d 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -2,6 +2,7 @@ use r_efi::protocols::file; use crate::ffi::OsString; use crate::fmt; +use crate::fs::TryLockError; use crate::hash::Hash; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::path::{Path, PathBuf}; @@ -227,11 +228,11 @@ impl File { self.0 } - pub fn try_lock(&self) -> io::Result { + pub fn try_lock(&self) -> Result<(), TryLockError> { self.0 } - pub fn try_lock_shared(&self) -> io::Result { + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { self.0 } diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 5af59a2a914c..863358596c19 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -75,6 +75,7 @@ use libc::{dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, st use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt::{self, Write as _}; +use crate::fs::TryLockError; use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; use crate::os::unix::prelude::*; @@ -1310,15 +1311,17 @@ impl File { target_os = "netbsd", target_vendor = "apple", ))] - pub fn try_lock(&self) -> io::Result { + pub fn try_lock(&self) -> Result<(), TryLockError> { let result = cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_EX | libc::LOCK_NB) }); - if let Err(ref err) = result { + if let Err(err) = result { if err.kind() == io::ErrorKind::WouldBlock { - return Ok(false); + Err(TryLockError::WouldBlock) + } else { + Err(TryLockError::Error(err)) } + } else { + Ok(()) } - result?; - return Ok(true); } #[cfg(not(any( @@ -1328,8 +1331,11 @@ impl File { target_os = "netbsd", target_vendor = "apple", )))] - pub fn try_lock(&self) -> io::Result { - Err(io::const_error!(io::ErrorKind::Unsupported, "try_lock() not supported")) + pub fn try_lock(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(io::const_error!( + io::ErrorKind::Unsupported, + "try_lock() not supported" + ))) } #[cfg(any( @@ -1339,15 +1345,17 @@ impl File { target_os = "netbsd", target_vendor = "apple", ))] - pub fn try_lock_shared(&self) -> io::Result { + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { let result = cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_SH | libc::LOCK_NB) }); - if let Err(ref err) = result { + if let Err(err) = result { if err.kind() == io::ErrorKind::WouldBlock { - return Ok(false); + Err(TryLockError::WouldBlock) + } else { + Err(TryLockError::Error(err)) } + } else { + Ok(()) } - result?; - return Ok(true); } #[cfg(not(any( @@ -1357,8 +1365,11 @@ impl File { target_os = "netbsd", target_vendor = "apple", )))] - pub fn try_lock_shared(&self) -> io::Result { - Err(io::const_error!(io::ErrorKind::Unsupported, "try_lock_shared() not supported")) + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(io::const_error!( + io::ErrorKind::Unsupported, + "try_lock_shared() not supported" + ))) } #[cfg(any( diff --git a/library/std/src/sys/fs/unsupported.rs b/library/std/src/sys/fs/unsupported.rs index 45e93deffa3a..0ff9533c0473 100644 --- a/library/std/src/sys/fs/unsupported.rs +++ b/library/std/src/sys/fs/unsupported.rs @@ -1,5 +1,6 @@ use crate::ffi::OsString; use crate::fmt; +use crate::fs::TryLockError; use crate::hash::{Hash, Hasher}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::path::{Path, PathBuf}; @@ -206,11 +207,11 @@ impl File { self.0 } - pub fn try_lock(&self) -> io::Result { + pub fn try_lock(&self) -> Result<(), TryLockError> { self.0 } - pub fn try_lock_shared(&self) -> io::Result { + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { self.0 } diff --git a/library/std/src/sys/fs/wasi.rs b/library/std/src/sys/fs/wasi.rs index 773040571bc9..ebfc7377a2ea 100644 --- a/library/std/src/sys/fs/wasi.rs +++ b/library/std/src/sys/fs/wasi.rs @@ -1,4 +1,5 @@ use crate::ffi::{CStr, OsStr, OsString}; +use crate::fs::TryLockError; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::mem::{self, ManuallyDrop}; use crate::os::raw::c_int; @@ -10,7 +11,7 @@ use crate::sys::common::small_c_string::run_path_with_cstr; use crate::sys::fd::WasiFd; pub use crate::sys::fs::common::exists; use crate::sys::time::SystemTime; -use crate::sys::unsupported; +use crate::sys::{unsupported, unsupported_err}; use crate::sys_common::{AsInner, FromInner, IntoInner, ignore_notfound}; use crate::{fmt, iter, ptr}; @@ -461,12 +462,12 @@ impl File { unsupported() } - pub fn try_lock(&self) -> io::Result { - unsupported() + pub fn try_lock(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(unsupported_err())) } - pub fn try_lock_shared(&self) -> io::Result { - unsupported() + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(unsupported_err())) } pub fn unlock(&self) -> io::Result<()> { diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 9215f9375671..9039fd00f5d6 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -3,6 +3,7 @@ use crate::alloc::{Layout, alloc, dealloc}; use crate::borrow::Cow; use crate::ffi::{OsStr, OsString, c_void}; +use crate::fs::TryLockError; use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem::{self, MaybeUninit, offset_of}; use crate::os::windows::io::{AsHandle, BorrowedHandle}; @@ -399,7 +400,7 @@ impl File { self.acquire_lock(0) } - pub fn try_lock(&self) -> io::Result { + pub fn try_lock(&self) -> Result<(), TryLockError> { let result = cvt(unsafe { let mut overlapped = mem::zeroed(); c::LockFileEx( @@ -413,18 +414,18 @@ impl File { }); match result { - Ok(_) => Ok(true), + Ok(_) => Ok(()), Err(err) if err.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) || err.raw_os_error() == Some(c::ERROR_LOCK_VIOLATION as i32) => { - Ok(false) + Err(TryLockError::WouldBlock) } - Err(err) => Err(err), + Err(err) => Err(TryLockError::Error(err)), } } - pub fn try_lock_shared(&self) -> io::Result { + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { let result = cvt(unsafe { let mut overlapped = mem::zeroed(); c::LockFileEx( @@ -438,14 +439,14 @@ impl File { }); match result { - Ok(_) => Ok(true), + Ok(_) => Ok(()), Err(err) if err.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) || err.raw_os_error() == Some(c::ERROR_LOCK_VIOLATION as i32) => { - Ok(false) + Err(TryLockError::WouldBlock) } - Err(err) => Err(err), + Err(err) => Err(TryLockError::Error(err)), } } diff --git a/library/std/src/sys/pal/unix/fuchsia.rs b/library/std/src/sys/pal/unix/fuchsia.rs index 7932bd26d76c..c118dee62476 100644 --- a/library/std/src/sys/pal/unix/fuchsia.rs +++ b/library/std/src/sys/pal/unix/fuchsia.rs @@ -1,48 +1,35 @@ -#![allow(non_camel_case_types, unused)] +#![expect(non_camel_case_types)] -use libc::{c_int, c_void, size_t}; +use libc::size_t; +use crate::ffi::{c_char, c_int, c_void}; use crate::io; -use crate::mem::MaybeUninit; -use crate::os::raw::c_char; + +////////// +// Time // +////////// + +pub type zx_time_t = i64; + +pub const ZX_TIME_INFINITE: zx_time_t = i64::MAX; + +unsafe extern "C" { + pub safe fn zx_clock_get_monotonic() -> zx_time_t; +} + +///////////// +// Handles // +///////////// pub type zx_handle_t = u32; -pub type zx_vaddr_t = usize; -pub type zx_rights_t = u32; -pub type zx_status_t = i32; pub const ZX_HANDLE_INVALID: zx_handle_t = 0; -pub type zx_time_t = i64; -pub const ZX_TIME_INFINITE: zx_time_t = i64::MAX; - -pub type zx_signals_t = u32; - -pub const ZX_OBJECT_SIGNAL_3: zx_signals_t = 1 << 3; - -pub const ZX_TASK_TERMINATED: zx_signals_t = ZX_OBJECT_SIGNAL_3; - -pub const ZX_RIGHT_SAME_RIGHTS: zx_rights_t = 1 << 31; - -// The upper four bits gives the minor version. -pub type zx_object_info_topic_t = u32; - -pub const ZX_INFO_PROCESS: zx_object_info_topic_t = 3 | (1 << 28); - -pub type zx_info_process_flags_t = u32; - -pub fn zx_cvt(t: T) -> io::Result -where - T: TryInto + Copy, -{ - if let Ok(status) = TryInto::try_into(t) { - if status < 0 { Err(io::Error::from_raw_os_error(status)) } else { Ok(t) } - } else { - Err(io::Error::last_os_error()) - } +unsafe extern "C" { + pub fn zx_handle_close(handle: zx_handle_t) -> zx_status_t; } -// Safe wrapper around zx_handle_t +/// A safe wrapper around `zx_handle_t`. pub struct Handle { raw: zx_handle_t, } @@ -65,6 +52,66 @@ impl Drop for Handle { } } +/////////// +// Futex // +/////////// + +pub type zx_futex_t = crate::sync::atomic::Atomic; + +unsafe extern "C" { + pub fn zx_object_wait_one( + handle: zx_handle_t, + signals: zx_signals_t, + timeout: zx_time_t, + pending: *mut zx_signals_t, + ) -> zx_status_t; + + pub fn zx_futex_wait( + value_ptr: *const zx_futex_t, + current_value: zx_futex_t, + new_futex_owner: zx_handle_t, + deadline: zx_time_t, + ) -> zx_status_t; + pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t; + pub fn zx_futex_wake_single_owner(value_ptr: *const zx_futex_t) -> zx_status_t; + pub safe fn zx_thread_self() -> zx_handle_t; +} + +//////////////// +// Properties // +//////////////// + +pub const ZX_PROP_NAME: u32 = 3; + +unsafe extern "C" { + pub fn zx_object_set_property( + handle: zx_handle_t, + property: u32, + value: *const libc::c_void, + value_size: libc::size_t, + ) -> zx_status_t; +} + +///////////// +// Signals // +///////////// + +pub type zx_signals_t = u32; + +pub const ZX_OBJECT_SIGNAL_3: zx_signals_t = 1 << 3; +pub const ZX_TASK_TERMINATED: zx_signals_t = ZX_OBJECT_SIGNAL_3; + +///////////////// +// Object info // +///////////////// + +// The upper four bits gives the minor version. +pub type zx_object_info_topic_t = u32; + +pub const ZX_INFO_PROCESS: zx_object_info_topic_t = 3 | (1 << 28); + +pub type zx_info_process_flags_t = u32; + // Returned for topic ZX_INFO_PROCESS #[derive(Default)] #[repr(C)] @@ -76,25 +123,6 @@ pub struct zx_info_process_t { } unsafe extern "C" { - pub fn zx_job_default() -> zx_handle_t; - - pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t; - - pub fn zx_handle_close(handle: zx_handle_t) -> zx_status_t; - - pub fn zx_handle_duplicate( - handle: zx_handle_t, - rights: zx_rights_t, - out: *const zx_handle_t, - ) -> zx_handle_t; - - pub fn zx_object_wait_one( - handle: zx_handle_t, - signals: zx_signals_t, - timeout: zx_time_t, - pending: *mut zx_signals_t, - ) -> zx_status_t; - pub fn zx_object_get_info( handle: zx_handle_t, topic: u32, @@ -105,6 +133,10 @@ unsafe extern "C" { ) -> zx_status_t; } +/////////////// +// Processes // +/////////////// + #[derive(Default)] #[repr(C)] pub struct fdio_spawn_action_t { @@ -130,6 +162,8 @@ unsafe extern "C" { pub fn fdio_fd_clone(fd: c_int, out_handle: *mut zx_handle_t) -> zx_status_t; pub fn fdio_fd_create(handle: zx_handle_t, fd: *mut c_int) -> zx_status_t; + + pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t; } // fdio_spawn_etc flags @@ -137,173 +171,34 @@ unsafe extern "C" { pub const FDIO_SPAWN_CLONE_JOB: u32 = 0x0001; pub const FDIO_SPAWN_CLONE_LDSVC: u32 = 0x0002; pub const FDIO_SPAWN_CLONE_NAMESPACE: u32 = 0x0004; -pub const FDIO_SPAWN_CLONE_STDIO: u32 = 0x0008; pub const FDIO_SPAWN_CLONE_ENVIRON: u32 = 0x0010; pub const FDIO_SPAWN_CLONE_UTC_CLOCK: u32 = 0x0020; -pub const FDIO_SPAWN_CLONE_ALL: u32 = 0xFFFF; // fdio_spawn_etc actions -pub const FDIO_SPAWN_ACTION_CLONE_FD: u32 = 0x0001; pub const FDIO_SPAWN_ACTION_TRANSFER_FD: u32 = 0x0002; -// Errors +//////////// +// Errors // +//////////// -#[allow(unused)] -pub const ERR_INTERNAL: zx_status_t = -1; +pub type zx_status_t = i32; -// ERR_NOT_SUPPORTED: The operation is not implemented, supported, -// or enabled. -#[allow(unused)] -pub const ERR_NOT_SUPPORTED: zx_status_t = -2; +pub const ZX_OK: zx_status_t = 0; +pub const ZX_ERR_NOT_SUPPORTED: zx_status_t = -2; +pub const ZX_ERR_INVALID_ARGS: zx_status_t = -10; +pub const ZX_ERR_BAD_HANDLE: zx_status_t = -11; +pub const ZX_ERR_WRONG_TYPE: zx_status_t = -12; +pub const ZX_ERR_BAD_STATE: zx_status_t = -20; +pub const ZX_ERR_TIMED_OUT: zx_status_t = -21; -// ERR_NO_RESOURCES: The system was not able to allocate some resource -// needed for the operation. -#[allow(unused)] -pub const ERR_NO_RESOURCES: zx_status_t = -3; - -// ERR_NO_MEMORY: The system was not able to allocate memory needed -// for the operation. -#[allow(unused)] -pub const ERR_NO_MEMORY: zx_status_t = -4; - -// ERR_CALL_FAILED: The second phase of zx_channel_call(; did not complete -// successfully. -#[allow(unused)] -pub const ERR_CALL_FAILED: zx_status_t = -5; - -// ERR_INTERRUPTED_RETRY: The system call was interrupted, but should be -// retried. This should not be seen outside of the VDSO. -#[allow(unused)] -pub const ERR_INTERRUPTED_RETRY: zx_status_t = -6; - -// ======= Parameter errors ======= -// ERR_INVALID_ARGS: an argument is invalid, ex. null pointer -#[allow(unused)] -pub const ERR_INVALID_ARGS: zx_status_t = -10; - -// ERR_BAD_HANDLE: A specified handle value does not refer to a handle. -#[allow(unused)] -pub const ERR_BAD_HANDLE: zx_status_t = -11; - -// ERR_WRONG_TYPE: The subject of the operation is the wrong type to -// perform the operation. -// Example: Attempting a message_read on a thread handle. -#[allow(unused)] -pub const ERR_WRONG_TYPE: zx_status_t = -12; - -// ERR_BAD_SYSCALL: The specified syscall number is invalid. -#[allow(unused)] -pub const ERR_BAD_SYSCALL: zx_status_t = -13; - -// ERR_OUT_OF_RANGE: An argument is outside the valid range for this -// operation. -#[allow(unused)] -pub const ERR_OUT_OF_RANGE: zx_status_t = -14; - -// ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for -// this operation. -#[allow(unused)] -pub const ERR_BUFFER_TOO_SMALL: zx_status_t = -15; - -// ======= Precondition or state errors ======= -// ERR_BAD_STATE: operation failed because the current state of the -// object does not allow it, or a precondition of the operation is -// not satisfied -#[allow(unused)] -pub const ERR_BAD_STATE: zx_status_t = -20; - -// ERR_TIMED_OUT: The time limit for the operation elapsed before -// the operation completed. -#[allow(unused)] -pub const ERR_TIMED_OUT: zx_status_t = -21; - -// ERR_SHOULD_WAIT: The operation cannot be performed currently but -// potentially could succeed if the caller waits for a prerequisite -// to be satisfied, for example waiting for a handle to be readable -// or writable. -// Example: Attempting to read from a message pipe that has no -// messages waiting but has an open remote will return ERR_SHOULD_WAIT. -// Attempting to read from a message pipe that has no messages waiting -// and has a closed remote end will return ERR_REMOTE_CLOSED. -#[allow(unused)] -pub const ERR_SHOULD_WAIT: zx_status_t = -22; - -// ERR_CANCELED: The in-progress operation (e.g., a wait) has been -// // canceled. -#[allow(unused)] -pub const ERR_CANCELED: zx_status_t = -23; - -// ERR_PEER_CLOSED: The operation failed because the remote end -// of the subject of the operation was closed. -#[allow(unused)] -pub const ERR_PEER_CLOSED: zx_status_t = -24; - -// ERR_NOT_FOUND: The requested entity is not found. -#[allow(unused)] -pub const ERR_NOT_FOUND: zx_status_t = -25; - -// ERR_ALREADY_EXISTS: An object with the specified identifier -// already exists. -// Example: Attempting to create a file when a file already exists -// with that name. -#[allow(unused)] -pub const ERR_ALREADY_EXISTS: zx_status_t = -26; - -// ERR_ALREADY_BOUND: The operation failed because the named entity -// is already owned or controlled by another entity. The operation -// could succeed later if the current owner releases the entity. -#[allow(unused)] -pub const ERR_ALREADY_BOUND: zx_status_t = -27; - -// ERR_UNAVAILABLE: The subject of the operation is currently unable -// to perform the operation. -// Note: This is used when there's no direct way for the caller to -// observe when the subject will be able to perform the operation -// and should thus retry. -#[allow(unused)] -pub const ERR_UNAVAILABLE: zx_status_t = -28; - -// ======= Permission check errors ======= -// ERR_ACCESS_DENIED: The caller did not have permission to perform -// the specified operation. -#[allow(unused)] -pub const ERR_ACCESS_DENIED: zx_status_t = -30; - -// ======= Input-output errors ======= -// ERR_IO: Otherwise unspecified error occurred during I/O. -#[allow(unused)] -pub const ERR_IO: zx_status_t = -40; - -// ERR_REFUSED: The entity the I/O operation is being performed on -// rejected the operation. -// Example: an I2C device NAK'ing a transaction or a disk controller -// rejecting an invalid command. -#[allow(unused)] -pub const ERR_IO_REFUSED: zx_status_t = -41; - -// ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity -// check and is possibly corrupted. -// Example: CRC or Parity error. -#[allow(unused)] -pub const ERR_IO_DATA_INTEGRITY: zx_status_t = -42; - -// ERR_IO_DATA_LOSS: The data in the operation is currently unavailable -// and may be permanently lost. -// Example: A disk block is irrecoverably damaged. -#[allow(unused)] -pub const ERR_IO_DATA_LOSS: zx_status_t = -43; - -// Filesystem specific errors -#[allow(unused)] -pub const ERR_BAD_PATH: zx_status_t = -50; -#[allow(unused)] -pub const ERR_NOT_DIR: zx_status_t = -51; -#[allow(unused)] -pub const ERR_NOT_FILE: zx_status_t = -52; -// ERR_FILE_BIG: A file exceeds a filesystem-specific size limit. -#[allow(unused)] -pub const ERR_FILE_BIG: zx_status_t = -53; -// ERR_NO_SPACE: Filesystem or device space is exhausted. -#[allow(unused)] -pub const ERR_NO_SPACE: zx_status_t = -54; +pub fn zx_cvt(t: T) -> io::Result +where + T: TryInto + Copy, +{ + if let Ok(status) = TryInto::try_into(t) { + if status < 0 { Err(io::Error::from_raw_os_error(status)) } else { Ok(t) } + } else { + Err(io::Error::last_os_error()) + } +} diff --git a/library/std/src/sys/pal/unix/futex.rs b/library/std/src/sys/pal/unix/futex.rs index 8d89163c42ce..c23278bdf5e5 100644 --- a/library/std/src/sys/pal/unix/futex.rs +++ b/library/std/src/sys/pal/unix/futex.rs @@ -254,67 +254,29 @@ pub fn futex_wake_all(futex: &Atomic) { unsafe { emscripten_futex_wake(futex, i32::MAX) }; } -#[cfg(target_os = "fuchsia")] -pub mod zircon { - pub type zx_futex_t = crate::sync::atomic::Atomic; - pub type zx_handle_t = u32; - pub type zx_status_t = i32; - pub type zx_time_t = i64; - - pub const ZX_HANDLE_INVALID: zx_handle_t = 0; - - pub const ZX_TIME_INFINITE: zx_time_t = zx_time_t::MAX; - - pub const ZX_OK: zx_status_t = 0; - pub const ZX_ERR_INVALID_ARGS: zx_status_t = -10; - pub const ZX_ERR_BAD_HANDLE: zx_status_t = -11; - pub const ZX_ERR_WRONG_TYPE: zx_status_t = -12; - pub const ZX_ERR_BAD_STATE: zx_status_t = -20; - pub const ZX_ERR_TIMED_OUT: zx_status_t = -21; - - unsafe extern "C" { - pub fn zx_clock_get_monotonic() -> zx_time_t; - pub fn zx_futex_wait( - value_ptr: *const zx_futex_t, - current_value: zx_futex_t, - new_futex_owner: zx_handle_t, - deadline: zx_time_t, - ) -> zx_status_t; - pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t; - pub fn zx_futex_wake_single_owner(value_ptr: *const zx_futex_t) -> zx_status_t; - pub fn zx_thread_self() -> zx_handle_t; - } -} - #[cfg(target_os = "fuchsia")] pub fn futex_wait(futex: &Atomic, expected: u32, timeout: Option) -> bool { + use super::fuchsia::*; + // Sleep forever if the timeout is longer than fits in a i64. let deadline = timeout - .and_then(|d| { - i64::try_from(d.as_nanos()) - .ok()? - .checked_add(unsafe { zircon::zx_clock_get_monotonic() }) - }) - .unwrap_or(zircon::ZX_TIME_INFINITE); + .and_then(|d| i64::try_from(d.as_nanos()).ok()?.checked_add(zx_clock_get_monotonic())) + .unwrap_or(ZX_TIME_INFINITE); unsafe { - zircon::zx_futex_wait( - futex, - core::sync::atomic::AtomicU32::new(expected), - zircon::ZX_HANDLE_INVALID, - deadline, - ) != zircon::ZX_ERR_TIMED_OUT + zx_futex_wait(futex, zx_futex_t::new(expected), ZX_HANDLE_INVALID, deadline) + != ZX_ERR_TIMED_OUT } } // Fuchsia doesn't tell us how many threads are woken up, so this always returns false. #[cfg(target_os = "fuchsia")] pub fn futex_wake(futex: &Atomic) -> bool { - unsafe { zircon::zx_futex_wake(futex, 1) }; + unsafe { super::fuchsia::zx_futex_wake(futex, 1) }; false } #[cfg(target_os = "fuchsia")] pub fn futex_wake_all(futex: &Atomic) { - unsafe { zircon::zx_futex_wake(futex, u32::MAX) }; + unsafe { super::fuchsia::zx_futex_wake(futex, u32::MAX) }; } diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 4cdc2eaf0e53..afda7c65e108 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -22,23 +22,6 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024; #[cfg(any(target_os = "espidf", target_os = "nuttx"))] pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF/NuttX menuconfig system should be used -#[cfg(target_os = "fuchsia")] -mod zircon { - type zx_handle_t = u32; - type zx_status_t = i32; - pub const ZX_PROP_NAME: u32 = 3; - - unsafe extern "C" { - pub fn zx_object_set_property( - handle: zx_handle_t, - property: u32, - value: *const libc::c_void, - value_size: libc::size_t, - ) -> zx_status_t; - pub fn zx_thread_self() -> zx_handle_t; - } -} - pub struct Thread { id: libc::pthread_t, } @@ -216,7 +199,7 @@ impl Thread { #[cfg(target_os = "fuchsia")] pub fn set_name(name: &CStr) { - use self::zircon::*; + use super::fuchsia::*; unsafe { zx_object_set_property( zx_thread_self(), diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys/process/env.rs similarity index 67% rename from library/std/src/sys_common/process.rs rename to library/std/src/sys/process/env.rs index 9f61d69d8587..e08b476540ef 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys/process/env.rs @@ -1,13 +1,9 @@ -#![allow(dead_code)] -#![unstable(feature = "process_internals", issue = "none")] - use crate::collections::BTreeMap; use crate::ffi::{OsStr, OsString}; -use crate::sys::pipe::read2; -use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes}; -use crate::{env, fmt, io}; +use crate::sys::process::EnvKey; +use crate::{env, fmt}; -// Stores a set of changes to an environment +/// Stores a set of changes to an environment #[derive(Clone, Default)] pub struct CommandEnv { clear: bool, @@ -92,30 +88,23 @@ impl CommandEnv { } } -/// An iterator over the command environment variables. -/// -/// This struct is created by -/// [`Command::get_envs`][crate::process::Command::get_envs]. See its -/// documentation for more. -#[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "command_access", since = "1.57.0")] #[derive(Debug)] pub struct CommandEnvs<'a> { iter: crate::collections::btree_map::Iter<'a, EnvKey, Option>, } -#[stable(feature = "command_access", since = "1.57.0")] impl<'a> Iterator for CommandEnvs<'a> { type Item = (&'a OsStr, Option<&'a OsStr>); + fn next(&mut self) -> Option { self.iter.next().map(|(key, value)| (key.as_ref(), value.as_deref())) } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } -#[stable(feature = "command_access", since = "1.57.0")] impl<'a> ExactSizeIterator for CommandEnvs<'a> { fn len(&self) -> usize { self.iter.len() @@ -124,30 +113,3 @@ impl<'a> ExactSizeIterator for CommandEnvs<'a> { self.iter.is_empty() } } - -pub fn wait_with_output( - mut process: Process, - mut pipes: StdioPipes, -) -> io::Result<(ExitStatus, Vec, Vec)> { - drop(pipes.stdin.take()); - - let (mut stdout, mut stderr) = (Vec::new(), Vec::new()); - match (pipes.stdout.take(), pipes.stderr.take()) { - (None, None) => {} - (Some(out), None) => { - let res = out.read_to_end(&mut stdout); - res.unwrap(); - } - (None, Some(err)) => { - let res = err.read_to_end(&mut stderr); - res.unwrap(); - } - (Some(out), Some(err)) => { - let res = read2(out, &mut stdout, err, &mut stderr); - res.unwrap(); - } - } - - let status = process.wait()?; - Ok((status, stdout, stderr)) -} diff --git a/library/std/src/sys/process/mod.rs b/library/std/src/sys/process/mod.rs index 92cfac7f47cf..91c7005a3285 100644 --- a/library/std/src/sys/process/mod.rs +++ b/library/std/src/sys/process/mod.rs @@ -14,6 +14,65 @@ cfg_if::cfg_if! { } } +// This module is shared by all platforms, but nearly all platforms except for +// the "normal" UNIX ones leave some of this code unused. +#[cfg_attr(not(target_os = "linux"), allow(dead_code))] +mod env; + +pub use env::CommandEnvs; pub use imp::{ Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio, StdioPipes, }; + +#[cfg(any( + all( + target_family = "unix", + not(any( + target_os = "espidf", + target_os = "horizon", + target_os = "vita", + target_os = "nuttx" + )) + ), + target_os = "windows", +))] +pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec, Vec)> { + use crate::sys::pipe::read2; + + let (mut process, mut pipes) = cmd.spawn(Stdio::MakePipe, false)?; + + drop(pipes.stdin.take()); + let (mut stdout, mut stderr) = (Vec::new(), Vec::new()); + match (pipes.stdout.take(), pipes.stderr.take()) { + (None, None) => {} + (Some(out), None) => { + let res = out.read_to_end(&mut stdout); + res.unwrap(); + } + (None, Some(err)) => { + let res = err.read_to_end(&mut stderr); + res.unwrap(); + } + (Some(out), Some(err)) => { + let res = read2(out, &mut stdout, err, &mut stderr); + res.unwrap(); + } + } + + let status = process.wait()?; + Ok((status, stdout, stderr)) +} + +#[cfg(not(any( + all( + target_family = "unix", + not(any( + target_os = "espidf", + target_os = "horizon", + target_os = "vita", + target_os = "nuttx" + )) + ), + target_os = "windows", +)))] +pub use imp::output; diff --git a/library/std/src/sys/process/uefi.rs b/library/std/src/sys/process/uefi.rs index 5f922292d054..4864c5869881 100644 --- a/library/std/src/sys/process/uefi.rs +++ b/library/std/src/sys/process/uefi.rs @@ -1,5 +1,6 @@ use r_efi::protocols::{simple_text_input, simple_text_output}; +use super::env::{CommandEnv, CommandEnvs}; use crate::collections::BTreeMap; pub use crate::ffi::OsString as EnvKey; use crate::ffi::{OsStr, OsString}; @@ -10,7 +11,6 @@ use crate::sys::pal::helpers; use crate::sys::pal::os::error_string; use crate::sys::pipe::AnonPipe; use crate::sys::unsupported; -use crate::sys_common::process::{CommandEnv, CommandEnvs}; use crate::{fmt, io}; //////////////////////////////////////////////////////////////////////////////// @@ -139,72 +139,72 @@ impl Command { Stdio::MakePipe => unsupported(), } } +} - pub fn output(&mut self) -> io::Result<(ExitStatus, Vec, Vec)> { - let mut cmd = uefi_command_internal::Image::load_image(&self.prog)?; +pub fn output(command: &mut Command) -> io::Result<(ExitStatus, Vec, Vec)> { + let mut cmd = uefi_command_internal::Image::load_image(&command.prog)?; - // UEFI adds the bin name by default - if !self.args.is_empty() { - let args = uefi_command_internal::create_args(&self.prog, &self.args); - cmd.set_args(args); - } - - // Setup Stdout - let stdout = self.stdout.unwrap_or(Stdio::MakePipe); - let stdout = Self::create_pipe(stdout)?; - if let Some(con) = stdout { - cmd.stdout_init(con) - } else { - cmd.stdout_inherit() - }; - - // Setup Stderr - let stderr = self.stderr.unwrap_or(Stdio::MakePipe); - let stderr = Self::create_pipe(stderr)?; - if let Some(con) = stderr { - cmd.stderr_init(con) - } else { - cmd.stderr_inherit() - }; - - // Setup Stdin - let stdin = self.stdin.unwrap_or(Stdio::Null); - let stdin = Self::create_stdin(stdin)?; - if let Some(con) = stdin { - cmd.stdin_init(con) - } else { - cmd.stdin_inherit() - }; - - let env = env_changes(&self.env); - - // Set any new vars - if let Some(e) = &env { - for (k, (_, v)) in e { - match v { - Some(v) => unsafe { crate::env::set_var(k, v) }, - None => unsafe { crate::env::remove_var(k) }, - } - } - } - - let stat = cmd.start_image()?; - - // Rollback any env changes - if let Some(e) = env { - for (k, (v, _)) in e { - match v { - Some(v) => unsafe { crate::env::set_var(k, v) }, - None => unsafe { crate::env::remove_var(k) }, - } - } - } - - let stdout = cmd.stdout()?; - let stderr = cmd.stderr()?; - - Ok((ExitStatus(stat), stdout, stderr)) + // UEFI adds the bin name by default + if !command.args.is_empty() { + let args = uefi_command_internal::create_args(&command.prog, &command.args); + cmd.set_args(args); } + + // Setup Stdout + let stdout = command.stdout.unwrap_or(Stdio::MakePipe); + let stdout = Command::create_pipe(stdout)?; + if let Some(con) = stdout { + cmd.stdout_init(con) + } else { + cmd.stdout_inherit() + }; + + // Setup Stderr + let stderr = command.stderr.unwrap_or(Stdio::MakePipe); + let stderr = Command::create_pipe(stderr)?; + if let Some(con) = stderr { + cmd.stderr_init(con) + } else { + cmd.stderr_inherit() + }; + + // Setup Stdin + let stdin = command.stdin.unwrap_or(Stdio::Null); + let stdin = Command::create_stdin(stdin)?; + if let Some(con) = stdin { + cmd.stdin_init(con) + } else { + cmd.stdin_inherit() + }; + + let env = env_changes(&command.env); + + // Set any new vars + if let Some(e) = &env { + for (k, (_, v)) in e { + match v { + Some(v) => unsafe { crate::env::set_var(k, v) }, + None => unsafe { crate::env::remove_var(k) }, + } + } + } + + let stat = cmd.start_image()?; + + // Rollback any env changes + if let Some(e) = env { + for (k, (v, _)) in e { + match v { + Some(v) => unsafe { crate::env::set_var(k, v) }, + None => unsafe { crate::env::remove_var(k) }, + } + } + } + + let stdout = cmd.stdout()?; + let stderr = cmd.stderr()?; + + Ok((ExitStatus(stat), stdout, stderr)) } impl From for Stdio { diff --git a/library/std/src/sys/process/unix/common.rs b/library/std/src/sys/process/unix/common.rs index 8bc17f314911..a9c2510e6d45 100644 --- a/library/std/src/sys/process/unix/common.rs +++ b/library/std/src/sys/process/unix/common.rs @@ -12,7 +12,7 @@ use crate::sys::fs::File; #[cfg(not(target_os = "fuchsia"))] use crate::sys::fs::OpenOptions; use crate::sys::pipe::{self, AnonPipe}; -use crate::sys_common::process::{CommandEnv, CommandEnvs}; +use crate::sys::process::env::{CommandEnv, CommandEnvs}; use crate::sys_common::{FromInner, IntoInner}; use crate::{fmt, io, ptr}; diff --git a/library/std/src/sys/process/unix/fuchsia.rs b/library/std/src/sys/process/unix/fuchsia.rs index 0de32ecffd4b..017ab91797ce 100644 --- a/library/std/src/sys/process/unix/fuchsia.rs +++ b/library/std/src/sys/process/unix/fuchsia.rs @@ -31,11 +31,6 @@ impl Command { Ok((Process { handle: Handle::new(process_handle) }, ours)) } - pub fn output(&mut self) -> io::Result<(ExitStatus, Vec, Vec)> { - let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?; - crate::sys_common::process::wait_with_output(proc, pipes) - } - pub fn exec(&mut self, default: Stdio) -> io::Error { if self.saw_nul() { return io::const_error!( @@ -81,7 +76,7 @@ impl Command { let mut handle = ZX_HANDLE_INVALID; let status = fdio_fd_clone(target_fd, &mut handle); - if status == ERR_INVALID_ARGS || status == ERR_NOT_SUPPORTED { + if status == ZX_ERR_INVALID_ARGS || status == ZX_ERR_NOT_SUPPORTED { // This descriptor is closed; skip it rather than generating an // error. return Ok(Default::default()); @@ -197,7 +192,7 @@ impl Process { zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED, 0, ptr::null_mut()); match status { 0 => {} // Success - x if x == ERR_TIMED_OUT => { + x if x == ZX_ERR_TIMED_OUT => { return Ok(None); } _ => { diff --git a/library/std/src/sys/process/unix/mod.rs b/library/std/src/sys/process/unix/mod.rs index 2e8b38f7de1b..ee8fd8b2ca3c 100644 --- a/library/std/src/sys/process/unix/mod.rs +++ b/library/std/src/sys/process/unix/mod.rs @@ -11,6 +11,7 @@ cfg_if::cfg_if! { } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] { mod unsupported; use unsupported as imp; + pub use unsupported::output; } else { mod unix; use unix as imp; diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index ae1c9558281e..1b3bd2de265d 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -162,11 +162,6 @@ impl Command { } } - pub fn output(&mut self) -> io::Result<(ExitStatus, Vec, Vec)> { - let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?; - crate::sys_common::process::wait_with_output(proc, pipes) - } - // WatchOS and TVOS headers mark the `fork`/`exec*` functions with // `__WATCHOS_PROHIBITED __TVOS_PROHIBITED`, and indicate that the // `posix_spawn*` functions should be used instead. It isn't entirely clear diff --git a/library/std/src/sys/process/unix/unsupported.rs b/library/std/src/sys/process/unix/unsupported.rs index 78d270923cfa..e86561a5c5c4 100644 --- a/library/std/src/sys/process/unix/unsupported.rs +++ b/library/std/src/sys/process/unix/unsupported.rs @@ -18,15 +18,15 @@ impl Command { unsupported() } - pub fn output(&mut self) -> io::Result<(ExitStatus, Vec, Vec)> { - unsupported() - } - pub fn exec(&mut self, _default: Stdio) -> io::Error { unsupported_err() } } +pub fn output(_: &mut Command) -> io::Result<(ExitStatus, Vec, Vec)> { + unsupported() +} + //////////////////////////////////////////////////////////////////////////////// // Processes //////////////////////////////////////////////////////////////////////////////// diff --git a/library/std/src/sys/process/unix/vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs index b92446f0cf67..fab3b36ebf3f 100644 --- a/library/std/src/sys/process/unix/vxworks.rs +++ b/library/std/src/sys/process/unix/vxworks.rs @@ -112,11 +112,6 @@ impl Command { } } - pub fn output(&mut self) -> io::Result<(ExitStatus, Vec, Vec)> { - let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?; - crate::sys_common::process::wait_with_output(proc, pipes) - } - pub fn exec(&mut self, default: Stdio) -> io::Error { let ret = Command::spawn(self, default, false); match ret { diff --git a/library/std/src/sys/process/unsupported.rs b/library/std/src/sys/process/unsupported.rs index fee81744f09e..469922c78aca 100644 --- a/library/std/src/sys/process/unsupported.rs +++ b/library/std/src/sys/process/unsupported.rs @@ -1,3 +1,4 @@ +use super::env::{CommandEnv, CommandEnvs}; pub use crate::ffi::OsString as EnvKey; use crate::ffi::{OsStr, OsString}; use crate::num::NonZero; @@ -5,7 +6,6 @@ use crate::path::Path; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::unsupported; -use crate::sys_common::process::{CommandEnv, CommandEnvs}; use crate::{fmt, io}; //////////////////////////////////////////////////////////////////////////////// @@ -104,10 +104,10 @@ impl Command { ) -> io::Result<(Process, StdioPipes)> { unsupported() } +} - pub fn output(&mut self) -> io::Result<(ExitStatus, Vec, Vec)> { - unsupported() - } +pub fn output(_cmd: &mut Command) -> io::Result<(ExitStatus, Vec, Vec)> { + unsupported() } impl From for Stdio { diff --git a/library/std/src/sys/process/windows.rs b/library/std/src/sys/process/windows.rs index 4cfdf908c58d..4acd753eec91 100644 --- a/library/std/src/sys/process/windows.rs +++ b/library/std/src/sys/process/windows.rs @@ -5,6 +5,7 @@ mod tests; use core::ffi::c_void; +use super::env::{CommandEnv, CommandEnvs}; use crate::collections::BTreeMap; use crate::env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use crate::ffi::{OsStr, OsString}; @@ -24,7 +25,6 @@ use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf}; use crate::sys::pipe::{self, AnonPipe}; use crate::sys::{cvt, path, stdio}; use crate::sys_common::IntoInner; -use crate::sys_common::process::{CommandEnv, CommandEnvs}; use crate::{cmp, env, fmt, ptr}; //////////////////////////////////////////////////////////////////////////////// @@ -389,11 +389,6 @@ impl Command { )) } } - - pub fn output(&mut self) -> io::Result<(ExitStatus, Vec, Vec)> { - let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?; - crate::sys_common::process::wait_with_output(proc, pipes) - } } impl fmt::Debug for Command { diff --git a/library/std/src/sys/sync/mutex/fuchsia.rs b/library/std/src/sys/sync/mutex/fuchsia.rs index 3d388a4564a3..cbb1926530f5 100644 --- a/library/std/src/sys/sync/mutex/fuchsia.rs +++ b/library/std/src/sys/sync/mutex/fuchsia.rs @@ -39,7 +39,7 @@ use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; use crate::sync::atomic::{Atomic, AtomicU32}; -use crate::sys::futex::zircon::{ +use crate::sys::fuchsia::{ ZX_ERR_BAD_HANDLE, ZX_ERR_BAD_STATE, ZX_ERR_INVALID_ARGS, ZX_ERR_TIMED_OUT, ZX_ERR_WRONG_TYPE, ZX_OK, ZX_TIME_INFINITE, zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t, zx_thread_self, @@ -83,13 +83,13 @@ impl Mutex { #[inline] pub fn try_lock(&self) -> bool { - let thread_self = unsafe { zx_thread_self() }; + let thread_self = zx_thread_self(); self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed).is_ok() } #[inline] pub fn lock(&self) { - let thread_self = unsafe { zx_thread_self() }; + let thread_self = zx_thread_self(); if let Err(state) = self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed) { diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 2a5de7f66661..b7f4656fa370 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -20,7 +20,6 @@ #[cfg(test)] mod tests; -pub mod process; pub mod wstr; pub mod wtf8; diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index acaf026c679b..7f56d1e36269 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -98,6 +98,15 @@ const SECONDARY_TEST_BENCH_BENCHMARKS_VAR: &str = "__RUST_TEST_BENCH_BENCHMARKS" // The default console test runner. It accepts the command line // arguments and a vector of test_descs. pub fn test_main(args: &[String], tests: Vec, options: Option) { + test_main_with_exit_callback(args, tests, options, || {}) +} + +pub fn test_main_with_exit_callback( + args: &[String], + tests: Vec, + options: Option, + exit_callback: F, +) { let mut opts = match cli::parse_opts(args) { Some(Ok(o)) => o, Some(Err(msg)) => { @@ -151,6 +160,7 @@ pub fn test_main(args: &[String], tests: Vec, options: Option {} Ok(false) => process::exit(ERROR_EXIT_CODE), diff --git a/library/windows_targets/src/lib.rs b/library/windows_targets/src/lib.rs index c7d158584ebd..bce54c5ffcef 100644 --- a/library/windows_targets/src/lib.rs +++ b/library/windows_targets/src/lib.rs @@ -34,6 +34,7 @@ pub macro link { } #[cfg(not(feature = "windows_raw_dylib"))] +#[cfg(not(target_os = "cygwin"))] // Cygwin doesn't need these libs #[cfg_attr(target_vendor = "win7", link(name = "advapi32"))] #[link(name = "ntdll")] #[link(name = "userenv")] diff --git a/rustfmt.toml b/rustfmt.toml index 7c384b876bf7..d9857a7e3e78 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -19,6 +19,7 @@ ignore = [ "/tests/debuginfo/", # These tests are somewhat sensitive to source code layout. "/tests/incremental/", # These tests are somewhat sensitive to source code layout. "/tests/pretty/", # These tests are very sensitive to source code layout. + "/tests/run-make/export", # These tests contain syntax errors. "/tests/run-make/translation/test.rs", # This test contains syntax errors. "/tests/rustdoc/", # Some have syntax errors, some are whitespace-sensitive. "/tests/rustdoc-gui/", # Some tests are sensitive to source code layout. diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index d415668f54a7..cdad3bd46fab 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -64,7 +64,7 @@ dependencies = [ "tracing-subscriber", "tracing-tree", "walkdir", - "windows", + "windows 0.57.0", "xz2", ] @@ -158,12 +158,6 @@ dependencies = [ "cc", ] -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - [[package]] name = "cpufeatures" version = "0.2.15" @@ -440,6 +434,25 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags", +] + +[[package]] +name = "objc2-io-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a" +dependencies = [ + "libc", + "objc2-core-foundation", +] + [[package]] name = "object" version = "0.36.5" @@ -700,15 +713,16 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.33.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "948512566b1895f93b1592c7574baeb2de842f224f2aab158799ecadb8ebbb46" +checksum = "b897c8ea620e181c7955369a31be5f48d9a9121cb59fd33ecef9ff2a34323422" dependencies = [ - "core-foundation-sys", "libc", "memchr", "ntapi", - "windows", + "objc2-core-foundation", + "objc2-io-kit", + "windows 0.61.1", ] [[package]] @@ -927,22 +941,67 @@ version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" dependencies = [ - "windows-core", + "windows-core 0.57.0", "windows-targets", ] +[[package]] +name = "windows" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" +dependencies = [ + "windows-collections", + "windows-core 0.61.0", + "windows-future", + "windows-link", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.0", +] + [[package]] name = "windows-core" version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", "windows-targets", ] +[[package]] +name = "windows-core" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +dependencies = [ + "windows-implement 0.60.0", + "windows-interface 0.59.1", + "windows-link", + "windows-result 0.3.2", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32" +dependencies = [ + "windows-core 0.61.0", + "windows-link", +] + [[package]] name = "windows-implement" version = "0.57.0" @@ -954,6 +1013,17 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-interface" version = "0.57.0" @@ -965,6 +1035,33 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.0", + "windows-link", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -974,6 +1071,24 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 712a9b04c1a1..e34de924cc18 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -58,7 +58,7 @@ walkdir = "2.4" xz2 = "0.1" # Dependencies needed by the build-metrics feature -sysinfo = { version = "0.33.0", default-features = false, optional = true, features = ["system"] } +sysinfo = { version = "0.35.0", default-features = false, optional = true, features = ["system"] } # Dependencies needed by the `tracing` feature tracing = { version = "0.1", optional = true, features = ["attributes"] } diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index cbfe00a757ce..833f80279517 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -163,7 +163,7 @@ fn check_version(config: &Config) -> Option { msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( - "add `change-id = {latest_change_id}` or change-id = \"ignore\" at the top of `bootstrap.toml`" + "add `change-id = {latest_change_id}` or `change-id = \"ignore\"` at the top of `bootstrap.toml`" )); return Some(msg); } @@ -195,7 +195,7 @@ fn check_version(config: &Config) -> Option { msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( - "update `bootstrap.toml` to use `change-id = {latest_change_id}` or change-id = \"ignore\" instead" + "update `bootstrap.toml` to use `change-id = {latest_change_id}` or `change-id = \"ignore\"` instead" )); if io::stdout().is_terminal() { diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index ae9511b78674..fa848c492b4d 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -527,3 +527,70 @@ tool_check_step!(Bootstrap { path: "src/bootstrap", default: false }); // `run-make-support` will be built as part of suitable run-make compiletest test steps, but support // check to make it easier to work on. tool_check_step!(RunMakeSupport { path: "src/tools/run-make-support", default: false }); + +/// Check step for the `coverage-dump` bootstrap tool. The coverage-dump tool +/// is used internally by coverage tests. +/// +/// FIXME(Zalathar): This is temporarily separate from the other tool check +/// steps so that it can use the stage 0 compiler instead of `top_stage`, +/// without introducing conflicts with the stage 0 redesign (#119899). +/// +/// After the stage 0 redesign lands, we can look into using the stage 0 +/// compiler to check all bootstrap tools (#139170). +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub(crate) struct CoverageDump; + +impl CoverageDump { + const PATH: &str = "src/tools/coverage-dump"; +} + +impl Step for CoverageDump { + type Output = (); + + /// Most contributors won't care about coverage-dump, so don't make their + /// check builds slower unless they opt in and check it explicitly. + const DEFAULT: bool = false; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path(Self::PATH) + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Self {}); + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + // Make sure we haven't forgotten any fields, if there are any. + let Self {} = self; + let display_name = "coverage-dump"; + let host = builder.config.build; + let target = host; + let mode = Mode::ToolBootstrap; + + let compiler = builder.compiler(0, host); + let cargo = prepare_tool_cargo( + builder, + compiler, + mode, + target, + builder.kind, + Self::PATH, + SourceType::InTree, + &[], + ); + + let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target)) + .with_prefix(&format!("{display_name}-check")); + + let _guard = builder.msg_tool( + builder.kind, + mode, + display_name, + compiler.stage, + &compiler.host, + &target, + ); + run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); + } +} diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 9da8b27a9177..93900a9043e7 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -9,7 +9,7 @@ use std::sync::mpsc::SyncSender; use build_helper::git::get_git_modified_files; use ignore::WalkBuilder; -use crate::core::builder::Builder; +use crate::core::builder::{Builder, Kind}; use crate::utils::build_stamp::BuildStamp; use crate::utils::exec::command; use crate::utils::helpers::{self, t}; @@ -122,6 +122,12 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) { } pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { + if build.kind == Kind::Format && build.top_stage != 0 { + eprintln!("ERROR: `x fmt` only supports stage 0."); + eprintln!("HELP: Use `x run rustfmt` to run in-tree rustfmt."); + crate::exit!(1); + } + if !paths.is_empty() { eprintln!( "fmt error: path arguments are no longer accepted; use `--all` to format everything" diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 5cacd5b99147..0bba441c3fa2 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -392,3 +392,84 @@ impl Step for CyclicStep { builder.ensure(CyclicStep { n: self.n.saturating_sub(1) }) } } + +/// Step to manually run the coverage-dump tool (`./x run coverage-dump`). +/// +/// The coverage-dump tool is an internal detail of coverage tests, so this run +/// step is only needed when testing coverage-dump manually. +#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] +pub struct CoverageDump; + +impl Step for CoverageDump { + type Output = (); + + const DEFAULT: bool = false; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/coverage-dump") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Self {}); + } + + fn run(self, builder: &Builder<'_>) { + let mut cmd = builder.tool_cmd(Tool::CoverageDump); + cmd.args(&builder.config.free_args); + cmd.run(builder); + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Rustfmt; + +impl Step for Rustfmt { + type Output = (); + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/rustfmt") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Rustfmt); + } + + fn run(self, builder: &Builder<'_>) { + let host = builder.build.build; + + // `x run` uses stage 0 by default but rustfmt does not work well with stage 0. + // Change the stage to 1 if it's not set explicitly. + let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 { + builder.top_stage + } else { + 1 + }; + + if stage == 0 { + eprintln!("rustfmt cannot be run at stage 0"); + eprintln!("HELP: Use `x fmt` to use stage 0 rustfmt."); + std::process::exit(1); + } + + let compiler = builder.compiler(stage, host); + let rustfmt_build = builder.ensure(tool::Rustfmt { compiler, target: host }); + + let mut rustfmt = tool::prepare_tool_cargo( + builder, + rustfmt_build.build_compiler, + Mode::ToolRustc, + host, + Kind::Run, + "src/tools/rustfmt", + SourceType::InTree, + &[], + ); + + rustfmt.args(["--bin", "rustfmt", "--"]); + rustfmt.args(builder.config.args()); + + rustfmt.into_cmd().run(builder); + } +} diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index a7a3b5a878c3..29fb576f5740 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -54,6 +54,7 @@ impl Step for CrateBootstrap { run.path("src/tools/jsondoclint") .path("src/tools/suggest-tests") .path("src/tools/replace-version-placeholder") + .path("src/tools/coverage-dump") // We want `./x test tidy` to _run_ the tidy tool, not its tests. // So we need a separate alias to test the tidy tool itself. .alias("tidyselftest") diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 36b3c95d638c..d625c2ef5847 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -112,9 +112,8 @@ impl Cargo { let mut cargo = builder.cargo(compiler, mode, source_type, target, cmd_kind); match cmd_kind { - // No need to configure the target linker for these command types, - // as they don't invoke rustc at all. - Kind::Clean | Kind::Suggest | Kind::Format | Kind::Setup => {} + // No need to configure the target linker for these command types. + Kind::Clean | Kind::Check | Kind::Suggest | Kind::Format | Kind::Setup => {} _ => { cargo.configure_linker(builder); } @@ -205,6 +204,8 @@ impl Cargo { self } + // FIXME(onur-ozkan): Add coverage to make sure modifications to this function + // doesn't cause cache invalidations (e.g., #130108). fn configure_linker(&mut self, builder: &Builder<'_>) -> &mut Cargo { let target = self.target; let compiler = self.compiler; diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index c32d9c2870cf..75cc5d3986b8 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -961,6 +961,7 @@ impl<'a> Builder<'a> { check::RunMakeSupport, check::Compiletest, check::FeaturesStatusDump, + check::CoverageDump, ), Kind::Test => describe!( crate::core::build_steps::toolstate::ToolStateCheck, @@ -1114,6 +1115,8 @@ impl<'a> Builder<'a> { run::UnicodeTableGenerator, run::FeaturesStatusDump, run::CyclicStep, + run::CoverageDump, + run::Rustfmt, ), Kind::Setup => { describe!(setup::Profile, setup::Hook, setup::Link, setup::Editor) @@ -1534,7 +1537,7 @@ impl<'a> Builder<'a> { let out = step.clone().run(self); let dur = start.elapsed(); let deps = self.time_spent_on_dependencies.replace(parent + dur); - (out, dur - deps) + (out, dur.saturating_sub(deps)) }; if self.config.print_step_timings && !self.config.dry_run() { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 88d181532a7f..1e6acad5c0fc 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -53,6 +53,7 @@ use tracing::{instrument, span}; pub use utils::change_tracker::{ CONFIG_CHANGE_HISTORY, find_recent_config_change_ids, human_readable_changes, }; +pub use utils::helpers::PanicTracker; use crate::core::build_steps::vendor::VENDOR_DIR; diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index 147b009d3f47..ceac24d4315c 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -96,6 +96,7 @@ pub fn find(build: &Build) { let targets: HashSet<_> = match build.config.cmd { // We don't need to check cross targets for these commands. crate::Subcommand::Clean { .. } + | crate::Subcommand::Check { .. } | crate::Subcommand::Suggest { .. } | crate::Subcommand::Format { .. } | crate::Subcommand::Setup { .. } => { diff --git a/src/bootstrap/src/utils/cc_detect/tests.rs b/src/bootstrap/src/utils/cc_detect/tests.rs index b4a1b52dd230..43d61ce02c5a 100644 --- a/src/bootstrap/src/utils/cc_detect/tests.rs +++ b/src/bootstrap/src/utils/cc_detect/tests.rs @@ -181,7 +181,7 @@ fn test_language_clang() { #[test] fn test_new_cc_build() { - let build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) }); + let build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) }); let target = TargetSelection::from_user("x86_64-unknown-linux-gnu"); let cfg = new_cc_build(&build, target.clone()); let compiler = cfg.get_compiler(); @@ -190,7 +190,7 @@ fn test_new_cc_build() { #[test] fn test_default_compiler_wasi() { - let build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) }); + let build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) }); let target = TargetSelection::from_user("wasm32-wasi"); let wasi_sdk = PathBuf::from("/wasi-sdk"); // SAFETY: bootstrap tests run on a single thread @@ -215,7 +215,7 @@ fn test_default_compiler_wasi() { #[test] fn test_default_compiler_fallback() { - let build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) }); + let build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) }); let target = TargetSelection::from_user("x86_64-unknown-linux-gnu"); let mut cfg = cc::Build::new(); let result = default_compiler(&mut cfg, Language::C, target, &build); @@ -224,7 +224,7 @@ fn test_default_compiler_fallback() { #[test] fn test_find_target_with_config() { - let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) }); + let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) }); let target = TargetSelection::from_user("x86_64-unknown-linux-gnu"); let mut target_config = Target::default(); target_config.cc = Some(PathBuf::from("dummy-cc")); @@ -249,7 +249,7 @@ fn test_find_target_with_config() { #[test] fn test_find_target_without_config() { - let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) }); + let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) }); let target = TargetSelection::from_user("x86_64-unknown-linux-gnu"); build.config.target_config.clear(); find_target(&build, target.clone()); @@ -262,7 +262,7 @@ fn test_find_target_without_config() { #[test] fn test_find() { - let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) }); + let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) }); let target1 = TargetSelection::from_user("x86_64-unknown-linux-gnu"); let target2 = TargetSelection::from_user("x86_64-unknown-openbsd"); build.targets.push(target1.clone()); diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index d926185ffaf1..1d0ea3ebf610 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -406,4 +406,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "Added a new option `rust.debug-assertions-tools` to control debug asssertions for tools.", }, + ChangeInfo { + change_id: 140732, + severity: ChangeSeverity::Info, + summary: "`./x run` now supports running in-tree `rustfmt`, e.g., `./x run rustfmt -- --check /path/to/file.rs`.", + }, ]; diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 1299fbb7d629..b31b2757767c 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -7,8 +7,9 @@ use std::ffi::OsStr; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::sync::OnceLock; +use std::thread::panicking; use std::time::{Instant, SystemTime, UNIX_EPOCH}; -use std::{env, fs, io, str}; +use std::{env, fs, io, panic, str}; use build_helper::util::fail; use object::read::archive::ArchiveFile; @@ -22,6 +23,23 @@ pub use crate::utils::shared_helpers::{dylib_path, dylib_path_var}; #[cfg(test)] mod tests; +/// A wrapper around `std::panic::Location` used to track the location of panics +/// triggered by `t` macro usage. +pub struct PanicTracker<'a>(pub &'a panic::Location<'a>); + +impl Drop for PanicTracker<'_> { + fn drop(&mut self) { + if panicking() { + eprintln!( + "Panic was initiated from {}:{}:{}", + self.0.file(), + self.0.line(), + self.0.column() + ); + } + } +} + /// A helper macro to `unwrap` a result except also print out details like: /// /// * The file/line of the panic @@ -32,19 +50,21 @@ mod tests; /// using a `Result` with `try!`, but this may change one day... #[macro_export] macro_rules! t { - ($e:expr) => { + ($e:expr) => {{ + let _panic_guard = $crate::PanicTracker(std::panic::Location::caller()); match $e { Ok(e) => e, Err(e) => panic!("{} failed with {}", stringify!($e), e), } - }; + }}; // it can show extra info in the second parameter - ($e:expr, $extra:expr) => { + ($e:expr, $extra:expr) => {{ + let _panic_guard = $crate::PanicTracker(std::panic::Location::caller()); match $e { Ok(e) => e, Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra), } - }; + }}; } pub use t; diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index 3428dd4826a7..e15121e0f316 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.20.3 \ No newline at end of file +0.20.6 \ No newline at end of file diff --git a/src/doc/reference b/src/doc/reference index 3bf3402aea98..387392674d74 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 3bf3402aea982b876eb56c87da17b0685c6461d5 +Subproject commit 387392674d74656f7cb437c05a96f0c52ea8e601 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 0d7964d5b22c..8a8918c69853 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 0d7964d5b22cf920237ef1282d869564b4883b88 +Subproject commit 8a8918c698534547fa8a1a693cb3e7277f0bfb2f diff --git a/src/doc/rustc-dev-guide/src/mir/dataflow.md b/src/doc/rustc-dev-guide/src/mir/dataflow.md index f31da5ca22ee..85e57dd839b8 100644 --- a/src/doc/rustc-dev-guide/src/mir/dataflow.md +++ b/src/doc/rustc-dev-guide/src/mir/dataflow.md @@ -148,8 +148,7 @@ whereas this code uses [`ResultsCursor`]: ```rust,ignore let mut results = MyAnalysis::new() - .into_engine(tcx, body, def_id) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None); .into_results_cursor(body); // Inspect the fixpoint state immediately before each `Drop` terminator. diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index c04f296ba0b1..825be11c82a9 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -135,12 +135,16 @@ There are several use-cases for try builds: - Run a specific CI job (e.g. Windows tests) on a PR, to quickly test if it passes the test suite executed by that job. -You can select which CI jobs will -be executed in the try build by adding lines containing `try-job: -` to the PR description. All such specified jobs will be executed -in the try build once the `@bors try` command is used on the PR. If no try -jobs are specified in this way, the jobs defined in the `try` section of -[`jobs.yml`] will be executed by default. +By default, if you send a comment with `@bors try`, the jobs defined in the `try` section of +[`jobs.yml`] will be executed. We call this mode a "fast try build". Such a try build +will not execute any tests, and it will allow compilation warnings. It is useful when you want to +get an optimized toolchain as fast as possible, for a crater run or performance benchmarks, +even if it might not be working fully correctly. + +If you want to run a custom CI job in a try build and make sure that it passes all tests and does +not produce any compilation warnings, you can select CI jobs to be executed by adding lines +containing `try-job: ` to the PR description. All such specified jobs will be executed +in the try build once the `@bors try` command is used on the PR. Each pattern can either be an exact name of a job or a glob pattern that matches multiple jobs, for example `*msvc*` or `*-alt`. You can start at most 20 jobs in a single try build. When using diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index b31c861c947a..721d20b65c5a 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -344,8 +344,7 @@ For checking runtime output, `//@ check-run-results` may be preferable. Only use `error-pattern` if none of the above works. -Line annotations `//~` are still checked in tests using `error-pattern`. -In exceptional cases, use `//@ compile-flags: --error-format=human` to opt out of these checks. +Line annotations `//~` and `error-pattern` are compatible and can be used in the same test. ### Diagnostic kinds (error levels) @@ -356,9 +355,12 @@ The diagnostic kinds that you can have are: - `NOTE` - `HELP` - `SUGGESTION` +- `RAW` The `SUGGESTION` kind is used for specifying what the expected replacement text should be for a diagnostic suggestion. +The `RAW` kind can be used for matching on lines from non-structured output sometimes emitted +by the compiler instead of or in addition to structured json. `ERROR` and `WARN` kinds are required to be exhaustively covered by line annotations `//~` by default. diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index cf41f5b86a85..a3939e5a5c45 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -58,6 +58,7 @@ - [thumbv7m-none-eabi](./platform-support/thumbv7m-none-eabi.md) - [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md) - [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md) + - [armv5te-unknown-linux-gnueabi](platform-support/armv5te-unknown-linux-gnueabi.md) - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) - [armv7-rtems-eabihf](platform-support/armv7-rtems-eabihf.md) - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 50c7ae3ef8db..60002a5f9e5d 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -156,7 +156,7 @@ target | std | notes [`arm64ec-pc-windows-msvc`](platform-support/arm64ec-pc-windows-msvc.md) | ✓ | Arm64EC Windows MSVC [`armebv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian [`armebv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian, hardfloat -`armv5te-unknown-linux-gnueabi` | ✓ | Armv5TE Linux (kernel 4.4, glibc 2.23) +[`armv5te-unknown-linux-gnueabi`](platform-support/armv5te-unknown-linux-gnueabi.md) | ✓ | Armv5TE Linux (kernel 4.4, glibc 2.23) `armv5te-unknown-linux-musleabi` | ✓ | Armv5TE Linux with musl 1.2.3 [`armv7-linux-androideabi`](platform-support/android.md) | ✓ | Armv7-A Android `armv7-unknown-linux-gnueabi` | ✓ | Armv7-A Linux (kernel 4.15, glibc 2.27) diff --git a/src/doc/rustc/src/platform-support/armv5te-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armv5te-unknown-linux-gnueabi.md new file mode 100644 index 000000000000..1baf1049994b --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv5te-unknown-linux-gnueabi.md @@ -0,0 +1,29 @@ +# `armv5te-unknown-linux-gnueabi` + +**Tier: 2** + +This target supports Linux programs with glibc on ARMv5TE CPUs without +floating-point units. + +## Target maintainers + +[@koalatux](https://github.com/koalatux) + +## Requirements + +The target is for cross-compilation only. Host tools are not supported. +std is fully supported. + +## Building the target + +Because this target is tier 2, artifacts are available from rustup. + +## Building Rust programs + +For building rust programs, you might want to specify GCC as linker in +`.cargo/config.toml` as follows: + +```toml +[target.armv5te-unknown-linux-gnueabi] +linker = "arm-linux-gnueabi-gcc" +``` diff --git a/src/doc/rustc/src/platform-support/riscv32im-risc0-zkvm-elf.md b/src/doc/rustc/src/platform-support/riscv32im-risc0-zkvm-elf.md index 09b42da26e74..1d02a7cfbc0b 100644 --- a/src/doc/rustc/src/platform-support/riscv32im-risc0-zkvm-elf.md +++ b/src/doc/rustc/src/platform-support/riscv32im-risc0-zkvm-elf.md @@ -8,7 +8,6 @@ RISC Zero's Zero Knowledge Virtual Machine (zkVM) implementing the RV32IM instru [@flaub](https://github.com/flaub) [@jbruestle](https://github.com/jbruestle) -[@SchmErik](https://github.com/SchmErik) ## Background diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md index 19e62c4867c9..81b7ff50052a 100644 --- a/src/doc/style-guide/src/editions.md +++ b/src/doc/style-guide/src/editions.md @@ -26,6 +26,10 @@ edition). Not all Rust editions have corresponding changes to the Rust style. For instance, Rust 2015, Rust 2018, and Rust 2021 all use the same style edition. +## Rust next style edition + +- Never break within a nullary function call `func()` or a unit literal `()`. + ## Rust 2024 style edition This style guide describes the Rust 2024 style edition. The Rust 2024 style diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 031e59d86e1d..9df5d7d18edb 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -183,6 +183,10 @@ let f = Foo { }; ``` +## Unit literals + +Never break between the opening and closing parentheses of the `()` unit literal. + ## Tuple literals Use a single-line form where possible. Do not put spaces between the opening @@ -377,6 +381,11 @@ Do put a space between an argument, and the comma which precedes it. Prefer not to break a line in the callee expression. +For a function call with no arguments (a nullary function call like `func()`), +never break within the parentheses, and never put a space between the +parentheses. Always write a nullary function call as a single-line call, never +a multi-line call. + ### Single-line calls Do not put a space between the function name and open paren, between the open diff --git a/src/doc/style-guide/src/nightly.md b/src/doc/style-guide/src/nightly.md index d870edf18882..66e7fa3c9f89 100644 --- a/src/doc/style-guide/src/nightly.md +++ b/src/doc/style-guide/src/nightly.md @@ -5,15 +5,3 @@ This chapter documents style and formatting for nightly-only syntax. The rest of Style and formatting for nightly-only syntax should be removed from this chapter and integrated into the appropriate sections of the style guide at the time of stabilization. There is no guarantee of the stability of this chapter in contrast to the rest of the style guide. Refer to the style team policy for nightly formatting procedure regarding breaking changes to this chapter. - -### `feature(precise_capturing)` - -A `use<'a, T>` precise capturing bound is formatted as if it were a single path segment with non-turbofished angle-bracketed args, like a trait bound whose identifier is `use`. - -``` -fn foo() -> impl Sized + use<'a> {} - -// is formatted analogously to: - -fn foo() -> impl Sized + Use<'a> {} -``` diff --git a/src/doc/style-guide/src/types.md b/src/doc/style-guide/src/types.md index b7921c8914e4..247f05b57695 100644 --- a/src/doc/style-guide/src/types.md +++ b/src/doc/style-guide/src/types.md @@ -59,3 +59,15 @@ Box< + Debug > ``` + +## Precise capturing bounds + +A `use<'a, T>` precise capturing bound is formatted as if it were a single path segment with non-turbofished angle-bracketed args, like a trait bound whose identifier is `use`. + +```rust +fn foo() -> impl Sized + use<'a> {} + +// is formatted analogously to: + +fn foo() -> impl Sized + Use<'a> {} +``` diff --git a/src/doc/unstable-book/src/language-features/arbitrary-self-types.md b/src/doc/unstable-book/src/language-features/arbitrary-self-types.md index 2f8b52d40439..d660dd13fe47 100644 --- a/src/doc/unstable-book/src/language-features/arbitrary-self-types.md +++ b/src/doc/unstable-book/src/language-features/arbitrary-self-types.md @@ -2,7 +2,7 @@ The tracking issue for this feature is: [#44874] -[#38788]: https://github.com/rust-lang/rust/issues/44874 +[#44874]: https://github.com/rust-lang/rust/issues/44874 ------------------------ diff --git a/src/doc/unstable-book/src/language-features/deref-patterns.md b/src/doc/unstable-book/src/language-features/deref-patterns.md index 0cc7106da48f..4c3d456b9af8 100644 --- a/src/doc/unstable-book/src/language-features/deref-patterns.md +++ b/src/doc/unstable-book/src/language-features/deref-patterns.md @@ -60,20 +60,30 @@ Like [`box_patterns`], deref patterns may move out of boxes: # #![feature(deref_patterns)] # #![allow(incomplete_features)] struct NoCopy; -// Match exhaustiveness analysis is not yet implemented. -let deref!(x) = Box::new(NoCopy) else { unreachable!() }; +let deref!(x) = Box::new(NoCopy); drop::(x); ``` -Additionally, when `deref_patterns` is enabled, string literal patterns may be written where `str` -is expected. Likewise, byte string literal patterns may be written where `[u8]` or `[u8; _]` is -expected. This lets them be used in `deref!(_)` patterns: +Additionally, `deref_patterns` implements changes to string and byte string literal patterns, +allowing then to be used in deref patterns: ```rust # #![feature(deref_patterns)] # #![allow(incomplete_features)] -match ("test".to_string(), b"test".to_vec()) { - (deref!("test"), deref!(b"test")) => {} +match ("test".to_string(), Box::from("test"), b"test".to_vec()) { + ("test", "test", b"test") => {} + _ => panic!(), +} + +// This works through multiple layers of reference and smart pointer: +match (&Box::new(&"test".to_string()), &&&"test") { + ("test", "test") => {} + _ => panic!(), +} + +// `deref!("...")` syntax may also be used: +match "test".to_string() { + deref!("test") => {} _ => panic!(), } @@ -82,10 +92,16 @@ match *"test" { "test" => {} _ => panic!(), } +match *b"test" { + b"test" => {} + _ => panic!(), +} +match *(b"test" as &[u8]) { + b"test" => {} + _ => panic!(), +} ``` -Implicit deref pattern syntax is not yet supported for string or byte string literals. - [`box_patterns`]: ./box-patterns.md [`string_deref_patterns`]: ./string-deref-patterns.md [smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors diff --git a/src/doc/unstable-book/src/language-features/f128.md b/src/doc/unstable-book/src/language-features/f128.md index 0cc5f6772302..b523ffe10f25 100644 --- a/src/doc/unstable-book/src/language-features/f128.md +++ b/src/doc/unstable-book/src/language-features/f128.md @@ -6,4 +6,4 @@ The tracking issue for this feature is: [#116909] --- -Enable the `f128` type for IEEE 128-bit floating numbers (quad precision). +Enable the `f128` type for IEEE 128-bit floating numbers (quad precision). diff --git a/src/doc/unstable-book/src/language-features/f16.md b/src/doc/unstable-book/src/language-features/f16.md index efb07a5146d4..5f31dcbb06c0 100644 --- a/src/doc/unstable-book/src/language-features/f16.md +++ b/src/doc/unstable-book/src/language-features/f16.md @@ -6,4 +6,4 @@ The tracking issue for this feature is: [#116909] --- -Enable the `f16` type for IEEE 16-bit floating numbers (half precision). +Enable the `f16` type for IEEE 16-bit floating numbers (half precision). diff --git a/src/doc/unstable-book/src/language-features/frontmatter.md b/src/doc/unstable-book/src/language-features/frontmatter.md new file mode 100644 index 000000000000..1d5b4feb6ac1 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/frontmatter.md @@ -0,0 +1,25 @@ +# `frontmatter` + +The tracking issue for this feature is: [#136889] + +------ + +The `frontmatter` feature allows an extra metadata block at the top of files for consumption by +external tools. For example, it can be used by [`cargo-script`] files to specify dependencies. + +```rust +#!/usr/bin/env -S cargo -Zscript +--- +[dependencies] +libc = "0.2.172" +--- +#![feature(frontmatter)] +# mod libc { pub type c_int = i32; } + +fn main() { + let x: libc::c_int = 1i32; +} +``` + +[#136889]: https://github.com/rust-lang/rust/issues/136889 +[`cargo-script`]: https://rust-lang.github.io/rfcs/3502-cargo-script.html diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 27ae0553c60d..dbfdd8ebd167 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -14,7 +14,6 @@ base64 = "0.21.7" itertools = "0.12" indexmap = "2" minifier = { version = "0.3.5", default-features = false } -pulldown-cmark-old = { version = "0.9.6", package = "pulldown-cmark", default-features = false } pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] } regex = "1" rustdoc-json-types = { path = "../rustdoc-json-types" } diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index e967fd406093..d684e6f8650f 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -167,7 +167,7 @@ fn print_tts(printer: &mut Printer<'_>, tts: &TokenStream) { } fn usually_needs_space_between_keyword_and_open_delim(symbol: Symbol, span: Span) -> bool { - let ident = Ident { name: symbol, span }; + let ident = Ident::new(symbol, span); let is_keyword = ident.is_used_keyword() || ident.is_unused_keyword(); if !is_keyword { // An identifier that is not a keyword usually does not need a space diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index bbe11bf56af3..15890fff0c33 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -786,7 +786,11 @@ impl Item { // because it isn't public API. None } - _ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)), + _ => Some({ + let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr); + assert_eq!(s.pop(), Some('\n')); + s + }), } } else if attr.has_any_name(ALLOWED_ATTRIBUTES) { Some( diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 829a9ca6e7dd..0cdf2f92a891 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -262,11 +262,21 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions Ok(None) => return, Err(error) => { eprintln!("{error}"); + // Since some files in the temporary folder are still owned and alive, we need + // to manually remove the folder. + let _ = std::fs::remove_dir_all(temp_dir.path()); std::process::exit(1); } }; - run_tests(opts, &rustdoc_options, &unused_extern_reports, standalone_tests, mergeable_tests); + run_tests( + opts, + &rustdoc_options, + &unused_extern_reports, + standalone_tests, + mergeable_tests, + Some(temp_dir), + ); let compiling_test_count = compiling_test_count.load(Ordering::SeqCst); @@ -316,6 +326,8 @@ pub(crate) fn run_tests( unused_extern_reports: &Arc>>, mut standalone_tests: Vec, mergeable_tests: FxIndexMap>, + // We pass this argument so we can drop it manually before using `exit`. + mut temp_dir: Option, ) { let mut test_args = Vec::with_capacity(rustdoc_options.test_args.len() + 1); test_args.insert(0, "rustdoctest".to_string()); @@ -382,9 +394,14 @@ pub(crate) fn run_tests( // `running 0 tests...`. if ran_edition_tests == 0 || !standalone_tests.is_empty() { standalone_tests.sort_by(|a, b| a.desc.name.as_slice().cmp(b.desc.name.as_slice())); - test::test_main(&test_args, standalone_tests, None); + test::test_main_with_exit_callback(&test_args, standalone_tests, None, || { + // We ensure temp dir destructor is called. + std::mem::drop(temp_dir.take()); + }); } if nb_errors != 0 { + // We ensure temp dir destructor is called. + std::mem::drop(temp_dir); // libtest::ERROR_EXIT_CODE is not public but it's the same value. std::process::exit(101); } @@ -450,7 +467,7 @@ enum TestFailure { } enum DirState { - Temp(tempfile::TempDir), + Temp(TempDir), Perm(PathBuf), } diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index 497a8d7c4a75..b3a3ce08a05a 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -116,6 +116,7 @@ pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> { &Arc::new(Mutex::new(Vec::new())), standalone_tests, mergeable_tests, + None, ); Ok(()) } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index c943d3ad4d05..2db1ea8450ce 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -9,7 +9,7 @@ use std::collections::VecDeque; use std::fmt::{Display, Write}; use rustc_data_structures::fx::FxIndexMap; -use rustc_lexer::{Cursor, LiteralKind, TokenKind}; +use rustc_lexer::{Cursor, FrontmatterAllowed, LiteralKind, TokenKind}; use rustc_span::edition::Edition; use rustc_span::symbol::Symbol; use rustc_span::{BytePos, DUMMY_SP, Span}; @@ -638,7 +638,8 @@ impl<'src> Classifier<'src> { /// Takes as argument the source code to HTML-ify, the rust edition to use and the source code /// file span which will be used later on by the `span_correspondence_map`. fn new(src: &'src str, file_span: Span, decoration_info: Option<&DecorationInfo>) -> Self { - let tokens = PeekIter::new(TokenIter { src, cursor: Cursor::new(src) }); + let tokens = + PeekIter::new(TokenIter { src, cursor: Cursor::new(src, FrontmatterAllowed::Yes) }); let decorations = decoration_info.map(Decorations::new); Classifier { tokens, @@ -884,6 +885,7 @@ impl<'src> Classifier<'src> { | TokenKind::At | TokenKind::Tilde | TokenKind::Colon + | TokenKind::Frontmatter { .. } | TokenKind::Unknown => return no_highlight(sink), TokenKind::Question => Class::QuestionMark, diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 19ac24a5d6e3..f838f3f1106f 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -55,6 +55,9 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\ --collapse-arrow-image: url('data:image/svg+xml,'); + --hamburger-image: url('data:image/svg+xml,\ + '); } :root.sans-serif { @@ -2001,9 +2004,11 @@ a.tooltip:hover::after { display: flex; margin-right: 4px; position: fixed; - left: 6px; height: 34px; width: 34px; +} +.hide-sidebar #sidebar-button { + left: 6px; background-color: var(--main-background-color); z-index: 1; } @@ -2019,6 +2024,8 @@ a.tooltip:hover::after { align-items: center; justify-content: center; flex-direction: column; +} +#settings-menu > a, #help-button > a, button#toggle-all-docs { border: 1px solid transparent; border-radius: var(--button-border-radius); color: var(--main-color); @@ -2031,14 +2038,15 @@ a.tooltip:hover::after { min-width: 0; } #sidebar-button > a { - background-color: var(--button-background-color); - border-color: var(--border-color); + background-color: var(--sidebar-background-color); width: 33px; } +#sidebar-button > a:hover, #sidebar-button > a:focus-visible { + background-color: var(--main-background-color); +} #settings-menu > a:hover, #settings-menu > a:focus-visible, #help-button > a:hover, #help-button > a:focus-visible, -#sidebar-button > a:hover, #sidebar-button > a:focus-visible, button#toggle-all-docs:hover, button#toggle-all-docs:focus-visible { border-color: var(--settings-button-border-focus); text-decoration: none; @@ -2405,10 +2413,9 @@ However, it's not needed with smaller screen width because the doc/code block is use hamburger button */ .src #sidebar-button > a::before, .sidebar-menu-toggle::before { /* hamburger button image */ - content: url('data:image/svg+xml,\ - '); + content: var(--hamburger-image); opacity: 0.75; + filter: var(--mobile-sidebar-menu-filter); } .sidebar-menu-toggle:hover::before, .sidebar-menu-toggle:active::before, @@ -2416,17 +2423,6 @@ However, it's not needed with smaller screen width because the doc/code block is opacity: 1; } -/* src sidebar button opens a folder view */ -.src #sidebar-button > a::before { - /* folder image */ - content: url('data:image/svg+xml,\ - \ - \ - '); - opacity: 0.75; -} - /* Media Queries */ /* Make sure all the buttons line wrap at the same time */ @@ -2611,9 +2607,6 @@ in src-script.js and main.js width: 22px; height: 22px; } - .sidebar-menu-toggle::before { - filter: var(--mobile-sidebar-menu-filter); - } .sidebar-menu-toggle:hover { background: var(--main-background-color); } @@ -2671,6 +2664,14 @@ in src-script.js and main.js margin: 0 0 -25px 0; padding: var(--nav-sub-mobile-padding); } + + html:not(.src-sidebar-expanded) .src #sidebar-button > a { + background-color: var(--main-background-color); + } + html:not(.src-sidebar-expanded) .src #sidebar-button > a:hover, + html:not(.src-sidebar-expanded) .src #sidebar-button > a:focus-visible { + background-color: var(--sidebar-background-color); + } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 44bd96a7e450..bca40b8117bd 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -170,12 +170,28 @@ pub fn main() { // NOTE: this compiles both versions of tracing unconditionally, because // - The compile time hit is not that bad, especially compared to rustdoc's incremental times, and // - Otherwise, there's no warning that logging is being ignored when `download-rustc` is enabled - // NOTE: The reason this doesn't show double logging when `download-rustc = false` and - // `debug_logging = true` is because all rustc logging goes to its version of tracing (the one - // in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml). - init_logging(&early_dcx); - rustc_driver::init_logger(&early_dcx, rustc_log::LoggerConfig::from_env("RUSTDOC_LOG")); + crate::init_logging(&early_dcx); + match rustc_log::init_logger(rustc_log::LoggerConfig::from_env("RUSTDOC_LOG")) { + Ok(()) => {} + // With `download-rustc = true` there are definitely 2 distinct tracing crates in the + // dependency graph: one in the downloaded sysroot and one built just now as a dependency of + // rustdoc. So the sysroot's tracing is definitely not yet initialized here. + // + // But otherwise, depending on link style, there may or may not be 2 tracing crates in play. + // The one we just initialized in `crate::init_logging` above is rustdoc's direct dependency + // on tracing. When rustdoc is built by x.py using Cargo, rustc_driver's and rustc_log's + // tracing dependency is distinct from this one and also needs to be initialized (using the + // same RUSTDOC_LOG environment variable for both). Other build systems may use just a + // single tracing crate throughout the rustc and rustdoc build. + // + // The reason initializing 2 tracings does not show double logging when `download-rustc = + // false` and `debug_logging = true` is because all rustc logging goes only to its version + // of tracing (the one in the sysroot) and all of rustdoc's logging only goes to its version + // (the one in Cargo.toml). + Err(rustc_log::Error::AlreadyInit(_)) => {} + Err(error) => early_dcx.early_fatal(error.to_string()), + } let exit_code = rustc_driver::catch_with_exit_code(|| { let at_args = rustc_driver::args::raw_args(&early_dcx); diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index dcc27cd62e38..b09ea0568859 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -196,14 +196,6 @@ declare_rustdoc_lint! { "detects redundant explicit links in doc comments" } -declare_rustdoc_lint! { - /// This compatibility lint checks for Markdown syntax that works in the old engine but not - /// the new one. - UNPORTABLE_MARKDOWN, - Warn, - "detects markdown that is interpreted differently in different parser" -} - pub(crate) static RUSTDOC_LINTS: Lazy> = Lazy::new(|| { vec![ BROKEN_INTRA_DOC_LINKS, @@ -217,7 +209,6 @@ pub(crate) static RUSTDOC_LINTS: Lazy> = Lazy::new(|| { MISSING_CRATE_LEVEL_DOCS, UNESCAPED_BACKTICKS, REDUNDANT_EXPLICIT_LINKS, - UNPORTABLE_MARKDOWN, ] }); @@ -241,4 +232,5 @@ pub(crate) fn register_lints(_sess: &Session, lint_store: &mut LintStore) { .register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links"); lint_store.register_renamed("non_autolinks", "rustdoc::bare_urls"); lint_store.register_renamed("rustdoc::non_autolinks", "rustdoc::bare_urls"); + lint_store.register_removed("rustdoc::unportable_markdown", "old parser removed"); } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 36f5889dcf4e..f3e2138d1a57 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -496,12 +496,21 @@ impl<'tcx> LinkCollector<'_, 'tcx> { // Try looking for methods and associated items. // NB: `path_root` could be empty when resolving in the root namespace (e.g. `::std`). - let (path_root, item_str) = path_str.rsplit_once("::").ok_or_else(|| { - // If there's no `::`, it's not an associated item. - // So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved. - debug!("found no `::`, assuming {path_str} was correctly not in scope"); - UnresolvedPath { item_id, module_id, partial_res: None, unresolved: path_str.into() } - })?; + let (path_root, item_str) = match path_str.rsplit_once("::") { + Some(res @ (_path_root, item_str)) if !item_str.is_empty() => res, + _ => { + // If there's no `::`, or the `::` is at the end (e.g. `String::`) it's not an + // associated item. So we can be sure that `rustc_resolve` was accurate when it + // said it wasn't resolved. + debug!("`::` missing or at end, assuming {path_str} was not in scope"); + return Err(UnresolvedPath { + item_id, + module_id, + partial_res: None, + unresolved: path_str.into(), + }); + } + }; let item_name = Symbol::intern(item_str); // FIXME(#83862): this arbitrarily gives precedence to primitives over modules to support diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs index 1ecb53e61ac3..7740d14148bf 100644 --- a/src/librustdoc/passes/lint.rs +++ b/src/librustdoc/passes/lint.rs @@ -6,7 +6,6 @@ mod check_code_block_syntax; mod html_tags; mod redundant_explicit_links; mod unescaped_backticks; -mod unportable_markdown; use super::Pass; use crate::clean::*; @@ -49,9 +48,6 @@ impl DocVisitor<'_> for Linter<'_, '_> { } if may_have_block_comment_or_html { html_tags::visit_item(self.cx, item, hir_id, &dox); - unportable_markdown::visit_item(self.cx, item, hir_id, &dox); - } else if may_have_link { - unportable_markdown::visit_item(self.cx, item, hir_id, &dox); } } diff --git a/src/librustdoc/passes/lint/unportable_markdown.rs b/src/librustdoc/passes/lint/unportable_markdown.rs deleted file mode 100644 index 95646413a2d2..000000000000 --- a/src/librustdoc/passes/lint/unportable_markdown.rs +++ /dev/null @@ -1,145 +0,0 @@ -//! Detects specific markdown syntax that's different between pulldown-cmark -//! 0.9 and 0.11. -//! -//! This is a mitigation for old parser bugs that affected some -//! real crates' docs. The old parser claimed to comply with CommonMark, -//! but it did not. These warnings will eventually be removed, -//! though some of them may become Clippy lints. -//! -//! -//! -//! - -use std::collections::{BTreeMap, BTreeSet}; - -use rustc_hir::HirId; -use rustc_lint_defs::Applicability; -use rustc_resolve::rustdoc::source_span_for_markdown_range; -use {pulldown_cmark as cmarkn, pulldown_cmark_old as cmarko}; - -use crate::clean::Item; -use crate::core::DocContext; - -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { - let tcx = cx.tcx; - - // P1: unintended strikethrough was fixed by requiring single-tildes to flank - // the same way underscores do, so nothing is done here - - // P2: block quotes without following space parsed wrong - // - // This is the set of starting points for block quotes with no space after - // the `>`. It is populated by the new parser, and if the old parser fails to - // clear it out, it'll produce a warning. - let mut spaceless_block_quotes = BTreeSet::new(); - - // P3: missing footnote references - // - // This is populated by listening for FootnoteReference from - // the new parser and old parser. - let mut missing_footnote_references = BTreeMap::new(); - let mut found_footnote_references = BTreeSet::new(); - - // populate problem cases from new parser - { - pub fn main_body_opts_new() -> cmarkn::Options { - cmarkn::Options::ENABLE_TABLES - | cmarkn::Options::ENABLE_FOOTNOTES - | cmarkn::Options::ENABLE_STRIKETHROUGH - | cmarkn::Options::ENABLE_TASKLISTS - | cmarkn::Options::ENABLE_SMART_PUNCTUATION - } - let parser_new = cmarkn::Parser::new_ext(dox, main_body_opts_new()).into_offset_iter(); - for (event, span) in parser_new { - if let cmarkn::Event::Start(cmarkn::Tag::BlockQuote(_)) = event { - if !dox[span.clone()].starts_with("> ") { - spaceless_block_quotes.insert(span.start); - } - } - if let cmarkn::Event::FootnoteReference(_) = event { - found_footnote_references.insert(span.start + 1); - } - } - } - - // remove cases where they don't actually differ - { - pub fn main_body_opts_old() -> cmarko::Options { - cmarko::Options::ENABLE_TABLES - | cmarko::Options::ENABLE_FOOTNOTES - | cmarko::Options::ENABLE_STRIKETHROUGH - | cmarko::Options::ENABLE_TASKLISTS - | cmarko::Options::ENABLE_SMART_PUNCTUATION - } - let parser_old = cmarko::Parser::new_ext(dox, main_body_opts_old()).into_offset_iter(); - for (event, span) in parser_old { - if let cmarko::Event::Start(cmarko::Tag::BlockQuote) = event - && !dox[span.clone()].starts_with("> ") - { - spaceless_block_quotes.remove(&span.start); - } - if let cmarko::Event::FootnoteReference(_) = event - && !found_footnote_references.contains(&(span.start + 1)) - { - missing_footnote_references.insert(span.start + 1, span); - } - } - } - - for start in spaceless_block_quotes { - let (span, precise) = - source_span_for_markdown_range(tcx, dox, &(start..start + 1), &item.attrs.doc_strings) - .map(|span| (span, true)) - .unwrap_or_else(|| (item.attr_span(tcx), false)); - - tcx.node_span_lint(crate::lint::UNPORTABLE_MARKDOWN, hir_id, span, |lint| { - lint.primary_message("unportable markdown"); - lint.help("confusing block quote with no space after the `>` marker".to_string()); - if precise { - lint.span_suggestion( - span.shrink_to_hi(), - "if the quote is intended, add a space", - " ", - Applicability::MaybeIncorrect, - ); - lint.span_suggestion( - span.shrink_to_lo(), - "if it should not be a quote, escape it", - "\\", - Applicability::MaybeIncorrect, - ); - } - }); - } - for (_caret, span) in missing_footnote_references { - let (ref_span, precise) = - source_span_for_markdown_range(tcx, dox, &span, &item.attrs.doc_strings) - .map(|span| (span, true)) - .unwrap_or_else(|| (item.attr_span(tcx), false)); - - tcx.node_span_lint(crate::lint::UNPORTABLE_MARKDOWN, hir_id, ref_span, |lint| { - lint.primary_message("unportable markdown"); - if precise { - lint.span_suggestion( - ref_span.shrink_to_lo(), - "if it should not be a footnote, escape it", - "\\", - Applicability::MaybeIncorrect, - ); - } - if dox.as_bytes().get(span.end) == Some(&b'[') { - lint.help("confusing footnote reference and link"); - if precise { - lint.span_suggestion( - ref_span.shrink_to_hi(), - "if the footnote is intended, add a space", - " ", - Applicability::MaybeIncorrect, - ); - } else { - lint.help("there should be a space between the link and the footnote"); - } - } - }); - } -} diff --git a/src/llvm-project b/src/llvm-project index a9865ceca081..8448283b4bd3 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit a9865ceca08101071e25f3bba97bba8bf0ea9719 +Subproject commit 8448283b4bd34ea00d76fd4f18ec730b549d6e1d diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 63859c0396e4..6d3e77b6b6e9 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -263,7 +263,7 @@ impl<'tcx> NonCopyConst<'tcx> { fn is_value_unfrozen_poly(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool { let def_id = body_id.hir_id.owner.to_def_id(); let args = ty::GenericArgs::identity_for_item(cx.tcx, def_id); - let instance = ty::Instance::new(def_id, args); + let instance = ty::Instance::new_raw(def_id, args); let cid = GlobalId { instance, promoted: None, diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index 5b3f60ad6ab0..45a5dbabeb4e 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -154,7 +154,7 @@ impl LateLintPass<'_> for WildcardImports { (span, false) }; - let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(); + let mut imports: Vec<_> = used_imports.iter().map(ToString::to_string).collect(); let imports_string = if imports.len() == 1 { imports.pop().unwrap() } else if braced_glob { diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 8db9cd593b33..da09edd7f7c0 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -20,8 +20,8 @@ use rustc_middle::traits::EvaluationResult; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef, - GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, + GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; @@ -915,7 +915,7 @@ pub fn for_each_top_level_late_bound_region( ControlFlow::Continue(()) } } - fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result { + fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result { self.index += 1; let res = t.super_visit_with(self); self.index -= 1; diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last.fixed b/src/tools/clippy/tests/ui/double_ended_iterator_last.fixed index 2ce0c04c3017..be31ee5fb486 100644 --- a/src/tools/clippy/tests/ui/double_ended_iterator_last.fixed +++ b/src/tools/clippy/tests/ui/double_ended_iterator_last.fixed @@ -84,6 +84,19 @@ fn issue_14139() { } fn drop_order() { + struct DropDeIterator(std::vec::IntoIter); + impl Iterator for DropDeIterator { + type Item = S; + fn next(&mut self) -> Option { + self.0.next() + } + } + impl DoubleEndedIterator for DropDeIterator { + fn next_back(&mut self) -> Option { + self.0.next_back() + } + } + struct S(&'static str); impl std::ops::Drop for S { fn drop(&mut self) { @@ -92,7 +105,7 @@ fn drop_order() { } let v = vec![S("one"), S("two"), S("three")]; - let mut v = v.into_iter(); + let mut v = DropDeIterator(v.into_iter()); println!("Last element is {}", v.next_back().unwrap().0); //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` println!("Done"); diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last.rs b/src/tools/clippy/tests/ui/double_ended_iterator_last.rs index a4eb9b3337b9..30864e15bce7 100644 --- a/src/tools/clippy/tests/ui/double_ended_iterator_last.rs +++ b/src/tools/clippy/tests/ui/double_ended_iterator_last.rs @@ -84,6 +84,19 @@ fn issue_14139() { } fn drop_order() { + struct DropDeIterator(std::vec::IntoIter); + impl Iterator for DropDeIterator { + type Item = S; + fn next(&mut self) -> Option { + self.0.next() + } + } + impl DoubleEndedIterator for DropDeIterator { + fn next_back(&mut self) -> Option { + self.0.next_back() + } + } + struct S(&'static str); impl std::ops::Drop for S { fn drop(&mut self) { @@ -92,7 +105,7 @@ fn drop_order() { } let v = vec![S("one"), S("two"), S("three")]; - let v = v.into_iter(); + let v = DropDeIterator(v.into_iter()); println!("Last element is {}", v.last().unwrap().0); //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` println!("Done"); diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last.stderr b/src/tools/clippy/tests/ui/double_ended_iterator_last.stderr index fe8cf2dcb259..72a6ead47a93 100644 --- a/src/tools/clippy/tests/ui/double_ended_iterator_last.stderr +++ b/src/tools/clippy/tests/ui/double_ended_iterator_last.stderr @@ -18,7 +18,7 @@ LL | let _ = DeIterator.last(); | help: try: `next_back()` error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator - --> tests/ui/double_ended_iterator_last.rs:96:36 + --> tests/ui/double_ended_iterator_last.rs:109:36 | LL | println!("Last element is {}", v.last().unwrap().0); | ^^^^^^^^ @@ -26,7 +26,7 @@ LL | println!("Last element is {}", v.last().unwrap().0); = note: this change will alter drop order which may be undesirable help: try | -LL ~ let mut v = v.into_iter(); +LL ~ let mut v = DropDeIterator(v.into_iter()); LL ~ println!("Last element is {}", v.next_back().unwrap().0); | diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs b/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs index 7c5de8832d69..e9218bbb4094 100644 --- a/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs +++ b/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs @@ -11,6 +11,19 @@ fn main() { } fn drop_order() { + struct DropDeIterator(std::vec::IntoIter); + impl Iterator for DropDeIterator { + type Item = S; + fn next(&mut self) -> Option { + self.0.next() + } + } + impl DoubleEndedIterator for DropDeIterator { + fn next_back(&mut self) -> Option { + self.0.next_back() + } + } + struct S(&'static str); impl std::ops::Drop for S { fn drop(&mut self) { @@ -19,7 +32,7 @@ fn drop_order() { } let v = vec![S("one"), S("two"), S("three")]; - let v = (v.into_iter(), 42); + let v = (DropDeIterator(v.into_iter()), 42); println!("Last element is {}", v.0.last().unwrap().0); //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` println!("Done"); diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr b/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr index 845afc11f042..e330a22a3548 100644 --- a/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr +++ b/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr @@ -1,5 +1,5 @@ error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator - --> tests/ui/double_ended_iterator_last_unfixable.rs:23:36 + --> tests/ui/double_ended_iterator_last_unfixable.rs:36:36 | LL | println!("Last element is {}", v.0.last().unwrap().0); | ^^^^------ @@ -8,7 +8,7 @@ LL | println!("Last element is {}", v.0.last().unwrap().0); | = note: this change will alter drop order which may be undesirable note: this must be made mutable to use `.next_back()` - --> tests/ui/double_ended_iterator_last_unfixable.rs:23:36 + --> tests/ui/double_ended_iterator_last_unfixable.rs:36:36 | LL | println!("Last element is {}", v.0.last().unwrap().0); | ^^^ diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed index a26b4a34190c..17510683f03e 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed @@ -16,7 +16,7 @@ use crate::fn_mod::foo; //~^ wildcard_imports use crate::mod_mod::inner_mod; //~^ wildcard_imports -use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +use crate::multi_fn_mod::{multi_foo, multi_bar, multi_inner_mod}; //~^ wildcard_imports #[macro_use] use crate::struct_mod::{A, inner_struct_mod}; @@ -26,7 +26,7 @@ use crate::struct_mod::{A, inner_struct_mod}; use wildcard_imports_helper::inner::inner_for_self_import; use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; //~^ wildcard_imports -use wildcard_imports_helper::{ExternA, extern_foo}; +use wildcard_imports_helper::{extern_foo, ExternA}; //~^ wildcard_imports use std::io::prelude::*; @@ -138,7 +138,7 @@ mod in_fn_test { fn test_extern() { use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; //~^ wildcard_imports - use wildcard_imports_helper::{ExternA, extern_foo}; + use wildcard_imports_helper::{extern_foo, ExternA}; //~^ wildcard_imports inner_for_self_import::inner_extern_foo(); @@ -160,7 +160,7 @@ mod in_fn_test { } fn test_extern_reexported() { - use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + use wildcard_imports_helper::{extern_exported, ExternExportedStruct, ExternExportedEnum}; //~^ wildcard_imports extern_exported(); @@ -190,7 +190,7 @@ mod in_fn_test { } fn test_reexported() { - use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + use crate::in_fn_test::{exported, ExportedStruct, ExportedEnum}; //~^ wildcard_imports exported(); diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr index f774126102bc..26434656a509 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr @@ -17,7 +17,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports.rs:19:5 | LL | use crate::multi_fn_mod::*; - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_foo, multi_bar, multi_inner_mod}` error: usage of wildcard import --> tests/ui/wildcard_imports.rs:22:5 @@ -35,7 +35,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports.rs:29:5 | LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{extern_foo, ExternA}` error: usage of wildcard import --> tests/ui/wildcard_imports.rs:100:13 @@ -59,7 +59,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports.rs:141:13 | LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{extern_foo, ExternA}` error: usage of wildcard import --> tests/ui/wildcard_imports.rs:154:20 @@ -77,13 +77,13 @@ error: usage of wildcard import --> tests/ui/wildcard_imports.rs:163:13 | LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{extern_exported, ExternExportedStruct, ExternExportedEnum}` error: usage of wildcard import --> tests/ui/wildcard_imports.rs:193:9 | LL | use crate::in_fn_test::*; - | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{exported, ExportedStruct, ExportedEnum}` error: usage of wildcard import --> tests/ui/wildcard_imports.rs:203:9 diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed index a3d1aebba8af..f97b883ea231 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed @@ -14,7 +14,7 @@ use crate::fn_mod::foo; //~^ wildcard_imports use crate::mod_mod::inner_mod; //~^ wildcard_imports -use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +use crate::multi_fn_mod::{multi_foo, multi_bar, multi_inner_mod}; //~^ wildcard_imports use crate::struct_mod::{A, inner_struct_mod}; //~^ wildcard_imports @@ -23,7 +23,7 @@ use crate::struct_mod::{A, inner_struct_mod}; use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; //~^ wildcard_imports use wildcard_imports_helper::prelude::v1::*; -use wildcard_imports_helper::{ExternA, extern_foo}; +use wildcard_imports_helper::{extern_foo, ExternA}; //~^ wildcard_imports use std::io::prelude::*; @@ -132,7 +132,7 @@ mod in_fn_test { fn test_extern() { use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; //~^ wildcard_imports - use wildcard_imports_helper::{ExternA, extern_foo}; + use wildcard_imports_helper::{extern_foo, ExternA}; //~^ wildcard_imports inner_for_self_import::inner_extern_foo(); @@ -154,7 +154,7 @@ mod in_fn_test { } fn test_extern_reexported() { - use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + use wildcard_imports_helper::{extern_exported, ExternExportedStruct, ExternExportedEnum}; //~^ wildcard_imports extern_exported(); @@ -184,7 +184,7 @@ mod in_fn_test { } fn test_reexported() { - use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + use crate::in_fn_test::{exported, ExportedStruct, ExportedEnum}; //~^ wildcard_imports exported(); diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr index a1b557f39f0d..873ce41b04f4 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr @@ -17,7 +17,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:17:5 | LL | use crate::multi_fn_mod::*; - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_foo, multi_bar, multi_inner_mod}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:19:5 @@ -35,7 +35,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:26:5 | LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{extern_foo, ExternA}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:95:13 @@ -59,7 +59,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:135:13 | LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{extern_foo, ExternA}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:148:20 @@ -77,13 +77,13 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:157:13 | LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{extern_exported, ExternExportedStruct, ExternExportedEnum}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:187:9 | LL | use crate::in_fn_test::*; - | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{exported, ExportedStruct, ExportedEnum}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:197:9 diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed index a3d1aebba8af..f97b883ea231 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed @@ -14,7 +14,7 @@ use crate::fn_mod::foo; //~^ wildcard_imports use crate::mod_mod::inner_mod; //~^ wildcard_imports -use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +use crate::multi_fn_mod::{multi_foo, multi_bar, multi_inner_mod}; //~^ wildcard_imports use crate::struct_mod::{A, inner_struct_mod}; //~^ wildcard_imports @@ -23,7 +23,7 @@ use crate::struct_mod::{A, inner_struct_mod}; use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; //~^ wildcard_imports use wildcard_imports_helper::prelude::v1::*; -use wildcard_imports_helper::{ExternA, extern_foo}; +use wildcard_imports_helper::{extern_foo, ExternA}; //~^ wildcard_imports use std::io::prelude::*; @@ -132,7 +132,7 @@ mod in_fn_test { fn test_extern() { use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; //~^ wildcard_imports - use wildcard_imports_helper::{ExternA, extern_foo}; + use wildcard_imports_helper::{extern_foo, ExternA}; //~^ wildcard_imports inner_for_self_import::inner_extern_foo(); @@ -154,7 +154,7 @@ mod in_fn_test { } fn test_extern_reexported() { - use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + use wildcard_imports_helper::{extern_exported, ExternExportedStruct, ExternExportedEnum}; //~^ wildcard_imports extern_exported(); @@ -184,7 +184,7 @@ mod in_fn_test { } fn test_reexported() { - use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + use crate::in_fn_test::{exported, ExportedStruct, ExportedEnum}; //~^ wildcard_imports exported(); diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr index a1b557f39f0d..873ce41b04f4 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr @@ -17,7 +17,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:17:5 | LL | use crate::multi_fn_mod::*; - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_foo, multi_bar, multi_inner_mod}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:19:5 @@ -35,7 +35,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:26:5 | LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{extern_foo, ExternA}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:95:13 @@ -59,7 +59,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:135:13 | LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{extern_foo, ExternA}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:148:20 @@ -77,13 +77,13 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:157:13 | LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{extern_exported, ExternExportedStruct, ExternExportedEnum}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:187:9 | LL | use crate::in_fn_test::*; - | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{exported, ExportedStruct, ExportedEnum}` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:197:9 diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 1449e9af19aa..5757e422ae21 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -35,6 +35,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-32bit", "ignore-64bit", "ignore-aarch64", + "ignore-aarch64-pc-windows-msvc", "ignore-aarch64-unknown-linux-gnu", "ignore-aix", "ignore-android", diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index a45f39b036cc..b5a2b7feac9d 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -15,6 +15,7 @@ pub enum ErrorKind { Note, Suggestion, Warning, + Raw, } impl ErrorKind { @@ -39,6 +40,7 @@ impl ErrorKind { "NOTE" | "note" | "MONO_ITEM" => ErrorKind::Note, "SUGGESTION" => ErrorKind::Suggestion, "WARN" | "WARNING" | "warn" | "warning" => ErrorKind::Warning, + "RAW" => ErrorKind::Raw, _ => panic!( "unexpected diagnostic kind `{s}`, expected \ `ERROR`, `WARN`, `NOTE`, `HELP` or `SUGGESTION`" @@ -55,6 +57,7 @@ impl fmt::Display for ErrorKind { ErrorKind::Note => write!(f, "NOTE"), ErrorKind::Suggestion => write!(f, "SUGGESTION"), ErrorKind::Warning => write!(f, "WARN"), + ErrorKind::Raw => write!(f, "RAW"), } } } diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 960f5ba58882..6ed2b52c66d2 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -7,7 +7,6 @@ use regex::Regex; use serde::Deserialize; use crate::errors::{Error, ErrorKind}; -use crate::runtest::ProcRes; #[derive(Deserialize)] struct Diagnostic { @@ -140,28 +139,19 @@ pub fn extract_rendered(output: &str) -> String { .collect() } -pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec { +pub fn parse_output(file_name: &str, output: &str) -> Vec { let mut errors = Vec::new(); for line in output.lines() { - // The compiler sometimes intermingles non-JSON stuff into the - // output. This hack just skips over such lines. Yuck. - if line.starts_with('{') { - match serde_json::from_str::(line) { - Ok(diagnostic) => push_actual_errors(&mut errors, &diagnostic, &[], file_name), - Err(error) => { - // Ignore the future compat report message - this is handled - // by `extract_rendered` - if serde_json::from_str::(line).is_err() { - proc_res.fatal( - Some(&format!( - "failed to decode compiler output as json: `{}`\nline: {}\noutput: {}", - error, line, output - )), - || (), - ); - } - } - } + // Compiler can emit non-json lines in non-`--error-format=json` modes, + // and in some situations even in json mode. + match serde_json::from_str::(line) { + Ok(diagnostic) => push_actual_errors(&mut errors, &diagnostic, &[], file_name), + Err(_) => errors.push(Error { + line_num: None, + kind: ErrorKind::Raw, + msg: line.to_string(), + require_annotation: false, + }), } } errors @@ -181,8 +171,6 @@ fn push_actual_errors( .filter(|(_, span)| Path::new(&span.file_name) == Path::new(&file_name)) .collect(); - let spans_in_this_file: Vec<_> = spans_info_in_this_file.iter().map(|(_, span)| span).collect(); - let primary_spans: Vec<_> = spans_info_in_this_file .iter() .filter(|(is_primary, _)| *is_primary) @@ -280,7 +268,9 @@ fn push_actual_errors( line_num: Some(span.line_start + index), kind: ErrorKind::Suggestion, msg: line.to_string(), - require_annotation: true, + // Empty suggestions (suggestions to remove something) are common + // and annotating them in source is not useful. + require_annotation: !line.is_empty(), }); } } @@ -294,13 +284,16 @@ fn push_actual_errors( } // Add notes for any labels that appear in the message. - for span in spans_in_this_file.iter().filter(|span| span.label.is_some()) { - errors.push(Error { - line_num: Some(span.line_start), - kind: ErrorKind::Note, - msg: span.label.clone().unwrap(), - require_annotation: true, - }); + for (_, span) in spans_info_in_this_file { + if let Some(label) = &span.label { + errors.push(Error { + line_num: Some(span.line_start), + kind: ErrorKind::Note, + msg: label.clone(), + // Empty labels (only underlining spans) are common and do not need annotations. + require_annotation: !label.is_empty(), + }); + } } // Flatten out the children. diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 97cb82c9e363..40c9f29375b2 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -23,7 +23,7 @@ use crate::common::{ output_base_dir, output_base_name, output_testname_unique, }; use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; -use crate::errors::{Error, ErrorKind}; +use crate::errors::{Error, ErrorKind, load_errors}; use crate::header::TestProps; use crate::read2::{Truncated, read2_abbreviated}; use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex}; @@ -577,23 +577,9 @@ impl<'test> TestCx<'test> { } } - fn check_all_error_patterns( - &self, - output_to_check: &str, - proc_res: &ProcRes, - pm: Option, - ) { - if self.props.error_patterns.is_empty() && self.props.regex_error_patterns.is_empty() { - if pm.is_some() { - // FIXME(#65865) - return; - } else { - self.fatal(&format!("no error pattern specified in {}", self.testpaths.file)); - } - } - + /// Check `error-pattern` and `regex-error-pattern` directives. + fn check_all_error_patterns(&self, output_to_check: &str, proc_res: &ProcRes) { let mut missing_patterns: Vec = Vec::new(); - self.check_error_patterns(output_to_check, &mut missing_patterns); self.check_regex_error_patterns(output_to_check, proc_res, &mut missing_patterns); @@ -670,7 +656,9 @@ impl<'test> TestCx<'test> { } } - fn check_expected_errors(&self, expected_errors: Vec, proc_res: &ProcRes) { + /// Check `//~ KIND message` annotations. + fn check_expected_errors(&self, proc_res: &ProcRes) { + let expected_errors = load_errors(&self.testpaths.file, self.revision); debug!( "check_expected_errors: expected_errors={:?} proc_res.status={:?}", expected_errors, proc_res.status @@ -711,11 +699,24 @@ impl<'test> TestCx<'test> { .collect(); // Parse the JSON output from the compiler and extract out the messages. - let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res); + let actual_errors = json::parse_output(&diagnostic_file_name, &self.get_output(proc_res)) + .into_iter() + .map(|e| Error { msg: self.normalize_output(&e.msg, &[]), ..e }); + let mut unexpected = Vec::new(); let mut found = vec![false; expected_errors.len()]; - for mut actual_error in actual_errors { - actual_error.msg = self.normalize_output(&actual_error.msg, &[]); + for actual_error in actual_errors { + for pattern in &self.props.error_patterns { + let pattern = pattern.trim(); + if actual_error.msg.contains(pattern) { + let q = if actual_error.line_num.is_none() { "?" } else { "" }; + self.fatal(&format!( + "error pattern '{pattern}' is found in structured \ + diagnostics, use `//~{q} {} {pattern}` instead", + actual_error.kind, + )); + } + } let opt_index = expected_errors.iter().enumerate().position(|(index, expected_error)| { diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index ea985866a052..90cff6bab4dc 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -100,16 +100,8 @@ impl TestCx<'_> { self.check_no_compiler_crash(&proc_res, self.props.should_ice); let output_to_check = self.get_output(&proc_res); - let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); - if !expected_errors.is_empty() { - if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty() - { - self.fatal("both error pattern and expected errors specified"); - } - self.check_expected_errors(expected_errors, &proc_res); - } else { - self.check_all_error_patterns(&output_to_check, &proc_res, pm); - } + self.check_expected_errors(&proc_res); + self.check_all_error_patterns(&output_to_check, &proc_res); if self.props.should_ice { match proc_res.status.code() { Some(101) => (), @@ -137,6 +129,6 @@ impl TestCx<'_> { let output_to_check = self.get_output(&proc_res); self.check_correct_failure_status(&proc_res); - self.check_all_error_patterns(&output_to_check, &proc_res, pm); + self.check_all_error_patterns(&output_to_check, &proc_res); } } diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index cf0ae14f81bf..cc50a918f757 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -9,7 +9,7 @@ use super::{ AllowUnused, Emit, FailMode, LinkToAux, PassMode, TargetLocation, TestCx, TestOutput, Truncated, UI_FIXED, WillExecute, }; -use crate::{errors, json}; +use crate::json; impl TestCx<'_> { pub(super) fn run_ui_test(&self) { @@ -127,9 +127,7 @@ impl TestCx<'_> { ); } - let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); - - if let WillExecute::Yes = should_run { + let output_to_check = if let WillExecute::Yes = should_run { let proc_res = self.exec_compiled_test(); let run_output_errors = if self.props.check_run_results { self.load_compare_outputs(&proc_res, TestOutput::Run, explicit) @@ -150,44 +148,19 @@ impl TestCx<'_> { self.fatal_proc_rec("test run succeeded!", &proc_res); } - let output_to_check = self.get_output(&proc_res); - if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty() - { - // "// error-pattern" comments - self.check_all_error_patterns(&output_to_check, &proc_res, pm); - } - self.check_forbid_output(&output_to_check, &proc_res) - } + self.get_output(&proc_res) + } else { + self.get_output(&proc_res) + }; debug!( - "run_ui_test: explicit={:?} config.compare_mode={:?} expected_errors={:?} \ + "run_ui_test: explicit={:?} config.compare_mode={:?} \ proc_res.status={:?} props.error_patterns={:?}", - explicit, - self.config.compare_mode, - expected_errors, - proc_res.status, - self.props.error_patterns + explicit, self.config.compare_mode, proc_res.status, self.props.error_patterns ); - if !explicit && self.config.compare_mode.is_none() { - // "//~ERROR comments" - self.check_expected_errors(expected_errors, &proc_res); - } else if explicit && !expected_errors.is_empty() { - let msg = format!( - "line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead", - expected_errors[0].line_num_str(), - expected_errors[0].kind, - ); - self.fatal(&msg); - } - let output_to_check = self.get_output(&proc_res); - if should_run == WillExecute::No - && (!self.props.error_patterns.is_empty() - || !self.props.regex_error_patterns.is_empty()) - { - // "// error-pattern" comments - self.check_all_error_patterns(&output_to_check, &proc_res, pm); - } + self.check_expected_errors(&proc_res); + self.check_all_error_patterns(&output_to_check, &proc_res); self.check_forbid_output(&output_to_check, &proc_res); if self.props.run_rustfix && self.config.compare_mode.is_none() { diff --git a/src/tools/coverage-dump/Cargo.toml b/src/tools/coverage-dump/Cargo.toml index 7f14286b5d0c..6f92ac50d963 100644 --- a/src/tools/coverage-dump/Cargo.toml +++ b/src/tools/coverage-dump/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0.71" +itertools = "0.12" leb128 = "0.2.5" md5 = { package = "md-5" , version = "0.10.5" } miniz_oxide = "0.7.1" diff --git a/src/tools/coverage-dump/src/covfun.rs b/src/tools/coverage-dump/src/covfun.rs index 82ebd33d0d1c..1cc9f4dc5d6a 100644 --- a/src/tools/coverage-dump/src/covfun.rs +++ b/src/tools/coverage-dump/src/covfun.rs @@ -1,23 +1,33 @@ use std::collections::HashMap; use std::fmt::{self, Debug, Write as _}; -use std::sync::OnceLock; +use std::sync::LazyLock; -use anyhow::{Context, anyhow}; +use anyhow::{Context, anyhow, bail, ensure}; +use itertools::Itertools; use regex::Regex; -use crate::parser::{Parser, unescape_llvm_string_contents}; +use crate::covmap::FilenameTables; +use crate::llvm_utils::unescape_llvm_string_contents; +use crate::parser::Parser; + +#[cfg(test)] +mod tests; pub(crate) fn dump_covfun_mappings( llvm_ir: &str, + filename_tables: &FilenameTables, function_names: &HashMap, ) -> anyhow::Result<()> { // Extract function coverage entries from the LLVM IR assembly, and associate // each entry with its (demangled) name. let mut covfun_entries = llvm_ir .lines() - .filter_map(covfun_line_data) - .map(|line_data| (function_names.get(&line_data.name_hash).map(String::as_str), line_data)) - .collect::>(); + .filter(|line| is_covfun_line(line)) + .map(parse_covfun_line) + .map_ok(|line_data| { + (function_names.get(&line_data.name_hash).map(String::as_str), line_data) + }) + .collect::, _>>()?; covfun_entries.sort_by(|a, b| { // Sort entries primarily by name, to help make the order consistent // across platforms and relatively insensitive to changes. @@ -41,8 +51,12 @@ pub(crate) fn dump_covfun_mappings( println!("Number of files: {num_files}"); for i in 0..num_files { - let global_file_id = parser.read_uleb128_u32()?; - println!("- file {i} => global file {global_file_id}"); + let global_file_id = parser.read_uleb128_usize()?; + let &CovfunLineData { filenames_hash, .. } = line_data; + let Some(filename) = filename_tables.lookup(filenames_hash, global_file_id) else { + bail!("couldn't resolve global file: {filenames_hash}, {global_file_id}"); + }; + println!("- file {i} => {filename}"); } let num_expressions = parser.read_uleb128_u32()?; @@ -107,36 +121,50 @@ pub(crate) fn dump_covfun_mappings( Ok(()) } +#[derive(Debug, PartialEq, Eq)] struct CovfunLineData { - name_hash: u64, is_used: bool, + name_hash: u64, + filenames_hash: u64, payload: Vec, } -/// Checks a line of LLVM IR assembly to see if it contains an `__llvm_covfun` -/// entry, and if so extracts relevant data in a `CovfunLineData`. -fn covfun_line_data(line: &str) -> Option { - let re = { - // We cheat a little bit and match variable names `@__covrec_[HASH]u` - // rather than the section name, because the section name is harder to - // extract and differs across Linux/Windows/macOS. We also extract the - // symbol name hash from the variable name rather than the data, since - // it's easier and both should match. - static RE: OnceLock = OnceLock::new(); - RE.get_or_init(|| { - Regex::new( - r#"^@__covrec_(?[0-9A-Z]+)(?u)? = .*\[[0-9]+ x i8\] c"(?[^"]*)".*$"#, - ) - .unwrap() - }) - }; +fn is_covfun_line(line: &str) -> bool { + line.starts_with("@__covrec_") +} - let captures = re.captures(line)?; - let name_hash = u64::from_str_radix(&captures["name_hash"], 16).unwrap(); +/// Given a line of LLVM IR assembly that should contain an `__llvm_covfun` +/// entry, parses it to extract relevant data in a `CovfunLineData`. +fn parse_covfun_line(line: &str) -> anyhow::Result { + ensure!(is_covfun_line(line)); + + // We cheat a little bit and match variable names `@__covrec_[HASH]u` + // rather than the section name, because the section name is harder to + // extract and differs across Linux/Windows/macOS. + const RE_STRING: &str = r#"(?x)^ + @__covrec_[0-9A-Z]+(?u)? + \ = \ # (trailing space) + .* + <\{ + \ i64 \ (? -? [0-9]+), + \ i32 \ -? [0-9]+, # (length of payload; currently unused) + \ i64 \ -? [0-9]+, # (source hash; currently unused) + \ i64 \ (? -? [0-9]+), + \ \[ [0-9]+ \ x \ i8 \] \ c"(?[^"]*)" + \ # (trailing space) + }> + .*$ + "#; + static RE: LazyLock = LazyLock::new(|| Regex::new(RE_STRING).unwrap()); + + let captures = + RE.captures(line).with_context(|| format!("couldn't parse covfun line: {line:?}"))?; let is_used = captures.name("is_used").is_some(); + let name_hash = i64::from_str_radix(&captures["name_hash"], 10).unwrap() as u64; + let filenames_hash = i64::from_str_radix(&captures["filenames_hash"], 10).unwrap() as u64; let payload = unescape_llvm_string_contents(&captures["payload"]); - Some(CovfunLineData { name_hash, is_used, payload }) + Ok(CovfunLineData { is_used, name_hash, filenames_hash, payload }) } // Extra parser methods only needed when parsing `covfun` payloads. diff --git a/src/tools/coverage-dump/src/covfun/tests.rs b/src/tools/coverage-dump/src/covfun/tests.rs new file mode 100644 index 000000000000..1ce833784bd4 --- /dev/null +++ b/src/tools/coverage-dump/src/covfun/tests.rs @@ -0,0 +1,53 @@ +use super::{CovfunLineData, parse_covfun_line}; + +/// Integers in LLVM IR are not inherently signed/unsigned, and the text format tends +/// to emit them in signed form, so this helper function converts `i64` to `u64`. +fn as_u64(x: i64) -> u64 { + x as u64 +} + +#[test] +fn parse_covfun_line_data() { + struct Case { + line: &'static str, + expected: CovfunLineData, + } + let cases = &[ + // Copied from `trivial.ll`: + Case { + line: r#"@__covrec_49A9BAAE5F896E81u = linkonce_odr hidden constant <{ i64, i32, i64, i64, [9 x i8] }> <{ i64 5307978893922758273, i32 9, i64 445092354169400020, i64 6343436898695299756, [9 x i8] c"\01\01\00\01\01\03\01\00\0D" }>, section "__LLVM_COV,__llvm_covfun", align 8"#, + expected: CovfunLineData { + is_used: true, + name_hash: as_u64(5307978893922758273), + filenames_hash: as_u64(6343436898695299756), + payload: b"\x01\x01\x00\x01\x01\x03\x01\x00\x0D".to_vec(), + }, + }, + // Copied from `on-off-sandwich.ll`: + Case { + line: r#"@__covrec_D0CE53C5E64F319Au = linkonce_odr hidden constant <{ i64, i32, i64, i64, [14 x i8] }> <{ i64 -3400688559180533350, i32 14, i64 7307957714577672185, i64 892196767019953100, [14 x i8] c"\01\01\00\02\01\10\05\02\10\01\07\05\00\06" }>, section "__LLVM_COV,__llvm_covfun", align 8"#, + expected: CovfunLineData { + is_used: true, + name_hash: as_u64(-3400688559180533350), + filenames_hash: as_u64(892196767019953100), + payload: b"\x01\x01\x00\x02\x01\x10\x05\x02\x10\x01\x07\x05\x00\x06".to_vec(), + }, + }, + // Copied from `no-core.ll`: + Case { + line: r#"@__covrec_F8016FC82D46106u = linkonce_odr hidden constant <{ i64, i32, i64, i64, [9 x i8] }> <{ i64 1116917981370409222, i32 9, i64 -8857254680411629915, i64 -3625186110715410276, [9 x i8] c"\01\01\00\01\01\0C\01\00\0D" }>, section "__LLVM_COV,__llvm_covfun", align 8"#, + expected: CovfunLineData { + is_used: true, + name_hash: as_u64(1116917981370409222), + filenames_hash: as_u64(-3625186110715410276), + payload: b"\x01\x01\x00\x01\x01\x0C\x01\x00\x0D".to_vec(), + }, + }, + ]; + + for &Case { line, ref expected } in cases { + println!("- {line}"); + let line_data = parse_covfun_line(line).map_err(|e| e.to_string()); + assert_eq!(line_data.as_ref(), Ok(expected)); + } +} diff --git a/src/tools/coverage-dump/src/covmap.rs b/src/tools/coverage-dump/src/covmap.rs new file mode 100644 index 000000000000..2246ca2d5757 --- /dev/null +++ b/src/tools/coverage-dump/src/covmap.rs @@ -0,0 +1,75 @@ +use std::collections::HashMap; +use std::sync::LazyLock; + +use anyhow::{Context, ensure}; +use regex::Regex; + +use crate::llvm_utils::{truncated_md5, unescape_llvm_string_contents}; +use crate::parser::Parser; + +#[derive(Debug, Default)] +pub(crate) struct FilenameTables { + map: HashMap>, +} + +impl FilenameTables { + pub(crate) fn lookup(&self, filenames_hash: u64, global_file_id: usize) -> Option<&str> { + let table = self.map.get(&filenames_hash)?; + let filename = table.get(global_file_id)?; + Some(filename) + } +} + +struct CovmapLineData { + payload: Vec, +} + +pub(crate) fn make_filename_tables(llvm_ir: &str) -> anyhow::Result { + let mut map = HashMap::default(); + + for line in llvm_ir.lines().filter(|line| is_covmap_line(line)) { + let CovmapLineData { payload } = parse_covmap_line(line)?; + + let mut parser = Parser::new(&payload); + let n_filenames = parser.read_uleb128_usize()?; + let uncompressed_bytes = parser.read_chunk_to_uncompressed_bytes()?; + parser.ensure_empty()?; + + let mut filenames_table = vec![]; + + let mut parser = Parser::new(&uncompressed_bytes); + for _ in 0..n_filenames { + let len = parser.read_uleb128_usize()?; + let bytes = parser.read_n_bytes(len)?; + let filename = str::from_utf8(bytes)?; + filenames_table.push(filename.to_owned()); + } + + let filenames_hash = truncated_md5(&payload); + map.insert(filenames_hash, filenames_table); + } + + Ok(FilenameTables { map }) +} + +fn is_covmap_line(line: &str) -> bool { + line.starts_with("@__llvm_coverage_mapping ") +} + +fn parse_covmap_line(line: &str) -> anyhow::Result { + ensure!(is_covmap_line(line)); + + const RE_STRING: &str = r#"(?x)^ + @__llvm_coverage_mapping \ = + .* + \[ [0-9]+ \ x \ i8 \] \ c"(?[^"]*)" + .*$ + "#; + static RE: LazyLock = LazyLock::new(|| Regex::new(RE_STRING).unwrap()); + + let captures = + RE.captures(line).with_context(|| format!("couldn't parse covmap line: {line:?}"))?; + let payload = unescape_llvm_string_contents(&captures["payload"]); + + Ok(CovmapLineData { payload }) +} diff --git a/src/tools/coverage-dump/src/llvm_utils.rs b/src/tools/coverage-dump/src/llvm_utils.rs new file mode 100644 index 000000000000..92322b256a82 --- /dev/null +++ b/src/tools/coverage-dump/src/llvm_utils.rs @@ -0,0 +1,85 @@ +use std::borrow::Cow; +use std::sync::OnceLock; + +use anyhow::{anyhow, ensure}; +use regex::bytes; + +use crate::parser::Parser; + +#[cfg(test)] +mod tests; + +/// Given the raw contents of a string literal in LLVM IR assembly, decodes any +/// backslash escapes and returns a vector containing the resulting byte string. +pub(crate) fn unescape_llvm_string_contents(contents: &str) -> Vec { + let escape_re = { + static RE: OnceLock = OnceLock::new(); + // LLVM IR supports two string escapes: `\\` and `\xx`. + RE.get_or_init(|| bytes::Regex::new(r"\\\\|\\([0-9A-Za-z]{2})").unwrap()) + }; + + fn u8_from_hex_digits(digits: &[u8]) -> u8 { + // We know that the input contains exactly 2 hex digits, so these calls + // should never fail. + assert_eq!(digits.len(), 2); + let digits = std::str::from_utf8(digits).unwrap(); + u8::from_str_radix(digits, 16).unwrap() + } + + escape_re + .replace_all(contents.as_bytes(), |captures: &bytes::Captures<'_>| { + let byte = match captures.get(1) { + None => b'\\', + Some(hex_digits) => u8_from_hex_digits(hex_digits.as_bytes()), + }; + [byte] + }) + .into_owned() +} + +/// LLVM's profiler/coverage metadata often uses an MD5 hash truncated to +/// 64 bits as a way to associate data stored in different tables/sections. +pub(crate) fn truncated_md5(bytes: &[u8]) -> u64 { + use md5::{Digest, Md5}; + let mut hasher = Md5::new(); + hasher.update(bytes); + let hash: [u8; 8] = hasher.finalize().as_slice()[..8].try_into().unwrap(); + // The truncated hash is explicitly little-endian, regardless of host + // or target platform. (See `MD5Result::low` in LLVM's `MD5.h`.) + u64::from_le_bytes(hash) +} + +impl<'a> Parser<'a> { + /// Reads a sequence of: + /// - Length of uncompressed data in bytes, as ULEB128 + /// - Length of compressed data in bytes (or 0), as ULEB128 + /// - The indicated number of compressed or uncompressed bytes + /// + /// If the number of compressed bytes is 0, the subsequent bytes are + /// uncompressed. Otherwise, the subsequent bytes are compressed, and will + /// be decompressed. + /// + /// Returns the uncompressed bytes that were read directly or decompressed. + pub(crate) fn read_chunk_to_uncompressed_bytes(&mut self) -> anyhow::Result> { + let uncompressed_len = self.read_uleb128_usize()?; + let compressed_len = self.read_uleb128_usize()?; + + if compressed_len == 0 { + // The bytes are uncompressed, so read them directly. + let uncompressed_bytes = self.read_n_bytes(uncompressed_len)?; + Ok(Cow::Borrowed(uncompressed_bytes)) + } else { + // The bytes are compressed, so read and decompress them. + let compressed_bytes = self.read_n_bytes(compressed_len)?; + + let uncompressed_bytes = miniz_oxide::inflate::decompress_to_vec_zlib_with_limit( + compressed_bytes, + uncompressed_len, + ) + .map_err(|e| anyhow!("{e:?}"))?; + ensure!(uncompressed_bytes.len() == uncompressed_len); + + Ok(Cow::Owned(uncompressed_bytes)) + } + } +} diff --git a/src/tools/coverage-dump/src/parser/tests.rs b/src/tools/coverage-dump/src/llvm_utils/tests.rs similarity index 80% rename from src/tools/coverage-dump/src/parser/tests.rs rename to src/tools/coverage-dump/src/llvm_utils/tests.rs index a673606b9c4c..506b0a6200bb 100644 --- a/src/tools/coverage-dump/src/parser/tests.rs +++ b/src/tools/coverage-dump/src/llvm_utils/tests.rs @@ -1,9 +1,5 @@ use super::unescape_llvm_string_contents; -// WARNING: These tests don't necessarily run in CI, and were mainly used to -// help track down problems when originally developing this tool. -// (The tool is still tested indirectly by snapshot tests that rely on it.) - // Tests for `unescape_llvm_string_contents`: #[test] diff --git a/src/tools/coverage-dump/src/main.rs b/src/tools/coverage-dump/src/main.rs index b21e3e292f2b..2c76d2f24602 100644 --- a/src/tools/coverage-dump/src/main.rs +++ b/src/tools/coverage-dump/src/main.rs @@ -1,4 +1,6 @@ mod covfun; +mod covmap; +mod llvm_utils; mod parser; mod prf_names; @@ -17,8 +19,9 @@ fn main() -> anyhow::Result<()> { let llvm_ir_path = args.get(1).context("LLVM IR file not specified")?; let llvm_ir = std::fs::read_to_string(llvm_ir_path).context("couldn't read LLVM IR file")?; + let filename_tables = covmap::make_filename_tables(&llvm_ir)?; let function_names = crate::prf_names::make_function_names_table(&llvm_ir)?; - crate::covfun::dump_covfun_mappings(&llvm_ir, &function_names)?; + crate::covfun::dump_covfun_mappings(&llvm_ir, &filename_tables, &function_names)?; Ok(()) } diff --git a/src/tools/coverage-dump/src/parser.rs b/src/tools/coverage-dump/src/parser.rs index 0bd4abdae3ef..f26a57b43b33 100644 --- a/src/tools/coverage-dump/src/parser.rs +++ b/src/tools/coverage-dump/src/parser.rs @@ -1,38 +1,4 @@ -#[cfg(test)] -mod tests; - -use std::sync::OnceLock; - use anyhow::ensure; -use regex::bytes; - -/// Given the raw contents of a string literal in LLVM IR assembly, decodes any -/// backslash escapes and returns a vector containing the resulting byte string. -pub(crate) fn unescape_llvm_string_contents(contents: &str) -> Vec { - let escape_re = { - static RE: OnceLock = OnceLock::new(); - // LLVM IR supports two string escapes: `\\` and `\xx`. - RE.get_or_init(|| bytes::Regex::new(r"\\\\|\\([0-9A-Za-z]{2})").unwrap()) - }; - - fn u8_from_hex_digits(digits: &[u8]) -> u8 { - // We know that the input contains exactly 2 hex digits, so these calls - // should never fail. - assert_eq!(digits.len(), 2); - let digits = std::str::from_utf8(digits).unwrap(); - u8::from_str_radix(digits, 16).unwrap() - } - - escape_re - .replace_all(contents.as_bytes(), |captures: &bytes::Captures<'_>| { - let byte = match captures.get(1) { - None => b'\\', - Some(hex_digits) => u8_from_hex_digits(hex_digits.as_bytes()), - }; - [byte] - }) - .into_owned() -} pub(crate) struct Parser<'a> { rest: &'a [u8], diff --git a/src/tools/coverage-dump/src/prf_names.rs b/src/tools/coverage-dump/src/prf_names.rs index 96d097c79a31..f9ab35deba50 100644 --- a/src/tools/coverage-dump/src/prf_names.rs +++ b/src/tools/coverage-dump/src/prf_names.rs @@ -1,10 +1,10 @@ use std::collections::HashMap; use std::sync::OnceLock; -use anyhow::{anyhow, ensure}; use regex::Regex; -use crate::parser::{Parser, unescape_llvm_string_contents}; +use crate::llvm_utils::{truncated_md5, unescape_llvm_string_contents}; +use crate::parser::Parser; /// Scans through the contents of an LLVM IR assembly file to find `__llvm_prf_names` /// entries, decodes them, and creates a table that maps name hash values to @@ -25,18 +25,6 @@ pub(crate) fn make_function_names_table(llvm_ir: &str) -> anyhow::Result u64 { - use md5::{Digest, Md5}; - let mut hasher = Md5::new(); - hasher.update(bytes); - let hash: [u8; 8] = hasher.finalize().as_slice()[..8].try_into().unwrap(); - // The truncated hash is explicitly little-endian, regardless of host - // or target platform. (See `MD5Result::low` in LLVM's `MD5.h`.) - u64::from_le_bytes(hash) - } - fn demangle_if_able(symbol_name_bytes: &[u8]) -> anyhow::Result { // In practice, raw symbol names should always be ASCII. let symbol_name_str = std::str::from_utf8(symbol_name_bytes)?; @@ -54,26 +42,8 @@ pub(crate) fn make_function_names_table(llvm_ir: &str) -> anyhow::Result anyhow::Result LintExtractor<'a> { if matches!( lint.name.as_str(), "unused_features" // broken lint + | "soft_unstable" // cannot have a stable example ) { return Ok(()); } diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 97bc826b57a4..9afbd3aa6357 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -2ad5f8607d0e192b60b130e5cc416b477b351c18 +fd9fad6dbcc1bae3cba2a8634339ffa620a49f28 diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs index 7aaf9c2624f9..731d8b577637 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs @@ -1,5 +1,6 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 +#![allow(unnecessary_transmutes)] #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml index cea234cc74cb..dfa884bc3f77 100644 --- a/src/tools/opt-dist/Cargo.toml +++ b/src/tools/opt-dist/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "opt-dist" version = "0.1.0" -edition = "2021" +edition = "2024" [dependencies] build_helper = { path = "../../build_helper" } @@ -10,12 +10,11 @@ log = "0.4" anyhow = "1" humantime = "2" humansize = "2" -sysinfo = { version = "0.31.2", default-features = false, features = ["disk"] } +sysinfo = { version = "0.35.0", default-features = false, features = ["disk"] } fs_extra = "1" camino = "1" tar = "0.4" xz = { version = "0.1", package = "xz2" } -serde = { version = "1", features = ["derive"] } serde_json = "1" glob = "0.3" tempfile = "3.5" diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs index 9342d164be41..946e926a3c01 100644 --- a/src/tools/opt-dist/src/environment.rs +++ b/src/tools/opt-dist/src/environment.rs @@ -26,6 +26,7 @@ pub struct Environment { use_bolt: bool, shared_llvm: bool, run_tests: bool, + fast_try_build: bool, } impl Environment { @@ -106,6 +107,10 @@ impl Environment { pub fn run_tests(&self) -> bool { self.run_tests } + + pub fn is_fast_try_build(&self) -> bool { + self.fast_try_build + } } /// What is the extension of binary executables on this platform? diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs index deff69a7f9c0..64ce5cc37752 100644 --- a/src/tools/opt-dist/src/exec.rs +++ b/src/tools/opt-dist/src/exec.rs @@ -113,13 +113,16 @@ impl Bootstrap { "library/std", ]) .env("RUST_BACKTRACE", "full"); + let cmd = add_shared_x_flags(env, cmd); + Self { cmd, metrics_path } } pub fn dist(env: &Environment, dist_args: &[String]) -> Self { let metrics_path = env.build_root().join("build").join("metrics.json"); - let cmd = cmd(&dist_args.iter().map(|arg| arg.as_str()).collect::>()) - .env("RUST_BACKTRACE", "full"); + let args = dist_args.iter().map(|arg| arg.as_str()).collect::>(); + let cmd = cmd(&args).env("RUST_BACKTRACE", "full"); + let cmd = add_shared_x_flags(env, cmd); Self { cmd, metrics_path } } @@ -184,3 +187,7 @@ impl Bootstrap { Ok(()) } } + +fn add_shared_x_flags(env: &Environment, cmd: CmdBuilder) -> CmdBuilder { + if env.is_fast_try_build() { cmd.arg("--set").arg("rust.deny-warnings=false") } else { cmd } +} diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index d5e6640fb430..d2827ec01ca7 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -95,7 +95,7 @@ enum EnvironmentCmd { #[arg(long)] benchmark_cargo_config: Vec, - /// Perform tests after final build if it's not a try build + /// Perform tests after final build if it's not a fast try build #[arg(long)] run_tests: bool, }, @@ -111,11 +111,14 @@ enum EnvironmentCmd { }, } -fn is_try_build() -> bool { +/// For a fast try build, we want to only build the bare minimum of components to get a +/// working toolchain, and not run any tests. +fn is_fast_try_build() -> bool { std::env::var("DIST_TRY_BUILD").unwrap_or_else(|_| "0".to_string()) != "0" } fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> { + let is_fast_try_build = is_fast_try_build(); let (env, args) = match args.env { EnvironmentCmd::Local { target_triple, @@ -144,6 +147,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .skipped_tests(skipped_tests) .benchmark_cargo_config(benchmark_cargo_config) .run_tests(run_tests) + .fast_try_build(is_fast_try_build) .build()?; (env, shared.build_args) @@ -167,6 +171,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .use_bolt(!is_aarch64) .skipped_tests(vec![]) .run_tests(true) + .fast_try_build(is_fast_try_build) .build()?; (env, shared.build_args) @@ -187,6 +192,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .use_bolt(false) .skipped_tests(vec![]) .run_tests(true) + .fast_try_build(is_fast_try_build) .build()?; (env, shared.build_args) @@ -350,9 +356,8 @@ fn execute_pipeline( // After dist has finished, run a subset of the test suite on the optimized artifacts to discover // possible regressions. - // The tests are not executed for try builds, which can be in various broken states, so we don't - // want to gatekeep them with tests. - if !is_try_build() && env.run_tests() { + // The tests are not executed for fast try builds, which can be broken and might not pass them. + if !is_fast_try_build() && env.run_tests() { timer.section("Run tests", |_| run_tests(env))?; } @@ -361,7 +366,10 @@ fn execute_pipeline( fn main() -> anyhow::Result<()> { // Make sure that we get backtraces for easier debugging in CI - std::env::set_var("RUST_BACKTRACE", "1"); + unsafe { + // SAFETY: we are the only thread running at this point + std::env::set_var("RUST_BACKTRACE", "1"); + } env_logger::builder() .filter_level(LevelFilter::Info) @@ -393,9 +401,9 @@ fn main() -> anyhow::Result<()> { let (env, mut build_args) = create_environment(args).context("Cannot create environment")?; - // Skip components that are not needed for try builds to speed them up - if is_try_build() { - log::info!("Skipping building of unimportant components for a try build"); + // Skip components that are not needed for fast try builds to speed them up + if is_fast_try_build() { + log::info!("Skipping building of unimportant components for a fast try build"); for target in [ "rust-docs", "rustc-docs", diff --git a/src/tools/run-make-support/src/external_deps/cargo.rs b/src/tools/run-make-support/src/external_deps/cargo.rs index e91d101cb995..8da9f002c41b 100644 --- a/src/tools/run-make-support/src/external_deps/cargo.rs +++ b/src/tools/run-make-support/src/external_deps/cargo.rs @@ -1,8 +1,11 @@ use crate::command::Command; use crate::env_var; +use crate::util::set_host_compiler_dylib_path; /// Returns a command that can be used to invoke cargo. The cargo is provided by compiletest /// through the `CARGO` env var. pub fn cargo() -> Command { - Command::new(env_var("CARGO")) + let mut cmd = Command::new(env_var("CARGO")); + set_host_compiler_dylib_path(&mut cmd); + cmd } diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 9f6b80c63790..8d6c8284e44e 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -85,6 +85,7 @@ dependencies = [ "query-group-macro", "rustc-hash 2.1.1", "salsa", + "salsa-macros", "semver", "span", "syntax", @@ -630,6 +631,7 @@ dependencies = [ "rustc-hash 2.1.1", "rustc_apfloat", "salsa", + "salsa-macros", "smallvec", "span", "stdx", @@ -660,6 +662,7 @@ dependencies = [ "query-group-macro", "rustc-hash 2.1.1", "salsa", + "salsa-macros", "smallvec", "span", "stdx", @@ -700,6 +703,7 @@ dependencies = [ "rustc-hash 2.1.1", "rustc_apfloat", "salsa", + "salsa-macros", "scoped-tls", "smallvec", "span", @@ -936,6 +940,7 @@ dependencies = [ "rayon", "rustc-hash 2.1.1", "salsa", + "salsa-macros", "span", "stdx", "syntax", @@ -1729,6 +1734,7 @@ dependencies = [ "proc-macro2", "quote", "salsa", + "salsa-macros", "syn", ] @@ -2033,9 +2039,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be22155f8d9732518b2db2bf379fe6f0b2375e76b08b7c8fe6c1b887d548c24" +checksum = "6f80d5cf3c3fcab2cef898012f242a670477a1baa609267376af9cb4409026c5" dependencies = [ "boxcar", "crossbeam-queue", @@ -2056,15 +2062,15 @@ dependencies = [ [[package]] name = "salsa-macro-rules" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55a7ef0a84e336f7c5f0332d81727f5629fe042d2aa556c75307afebc9f78a5" +checksum = "05303d72606fbf2b9c9523cda2039bb8ecb00304027a3cd7e52b02a65c7d9185" [[package]] name = "salsa-macros" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d0e88a9c0c0d231a63f83dcd1a2c5e5d11044fac4b65bc9ad3b68ab48b0a0ab" +checksum = "eb2f0e2a30c65cb3cd63440c491dde68d9af7e1be2b77832ac7057141107db50" dependencies = [ "heck", "proc-macro2", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 6fa171702dd4..c4c2fdf34bae 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -131,7 +131,9 @@ process-wrap = { version = "8.2.0", features = ["std"] } pulldown-cmark-to-cmark = "10.0.4" pulldown-cmark = { version = "0.9.6", default-features = false } rayon = "1.10.0" -salsa = "0.20.0" +rowan = "=0.15.15" +salsa = { version = "0.21.1", default-features = false, features = ["rayon","salsa_unstable"] } +salsa-macros = "0.21.1" semver = "1.0.26" serde = { version = "1.0.219" } serde_derive = { version = "1.0.219" } diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml index 441434504c29..e2e3253773fe 100644 --- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml @@ -15,6 +15,7 @@ rust-version.workspace = true la-arena.workspace = true dashmap.workspace = true salsa.workspace = true +salsa-macros.workspace = true query-group.workspace = true rustc-hash.workspace = true triomphe.workspace = true diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 499c9b3716b2..9660e6e87cca 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -392,7 +392,7 @@ impl BuiltDependency { pub type CratesIdMap = FxHashMap; -#[salsa::input] +#[salsa_macros::input] #[derive(Debug)] pub struct Crate { #[return_ref] diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index 7f7a712577e4..a67fbf75c02f 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -1,9 +1,13 @@ //! base_db defines basic database traits. The concrete DB is defined by ide. + +pub use salsa; +pub use salsa_macros; + // FIXME: Rename this crate, base db is non descriptive mod change; mod input; -use std::hash::BuildHasherDefault; +use std::{cell::RefCell, hash::BuildHasherDefault, panic, sync::Once}; pub use crate::{ change::FileChange, @@ -17,7 +21,6 @@ pub use crate::{ use dashmap::{DashMap, mapref::entry::Entry}; pub use query_group::{self}; use rustc_hash::{FxHashSet, FxHasher}; -pub use salsa::{self}; use salsa::{Durability, Setter}; pub use semver::{BuildMetadata, Prerelease, Version, VersionReq}; use span::Edition; @@ -28,7 +31,7 @@ pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet} #[macro_export] macro_rules! impl_intern_key { ($id:ident, $loc:ident) => { - #[salsa::interned(no_lifetime)] + #[salsa_macros::interned(no_lifetime)] pub struct $id { pub loc: $loc, } @@ -57,7 +60,12 @@ pub struct Files { impl Files { pub fn file_text(&self, file_id: vfs::FileId) -> FileText { - *self.files.get(&file_id).expect("Unable to fetch file; this is a bug") + match self.files.get(&file_id) { + Some(text) => *text, + None => { + panic!("Unable to fetch file text for `vfs::FileId`: {file_id:?}; this is a bug") + } + } } pub fn set_file_text(&self, db: &mut dyn SourceDatabase, file_id: vfs::FileId, text: &str) { @@ -93,10 +101,12 @@ impl Files { /// Source root of the file. pub fn source_root(&self, source_root_id: SourceRootId) -> SourceRootInput { - let source_root = self - .source_roots - .get(&source_root_id) - .expect("Unable to fetch source root id; this is a bug"); + let source_root = match self.source_roots.get(&source_root_id) { + Some(source_root) => source_root, + None => panic!( + "Unable to fetch `SourceRootInput` with `SourceRootId` ({source_root_id:?}); this is a bug" + ), + }; *source_root } @@ -121,10 +131,12 @@ impl Files { } pub fn file_source_root(&self, id: vfs::FileId) -> FileSourceRootInput { - let file_source_root = self - .file_source_roots - .get(&id) - .expect("Unable to fetch FileSourceRootInput; this is a bug"); + let file_source_root = match self.file_source_roots.get(&id) { + Some(file_source_root) => file_source_root, + None => panic!( + "Unable to get `FileSourceRootInput` with `vfs::FileId` ({id:?}); this is a bug", + ), + }; *file_source_root } @@ -152,7 +164,7 @@ impl Files { } } -#[salsa::interned(no_lifetime, debug, constructor=from_span)] +#[salsa_macros::interned(no_lifetime, debug, constructor=from_span)] pub struct EditionedFileId { pub editioned_file_id: span::EditionedFileId, } @@ -187,18 +199,18 @@ impl EditionedFileId { } } -#[salsa::input(debug)] +#[salsa_macros::input(debug)] pub struct FileText { pub text: Arc, pub file_id: vfs::FileId, } -#[salsa::input(debug)] +#[salsa_macros::input(debug)] pub struct FileSourceRootInput { pub source_root_id: SourceRootId, } -#[salsa::input(debug)] +#[salsa_macros::input(debug)] pub struct SourceRootInput { pub source_root: Arc, } @@ -265,7 +277,7 @@ pub fn transitive_deps(db: &dyn SourceDatabase, crate_id: Crate) -> FxHashSet FileText; @@ -344,7 +356,7 @@ fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse Option<&[SyntaxError]> { - #[salsa::tracked(return_ref)] + #[salsa_macros::tracked(return_ref)] fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option> { let errors = db.parse(file_id).errors(); match &*errors { @@ -373,3 +385,49 @@ fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[Crate]> { let source_root = db.file_source_root(file_id); db.source_root_crates(source_root.source_root_id(db)) } + +#[must_use] +#[non_exhaustive] +pub struct DbPanicContext; + +impl Drop for DbPanicContext { + fn drop(&mut self) { + Self::with_ctx(|ctx| assert!(ctx.pop().is_some())); + } +} + +impl DbPanicContext { + pub fn enter(frame: String) -> DbPanicContext { + #[expect(clippy::print_stderr, reason = "already panicking anyway")] + fn set_hook() { + let default_hook = panic::take_hook(); + panic::set_hook(Box::new(move |panic_info| { + default_hook(panic_info); + if let Some(backtrace) = salsa::Backtrace::capture() { + eprintln!("{backtrace:#}"); + } + DbPanicContext::with_ctx(|ctx| { + if !ctx.is_empty() { + eprintln!("additional context:"); + for (idx, frame) in ctx.iter().enumerate() { + eprintln!("{idx:>4}: {frame}\n"); + } + } + }); + })); + } + + static SET_HOOK: Once = Once::new(); + SET_HOOK.call_once(set_hook); + + Self::with_ctx(|ctx| ctx.push(frame)); + DbPanicContext + } + + fn with_ctx(f: impl FnOnce(&mut Vec)) { + thread_local! { + static CTX: RefCell> = const { RefCell::new(Vec::new()) }; + } + CTX.with(|ctx| f(&mut ctx.borrow_mut())); + } +} diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index f97597ffe5a6..c1c89e8d1cc3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -28,6 +28,7 @@ triomphe.workspace = true rustc_apfloat = "0.2.2" text-size.workspace = true salsa.workspace = true +salsa-macros.workspace = true query-group.workspace = true ra-ap-rustc_parse_format.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index a80313aba3e4..bb6222b1d464 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -1,6 +1,6 @@ //! A higher level attributes based on TokenTree, with also some shortcuts. -use std::{borrow::Cow, hash::Hash, ops}; +use std::{borrow::Cow, convert::identity, hash::Hash, ops}; use base_db::Crate; use cfg::{CfgExpr, CfgOptions}; @@ -8,6 +8,7 @@ use either::Either; use hir_expand::{ HirFileId, InFile, attrs::{Attr, AttrId, RawAttrs, collect_attrs}, + span_map::SpanMapRef, }; use intern::{Symbol, sym}; use la_arena::{ArenaMap, Idx, RawIdx}; @@ -45,8 +46,27 @@ impl Attrs { (**self).iter().find(|attr| attr.id == id) } - pub(crate) fn filter(db: &dyn DefDatabase, krate: Crate, raw_attrs: RawAttrs) -> Attrs { - Attrs(raw_attrs.filter(db, krate)) + pub(crate) fn expand_cfg_attr( + db: &dyn DefDatabase, + krate: Crate, + raw_attrs: RawAttrs, + ) -> Attrs { + Attrs(raw_attrs.expand_cfg_attr(db, krate)) + } + + pub(crate) fn is_cfg_enabled_for( + db: &dyn DefDatabase, + owner: &dyn ast::HasAttrs, + span_map: SpanMapRef<'_>, + cfg_options: &CfgOptions, + ) -> Result<(), CfgExpr> { + RawAttrs::attrs_iter_expanded::(db, owner, span_map, cfg_options) + .filter_map(|attr| attr.cfg()) + .find_map(|cfg| match cfg_options.check(&cfg).is_none_or(identity) { + true => None, + false => Some(cfg), + }) + .map_or(Ok(()), Err) } } @@ -522,38 +542,41 @@ impl AttrsWithOwner { GenericParamId::ConstParamId(it) => { let src = it.parent().child_source(db); // FIXME: We should be never getting `None` here. - match src.value.get(it.local_id()) { - Some(val) => RawAttrs::from_attrs_owner( + return Attrs(match src.value.get(it.local_id()) { + Some(val) => RawAttrs::new_expanded( db, - src.with_value(val), + val, db.span_map(src.file_id).as_ref(), + def.krate(db).cfg_options(db), ), None => RawAttrs::EMPTY, - } + }); } GenericParamId::TypeParamId(it) => { let src = it.parent().child_source(db); // FIXME: We should be never getting `None` here. - match src.value.get(it.local_id()) { - Some(val) => RawAttrs::from_attrs_owner( + return Attrs(match src.value.get(it.local_id()) { + Some(val) => RawAttrs::new_expanded( db, - src.with_value(val), + val, db.span_map(src.file_id).as_ref(), + def.krate(db).cfg_options(db), ), None => RawAttrs::EMPTY, - } + }); } GenericParamId::LifetimeParamId(it) => { let src = it.parent.child_source(db); // FIXME: We should be never getting `None` here. - match src.value.get(it.local_id) { - Some(val) => RawAttrs::from_attrs_owner( + return Attrs(match src.value.get(it.local_id) { + Some(val) => RawAttrs::new_expanded( db, - src.with_value(val), + val, db.span_map(src.file_id).as_ref(), + def.krate(db).cfg_options(db), ), None => RawAttrs::EMPTY, - } + }); } }, AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it), @@ -561,7 +584,7 @@ impl AttrsWithOwner { AttrDefId::UseId(it) => attrs_from_item_tree_loc(db, it), }; - let attrs = raw_attrs.filter(db, def.krate(db)); + let attrs = raw_attrs.expand_cfg_attr(db, def.krate(db)); Attrs(attrs) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 34cf42d02bdb..2cbdbe16f9bb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -22,7 +22,7 @@ use crate::{ hir::generics::GenericParams, import_map::ImportMap, item_tree::{AttrOwner, ItemTree}, - lang_item::{self, LangItem, LangItemTarget, LangItems}, + lang_item::{self, LangItem}, nameres::{ DefMap, LocalDefMap, assoc::{ImplItems, TraitItems}, @@ -325,9 +325,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { // endregion:attrs - #[salsa::invoke(LangItems::lang_item_query)] - fn lang_item(&self, start_crate: Crate, item: LangItem) -> Option; - #[salsa::invoke(ImportMap::import_map_query)] fn import_map(&self, krate: Crate) -> Arc; @@ -349,9 +346,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { // endregion:visibilities - #[salsa::invoke(LangItems::crate_lang_items_query)] - fn crate_lang_items(&self, krate: Crate) -> Option>; - #[salsa::invoke(crate::lang_item::notable_traits_in_deps)] fn notable_traits_in_deps(&self, krate: Crate) -> Arc<[Arc<[TraitId]>]>; #[salsa::invoke(crate::lang_item::crate_notable_traits)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs index 7eec913dd654..3823fb5a1e75 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs @@ -3,21 +3,24 @@ use std::mem; use base_db::Crate; +use cfg::CfgOptions; use drop_bomb::DropBomb; +use hir_expand::AstId; use hir_expand::{ ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId, - attrs::RawAttrs, eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap, + eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap, }; use span::{AstIdMap, Edition, SyntaxContext}; use syntax::ast::HasAttrs; -use syntax::{Parse, ast}; +use syntax::{AstNode, Parse, ast}; use triomphe::Arc; use tt::TextRange; use crate::attr::Attrs; use crate::expr_store::HygieneId; +use crate::macro_call_as_call_id; use crate::nameres::DefMap; -use crate::{AsMacroCall, MacroId, UnresolvedMacro, db::DefDatabase}; +use crate::{MacroId, UnresolvedMacro, db::DefDatabase}; #[derive(Debug)] pub(super) struct Expander { @@ -64,22 +67,13 @@ impl Expander { } } - pub(super) fn attrs( - &self, - db: &dyn DefDatabase, - krate: Crate, - has_attrs: &dyn HasAttrs, - ) -> Attrs { - Attrs::filter(db, krate, RawAttrs::new(db, has_attrs, self.span_map.as_ref())) - } - pub(super) fn is_cfg_enabled( &self, db: &dyn DefDatabase, - krate: Crate, has_attrs: &dyn HasAttrs, - ) -> bool { - self.attrs(db, krate, has_attrs).is_cfg_enabled(krate.cfg_options(db)) + cfg_options: &CfgOptions, + ) -> Result<(), cfg::CfgExpr> { + Attrs::is_cfg_enabled_for(db, has_attrs, self.span_map.as_ref(), cfg_options) } pub(super) fn call_syntax_ctx(&self) -> SyntaxContext { @@ -100,8 +94,31 @@ impl Expander { let result = self.within_limit(db, |this| { let macro_call = this.in_file(¯o_call); - match macro_call.as_call_id_with_errors( + + let expands_to = hir_expand::ExpandTo::from_call_site(macro_call.value); + let ast_id = AstId::new(macro_call.file_id, this.ast_id_map().ast_id(macro_call.value)); + let path = macro_call.value.path().and_then(|path| { + let range = path.syntax().text_range(); + let mod_path = ModPath::from_src(db, path, &mut |range| { + this.span_map.span_for_range(range).ctx + })?; + let call_site = this.span_map.span_for_range(range); + Some((call_site, mod_path)) + }); + + let Some((call_site, path)) = path else { + return ExpandResult::only_err(ExpandError::other( + this.span_map.span_for_range(macro_call.value.syntax().text_range()), + "malformed macro invocation", + )); + }; + + match macro_call_as_call_id( db, + ast_id, + &path, + call_site.ctx, + expands_to, krate, |path| resolver(path).map(|it| db.macro_def(it)), eager_callback, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 7f907fdba8e3..50505d54ba2f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -7,6 +7,7 @@ mod path; use std::mem; +use cfg::CfgOptions; use either::Either; use hir_expand::{ HirFileId, InFile, Lookup, MacroDefId, @@ -81,8 +82,6 @@ pub(super) fn lower_body( // even though they should be the same. Also, when the body comes from multiple expansions, their // hygiene is different. - let krate = module.krate(); - let mut self_param = None; let mut source_map_self_param = None; let mut params = vec![]; @@ -100,9 +99,8 @@ pub(super) fn lower_body( // and skip the body. if skip_body { if let Some(param_list) = parameters { - if let Some(self_param_syn) = param_list - .self_param() - .filter(|self_param| collector.expander.is_cfg_enabled(db, krate, self_param)) + if let Some(self_param_syn) = + param_list.self_param().filter(|self_param| collector.check_cfg(self_param)) { let is_mutable = self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none(); @@ -119,10 +117,7 @@ pub(super) fn lower_body( source_map_self_param = Some(collector.expander.in_file(AstPtr::new(&self_param_syn))); } - let count = param_list - .params() - .filter(|it| collector.expander.is_cfg_enabled(db, krate, it)) - .count(); + let count = param_list.params().filter(|it| collector.check_cfg(it)).count(); params = (0..count).map(|_| collector.missing_pat()).collect(); }; let body_expr = collector.missing_expr(); @@ -138,9 +133,7 @@ pub(super) fn lower_body( } if let Some(param_list) = parameters { - if let Some(self_param_syn) = - param_list.self_param().filter(|it| collector.expander.is_cfg_enabled(db, krate, it)) - { + if let Some(self_param_syn) = param_list.self_param().filter(|it| collector.check_cfg(it)) { let is_mutable = self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none(); let hygiene = self_param_syn @@ -157,7 +150,7 @@ pub(super) fn lower_body( } for param in param_list.params() { - if collector.expander.is_cfg_enabled(db, krate, ¶m) { + if collector.check_cfg(¶m) { let param_pat = collector.collect_pat_top(param.pat()); params.push(param_pat); } @@ -346,7 +339,7 @@ pub(crate) fn lower_function( collector.collect_impl_trait(&mut expr_collector, |collector, mut impl_trait_lower_fn| { if let Some(param_list) = fn_.value.param_list() { if let Some(param) = param_list.self_param() { - let enabled = collector.expander.is_cfg_enabled(db, module.krate(), ¶m); + let enabled = collector.check_cfg(¶m); if enabled { has_self_param = true; params.push(match param.ty() { @@ -381,7 +374,7 @@ pub(crate) fn lower_function( } let p = param_list .params() - .filter(|param| collector.expander.is_cfg_enabled(db, module.krate(), param)) + .filter(|param| collector.check_cfg(param)) .filter(|param| { let is_variadic = param.dotdotdot_token().is_some(); has_variadic |= is_variadic; @@ -441,6 +434,7 @@ pub(crate) fn lower_function( pub struct ExprCollector<'db> { db: &'db dyn DefDatabase, + cfg_options: &'db CfgOptions, expander: Expander, def_map: Arc, local_def_map: Arc, @@ -553,6 +547,7 @@ impl ExprCollector<'_> { let expander = Expander::new(db, current_file_id, &def_map); ExprCollector { db, + cfg_options: module.krate().cfg_options(db), module, def_map, local_def_map, @@ -1026,7 +1021,9 @@ impl ExprCollector<'_> { /// Returns `None` if and only if the expression is `#[cfg]`d out. fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option { let syntax_ptr = AstPtr::new(&expr); - self.check_cfg(&expr)?; + if !self.check_cfg(&expr) { + return None; + } // FIXME: Move some of these arms out into separate methods for clarity Some(match expr { @@ -1114,6 +1111,7 @@ impl ExprCollector<'_> { ast::Expr::WhileExpr(e) => self.collect_while_loop(syntax_ptr, e), ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e), ast::Expr::CallExpr(e) => { + // FIXME: Remove this once we drop support for <1.86, https://github.com/rust-lang/rust/commit/ac9cb908ac4301dfc25e7a2edee574320022ae2c let is_rustc_box = { let attrs = e.attrs(); attrs.filter_map(|it| it.as_simple_atom()).any(|it| it == "rustc_box") @@ -1156,13 +1154,17 @@ impl ExprCollector<'_> { match_arm_list .arms() .filter_map(|arm| { - self.check_cfg(&arm).map(|()| MatchArm { - pat: self.collect_pat_top(arm.pat()), - expr: self.collect_expr_opt(arm.expr()), - guard: arm - .guard() - .map(|guard| self.collect_expr_opt(guard.condition())), - }) + if self.check_cfg(&arm) { + Some(MatchArm { + pat: self.collect_pat_top(arm.pat()), + expr: self.collect_expr_opt(arm.expr()), + guard: arm + .guard() + .map(|guard| self.collect_expr_opt(guard.condition())), + }) + } else { + None + } }) .collect() } else { @@ -1230,7 +1232,9 @@ impl ExprCollector<'_> { let fields = nfl .fields() .filter_map(|field| { - self.check_cfg(&field)?; + if !self.check_cfg(&field) { + return None; + } let name = field.field_name()?.as_name(); @@ -1483,7 +1487,9 @@ impl ExprCollector<'_> { } fn maybe_collect_expr_as_pat(&mut self, expr: &ast::Expr) -> Option { - self.check_cfg(expr)?; + if !self.check_cfg(expr) { + return None; + } let syntax_ptr = AstPtr::new(expr); let result = match expr { @@ -1558,7 +1564,9 @@ impl ExprCollector<'_> { let args = record_field_list .fields() .filter_map(|f| { - self.check_cfg(&f)?; + if !self.check_cfg(&f) { + return None; + } let field_expr = f.expr()?; let pat = self.collect_expr_as_pat(field_expr); let name = f.field_name()?.as_name(); @@ -2044,7 +2052,7 @@ impl ExprCollector<'_> { fn collect_stmt(&mut self, statements: &mut Vec, s: ast::Stmt) { match s { ast::Stmt::LetStmt(stmt) => { - if self.check_cfg(&stmt).is_none() { + if !self.check_cfg(&stmt) { return; } let pat = self.collect_pat_top(stmt.pat()); @@ -2059,7 +2067,7 @@ impl ExprCollector<'_> { ast::Stmt::ExprStmt(stmt) => { let expr = stmt.expr(); match &expr { - Some(expr) if self.check_cfg(expr).is_none() => return, + Some(expr) if !self.check_cfg(expr) => return, _ => (), } let has_semi = stmt.semicolon_token().is_some(); @@ -2074,7 +2082,7 @@ impl ExprCollector<'_> { } } ast::Stmt::Item(ast::Item::MacroDef(macro_)) => { - if self.check_cfg(¯o_).is_none() { + if !self.check_cfg(¯o_) { return; } let Some(name) = macro_.name() else { @@ -2086,7 +2094,7 @@ impl ExprCollector<'_> { self.collect_macro_def(statements, macro_id); } ast::Stmt::Item(ast::Item::MacroRules(macro_)) => { - if self.check_cfg(¯o_).is_none() { + if !self.check_cfg(¯o_) { return; } let Some(name) = macro_.name() else { @@ -2360,7 +2368,9 @@ impl ExprCollector<'_> { let args = record_pat_field_list .fields() .filter_map(|f| { - self.check_cfg(&f)?; + if !self.check_cfg(&f) { + return None; + } let ast_pat = f.pat()?; let pat = self.collect_pat(ast_pat, binding_list); let name = f.field_name()?.as_name(); @@ -2536,25 +2546,18 @@ impl ExprCollector<'_> { /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when /// not. - fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> Option<()> { - let attrs = self.expander.attrs(self.db, self.module.krate(), owner); - match attrs.cfg() { - Some(cfg) => { - let cfg_options = self.module.krate().cfg_options(self.db); - - if cfg_options.check(&cfg) != Some(false) { - return Some(()); - } - + fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> bool { + let enabled = self.expander.is_cfg_enabled(self.db, owner, self.cfg_options); + match enabled { + Ok(()) => true, + Err(cfg) => { self.source_map.diagnostics.push(ExpressionStoreDiagnostics::InactiveCode { node: self.expander.in_file(SyntaxNodePtr::new(owner.syntax())), cfg, - opts: cfg_options.clone(), + opts: self.cfg_options.clone(), }); - - None + false } - None => Some(()), } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs index 9ef03065651a..d36e5205c739 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs @@ -224,7 +224,7 @@ impl ExprCollector<'_> { curarg = parser.curarg; - let to_span = |inner_span: rustc_parse_format::InnerSpan| { + let to_span = |inner_span: std::ops::Range| { is_direct_literal.then(|| { TextRange::new( inner_span.start.try_into().unwrap(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs index 9485e703d9cb..02a1d274fb5e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs @@ -110,7 +110,7 @@ impl GenericParamsCollector { fn lower_param_list(&mut self, ec: &mut ExprCollector<'_>, params: ast::GenericParamList) { for generic_param in params.generic_params() { - let enabled = ec.expander.is_cfg_enabled(ec.db, ec.module.krate(), &generic_param); + let enabled = ec.check_cfg(&generic_param); if !enabled { continue; } @@ -270,7 +270,7 @@ impl GenericParamsCollector { let self_ = Name::new_symbol_root(sym::Self_); let idx = self.type_or_consts.alloc( TypeParamData { - name: Some(self_.clone()), + name: Some(self_), default: None, provenance: TypeParamProvenance::TraitSelf, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index 2fd21bb0ed3a..f27a4062a63b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -214,7 +214,7 @@ pub(crate) fn parse( }; } - let to_span = |inner_span: parse::InnerSpan| { + let to_span = |inner_span: std::ops::Range| { is_source_literal.then(|| { TextRange::new(inner_span.start.try_into().unwrap(), inner_span.end.try_into().unwrap()) }) @@ -297,7 +297,7 @@ pub(crate) fn parse( unfinished_literal.clear(); } - let span = parser.arg_places.get(placeholder_index).and_then(|&s| to_span(s)); + let span = parser.arg_places.get(placeholder_index).and_then(|s| to_span(s.clone())); placeholder_index += 1; let position_span = to_span(position_span); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index bece940950d8..5362c0588dbe 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -167,7 +167,7 @@ pub struct ItemScope { // the resolutions of the imports of this scope use_imports_types: FxHashMap, use_imports_values: FxHashMap, - use_imports_macros: FxHashMap, + use_imports_macros: FxHashMap, use_decls: Vec, extern_crate_decls: Vec, @@ -242,7 +242,7 @@ impl ItemScope { self.types.iter().map(|(n, &i)| (n, i)) } - pub fn macros(&self) -> impl Iterator)> + '_ { + pub fn macros(&self) -> impl Iterator)> + '_ { self.macros.iter().map(|(n, &i)| (n, i)) } @@ -250,9 +250,9 @@ impl ItemScope { self.use_imports_types .keys() .copied() + .chain(self.use_imports_macros.keys().copied()) .filter_map(ImportOrExternCrate::import_or_glob) .chain(self.use_imports_values.keys().copied()) - .chain(self.use_imports_macros.keys().copied()) .filter_map(ImportOrGlob::into_import) .sorted() .dedup() @@ -263,7 +263,7 @@ impl ItemScope { let mut def_map; let mut scope = self; - while let Some(&m) = scope.use_imports_macros.get(&ImportOrGlob::Import(import)) { + while let Some(&m) = scope.use_imports_macros.get(&ImportOrExternCrate::Import(import)) { match m { ImportOrDef::Import(i) => { let module_id = i.use_.lookup(db).container; @@ -682,7 +682,6 @@ impl ItemScope { } _ => _ = glob_imports.macros.remove(&lookup), } - let import = import.and_then(ImportOrExternCrate::import_or_glob); let prev = std::mem::replace(&mut fld.import, import); if let Some(import) = import { self.use_imports_macros.insert( @@ -698,7 +697,6 @@ impl ItemScope { { if glob_imports.macros.remove(&lookup) { cov_mark::hit!(import_shadowed); - let import = import.and_then(ImportOrExternCrate::import_or_glob); let prev = std::mem::replace(&mut fld.import, import); if let Some(import) = import { self.use_imports_macros.insert( @@ -783,8 +781,9 @@ impl ItemScope { if let Some(Item { import, .. }) = def.macros { buf.push_str(" m"); match import { - Some(ImportOrGlob::Import(_)) => buf.push('i'), - Some(ImportOrGlob::Glob(_)) => buf.push('g'), + Some(ImportOrExternCrate::Import(_)) => buf.push('i'), + Some(ImportOrExternCrate::Glob(_)) => buf.push('g'), + Some(ImportOrExternCrate::ExternCrate(_)) => buf.push('e'), None => (), } } @@ -893,9 +892,7 @@ impl PerNs { ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import), ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import), ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import), - ModuleDefId::MacroId(mac) => { - PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::import_or_glob)) - } + ModuleDefId::MacroId(mac) => PerNs::macros(mac, v, import), } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 01d340cea6df..1b97eb72b6f2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -179,7 +179,7 @@ impl ItemTree { /// Returns the inner attributes of the source file. pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { - Attrs::filter( + Attrs::expand_cfg_attr( db, krate, self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone(), @@ -191,7 +191,7 @@ impl ItemTree { } pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: Crate, of: AttrOwner) -> Attrs { - Attrs::filter(db, krate, self.raw_attrs(of).clone()) + Attrs::expand_cfg_attr(db, krate, self.raw_attrs(of).clone()) } /// Returns a count of a few, expensive items. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 5431ec9679c5..51a833b5f150 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -83,6 +83,91 @@ impl LangItemTarget { } } +/// Salsa query. This will look for lang items in a specific crate. +#[salsa_macros::tracked(return_ref)] +pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option> { + let _p = tracing::info_span!("crate_lang_items_query").entered(); + + let mut lang_items = LangItems::default(); + + let crate_def_map = db.crate_def_map(krate); + + for (_, module_data) in crate_def_map.modules() { + for impl_def in module_data.scope.impls() { + lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef); + for &(_, assoc) in db.impl_items(impl_def).items.iter() { + match assoc { + AssocItemId::FunctionId(f) => { + lang_items.collect_lang_item(db, f, LangItemTarget::Function) + } + AssocItemId::TypeAliasId(t) => { + lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias) + } + AssocItemId::ConstId(_) => (), + } + } + } + + for def in module_data.scope.declarations() { + match def { + ModuleDefId::TraitId(trait_) => { + lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait); + db.trait_items(trait_).items.iter().for_each(|&(_, assoc_id)| match assoc_id { + AssocItemId::FunctionId(f) => { + lang_items.collect_lang_item(db, f, LangItemTarget::Function); + } + AssocItemId::TypeAliasId(alias) => { + lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias) + } + AssocItemId::ConstId(_) => {} + }); + } + ModuleDefId::AdtId(AdtId::EnumId(e)) => { + lang_items.collect_lang_item(db, e, LangItemTarget::EnumId); + db.enum_variants(e).variants.iter().for_each(|&(id, _)| { + lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant); + }); + } + ModuleDefId::AdtId(AdtId::StructId(s)) => { + lang_items.collect_lang_item(db, s, LangItemTarget::Struct); + } + ModuleDefId::AdtId(AdtId::UnionId(u)) => { + lang_items.collect_lang_item(db, u, LangItemTarget::Union); + } + ModuleDefId::FunctionId(f) => { + lang_items.collect_lang_item(db, f, LangItemTarget::Function); + } + ModuleDefId::StaticId(s) => { + lang_items.collect_lang_item(db, s, LangItemTarget::Static); + } + ModuleDefId::TypeAliasId(t) => { + lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias); + } + _ => {} + } + } + } + + if lang_items.items.is_empty() { None } else { Some(Box::new(lang_items)) } +} + +/// Salsa query. Look for a lang item, starting from the specified crate and recursively +/// traversing its dependencies. +#[salsa_macros::tracked] +pub fn lang_item( + db: &dyn DefDatabase, + start_crate: Crate, + item: LangItem, +) -> Option { + let _p = tracing::info_span!("lang_item_query").entered(); + if let Some(target) = + crate_lang_items(db, start_crate).as_ref().and_then(|it| it.items.get(&item).copied()) + { + return Some(target); + } + start_crate.data(db).dependencies.iter().find_map(|dep| lang_item(db, dep.crate_id, item)) +} + #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct LangItems { items: FxHashMap, @@ -93,96 +178,6 @@ impl LangItems { self.items.get(&item).copied() } - /// Salsa query. This will look for lang items in a specific crate. - pub(crate) fn crate_lang_items_query( - db: &dyn DefDatabase, - krate: Crate, - ) -> Option> { - let _p = tracing::info_span!("crate_lang_items_query").entered(); - - let mut lang_items = LangItems::default(); - - let crate_def_map = db.crate_def_map(krate); - - for (_, module_data) in crate_def_map.modules() { - for impl_def in module_data.scope.impls() { - lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef); - for &(_, assoc) in db.impl_items(impl_def).items.iter() { - match assoc { - AssocItemId::FunctionId(f) => { - lang_items.collect_lang_item(db, f, LangItemTarget::Function) - } - AssocItemId::TypeAliasId(t) => { - lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias) - } - AssocItemId::ConstId(_) => (), - } - } - } - - for def in module_data.scope.declarations() { - match def { - ModuleDefId::TraitId(trait_) => { - lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait); - db.trait_items(trait_).items.iter().for_each( - |&(_, assoc_id)| match assoc_id { - AssocItemId::FunctionId(f) => { - lang_items.collect_lang_item(db, f, LangItemTarget::Function); - } - AssocItemId::TypeAliasId(alias) => lang_items.collect_lang_item( - db, - alias, - LangItemTarget::TypeAlias, - ), - AssocItemId::ConstId(_) => {} - }, - ); - } - ModuleDefId::AdtId(AdtId::EnumId(e)) => { - lang_items.collect_lang_item(db, e, LangItemTarget::EnumId); - db.enum_variants(e).variants.iter().for_each(|&(id, _)| { - lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant); - }); - } - ModuleDefId::AdtId(AdtId::StructId(s)) => { - lang_items.collect_lang_item(db, s, LangItemTarget::Struct); - } - ModuleDefId::AdtId(AdtId::UnionId(u)) => { - lang_items.collect_lang_item(db, u, LangItemTarget::Union); - } - ModuleDefId::FunctionId(f) => { - lang_items.collect_lang_item(db, f, LangItemTarget::Function); - } - ModuleDefId::StaticId(s) => { - lang_items.collect_lang_item(db, s, LangItemTarget::Static); - } - ModuleDefId::TypeAliasId(t) => { - lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias); - } - _ => {} - } - } - } - - if lang_items.items.is_empty() { None } else { Some(Arc::new(lang_items)) } - } - - /// Salsa query. Look for a lang item, starting from the specified crate and recursively - /// traversing its dependencies. - pub(crate) fn lang_item_query( - db: &dyn DefDatabase, - start_crate: Crate, - item: LangItem, - ) -> Option { - let _p = tracing::info_span!("lang_item_query").entered(); - if let Some(target) = - db.crate_lang_items(start_crate).and_then(|it| it.items.get(&item).copied()) - { - return Some(target); - } - start_crate.data(db).dependencies.iter().find_map(|dep| db.lang_item(dep.crate_id, item)) - } - fn collect_lang_item( &mut self, db: &dyn DefDatabase, @@ -269,18 +264,38 @@ macro_rules! language_item_table { } impl LangItem { + pub fn resolve_function(self, db: &dyn DefDatabase, start_crate: Crate) -> Option { + lang_item(db, start_crate, self).and_then(|t| t.as_function()) + } + + pub fn resolve_trait(self, db: &dyn DefDatabase, start_crate: Crate) -> Option { + lang_item(db, start_crate, self).and_then(|t| t.as_trait()) + } + + pub fn resolve_enum(self, db: &dyn DefDatabase, start_crate: Crate) -> Option { + lang_item(db, start_crate, self).and_then(|t| t.as_enum()) + } + + pub fn resolve_type_alias( + self, + db: &dyn DefDatabase, + start_crate: Crate, + ) -> Option { + lang_item(db, start_crate, self).and_then(|t| t.as_type_alias()) + } + /// Opposite of [`LangItem::name`] pub fn from_name(name: &hir_expand::name::Name) -> Option { Self::from_symbol(name.symbol()) } pub fn path(&self, db: &dyn DefDatabase, start_crate: Crate) -> Option { - let t = db.lang_item(start_crate, *self)?; + let t = lang_item(db, start_crate, *self)?; Some(Path::LangItem(t, None)) } pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option { - let t = db.lang_item(start_crate, *self)?; + let t = lang_item(db, start_crate, *self)?; Some(Path::LangItem(t, Some(seg))) } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 737941dba07e..28011bda7c54 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -64,8 +64,8 @@ use std::hash::{Hash, Hasher}; use base_db::{Crate, impl_intern_key}; use hir_expand::{ - AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, - MacroDefId, MacroDefKind, + AstId, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, + MacroDefKind, builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, eager::expand_eager_macro_input, @@ -79,7 +79,7 @@ use la_arena::Idx; use nameres::DefMap; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::impl_from; -use syntax::{AstNode, ast}; +use syntax::ast; pub use hir_expand::{Intern, Lookup, tt}; @@ -554,7 +554,7 @@ pub enum ItemContainerId { impl_from!(ModuleId for ItemContainerId); /// A Data Type -#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum AdtId { StructId(StructId), UnionId(UnionId), @@ -563,7 +563,7 @@ pub enum AdtId { impl_from!(StructId, UnionId, EnumId for AdtId); /// A macro -#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum MacroId { Macro2Id(Macro2Id), MacroRulesId(MacroRulesId), @@ -619,7 +619,7 @@ impl_from!( /// A constant, which might appears as a const item, an anonymous const block in expressions /// or patterns, or as a constant in types with const generics. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum GeneralConstId { ConstId(ConstId), StaticId(StaticId), @@ -656,7 +656,7 @@ impl GeneralConstId { } /// The defs which have a body (have root expressions for type inference). -#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum DefWithBodyId { FunctionId(FunctionId), StaticId(StaticId), @@ -701,7 +701,7 @@ pub enum AssocItemId { // casting them, and somehow making the constructors private, which would be annoying. impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId); -#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum GenericDefId { AdtId(AdtId), // consts can have type parameters from their parents (i.e. associated consts of traits) @@ -790,7 +790,7 @@ impl From for GenericDefId { } } -#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] +#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum CallableDefId { FunctionId(FunctionId), StructId(StructId), @@ -906,7 +906,7 @@ impl From for AttrDefId { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum VariantId { EnumVariantId(EnumVariantId), StructId(StructId), @@ -1166,66 +1166,6 @@ impl ModuleDefId { }) } } - -// FIXME: Replace this with a plain function, it only has one impl -/// A helper trait for converting to MacroCallId -trait AsMacroCall { - fn as_call_id_with_errors( - &self, - db: &dyn ExpandDatabase, - krate: Crate, - resolver: impl Fn(&ModPath) -> Option + Copy, - eager_callback: &mut dyn FnMut( - InFile<(syntax::AstPtr, span::FileAstId)>, - MacroCallId, - ), - ) -> Result>, UnresolvedMacro>; -} - -impl AsMacroCall for InFile<&ast::MacroCall> { - fn as_call_id_with_errors( - &self, - db: &dyn ExpandDatabase, - krate: Crate, - resolver: impl Fn(&ModPath) -> Option + Copy, - eager_callback: &mut dyn FnMut( - InFile<(syntax::AstPtr, span::FileAstId)>, - MacroCallId, - ), - ) -> Result>, UnresolvedMacro> { - let expands_to = hir_expand::ExpandTo::from_call_site(self.value); - let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); - let span_map = db.span_map(self.file_id); - let path = self.value.path().and_then(|path| { - let range = path.syntax().text_range(); - let mod_path = ModPath::from_src(db, path, &mut |range| { - span_map.as_ref().span_for_range(range).ctx - })?; - let call_site = span_map.span_for_range(range); - Some((call_site, mod_path)) - }); - - let Some((call_site, path)) = path else { - return Ok(ExpandResult::only_err(ExpandError::other( - span_map.span_for_range(self.value.syntax().text_range()), - "malformed macro invocation", - ))); - }; - - macro_call_as_call_id_with_eager( - db, - ast_id, - &path, - call_site.ctx, - expands_to, - krate, - resolver, - resolver, - eager_callback, - ) - } -} - /// Helper wrapper for `AstId` with `ModPath` #[derive(Clone, Debug, Eq, PartialEq)] struct AstIdWithPath { @@ -1239,41 +1179,14 @@ impl AstIdWithPath { } } -fn macro_call_as_call_id( - db: &dyn ExpandDatabase, - call: &AstIdWithPath, - call_site: SyntaxContext, - expand_to: ExpandTo, - krate: Crate, - resolver: impl Fn(&ModPath) -> Option + Copy, - eager_callback: &mut dyn FnMut( - InFile<(syntax::AstPtr, span::FileAstId)>, - MacroCallId, - ), -) -> Result, UnresolvedMacro> { - macro_call_as_call_id_with_eager( - db, - call.ast_id, - &call.path, - call_site, - expand_to, - krate, - resolver, - resolver, - eager_callback, - ) - .map(|res| res.value) -} - -fn macro_call_as_call_id_with_eager( +pub fn macro_call_as_call_id( db: &dyn ExpandDatabase, ast_id: AstId, path: &ModPath, call_site: SyntaxContext, expand_to: ExpandTo, krate: Crate, - resolver: impl FnOnce(&ModPath) -> Option, - eager_resolver: impl Fn(&ModPath) -> Option, + resolver: impl Fn(&ModPath) -> Option + Copy, eager_callback: &mut dyn FnMut( InFile<(syntax::AstPtr, span::FileAstId)>, MacroCallId, @@ -1289,7 +1202,7 @@ fn macro_call_as_call_id_with_eager( ast_id, def, call_site, - &|path| eager_resolver(path).filter(MacroDefId::is_fn_like), + &|path| resolver(path).filter(MacroDefId::is_fn_like), eager_callback, ), _ if def.is_fn_like() => ExpandResult { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index a3b48831a0b0..e21d1415aa29 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -285,8 +285,6 @@ fn main() { /* parse error: expected expression */ builtin #format_args (x = ); /* parse error: expected expression */ -/* parse error: expected R_PAREN */ -/* parse error: expected expression, item or let statement */ builtin #format_args (x = , x = 2); /* parse error: expected expression */ builtin #format_args ("{}", x = ); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index abb5bd5ed726..38fc4b3d118a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -2001,8 +2001,9 @@ macro_rules! bug { true }; } - -let _ = bug!(a;;;test); +fn f() { + let _ = bug!(a;;;test); +} "#, expect![[r#" macro_rules! bug { @@ -2022,8 +2023,9 @@ macro_rules! bug { true }; } - -let _ = true; +fn f() { + let _ = true; +} "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index 143b5df77305..800c96ebdae0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -19,7 +19,7 @@ use std::{iter, ops::Range, sync}; use base_db::RootQueryDb; use expect_test::Expect; use hir_expand::{ - InFile, MacroCallKind, MacroKind, + AstId, InFile, MacroCallId, MacroCallKind, MacroKind, db::ExpandDatabase, proc_macro::{ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind}, span_map::SpanMapRef, @@ -29,7 +29,7 @@ use itertools::Itertools; use span::{Edition, Span}; use stdx::{format_to, format_to_acc}; use syntax::{ - AstNode, + AstNode, AstPtr, SyntaxKind::{COMMENT, EOF, IDENT, LIFETIME_IDENT}, SyntaxNode, T, ast::{self, edit::IndentLevel}, @@ -37,10 +37,9 @@ use syntax::{ use test_fixture::WithFixture; use crate::{ - AdtId, AsMacroCall, Lookup, ModuleDefId, + AdtId, Lookup, ModuleDefId, db::DefDatabase, - nameres::{DefMap, MacroSubNs, ModuleSource}, - resolver::HasResolver, + nameres::{DefMap, ModuleSource}, src::HasSource, test_db::TestDB, tt::TopSubtree, @@ -78,7 +77,6 @@ fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) expect.assert_eq(&errors); } -#[track_caller] fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, mut expect: Expect) { let extra_proc_macros = vec![( r#" @@ -95,54 +93,59 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream disabled: false, }, )]; + + fn resolve( + db: &dyn DefDatabase, + def_map: &DefMap, + ast_id: AstId, + ast_ptr: InFile>, + ) -> Option { + def_map.modules().find_map(|module| { + for decl in + module.1.scope.declarations().chain(module.1.scope.unnamed_consts().map(Into::into)) + { + let body = match decl { + ModuleDefId::FunctionId(it) => it.into(), + ModuleDefId::ConstId(it) => it.into(), + ModuleDefId::StaticId(it) => it.into(), + _ => continue, + }; + + let (body, sm) = db.body_with_source_map(body); + if let Some(it) = + body.blocks(db).find_map(|block| resolve(db, &block.1, ast_id, ast_ptr)) + { + return Some(it); + } + if let Some((_, res)) = sm.macro_calls().find(|it| it.0 == ast_ptr) { + return Some(res); + } + } + module.1.scope.macro_invoc(ast_id) + }) + } + let db = TestDB::with_files_extra_proc_macros(ra_fixture, extra_proc_macros); let krate = db.fetch_test_crate(); let def_map = db.crate_def_map(krate); let local_id = DefMap::ROOT; - let module = def_map.module_id(local_id); - let resolver = module.resolver(&db); let source = def_map[local_id].definition_source(&db); let source_file = match source.value { ModuleSource::SourceFile(it) => it, ModuleSource::Module(_) | ModuleSource::BlockExpr(_) => panic!(), }; - // What we want to do is to replace all macros (fn-like, derive, attr) with - // their expansions. Turns out, we don't actually store enough information - // to do this precisely though! Specifically, if a macro expands to nothing, - // it leaves zero traces in def-map, so we can't get its expansion after the - // fact. - // - // This is the usual - // - // resolve/record tension! - // - // So here we try to do a resolve, which is necessary a heuristic. For macro - // calls, we use `as_call_id_with_errors`. For derives, we look at the impls - // in the module and assume that, if impls's source is a different - // `HirFileId`, than it came from macro expansion. - let mut text_edits = Vec::new(); let mut expansions = Vec::new(); - for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) { - let macro_call = InFile::new(source.file_id, ¯o_call); - let res = macro_call - .as_call_id_with_errors( - &db, - krate, - |path| { - resolver - .resolve_path_as_macro(&db, path, Some(MacroSubNs::Bang)) - .map(|(it, _)| db.macro_def(it)) - }, - &mut |_, _| (), - ) - .unwrap(); - let macro_call_id = res.value.unwrap(); - let mut expansion_result = db.parse_macro_expansion(macro_call_id); - expansion_result.err = expansion_result.err.or(res.err); - expansions.push((macro_call.value.clone(), expansion_result)); + for macro_call_node in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) { + let ast_id = db.ast_id_map(source.file_id).ast_id(¯o_call_node); + let ast_id = InFile::new(source.file_id, ast_id); + let ptr = InFile::new(source.file_id, AstPtr::new(¯o_call_node)); + let macro_call_id = resolve(&db, &def_map, ast_id, ptr) + .unwrap_or_else(|| panic!("unable to find semantic macro call {macro_call_node}")); + let expansion_result = db.parse_macro_expansion(macro_call_id); + expansions.push((macro_call_node.clone(), expansion_result)); } for (call, exp) in expansions.into_iter().rev() { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs index b09706552947..448b908936a2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs @@ -259,7 +259,8 @@ impl<'a> AssocItemCollector<'a> { }; match macro_call_as_call_id( self.db, - &AstIdWithPath::new(tree_id.file_id(), ast_id, Clone::clone(path)), + InFile::new(tree_id.file_id(), ast_id), + path, ctxt, expand_to, self.module_id.krate(), @@ -268,12 +269,15 @@ impl<'a> AssocItemCollector<'a> { self.macro_calls.push((ptr.map(|(_, it)| it.upcast()), call_id)) }, ) { - Ok(Some(call_id)) => { - self.macro_calls - .push((InFile::new(tree_id.file_id(), ast_id.upcast()), call_id)); - self.collect_macro_items(call_id); - } - Ok(None) => (), + // FIXME: Expansion error? + Ok(call_id) => match call_id.value { + Some(call_id) => { + self.macro_calls + .push((InFile::new(tree_id.file_id(), ast_id.upcast()), call_id)); + self.collect_macro_items(call_id); + } + None => (), + }, Err(_) => { self.diagnostics.push(DefDiagnostic::unresolved_macro_call( self.module_id.local_id, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 77effbcc8800..8df0f092cd0b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -39,7 +39,7 @@ use crate::{ ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, }, - macro_call_as_call_id, macro_call_as_call_id_with_eager, + macro_call_as_call_id, nameres::{ BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode, attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id}, @@ -1256,7 +1256,8 @@ impl DefCollector<'_> { MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt: call_site } => { let call_id = macro_call_as_call_id( self.db, - ast_id, + ast_id.ast_id, + &ast_id.path, *call_site, *expand_to, self.def_map.krate, @@ -1265,15 +1266,18 @@ impl DefCollector<'_> { eager_callback_buffer.push((directive.module_id, ptr, call_id)); }, ); - if let Ok(Some(call_id)) = call_id { - self.def_map.modules[directive.module_id] - .scope - .add_macro_invoc(ast_id.ast_id, call_id); + if let Ok(call_id) = call_id { + // FIXME: Expansion error + if let Some(call_id) = call_id.value { + self.def_map.modules[directive.module_id] + .scope + .add_macro_invoc(ast_id.ast_id, call_id); - push_resolved(directive, call_id); + push_resolved(directive, call_id); - res = ReachedFixedPoint::No; - return Resolved::Yes; + res = ReachedFixedPoint::No; + return Resolved::Yes; + } } } MacroDirectiveKind::Derive { @@ -1542,7 +1546,8 @@ impl DefCollector<'_> { // FIXME: we shouldn't need to re-resolve the macro here just to get the unresolved error! let macro_call_as_call_id = macro_call_as_call_id( self.db, - ast_id, + ast_id.ast_id, + &ast_id.path, *call_site, *expand_to, self.def_map.krate, @@ -2420,7 +2425,7 @@ impl ModCollector<'_, '_> { let mut eager_callback_buffer = vec![]; // Case 1: try to resolve macro calls with single-segment name and expand macro_rules - if let Ok(res) = macro_call_as_call_id_with_eager( + if let Ok(res) = macro_call_as_call_id( db, ast_id.ast_id, &ast_id.path, @@ -2445,21 +2450,6 @@ impl ModCollector<'_, '_> { .map(|it| self.def_collector.db.macro_def(it)) }) }, - |path| { - let resolved_res = self.def_collector.def_map.resolve_path_fp_with_macro( - self.def_collector - .crate_local_def_map - .as_deref() - .unwrap_or(&self.def_collector.local_def_map), - db, - ResolveMode::Other, - self.module_id, - path, - BuiltinShadowMode::Module, - Some(MacroSubNs::Bang), - ); - resolved_res.resolved_def.take_macros().map(|it| db.macro_def(it)) - }, &mut |ptr, call_id| eager_callback_buffer.push((ptr, call_id)), ) { for (ptr, call_id) in eager_callback_buffer { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs index d6c9f5a00c91..0c50f13edfb6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs @@ -86,7 +86,7 @@ impl ModDir { let dir_path = if root_dir_owner { DirPath::empty() } else { - DirPath::new(format!("{}/", name)) + DirPath::new(format!("{name}/")) }; if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) { return Ok(( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index f8b2c73a8f68..a49155d878ca 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -673,12 +673,11 @@ impl DefMap { } fn resolve_in_macro_use_prelude(&self, name: &Name) -> PerNs { - self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { + self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| { PerNs::macros( it, Visibility::Public, - // FIXME? - None, // extern_crate.map(ImportOrExternCrate::ExternCrate), + extern_crate.map(ImportOrExternCrate::ExternCrate), ) }) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs index 1f7dd6f0c407..8721cd65dbac 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs @@ -37,7 +37,8 @@ pub struct Item { pub type TypesItem = Item; pub type ValuesItem = Item; -pub type MacrosItem = Item; +// May be Externcrate for `[macro_use]`'d macros +pub type MacrosItem = Item; #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] pub struct PerNs { @@ -84,7 +85,7 @@ impl PerNs { } } - pub fn macros(def: MacroId, vis: Visibility, import: Option) -> PerNs { + pub fn macros(def: MacroId, vis: Visibility, import: Option) -> PerNs { PerNs { types: None, values: None, macros: Some(Item { def, vis, import }) } } @@ -116,7 +117,7 @@ impl PerNs { self.macros.map(|it| it.def) } - pub fn take_macros_import(self) -> Option<(MacroId, Option)> { + pub fn take_macros_import(self) -> Option<(MacroId, Option)> { self.macros.map(|it| (it.def, it.import)) } @@ -158,9 +159,6 @@ impl PerNs { self.values .map(|it| (ItemInNs::Values(it.def), it.import.map(ImportOrExternCrate::from))), ) - .chain( - self.macros - .map(|it| (ItemInNs::Macros(it.def), it.import.map(ImportOrExternCrate::from))), - ) + .chain(self.macros.map(|it| (ItemInNs::Macros(it.def), it.import))) } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 46c12574fded..8a8d17018c1b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -493,7 +493,7 @@ impl Resolver { db: &dyn DefDatabase, path: &ModPath, expected_macro_kind: Option, - ) -> Option<(MacroId, Option)> { + ) -> Option<(MacroId, Option)> { let (item_map, item_local_map, module) = self.item_scope_(); item_map .resolve_path( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs index 2f7675134ca7..470975482951 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs @@ -19,7 +19,7 @@ use crate::{ src::HasSource, }; -#[salsa::db] +#[salsa_macros::db] #[derive(Clone)] pub(crate) struct TestDB { storage: salsa::Storage, @@ -44,7 +44,7 @@ impl Default for TestDB { } } -#[salsa::db] +#[salsa_macros::db] impl salsa::Database for TestDB { fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) { let mut events = self.events.lock().unwrap(); @@ -63,7 +63,7 @@ impl fmt::Debug for TestDB { impl panic::RefUnwindSafe for TestDB {} -#[salsa::db] +#[salsa_macros::db] impl SourceDatabase for TestDB { fn file_text(&self, file_id: base_db::FileId) -> FileText { self.files.file_text(file_id) diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml index b83efca25528..ed818c5be3f7 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml @@ -21,6 +21,7 @@ smallvec.workspace = true triomphe.workspace = true query-group.workspace = true salsa.workspace = true +salsa-macros.workspace = true # local deps stdx.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index 5dae27f7a16c..bb17eb062760 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, fmt, ops}; use base_db::Crate; -use cfg::CfgExpr; +use cfg::{CfgExpr, CfgOptions}; use either::Either; use intern::{Interned, Symbol, sym}; @@ -14,11 +14,10 @@ use syntax::{AstNode, AstToken, SyntaxNode, ast, match_ast}; use syntax_bridge::{DocCommentDesugarMode, desugar_doc_comment_text, syntax_node_to_token_tree}; use triomphe::ThinArc; -use crate::name::Name; use crate::{ - InFile, db::ExpandDatabase, mod_path::ModPath, + name::Name, span_map::SpanMapRef, tt::{self, TopSubtree, token_to_literal}, }; @@ -49,29 +48,7 @@ impl RawAttrs { owner: &dyn ast::HasAttrs, span_map: SpanMapRef<'_>, ) -> Self { - let entries: Vec<_> = collect_attrs(owner) - .filter_map(|(id, attr)| match attr { - Either::Left(attr) => { - attr.meta().and_then(|meta| Attr::from_src(db, meta, span_map, id)) - } - Either::Right(comment) => comment.doc_comment().map(|doc| { - let span = span_map.span_for_range(comment.syntax().text_range()); - let (text, kind) = - desugar_doc_comment_text(doc, DocCommentDesugarMode::ProcMacro); - Attr { - id, - input: Some(Box::new(AttrInput::Literal(tt::Literal { - symbol: text, - span, - kind, - suffix: None, - }))), - path: Interned::new(ModPath::from(Name::new_symbol(sym::doc, span.ctx))), - ctxt: span.ctx, - } - }), - }) - .collect(); + let entries: Vec<_> = Self::attrs_iter::(db, owner, span_map).collect(); let entries = if entries.is_empty() { None @@ -82,12 +59,61 @@ impl RawAttrs { RawAttrs { entries } } - pub fn from_attrs_owner( + /// A [`RawAttrs`] that has its `#[cfg_attr(...)]` attributes expanded. + pub fn new_expanded( db: &dyn ExpandDatabase, - owner: InFile<&dyn ast::HasAttrs>, + owner: &dyn ast::HasAttrs, span_map: SpanMapRef<'_>, + cfg_options: &CfgOptions, ) -> Self { - Self::new(db, owner.value, span_map) + let entries: Vec<_> = + Self::attrs_iter_expanded::(db, owner, span_map, cfg_options).collect(); + + let entries = if entries.is_empty() { + None + } else { + Some(ThinArc::from_header_and_iter((), entries.into_iter())) + }; + + RawAttrs { entries } + } + + pub fn attrs_iter( + db: &dyn ExpandDatabase, + owner: &dyn ast::HasAttrs, + span_map: SpanMapRef<'_>, + ) -> impl Iterator { + collect_attrs(owner).filter_map(move |(id, attr)| match attr { + Either::Left(attr) => { + attr.meta().and_then(|meta| Attr::from_src(db, meta, span_map, id)) + } + Either::Right(comment) if DESUGAR_COMMENTS => comment.doc_comment().map(|doc| { + let span = span_map.span_for_range(comment.syntax().text_range()); + let (text, kind) = desugar_doc_comment_text(doc, DocCommentDesugarMode::ProcMacro); + Attr { + id, + input: Some(Box::new(AttrInput::Literal(tt::Literal { + symbol: text, + span, + kind, + suffix: None, + }))), + path: Interned::new(ModPath::from(Name::new_symbol(sym::doc, span.ctx))), + ctxt: span.ctx, + } + }), + Either::Right(_) => None, + }) + } + + pub fn attrs_iter_expanded( + db: &dyn ExpandDatabase, + owner: &dyn ast::HasAttrs, + span_map: SpanMapRef<'_>, + cfg_options: &CfgOptions, + ) -> impl Iterator { + Self::attrs_iter::(db, owner, span_map) + .flat_map(|attr| attr.expand_cfg_attr(db, cfg_options)) } pub fn merge(&self, other: Self) -> Self { @@ -114,9 +140,8 @@ impl RawAttrs { } } - /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`. - // FIXME: This should return a different type, signaling it was filtered? - pub fn filter(self, db: &dyn ExpandDatabase, krate: Crate) -> RawAttrs { + /// Processes `cfg_attr`s + pub fn expand_cfg_attr(self, db: &dyn ExpandDatabase, krate: Crate) -> RawAttrs { let has_cfg_attrs = self.iter().any(|attr| attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr)); if !has_cfg_attrs { @@ -126,37 +151,8 @@ impl RawAttrs { let cfg_options = krate.cfg_options(db); let new_attrs = self .iter() - .flat_map(|attr| -> SmallVec<[_; 1]> { - let is_cfg_attr = attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr); - if !is_cfg_attr { - return smallvec![attr.clone()]; - } - - let subtree = match attr.token_tree_value() { - Some(it) => it, - _ => return smallvec![attr.clone()], - }; - - let (cfg, parts) = match parse_cfg_attr_input(subtree) { - Some(it) => it, - None => return smallvec![attr.clone()], - }; - let index = attr.id; - let attrs = parts - .enumerate() - .take(1 << AttrId::CFG_ATTR_BITS) - .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx))); - - let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg); - let cfg = CfgExpr::parse(&cfg); - if cfg_options.check(&cfg) == Some(false) { - smallvec![] - } else { - cov_mark::hit!(cfg_attr_active); - - attrs.collect() - } - }) + .cloned() + .flat_map(|attr| attr.expand_cfg_attr(db, cfg_options)) .collect::>(); let entries = if new_attrs.is_empty() { None @@ -316,6 +312,42 @@ impl Attr { pub fn path(&self) -> &ModPath { &self.path } + + pub fn expand_cfg_attr( + self, + db: &dyn ExpandDatabase, + cfg_options: &CfgOptions, + ) -> impl IntoIterator { + let is_cfg_attr = self.path.as_ident().is_some_and(|name| *name == sym::cfg_attr); + if !is_cfg_attr { + return smallvec![self]; + } + + let subtree = match self.token_tree_value() { + Some(it) => it, + _ => return smallvec![self.clone()], + }; + + let (cfg, parts) = match parse_cfg_attr_input(subtree) { + Some(it) => it, + None => return smallvec![self.clone()], + }; + let index = self.id; + let attrs = parts + .enumerate() + .take(1 << AttrId::CFG_ATTR_BITS) + .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx))); + + let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg); + let cfg = CfgExpr::parse(&cfg); + if cfg_options.check(&cfg) == Some(false) { + smallvec![] + } else { + cov_mark::hit!(cfg_attr_active); + + attrs.collect::>() + } + } } impl Attr { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs index 6873cb7eaf9c..3959741e6f13 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs @@ -1,7 +1,6 @@ //! Defines a unit of change that can applied to the database to get the next //! state. Changes are transactional. -use base_db::{CrateGraphBuilder, FileChange, SourceRoot}; -use salsa::Durability; +use base_db::{CrateGraphBuilder, FileChange, SourceRoot, salsa::Durability}; use span::FileId; use triomphe::Arc; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 29b7b33fd0fb..7cb1b6c02075 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -18,10 +18,7 @@ use crate::{ cfg_process, declarative::DeclarativeMacroExpander, fixup::{self, SyntaxFixupUndoInfo}, - hygiene::{ - SyntaxContextExt as _, span_with_call_site_ctxt, span_with_def_site_ctxt, - span_with_mixed_site_ctxt, - }, + hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt}, proc_macro::{CrateProcMacros, CustomProcMacroExpander, ProcMacros}, span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef}, tt, @@ -147,7 +144,7 @@ pub trait ExpandDatabase: RootQueryDb { fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext; } -#[salsa::interned(no_lifetime, id = span::SyntaxContext)] +#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext)] pub struct SyntaxContextWrapper { pub data: SyntaxContext, } @@ -752,8 +749,7 @@ fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> { err: Some(ExpandError::other( tt.delimiter.open, format!( - "macro invocation exceeds token limit: produced {} tokens, limit is {}", - count, TOKEN_LIMIT, + "macro invocation exceeds token limit: produced {count} tokens, limit is {TOKEN_LIMIT}", ), )), }) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index 1fa682ce3a2d..0d100c1364ab 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -82,7 +82,7 @@ impl DeclarativeMacroExpander { let transparency = |node| { // ... would be nice to have the item tree here - let attrs = RawAttrs::new(db, node, map.as_ref()).filter(db, def_crate); + let attrs = RawAttrs::new_expanded(db, node, map.as_ref(), def_crate.cfg_options(db)); match attrs .iter() .find(|it| { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs index e7856920bc42..28800c6fabdb 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs @@ -22,7 +22,7 @@ // FIXME: Move this into the span crate? Not quite possible today as that depends on `MacroCallLoc` // which contains a bunch of unrelated things -use std::{convert::identity, iter}; +use std::convert::identity; use span::{Edition, MacroCallId, Span, SyntaxContext}; @@ -141,61 +141,3 @@ fn apply_mark_internal( |_| opaque_and_semitransparent, ) } - -pub trait SyntaxContextExt { - fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContext; - fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContext; - fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContext; - fn remove_mark(&mut self, db: &dyn ExpandDatabase) - -> (Option, Transparency); - fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option, Transparency); - fn marks(self, db: &dyn ExpandDatabase) -> Vec<(span::MacroCallId, Transparency)>; - fn is_opaque(self, db: &dyn ExpandDatabase) -> bool; -} - -impl SyntaxContextExt for SyntaxContext { - fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContext { - self.opaque_and_semitransparent(db) - } - fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContext { - self.opaque(db) - } - fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContext { - self.parent(db) - } - fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option, Transparency) { - let data = self; - (data.outer_expn(db), data.outer_transparency(db)) - } - fn remove_mark( - &mut self, - db: &dyn ExpandDatabase, - ) -> (Option, Transparency) { - let data = *self; - *self = data.parent(db); - (data.outer_expn(db), data.outer_transparency(db)) - } - fn marks(self, db: &dyn ExpandDatabase) -> Vec<(span::MacroCallId, Transparency)> { - let mut marks = marks_rev(self, db).collect::>(); - marks.reverse(); - marks - } - fn is_opaque(self, db: &dyn ExpandDatabase) -> bool { - !self.is_root() && self.outer_transparency(db).is_opaque() - } -} - -// FIXME: Make this a SyntaxContextExt method once we have RPIT -pub fn marks_rev( - ctxt: SyntaxContext, - db: &dyn ExpandDatabase, -) -> impl Iterator + '_ { - iter::successors(Some(ctxt), move |&mark| Some(mark.parent_ctxt(db))) - .take_while(|&it| !it.is_root()) - .map(|ctx| { - let mark = ctx.outer_mark(db); - // We stop before taking the root expansion, as such we cannot encounter a `None` outer - // expansion, as only the ROOT has it. - (mark.0.unwrap(), mark.1) - }) -} diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index f0a9a2ad52c8..d844d8f41eef 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -206,8 +206,7 @@ impl ExpandErrorKind { }, None => RenderedExpandError { message: format!( - "internal error: proc-macro map is missing error entry for crate {:?}", - def_crate + "internal error: proc-macro map is missing error entry for crate {def_crate:?}" ), error: true, kind: RenderedExpandError::GENERAL_KIND, @@ -1051,7 +1050,7 @@ impl ExpandTo { intern::impl_internable!(ModPath, attrs::AttrInput); -#[salsa::interned(no_lifetime, debug)] +#[salsa_macros::interned(no_lifetime, debug)] #[doc(alias = "MacroFileId")] pub struct MacroCallId { pub loc: MacroCallLoc, @@ -1071,7 +1070,7 @@ impl From for span::MacroCallId { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum HirFileId { FileId(EditionedFileId), MacroFile(MacroCallId), diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index 72a5627636bf..9f1e3879e1ee 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -7,7 +7,7 @@ use std::{ use crate::{ db::ExpandDatabase, - hygiene::{SyntaxContextExt, Transparency, marks_rev}, + hygiene::Transparency, name::{AsName, Name}, tt, }; @@ -340,7 +340,7 @@ pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContext) -> O // definitions actually produced by `macro` and `macro` definitions produced by // `macro_rules!`, but at least such configurations are not stable yet. ctxt = ctxt.normalize_to_macro_rules(db); - let mut iter = marks_rev(ctxt, db).peekable(); + let mut iter = ctxt.marks_rev(db).peekable(); let mut result_mark = None; // Find the last opaque mark from the end if it exists. while let Some(&(mark, Transparency::Opaque)) = iter.peek() { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index d43ef38f291d..217d991d110d 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -191,7 +191,7 @@ impl Name { // FIXME: Remove this in favor of `display`, see fixme on `as_str` #[doc(hidden)] pub fn display_no_db(&self, edition: Edition) -> impl fmt::Display + '_ { - Display { name: self, needs_escaping: is_raw_identifier(self.symbol.as_str(), edition) } + Display { name: self, edition } } pub fn symbol(&self) -> &Symbol { @@ -201,15 +201,28 @@ impl Name { struct Display<'a> { name: &'a Name, - needs_escaping: bool, + edition: Edition, } impl fmt::Display for Display<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.needs_escaping { - write!(f, "r#")?; + let mut symbol = self.name.symbol.as_str(); + + if symbol == "'static" { + // FIXME: '`static` can also be a label, and there it does need escaping. + // But knowing where it is will require adding a parameter to `display()`, + // and that is an infectious change. + return f.write_str(symbol); } - fmt::Display::fmt(self.name.symbol.as_str(), f) + + if let Some(s) = symbol.strip_prefix('\'') { + f.write_str("'")?; + symbol = s; + } + if is_raw_identifier(symbol, self.edition) { + f.write_str("r#")?; + } + f.write_str(symbol) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml index 69ad7703c2ca..efa544cf3965 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml @@ -34,6 +34,7 @@ indexmap.workspace = true rustc_apfloat = "0.2.2" query-group.workspace = true salsa.workspace = true +salsa-macros.workspace = true ra-ap-rustc_abi.workspace = true ra-ap-rustc_index.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs index 711544545681..7acc9456ec9c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs @@ -198,15 +198,13 @@ pub(crate) fn deref_by_trait( // blanked impl on `Deref`. #[expect(clippy::overly_complex_bool_expr)] if use_receiver_trait && false { - if let Some(receiver) = - db.lang_item(table.trait_env.krate, LangItem::Receiver).and_then(|l| l.as_trait()) - { + if let Some(receiver) = LangItem::Receiver.resolve_trait(db, table.trait_env.krate) { return Some(receiver); } } // Old rustc versions might not have `Receiver` trait. // Fallback to `Deref` if they don't - db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait()) + LangItem::Deref.resolve_trait(db, table.trait_env.krate) }; let trait_id = trait_id()?; let target = diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 2aa9401eefa9..cd799c03ddf7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -16,7 +16,7 @@ use hir_def::{ AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup, TypeAliasId, VariantId, hir::Movability, - lang_item::{LangItem, LangItemTarget}, + lang_item::LangItem, signatures::{ImplFlags, StructFlags, TraitFlags}, }; @@ -262,10 +262,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { well_known_trait: rust_ir::WellKnownTrait, ) -> Option> { let lang_attr = lang_item_from_well_known_trait(well_known_trait); - let trait_ = match self.db.lang_item(self.krate, lang_attr) { - Some(LangItemTarget::Trait(trait_)) => trait_, - _ => return None, - }; + let trait_ = lang_attr.resolve_trait(self.db, self.krate)?; Some(to_chalk_trait_id(trait_)) } @@ -306,11 +303,8 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { chalk_ir::Binders::new(binders, bound) } crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => { - if let Some((future_trait, future_output)) = self - .db - .lang_item(self.krate, LangItem::Future) - .and_then(|item| item.as_trait()) - .and_then(|trait_| { + if let Some((future_trait, future_output)) = + LangItem::Future.resolve_trait(self.db, self.krate).and_then(|trait_| { let alias = self .db .trait_items(trait_) @@ -338,10 +332,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { }); let mut binder = vec![]; binder.push(crate::wrap_empty_binders(impl_bound)); - let sized_trait = self - .db - .lang_item(self.krate, LangItem::Sized) - .and_then(|item| item.as_trait()); + let sized_trait = LangItem::Sized.resolve_trait(self.db, self.krate); if let Some(sized_trait_) = sized_trait { let sized_bound = WhereClause::Implemented(TraitRef { trait_id: to_chalk_trait_id(sized_trait_), @@ -646,7 +637,10 @@ pub(crate) fn associated_ty_data_query( .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0) .build(); let pro_ty = TyBuilder::assoc_type_projection(db, type_alias, Some(trait_subst)) - .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self()) + .fill_with_bound_vars( + crate::DebruijnIndex::INNERMOST, + generic_params.parent_generics().map_or(0, |it| it.len()), + ) .build(); let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner); @@ -660,9 +654,8 @@ pub(crate) fn associated_ty_data_query( } if !ctx.unsized_types.contains(&self_ty) { - let sized_trait = db - .lang_item(resolver.krate(), LangItem::Sized) - .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id)); + let sized_trait = + LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id); let sized_bound = sized_trait.into_iter().map(|sized_trait| { let trait_bound = rust_ir::TraitBound { trait_id: sized_trait, args_no_self: Default::default() }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs index 0f0cf6ae7ae6..aabc4c4234db 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs @@ -251,9 +251,7 @@ impl TyExt for Ty { match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => { let krate = def.module(db).krate(); - if let Some(future_trait) = - db.lang_item(krate, LangItem::Future).and_then(|item| item.as_trait()) - { + if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) { // This is only used by type walking. // Parameters will be walked outside, and projection predicate is not used. // So just provide the Future trait. @@ -364,8 +362,7 @@ impl TyExt for Ty { fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool { let crate_id = owner.module(db).krate(); - let Some(copy_trait) = db.lang_item(crate_id, LangItem::Copy).and_then(|it| it.as_trait()) - else { + let Some(copy_trait) = LangItem::Copy.resolve_trait(db, crate_id) else { return false; }; let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(self).build(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index c24ef16b4969..980ee264b027 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -283,8 +283,9 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { #[salsa::invoke(crate::variance::variances_of)] #[salsa::cycle( - cycle_fn = crate::variance::variances_of_cycle_fn, - cycle_initial = crate::variance::variances_of_cycle_initial, + // cycle_fn = crate::variance::variances_of_cycle_fn, + // cycle_initial = crate::variance::variances_of_cycle_initial, + cycle_result = crate::variance::variances_of_cycle_initial, )] fn variances_of(&self, def: GenericDefId) -> Option>; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 5e3d88058962..57106412765a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -482,9 +482,8 @@ struct FilterMapNextChecker { impl FilterMapNextChecker { fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self { // Find and store the FunctionIds for Iterator::filter_map and Iterator::next - let (next_function_id, filter_map_function_id) = match db - .lang_item(resolver.krate(), LangItem::IteratorNext) - .and_then(|it| it.as_function()) + let (next_function_id, filter_map_function_id) = match LangItem::IteratorNext + .resolve_function(db, resolver.krate()) { Some(next_function_id) => ( Some(next_function_id), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index 6323d8b71b72..068fc22f2cac 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -301,6 +301,7 @@ impl<'db> MatchCheckCtx<'db> { // ignore this issue. Ref => PatKind::Deref { subpattern: subpatterns.next().unwrap() }, Slice(_) => unimplemented!(), + DerefPattern(_) => unimplemented!(), &Str(void) => match void {}, Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild, Never => PatKind::Never, @@ -351,6 +352,7 @@ impl PatCx for MatchCheckCtx<'_> { }, Ref => 1, Slice(..) => unimplemented!(), + DerefPattern(..) => unimplemented!(), Never | Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Str(..) | Opaque(..) | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => 0, @@ -411,6 +413,7 @@ impl PatCx for MatchCheckCtx<'_> { } }, Slice(_) => unreachable!("Found a `Slice` constructor in match checking"), + DerefPattern(_) => unreachable!("Found a `DerefPattern` constructor in match checking"), Never | Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Str(..) | Opaque(..) | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index f62e4bb4f806..f0989d9de91f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -19,7 +19,7 @@ use hir_def::{ hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate}, item_scope::ItemInNs, item_tree::FieldsShape, - lang_item::{LangItem, LangItemTarget}, + lang_item::LangItem, nameres::DefMap, signatures::VariantFields, type_ref::{ @@ -90,11 +90,26 @@ pub struct HirFormatter<'a> { show_container_bounds: bool, omit_verbose_types: bool, closure_style: ClosureStyle, + display_lifetimes: DisplayLifetime, display_kind: DisplayKind, display_target: DisplayTarget, bounds_formatting_ctx: BoundsFormattingCtx, } +// FIXME: To consider, ref and dyn trait lifetimes can be omitted if they are `'_`, path args should +// not be when in signatures +// So this enum does not encode this well enough +// Also 'static can be omitted for ref and dyn trait lifetimes in static/const item types +// FIXME: Also named lifetimes may be rendered in places where their name is not in scope? +#[derive(Copy, Clone)] +pub enum DisplayLifetime { + Always, + OnlyStatic, + OnlyNamed, + OnlyNamedOrStatic, + Never, +} + #[derive(Default)] enum BoundsFormattingCtx { Entered { @@ -155,6 +170,21 @@ impl HirFormatter<'_> { } } } + + fn render_lifetime(&self, lifetime: &Lifetime) -> bool { + match self.display_lifetimes { + DisplayLifetime::Always => true, + DisplayLifetime::OnlyStatic => matches!(***lifetime.interned(), LifetimeData::Static), + DisplayLifetime::OnlyNamed => { + matches!(***lifetime.interned(), LifetimeData::Placeholder(_)) + } + DisplayLifetime::OnlyNamedOrStatic => matches!( + ***lifetime.interned(), + LifetimeData::Static | LifetimeData::Placeholder(_) + ), + DisplayLifetime::Never => false, + } + } } pub trait HirDisplay { @@ -189,6 +219,7 @@ pub trait HirDisplay { display_kind, closure_style, show_container_bounds, + display_lifetimes: DisplayLifetime::OnlyNamedOrStatic, } } @@ -212,6 +243,7 @@ pub trait HirDisplay { display_target, display_kind: DisplayKind::Diagnostics, show_container_bounds: false, + display_lifetimes: DisplayLifetime::OnlyNamedOrStatic, } } @@ -236,6 +268,7 @@ pub trait HirDisplay { display_target, display_kind: DisplayKind::Diagnostics, show_container_bounds: false, + display_lifetimes: DisplayLifetime::OnlyNamedOrStatic, } } @@ -260,6 +293,7 @@ pub trait HirDisplay { display_target, display_kind: DisplayKind::Diagnostics, show_container_bounds: false, + display_lifetimes: DisplayLifetime::OnlyNamedOrStatic, } } @@ -284,6 +318,7 @@ pub trait HirDisplay { display_target: DisplayTarget::from_crate(db, module_id.krate()), display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque }, show_container_bounds: false, + display_lifetimes: DisplayLifetime::OnlyNamedOrStatic, bounds_formatting_ctx: Default::default(), }) { Ok(()) => {} @@ -312,6 +347,7 @@ pub trait HirDisplay { display_target, display_kind: DisplayKind::Test, show_container_bounds: false, + display_lifetimes: DisplayLifetime::Always, } } @@ -336,6 +372,7 @@ pub trait HirDisplay { display_target, display_kind: DisplayKind::Diagnostics, show_container_bounds, + display_lifetimes: DisplayLifetime::OnlyNamedOrStatic, } } } @@ -480,6 +517,7 @@ pub struct HirDisplayWrapper<'a, T> { display_kind: DisplayKind, display_target: DisplayTarget, show_container_bounds: bool, + display_lifetimes: DisplayLifetime, } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -502,7 +540,7 @@ impl HirDisplayWrapper<'_, T> { self.t.hir_fmt(&mut HirFormatter { db: self.db, fmt: f, - buf: String::with_capacity(20), + buf: String::with_capacity(self.max_size.unwrap_or(20)), curr_size: 0, max_size: self.max_size, entity_limit: self.limited_size, @@ -511,6 +549,7 @@ impl HirDisplayWrapper<'_, T> { display_target: self.display_target, closure_style: self.closure_style, show_container_bounds: self.show_container_bounds, + display_lifetimes: self.display_lifetimes, bounds_formatting_ctx: Default::default(), }) } @@ -519,6 +558,11 @@ impl HirDisplayWrapper<'_, T> { self.closure_style = c; self } + + pub fn with_lifetime_display(mut self, l: DisplayLifetime) -> Self { + self.display_lifetimes = l; + self + } } impl fmt::Display for HirDisplayWrapper<'_, T> @@ -1022,9 +1066,7 @@ impl HirDisplay for Ty { kind @ (TyKind::Raw(m, t) | TyKind::Ref(m, _, t)) => { if let TyKind::Ref(_, l, _) = kind { f.write_char('&')?; - if cfg!(test) { - // rendering these unconditionally is probably too much (at least for inlay - // hints) so we gate it to testing only for the time being + if f.render_lifetime(l) { l.hir_fmt(f)?; f.write_char(' ')?; } @@ -1055,9 +1097,10 @@ impl HirDisplay for Ty { }) }; let (preds_to_print, has_impl_fn_pred) = match t.kind(Interner) { - TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { + TyKind::Dyn(dyn_ty) => { let bounds = dyn_ty.bounds.skip_binders().interned(); - (bounds.len(), contains_impl_fn(bounds)) + let render_lifetime = f.render_lifetime(&dyn_ty.lifetime); + (bounds.len() + render_lifetime as usize, contains_impl_fn(bounds)) } TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, @@ -1348,9 +1391,8 @@ impl HirDisplay for Ty { )?; } ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => { - let future_trait = db - .lang_item(body.module(db).krate(), LangItem::Future) - .and_then(LangItemTarget::as_trait); + let future_trait = + LangItem::Future.resolve_trait(db, body.module(db).krate()); let output = future_trait.and_then(|t| { db.trait_items(t) .associated_type_by_name(&Name::new_symbol_root(sym::Output)) @@ -1480,7 +1522,7 @@ impl HirDisplay for Ty { TyKind::BoundVar(idx) => idx.hir_fmt(f)?, TyKind::Dyn(dyn_ty) => { // Reorder bounds to satisfy `write_bounds_like_dyn_trait()`'s expectation. - // FIXME: `Iterator::partition_in_place()` or `Vec::drain_filter()` may make it + // FIXME: `Iterator::partition_in_place()` or `Vec::extract_if()` may make it // more efficient when either of them hits stable. let mut bounds: SmallVec<[_; 4]> = dyn_ty.bounds.skip_binders().iter(Interner).cloned().collect(); @@ -1489,6 +1531,17 @@ impl HirDisplay for Ty { bounds.extend(others); bounds.extend(auto_traits); + if f.render_lifetime(&dyn_ty.lifetime) { + // we skip the binders in `write_bounds_like_dyn_trait_with_prefix` + bounds.push(Binders::empty( + Interner, + chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives { + ty: self.clone(), + lifetime: dyn_ty.lifetime.clone(), + }), + )); + } + write_bounds_like_dyn_trait_with_prefix( f, "dyn", @@ -1728,9 +1781,7 @@ impl SizedByDefault { match self { Self::NotSized => false, Self::Sized { anchor } => { - let sized_trait = db - .lang_item(anchor, LangItem::Sized) - .and_then(|lang_item| lang_item.as_trait()); + let sized_trait = LangItem::Sized.resolve_trait(db, anchor); Some(trait_) == sized_trait } } @@ -1895,8 +1946,7 @@ fn write_bounds_like_dyn_trait( write!(f, ">")?; } if let SizedByDefault::Sized { anchor } = default_sized { - let sized_trait = - f.db.lang_item(anchor, LangItem::Sized).and_then(|lang_item| lang_item.as_trait()); + let sized_trait = LangItem::Sized.resolve_trait(f.db, anchor); if !is_sized { if !first { write!(f, " + ")?; @@ -1993,7 +2043,6 @@ impl HirDisplay for LifetimeData { write!(f, "{}", param_data.name.display(f.db, f.edition()))?; Ok(()) } - _ if f.display_kind.is_source_code() => write!(f, "'_"), LifetimeData::BoundVar(idx) => idx.hir_fmt(f), LifetimeData::InferenceVar(_) => write!(f, "_"), LifetimeData::Static => write!(f, "'static"), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs index 9823c854d5b3..70763759ef0e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs @@ -19,9 +19,7 @@ fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool { AdtId::StructId(id) => db.lookup_intern_struct(id).container, AdtId::UnionId(id) => db.lookup_intern_union(id).container, }; - let Some(drop_trait) = - db.lang_item(module.krate(), LangItem::Drop).and_then(|it| it.as_trait()) - else { + let Some(drop_trait) = LangItem::Drop.resolve_trait(db, module.krate()) else { return false; }; let impls = match module.containing_block() { @@ -181,8 +179,7 @@ fn projection_has_drop_glue( } fn is_copy(db: &dyn HirDatabase, ty: Ty, env: Arc) -> bool { - let Some(copy_trait) = db.lang_item(env.krate, LangItem::Copy).and_then(|it| it.as_trait()) - else { + let Some(copy_trait) = LangItem::Copy.resolve_trait(db, env.krate) else { return false; }; let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(ty).build(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index 80b18473907d..106b996b13ef 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -124,7 +124,7 @@ pub fn dyn_compatibility_of_trait_query( fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool { let krate = def.module(db).krate(); - let Some(sized) = db.lang_item(krate, LangItem::Sized).and_then(|l| l.as_trait()) else { + let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else { return false; }; @@ -491,8 +491,8 @@ fn receiver_is_dispatchable( let krate = func.module(db).krate(); let traits = ( - db.lang_item(krate, LangItem::Unsize).and_then(|it| it.as_trait()), - db.lang_item(krate, LangItem::DispatchFromDyn).and_then(|it| it.as_trait()), + LangItem::Unsize.resolve_trait(db, krate), + LangItem::DispatchFromDyn.resolve_trait(db, krate), ); let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else { return false; @@ -515,7 +515,7 @@ fn receiver_is_dispatchable( trait_id: to_chalk_trait_id(trait_), substitution: Substitution::from_iter( Interner, - std::iter::once(unsized_self_ty.clone().cast(Interner)) + std::iter::once(unsized_self_ty.cast(Interner)) .chain(placeholder_subst.iter(Interner).skip(1).cloned()), ), }); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 790914fdaf2a..f0ec31db8bb9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -39,7 +39,7 @@ use hir_def::{ builtin_type::{BuiltinInt, BuiltinType, BuiltinUint}, expr_store::{Body, ExpressionStore, HygieneId, path::Path}, hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId}, - lang_item::{LangItem, LangItemTarget}, + lang_item::{LangItem, LangItemTarget, lang_item}, layout::Integer, resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, signatures::{ConstSignature, StaticSignature}, @@ -1801,7 +1801,7 @@ impl<'a> InferenceContext<'a> { fn resolve_lang_item(&self, item: LangItem) -> Option { let krate = self.resolver.krate(); - self.db.lang_item(krate, item) + lang_item(self.db, krate, item) } fn resolve_output_on(&self, trait_: TraitId) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index cf3b15d2a679..800897c6fc3a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -127,7 +127,7 @@ impl InferenceContext<'_> { let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let prev_closure = mem::replace(&mut self.current_closure, id); let prev_ret_ty = mem::replace(&mut self.return_ty, body_ret_ty.clone()); - let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(body_ret_ty.clone())); + let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(body_ret_ty)); let prev_resume_yield_tys = mem::replace(&mut self.resume_yield_tys, resume_yield_tys); self.with_breakable_ctx(BreakableKind::Border, None, None, |this| { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs index 847dd43a02d6..39bd90849fe8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs @@ -8,10 +8,7 @@ use std::iter; use chalk_ir::{BoundVar, Goal, Mutability, TyKind, TyVariableKind, cast::Cast}; -use hir_def::{ - hir::ExprId, - lang_item::{LangItem, LangItemTarget}, -}; +use hir_def::{hir::ExprId, lang_item::LangItem}; use stdx::always; use triomphe::Arc; @@ -701,8 +698,8 @@ impl InferenceTable<'_> { reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone()); let krate = self.trait_env.krate; - let coerce_unsized_trait = match self.db.lang_item(krate, LangItem::CoerceUnsized) { - Some(LangItemTarget::Trait(trait_)) => trait_, + let coerce_unsized_trait = match LangItem::CoerceUnsized.resolve_trait(self.db, krate) { + Some(trait_) => trait_, _ => return Err(TypeError), }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 5468254ab910..8084b394d044 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -827,9 +827,9 @@ impl InferenceContext<'_> { } let assoc = self.resolve_ops_index_output(); self.resolve_associated_type_with_params( - self_ty.clone(), + self_ty, assoc, - &[index_ty.clone().cast(Interner)], + &[index_ty.cast(Interner)], ) } else { self.err_ty() diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index cf0152ecd263..ac450c0b5591 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -126,10 +126,8 @@ impl InferenceContext<'_> { &Expr::Index { base, index } => { if mutability == Mutability::Mut { if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) { - if let Some(index_trait) = self - .db - .lang_item(self.table.trait_env.krate, LangItem::IndexMut) - .and_then(|l| l.as_trait()) + if let Some(index_trait) = + LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate) { if let Some(index_fn) = self .db @@ -183,10 +181,8 @@ impl InferenceContext<'_> { let mut mutability = mutability; if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) { if mutability == Mutability::Mut { - if let Some(deref_trait) = self - .db - .lang_item(self.table.trait_env.krate, LangItem::DerefMut) - .and_then(|l| l.as_trait()) + if let Some(deref_trait) = + LangItem::DerefMut.resolve_trait(self.db, self.table.trait_env.krate) { let ty = self.result.type_of_expr.get(*expr); let is_mut_ptr = ty.is_some_and(|ty| { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs index dc1de3b9e851..a9a3265858e4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs @@ -435,7 +435,7 @@ impl InferenceContext<'_> { decl: Option, ) -> Ty { let (expectation_type, expectation_lt) = match expected.as_reference() { - Some((inner_ty, lifetime, _exp_mut)) => (inner_ty.clone(), lifetime.clone()), + Some((inner_ty, lifetime, _exp_mut)) => (inner_ty.clone(), lifetime), None => { let inner_ty = self.table.new_type_var(); let inner_lt = self.table.new_lifetime_var(); @@ -597,7 +597,7 @@ impl InferenceContext<'_> { let size = consteval::usize_const(self.db, Some(len as u128), self.owner.krate(self.db)); let elem_ty = self.table.new_type_var(); - let array_ty = TyKind::Array(elem_ty.clone(), size).intern(Interner); + let array_ty = TyKind::Array(elem_ty, size).intern(Interner); Some(array_ty) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 60aa9b5a17a8..631b571465fe 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -1024,16 +1024,12 @@ impl<'a> InferenceTable<'a> { } } - let Some(sized) = self - .db - .lang_item(self.trait_env.krate, LangItem::Sized) - .and_then(|sized| sized.as_trait()) - else { + let Some(sized) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else { return false; }; let sized_pred = WhereClause::Implemented(TraitRef { trait_id: to_chalk_trait_id(sized), - substitution: Substitution::from1(Interner, ty.clone()), + substitution: Substitution::from1(Interner, ty), }); let goal = GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(sized_pred)).intern(Interner); matches!(self.try_obligation(goal), Some(Solution::Unique(_))) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index e4688d044e98..9def39d5f979 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -590,10 +590,7 @@ impl<'a> TyLoweringContext<'a> { } } &TypeBound::Path(path, TraitBoundModifier::Maybe) => { - let sized_trait = self - .db - .lang_item(self.resolver.krate(), LangItem::Sized) - .and_then(|lang_item| lang_item.as_trait()); + let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate()); // Don't lower associated type bindings as the only possible relaxed trait bound // `?Sized` has no of them. // If we got another trait here ignore the bound completely. @@ -736,10 +733,8 @@ impl<'a> TyLoweringContext<'a> { } if !ctx.unsized_types.contains(&self_ty) { - let sized_trait = ctx - .db - .lang_item(krate, LangItem::Sized) - .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id)); + let sized_trait = + LangItem::Sized.resolve_trait(ctx.db, krate).map(to_chalk_trait_id); let sized_clause = sized_trait.map(|trait_id| { let clause = WhereClause::Implemented(TraitRef { trait_id, @@ -1188,9 +1183,7 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>( substitution: &'subst Substitution, resolver: &Resolver, ) -> Option + Captures<'a> + Captures<'subst>> { - let sized_trait = db - .lang_item(resolver.krate(), LangItem::Sized) - .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id))?; + let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id)?; let trait_self_idx = trait_self_param_idx(db, def); @@ -1475,7 +1468,7 @@ fn type_for_enum_variant_constructor( } } -#[salsa::tracked(cycle_result = type_for_adt_cycle_result)] +#[salsa_macros::tracked(cycle_result = type_for_adt_cycle_result)] fn type_for_adt_tracked(db: &dyn HirDatabase, adt: AdtId) -> Binders { type_for_adt(db, adt) } @@ -1540,7 +1533,7 @@ pub enum TyDefId { } impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum ValueTyDefId { FunctionId(FunctionId), StructId(StructId), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index 8f8e26eca2ae..8e549ca0cbd5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -515,9 +515,15 @@ impl From> for VisibleFromModule { } } +#[derive(Debug, Clone)] +pub enum AutorefOrPtrAdjustment { + Autoref(Mutability), + ToConstPtr, +} + #[derive(Debug, Clone, Default)] pub struct ReceiverAdjustments { - autoref: Option, + autoref: Option, autoderefs: usize, unsize_array: bool, } @@ -535,10 +541,15 @@ impl ReceiverAdjustments { } Some((kind, new_ty)) => { ty = new_ty.clone(); + let mutbl = match self.autoref { + Some(AutorefOrPtrAdjustment::Autoref(m)) => Some(m), + Some(AutorefOrPtrAdjustment::ToConstPtr) => Some(Mutability::Not), + // FIXME should we know the mutability here, when autoref is `None`? + None => None, + }; adjust.push(Adjustment { kind: Adjust::Deref(match kind { - // FIXME should we know the mutability here, when autoref is `None`? - AutoderefKind::Overloaded => Some(OverloadedDeref(self.autoref)), + AutoderefKind::Overloaded => Some(OverloadedDeref(mutbl)), AutoderefKind::Builtin => None, }), target: new_ty, @@ -546,11 +557,27 @@ impl ReceiverAdjustments { } } } - if let Some(m) = self.autoref { + if let Some(autoref) = &self.autoref { let lt = table.new_lifetime_var(); - let a = Adjustment::borrow(m, ty, lt); - ty = a.target.clone(); - adjust.push(a); + match autoref { + AutorefOrPtrAdjustment::Autoref(m) => { + let a = Adjustment::borrow(*m, ty, lt); + ty = a.target.clone(); + adjust.push(a); + } + AutorefOrPtrAdjustment::ToConstPtr => { + if let TyKind::Raw(Mutability::Mut, pointee) = ty.kind(Interner) { + let a = Adjustment { + kind: Adjust::Pointer(PointerCast::MutToConstPointer), + target: TyKind::Raw(Mutability::Not, pointee.clone()).intern(Interner), + }; + ty = a.target.clone(); + adjust.push(a); + } else { + never!("`ToConstPtr` target is not a raw mutable pointer"); + } + } + }; } if self.unsize_array { ty = 'it: { @@ -575,8 +602,8 @@ impl ReceiverAdjustments { (ty, adjust) } - fn with_autoref(&self, m: Mutability) -> ReceiverAdjustments { - Self { autoref: Some(m), ..*self } + fn with_autoref(&self, a: AutorefOrPtrAdjustment) -> ReceiverAdjustments { + Self { autoref: Some(a), ..*self } } } @@ -1051,7 +1078,7 @@ fn iterate_method_candidates_with_autoref( let mut maybe_reborrowed = first_adjustment.clone(); if let Some((_, _, m)) = receiver_ty.value.as_reference() { // Prefer reborrow of references to move - maybe_reborrowed.autoref = Some(m); + maybe_reborrowed.autoref = Some(AutorefOrPtrAdjustment::Autoref(m)); maybe_reborrowed.autoderefs += 1; } @@ -1063,15 +1090,34 @@ fn iterate_method_candidates_with_autoref( binders: receiver_ty.binders.clone(), }; - iterate_method_candidates_by_receiver(refed, first_adjustment.with_autoref(Mutability::Not))?; + iterate_method_candidates_by_receiver( + refed, + first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)), + )?; let ref_muted = Canonical { value: TyKind::Ref(Mutability::Mut, error_lifetime(), receiver_ty.value.clone()) .intern(Interner), - binders: receiver_ty.binders, + binders: receiver_ty.binders.clone(), }; - iterate_method_candidates_by_receiver(ref_muted, first_adjustment.with_autoref(Mutability::Mut)) + iterate_method_candidates_by_receiver( + ref_muted, + first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)), + )?; + + if let Some((ty, Mutability::Mut)) = receiver_ty.value.as_raw_ptr() { + let const_ptr_ty = Canonical { + value: TyKind::Raw(Mutability::Not, ty.clone()).intern(Interner), + binders: receiver_ty.binders, + }; + iterate_method_candidates_by_receiver( + const_ptr_ty, + first_adjustment.with_autoref(AutorefOrPtrAdjustment::ToConstPtr), + )?; + } + + ControlFlow::Continue(()) } pub trait MethodCandidateCallback { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index 6dc20203e0ee..bf80ed7967aa 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -77,7 +77,14 @@ pub struct Local { /// currently implements it, but it seems like this may be something to check against in the /// validator. #[derive(Debug, PartialEq, Eq, Clone)] -pub enum Operand { +pub struct Operand { + kind: OperandKind, + // FIXME : This should actually just be of type `MirSpan`. + span: Option, +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum OperandKind { /// Creates a value by loading the given place. /// /// Before drop elaboration, the type of the place must be `Copy`. After drop elaboration there @@ -101,7 +108,13 @@ pub enum Operand { impl Operand { fn from_concrete_const(data: Box<[u8]>, memory_map: MemoryMap, ty: Ty) -> Self { - Operand::Constant(intern_const_scalar(ConstScalar::Bytes(data, memory_map), ty)) + Operand { + kind: OperandKind::Constant(intern_const_scalar( + ConstScalar::Bytes(data, memory_map), + ty, + )), + span: None, + } } fn from_bytes(data: Box<[u8]>, ty: Ty) -> Self { @@ -1076,11 +1089,11 @@ impl MirBody { f: &mut impl FnMut(&mut Place, &mut ProjectionStore), store: &mut ProjectionStore, ) { - match op { - Operand::Copy(p) | Operand::Move(p) => { + match &mut op.kind { + OperandKind::Copy(p) | OperandKind::Move(p) => { f(p, store); } - Operand::Constant(_) | Operand::Static(_) => (), + OperandKind::Constant(_) | OperandKind::Static(_) => (), } } for (_, block) in self.basic_blocks.iter_mut() { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs index eca6f4692a4c..fb0c0dee095f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs @@ -15,13 +15,13 @@ use crate::{ ClosureId, Interner, Substitution, Ty, TyExt, TypeFlags, db::{HirDatabase, InternedClosure}, display::DisplayTarget, - mir::Operand, + mir::OperandKind, utils::ClosureSubst, }; use super::{ - BasicBlockId, BorrowKind, LocalId, MirBody, MirLowerError, MirSpan, MutBorrowKind, Place, - ProjectionElem, Rvalue, StatementKind, TerminatorKind, + BasicBlockId, BorrowKind, LocalId, MirBody, MirLowerError, MirSpan, MutBorrowKind, Operand, + Place, ProjectionElem, Rvalue, StatementKind, TerminatorKind, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -120,8 +120,8 @@ fn make_fetch_closure_field( fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec { let mut result = vec![]; - let mut for_operand = |op: &Operand, span: MirSpan| match op { - Operand::Copy(p) | Operand::Move(p) => { + let mut for_operand = |op: &Operand, span: MirSpan| match op.kind { + OperandKind::Copy(p) | OperandKind::Move(p) => { let mut ty: Ty = body.locals[p.local].ty.clone(); let mut is_dereference_of_ref = false; for proj in p.projection.lookup(&body.projection_store) { @@ -139,10 +139,10 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec && !ty.clone().is_copy(db, body.owner) && !ty.data(Interner).flags.intersects(TypeFlags::HAS_ERROR) { - result.push(MovedOutOfRef { span, ty }); + result.push(MovedOutOfRef { span: op.span.unwrap_or(span), ty }); } } - Operand::Constant(_) | Operand::Static(_) => (), + OperandKind::Constant(_) | OperandKind::Static(_) => (), }; for (_, block) in body.basic_blocks.iter() { db.unwind_if_revision_cancelled(); @@ -215,8 +215,8 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec fn partially_moved(db: &dyn HirDatabase, body: &MirBody) -> Vec { let mut result = vec![]; - let mut for_operand = |op: &Operand, span: MirSpan| match op { - Operand::Copy(p) | Operand::Move(p) => { + let mut for_operand = |op: &Operand, span: MirSpan| match op.kind { + OperandKind::Copy(p) | OperandKind::Move(p) => { let mut ty: Ty = body.locals[p.local].ty.clone(); for proj in p.projection.lookup(&body.projection_store) { ty = proj.projected_ty( @@ -232,7 +232,7 @@ fn partially_moved(db: &dyn HirDatabase, body: &MirBody) -> Vec result.push(PartiallyMoved { span, ty, local: p.local }); } } - Operand::Constant(_) | Operand::Static(_) => (), + OperandKind::Constant(_) | OperandKind::Static(_) => (), }; for (_, block) in body.basic_blocks.iter() { db.unwind_if_revision_cancelled(); @@ -492,7 +492,7 @@ fn record_usage(local: LocalId, result: &mut ArenaMap } fn record_usage_for_operand(arg: &Operand, result: &mut ArenaMap) { - if let Operand::Copy(p) | Operand::Move(p) = arg { + if let OperandKind::Copy(p) | OperandKind::Move(p) = arg.kind { record_usage(p.local, result); } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 386226b16d5d..21e5428520e2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -47,7 +47,7 @@ use crate::{ use super::{ AggregateKind, BasicBlockId, BinOp, CastKind, LocalId, MirBody, MirLowerError, MirSpan, - Operand, Place, PlaceElem, ProjectionElem, ProjectionStore, Rvalue, StatementKind, + Operand, OperandKind, Place, PlaceElem, ProjectionElem, ProjectionStore, Rvalue, StatementKind, TerminatorKind, UnOp, return_slot, }; @@ -655,22 +655,15 @@ impl Evaluator<'_> { mir_or_dyn_index_cache: RefCell::new(Default::default()), unused_locals_store: RefCell::new(Default::default()), cached_ptr_size, - cached_fn_trait_func: db - .lang_item(crate_id, LangItem::Fn) - .and_then(|x| x.as_trait()) + cached_fn_trait_func: LangItem::Fn + .resolve_trait(db, crate_id) .and_then(|x| db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call))), - cached_fn_mut_trait_func: db - .lang_item(crate_id, LangItem::FnMut) - .and_then(|x| x.as_trait()) - .and_then(|x| { - db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut)) - }), - cached_fn_once_trait_func: db - .lang_item(crate_id, LangItem::FnOnce) - .and_then(|x| x.as_trait()) - .and_then(|x| { - db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once)) - }), + cached_fn_mut_trait_func: LangItem::FnMut.resolve_trait(db, crate_id).and_then(|x| { + db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut)) + }), + cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| { + db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once)) + }), }) } @@ -863,10 +856,10 @@ impl Evaluator<'_> { } fn operand_ty(&self, o: &Operand, locals: &Locals) -> Result { - Ok(match o { - Operand::Copy(p) | Operand::Move(p) => self.place_ty(p, locals)?, - Operand::Constant(c) => c.data(Interner).ty.clone(), - &Operand::Static(s) => { + Ok(match &o.kind { + OperandKind::Copy(p) | OperandKind::Move(p) => self.place_ty(p, locals)?, + OperandKind::Constant(c) => c.data(Interner).ty.clone(), + &OperandKind::Static(s) => { let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr].clone(); TyKind::Ref(Mutability::Not, static_lifetime(), ty).intern(Interner) } @@ -1880,16 +1873,16 @@ impl Evaluator<'_> { } fn eval_operand(&mut self, it: &Operand, locals: &mut Locals) -> Result { - Ok(match it { - Operand::Copy(p) | Operand::Move(p) => { + Ok(match &it.kind { + OperandKind::Copy(p) | OperandKind::Move(p) => { locals.drop_flags.remove_place(p, &locals.body.projection_store); self.eval_place(p, locals)? } - Operand::Static(st) => { + OperandKind::Static(st) => { let addr = self.eval_static(*st, locals)?; Interval::new(addr, self.ptr_size()) } - Operand::Constant(konst) => self.allocate_const_in_heap(locals, konst)?, + OperandKind::Constant(konst) => self.allocate_const_in_heap(locals, konst)?, }) } @@ -2811,7 +2804,7 @@ impl Evaluator<'_> { span: MirSpan, ) -> Result<()> { let Some(drop_fn) = (|| { - let drop_trait = self.db.lang_item(self.crate_id, LangItem::Drop)?.as_trait()?; + let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?; self.db.trait_items(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop)) })() else { // in some tests we don't have drop trait in minicore, and diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 4de44cfd02e9..26ef95d264be 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -6,7 +6,6 @@ use std::cmp::{self, Ordering}; use chalk_ir::TyKind; use hir_def::{ builtin_type::{BuiltinInt, BuiltinUint}, - lang_item::LangItemTarget, resolver::HasResolver, }; use hir_expand::name::Name; @@ -156,8 +155,8 @@ impl Evaluator<'_> { if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) { let resolver = self.db.crate_def_map(self.crate_id).crate_root().resolver(self.db); - let Some(hir_def::lang_item::LangItemTarget::Function(const_panic_fmt)) = - self.db.lang_item(resolver.krate(), LangItem::ConstPanicFmt) + let Some(const_panic_fmt) = + LangItem::ConstPanicFmt.resolve_function(self.db, resolver.krate()) else { not_supported!("const_panic_fmt lang item not found or not a function"); }; @@ -1257,12 +1256,12 @@ impl Evaluator<'_> { let addr = tuple.interval.addr.offset(offset); args.push(IntervalAndTy::new(addr, field, self, locals)?); } - if let Some(target) = self.db.lang_item(self.crate_id, LangItem::FnOnce) { - if let Some(def) = target.as_trait().and_then(|it| { - self.db - .trait_items(it) - .method_by_name(&Name::new_symbol_root(sym::call_once)) - }) { + if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) { + if let Some(def) = self + .db + .trait_items(target) + .method_by_name(&Name::new_symbol_root(sym::call_once)) + { self.exec_fn_trait( def, &args, @@ -1376,9 +1375,7 @@ impl Evaluator<'_> { } } } - if let Some(LangItemTarget::EnumId(e)) = - self.db.lang_item(self.crate_id, LangItem::Ordering) - { + if let Some(e) = LangItem::Ordering.resolve_enum(self.db, self.crate_id) { let ty = self.db.ty(e.into()); let r = self .compute_discriminant(ty.skip_binders().clone(), &[result as i8 as u8])?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 557027756f39..7b48b15d9ea9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -13,7 +13,7 @@ use hir_def::{ Pat, PatId, RecordFieldPat, RecordLitField, }, item_tree::FieldsShape, - lang_item::{LangItem, LangItemTarget}, + lang_item::{LangItem, LangItemTarget, lang_item}, resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs}, }; use hir_expand::name::Name; @@ -48,6 +48,8 @@ use crate::{ utils::ClosureSubst, }; +use super::OperandKind; + mod as_place; mod pattern_matching; @@ -324,7 +326,7 @@ impl<'ctx> MirLowerCtx<'ctx> { let Some((p, current)) = self.lower_expr_as_place(current, expr_id, true)? else { return Ok(None); }; - Ok(Some((Operand::Copy(p), current))) + Ok(Some((Operand { kind: OperandKind::Copy(p), span: Some(expr_id.into()) }, current))) } fn lower_expr_to_place_with_adjust( @@ -347,7 +349,12 @@ impl<'ctx> MirLowerCtx<'ctx> { else { return Ok(None); }; - self.push_assignment(current, place, Operand::Copy(p).into(), expr_id.into()); + self.push_assignment( + current, + place, + Operand { kind: OperandKind::Copy(p), span: None }.into(), + expr_id.into(), + ); Ok(Some(current)) } Adjust::Borrow(AutoBorrow::Ref(_, m) | AutoBorrow::RawPtr(m)) => { @@ -371,7 +378,7 @@ impl<'ctx> MirLowerCtx<'ctx> { place, Rvalue::Cast( CastKind::PointerCoercion(*cast), - Operand::Copy(p), + Operand { kind: OperandKind::Copy(p), span: None }, last.target.clone(), ), expr_id.into(), @@ -476,7 +483,7 @@ impl<'ctx> MirLowerCtx<'ctx> { self.push_assignment( current, place, - Operand::Copy(temp).into(), + Operand { kind: OperandKind::Copy(temp), span: None }.into(), expr_id.into(), ); Ok(Some(current)) @@ -517,21 +524,23 @@ impl<'ctx> MirLowerCtx<'ctx> { self.push_assignment( current, place, - Operand::Constant( - ConstData { - ty, - value: chalk_ir::ConstValue::BoundVar(BoundVar::new( - DebruijnIndex::INNERMOST, - generics.type_or_const_param_idx(p.into()).ok_or( - MirLowerError::TypeError( - "fail to lower const generic param", - ), - )?, - )), - } - .intern(Interner), - ) - .into(), + Rvalue::from(Operand { + kind: OperandKind::Constant( + ConstData { + ty, + value: chalk_ir::ConstValue::BoundVar(BoundVar::new( + DebruijnIndex::INNERMOST, + generics.type_or_const_param_idx(p.into()).ok_or( + MirLowerError::TypeError( + "fail to lower const generic param", + ), + )?, + )), + } + .intern(Interner), + ), + span: None, + }), expr_id.into(), ); Ok(Some(current)) @@ -876,7 +885,7 @@ impl<'ctx> MirLowerCtx<'ctx> { })), &mut self.result.projection_store, ); - Operand::Copy(p) + Operand { kind: OperandKind::Copy(p), span: None } } }) .collect(), @@ -979,7 +988,12 @@ impl<'ctx> MirLowerCtx<'ctx> { else { return Ok(None); }; - self.push_assignment(current, place, Operand::Copy(p).into(), expr_id.into()); + self.push_assignment( + current, + place, + Operand { kind: OperandKind::Copy(p), span: None }.into(), + expr_id.into(), + ); Ok(Some(current)) } Expr::UnaryOp { @@ -1056,8 +1070,11 @@ impl<'ctx> MirLowerCtx<'ctx> { else { return Ok(None); }; - let r_value = - Rvalue::CheckedBinaryOp(op.into(), Operand::Copy(lhs_place), rhs_op); + let r_value = Rvalue::CheckedBinaryOp( + op.into(), + Operand { kind: OperandKind::Copy(lhs_place), span: None }, + rhs_op, + ); self.push_assignment(current, lhs_place, r_value, expr_id.into()); return Ok(Some(current)); } @@ -1232,9 +1249,11 @@ impl<'ctx> MirLowerCtx<'ctx> { Rvalue::Ref(*bk, p), capture_spans[0], ); - operands.push(Operand::Move(tmp)); + operands.push(Operand { kind: OperandKind::Move(tmp), span: None }); + } + CaptureKind::ByValue => { + operands.push(Operand { kind: OperandKind::Move(p), span: None }) } - CaptureKind::ByValue => operands.push(Operand::Move(p)), } } self.push_assignment( @@ -1476,7 +1495,7 @@ impl<'ctx> MirLowerCtx<'ctx> { .const_eval(const_id, subst, None) .map_err(|e| MirLowerError::ConstEvalError(name.into(), Box::new(e)))? }; - Ok(Operand::Constant(c)) + Ok(Operand { kind: OperandKind::Constant(c), span: None }) } fn write_bytes_to_place( @@ -1727,7 +1746,7 @@ impl<'ctx> MirLowerCtx<'ctx> { fn resolve_lang_item(&self, item: LangItem) -> Result { let crate_id = self.owner.module(self.db).krate(); - self.db.lang_item(crate_id, item).ok_or(MirLowerError::LangItemNotFound(item)) + lang_item(self.db, crate_id, item).ok_or(MirLowerError::LangItemNotFound(item)) } fn lower_block_to_place( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs index d3cd0099246a..c22bada7a903 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs @@ -1,6 +1,6 @@ //! MIR lowering for places -use crate::mir::MutBorrowKind; +use crate::mir::{MutBorrowKind, Operand, OperandKind}; use super::*; use hir_def::FunctionId; @@ -155,7 +155,7 @@ impl MirLowerCtx<'_> { self.push_assignment( current, temp, - Operand::Static(s).into(), + Operand { kind: OperandKind::Static(s), span: None }.into(), expr_id.into(), ); Ok(Some(( @@ -305,7 +305,7 @@ impl MirLowerCtx<'_> { ); let Some(current) = self.lower_call( index_fn_op, - Box::new([Operand::Copy(place), index_operand]), + Box::new([Operand { kind: OperandKind::Copy(place), span: None }, index_operand]), result, current, false, @@ -365,7 +365,7 @@ impl MirLowerCtx<'_> { let mut result: Place = self.temp(target_ty_ref, current, span)?.into(); let Some(current) = self.lower_call( deref_fn_op, - Box::new([Operand::Copy(ref_place)]), + Box::new([Operand { kind: OperandKind::Copy(ref_place), span: None }]), result, current, false, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index abfa7aee04f7..b3c1f6f387f2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -5,10 +5,10 @@ use hir_def::{AssocItemId, hir::ExprId, signatures::VariantFields}; use crate::{ BindingMode, mir::{ - LocalId, MutBorrowKind, + LocalId, MutBorrowKind, Operand, OperandKind, lower::{ BasicBlockId, BinOp, BindingId, BorrowKind, Either, Expr, FieldId, Idx, Interner, - MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Mutability, Operand, Pat, PatId, Place, + MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Mutability, Pat, PatId, Place, PlaceElem, ProjectionElem, RecordFieldPat, ResolveValueResult, Result, Rvalue, Substitution, SwitchTargets, TerminatorKind, TupleFieldId, TupleId, TyBuilder, TyKind, ValueNs, VariantId, @@ -217,10 +217,14 @@ impl MirLowerCtx<'_> { self.push_assignment( current, discr, - Rvalue::CheckedBinaryOp(binop, lv, Operand::Copy(cond_place)), + Rvalue::CheckedBinaryOp( + binop, + lv, + Operand { kind: OperandKind::Copy(cond_place), span: None }, + ), pattern.into(), ); - let discr = Operand::Copy(discr); + let discr = Operand { kind: OperandKind::Copy(discr), span: None }; self.set_terminator( current, TerminatorKind::SwitchInt { @@ -262,7 +266,10 @@ impl MirLowerCtx<'_> { self.set_terminator( current, TerminatorKind::SwitchInt { - discr: Operand::Copy(place_len), + discr: Operand { + kind: OperandKind::Copy(place_len), + span: None, + }, targets: SwitchTargets::static_if( pattern_len as u128, next, @@ -282,10 +289,14 @@ impl MirLowerCtx<'_> { self.push_assignment( current, discr, - Rvalue::CheckedBinaryOp(BinOp::Le, c, Operand::Copy(place_len)), + Rvalue::CheckedBinaryOp( + BinOp::Le, + c, + Operand { kind: OperandKind::Copy(place_len), span: None }, + ), pattern.into(), ); - let discr = Operand::Copy(discr); + let discr = Operand { kind: OperandKind::Copy(discr), span: None }; self.set_terminator( current, TerminatorKind::SwitchInt { @@ -407,8 +418,8 @@ impl MirLowerCtx<'_> { tmp2, Rvalue::CheckedBinaryOp( BinOp::Eq, - Operand::Copy(tmp), - Operand::Copy(cond_place), + Operand { kind: OperandKind::Copy(tmp), span: None }, + Operand { kind: OperandKind::Copy(cond_place), span: None }, ), span, ); @@ -417,7 +428,7 @@ impl MirLowerCtx<'_> { self.set_terminator( current, TerminatorKind::SwitchInt { - discr: Operand::Copy(tmp2), + discr: Operand { kind: OperandKind::Copy(tmp2), span: None }, targets: SwitchTargets::static_if(1, next, else_target), }, span, @@ -486,7 +497,7 @@ impl MirLowerCtx<'_> { self.push_assignment( current, lhs_place, - Operand::Copy(cond_place).into(), + Operand { kind: OperandKind::Copy(cond_place), span: None }.into(), expr.into(), ); (current, current_else) @@ -523,7 +534,9 @@ impl MirLowerCtx<'_> { current, target_place.into(), match mode { - BindingMode::Move => Operand::Copy(cond_place).into(), + BindingMode::Move => { + Operand { kind: OperandKind::Copy(cond_place), span: None }.into() + } BindingMode::Ref(Mutability::Not) => Rvalue::Ref(BorrowKind::Shared, cond_place), BindingMode::Ref(Mutability::Mut) => { Rvalue::Ref(BorrowKind::Mut { kind: MutBorrowKind::Default }, cond_place) @@ -547,10 +560,14 @@ impl MirLowerCtx<'_> { self.push_assignment( current, discr, - Rvalue::CheckedBinaryOp(BinOp::Eq, c, Operand::Copy(cond_place)), + Rvalue::CheckedBinaryOp( + BinOp::Eq, + c, + Operand { kind: OperandKind::Copy(cond_place), span: None }, + ), pattern.into(), ); - let discr = Operand::Copy(discr); + let discr = Operand { kind: OperandKind::Copy(discr), span: None }; self.set_terminator( current, TerminatorKind::SwitchInt { @@ -583,7 +600,7 @@ impl MirLowerCtx<'_> { self.set_terminator( current, TerminatorKind::SwitchInt { - discr: Operand::Copy(tmp), + discr: Operand { kind: OperandKind::Copy(tmp), span: None }, targets: SwitchTargets::static_if(e, next, *else_target), }, span, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs index d4f10c032cb1..d8f443145ca0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs @@ -25,7 +25,7 @@ use crate::{ infer::normalize, }; -use super::{MirBody, MirLowerError, Operand, Rvalue, StatementKind, TerminatorKind}; +use super::{MirBody, MirLowerError, Operand, OperandKind, Rvalue, StatementKind, TerminatorKind}; macro_rules! not_supported { ($it: expr) => { @@ -170,8 +170,8 @@ impl Filler<'_> { } fn fill_operand(&mut self, op: &mut Operand) -> Result<(), MirLowerError> { - match op { - Operand::Constant(c) => { + match &mut op.kind { + OperandKind::Constant(c) => { match &c.data(Interner).value { chalk_ir::ConstValue::BoundVar(b) => { let resolved = self @@ -215,7 +215,7 @@ impl Filler<'_> { } self.fill_const(c)?; } - Operand::Copy(_) | Operand::Move(_) | Operand::Static(_) => (), + OperandKind::Copy(_) | OperandKind::Move(_) | OperandKind::Static(_) => (), } Ok(()) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs index f71e29789766..7ae6e907e7ad 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs @@ -18,8 +18,8 @@ use crate::{ }; use super::{ - AggregateKind, BasicBlockId, BorrowKind, LocalId, MirBody, MutBorrowKind, Operand, Place, - Rvalue, UnOp, + AggregateKind, BasicBlockId, BorrowKind, LocalId, MirBody, MutBorrowKind, Operand, OperandKind, + Place, Rvalue, UnOp, }; macro_rules! w { @@ -374,14 +374,14 @@ impl<'a> MirPrettyCtx<'a> { } fn operand(&mut self, r: &Operand) { - match r { - Operand::Copy(p) | Operand::Move(p) => { + match &r.kind { + OperandKind::Copy(p) | OperandKind::Move(p) => { // MIR at the time of writing doesn't have difference between move and copy, so we show them // equally. Feel free to change it. self.place(p); } - Operand::Constant(c) => w!(self, "Const({})", self.hir_display(c)), - Operand::Static(s) => w!(self, "Static({:?})", s), + OperandKind::Constant(c) => w!(self, "Const({})", self.hir_display(c)), + OperandKind::Static(s) => w!(self, "Static({:?})", s), } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs index d2bba120b68e..bcd8aa6c4e95 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs @@ -16,7 +16,7 @@ use syntax::TextRange; use test_utils::extract_annotations; use triomphe::Arc; -#[salsa::db] +#[salsa_macros::db] #[derive(Clone)] pub(crate) struct TestDB { storage: salsa::Storage, @@ -47,7 +47,7 @@ impl fmt::Debug for TestDB { } } -#[salsa::db] +#[salsa_macros::db] impl SourceDatabase for TestDB { fn file_text(&self, file_id: base_db::FileId) -> FileText { self.files.file_text(file_id) @@ -102,7 +102,7 @@ impl SourceDatabase for TestDB { } } -#[salsa::db] +#[salsa_macros::db] impl salsa::Database for TestDB { fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) { let mut events = self.events.lock().unwrap(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs index eeaacbf12eac..ddc5b715194d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs @@ -561,7 +561,7 @@ trait Foo {} fn test(f: impl Foo, g: &(impl Foo + ?Sized)) { let _: &dyn Foo = &f; let _: &dyn Foo = g; - //^ expected &'? dyn Foo, got &'? impl Foo + ?Sized + //^ expected &'? (dyn Foo + 'static), got &'? impl Foo + ?Sized } "#, ); @@ -827,11 +827,11 @@ struct V { t: T } fn main() { let a: V<&dyn Tr>; (a,) = V { t: &S }; - //^^^^expected V<&'? S>, got (V<&'? dyn Tr>,) + //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,) let mut a: V<&dyn Tr> = V { t: &S }; (a,) = V { t: &S }; - //^^^^expected V<&'? S>, got (V<&'? dyn Tr>,) + //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,) } "#, ); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs index 60c03b52246c..a986b54a7b06 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs @@ -65,13 +65,13 @@ trait A { } trait B: A {} -fn test( +fn test<'a>( _: &(dyn A + Send), - //^ &'_ (dyn A + Send) - _: &(dyn Send + A), - //^ &'_ (dyn A + Send) + //^ &(dyn A + Send + 'static) + _: &'a (dyn Send + A), + //^ &'a (dyn A + Send + 'static) _: &dyn B, - //^ &'_ (dyn B) + //^ &(dyn B + 'static) ) {} "#, ); @@ -85,7 +85,7 @@ fn render_dyn_for_ty() { trait Foo<'a> {} fn foo(foo: &dyn for<'a> Foo<'a>) {} - // ^^^ &'_ dyn Foo<'_> + // ^^^ &(dyn Foo<'?> + 'static) "#, ); } @@ -111,11 +111,11 @@ fn test( b; //^ impl Foo c; - //^ &'_ impl Foo + ?Sized + //^ &impl Foo + ?Sized d; //^ S ref_any; - //^^^^^^^ &'_ impl ?Sized + //^^^^^^^ &impl ?Sized empty; } //^^^^^ impl Sized "#, @@ -192,7 +192,7 @@ fn test( b; //^ fn(impl Foo) -> impl Foo c; -} //^ fn(&'_ impl Foo + ?Sized) -> &'_ impl Foo + ?Sized +} //^ fn(&impl Foo + ?Sized) -> &impl Foo + ?Sized "#, ); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs index 3a258ecad10a..94826acca305 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs @@ -1153,9 +1153,9 @@ fn dyn_trait_super_trait_not_in_scope() { 51..55 'self': &'? Self 64..69 '{ 0 }': u32 66..67 '0': u32 - 176..177 'd': &'? dyn Trait + 176..177 'd': &'? (dyn Trait + 'static) 191..207 '{ ...o(); }': () - 197..198 'd': &'? dyn Trait + 197..198 'd': &'? (dyn Trait + 'static) 197..204 'd.foo()': u32 "#]], ); @@ -2019,10 +2019,10 @@ impl dyn Error + Send { /// Attempts to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; - // ^^^^ expected Box, got Box + // ^^^^ expected Box, got Box // FIXME, type mismatch should not occur ::downcast(err).map_err(|_| loop {}) - //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box) -> Result, Box> + //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box) -> Result, Box> } } "#, @@ -2170,3 +2170,26 @@ fn main() { "#, ); } + +#[test] +fn mut_to_const_pointer() { + check( + r#" +pub trait X { + fn perform(self) -> u64; +} + +impl X for *const u8 { + fn perform(self) -> u64 { + 42 + } +} + +fn test(x: *mut u8) { + let _v = x.perform(); + // ^ adjustments: Pointer(MutToConstPointer) + // ^^^^^^^^^^^ type: u64 +} +"#, + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index 638306054a9d..47c695c69748 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -629,7 +629,7 @@ fn issue_4053_diesel_where_clauses() { 488..522 '{ ... }': () 498..502 'self': SelectStatement 498..508 'self.order': O - 498..515 'self.o...into()': dyn QueryFragment + 498..515 'self.o...into()': dyn QueryFragment + 'static "#]], ); } @@ -773,7 +773,7 @@ fn issue_4800() { "#, expect![[r#" 379..383 'self': &'? mut PeerSet - 401..424 '{ ... }': dyn Future + 401..424 '{ ... }': dyn Future + 'static 411..418 'loop {}': ! 416..418 '{}': () 575..579 'self': &'? mut Self @@ -2278,3 +2278,26 @@ fn test(x: bool) { "#]], ); } + +#[test] +fn issue_19730() { + check_infer( + r#" +trait Trait {} + +trait Foo { + type Bar: Trait; + + fn foo(bar: Self::Bar) { + let _ = bar; + } +} +"#, + expect![[r#" + 83..86 'bar': Foo::Bar + 105..133 '{ ... }': () + 119..120 '_': Foo::Bar + 123..126 'bar': Foo::Bar + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs index 0f5e44151de2..eeebe38f1826 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs @@ -2741,11 +2741,11 @@ impl B for Astruct {} 715..744 '#[rust...1i32])': Box<[i32; 1], Global> 737..743 '[1i32]': [i32; 1] 738..742 '1i32': i32 - 755..756 'v': Vec, Global> - 776..793 '<[_]> ...to_vec': fn into_vec, Global>(Box<[Box], Global>) -> Vec, Global> - 776..850 '<[_]> ...ct)]))': Vec, Global> - 794..849 '#[rust...uct)])': Box<[Box; 1], Global> - 816..848 '[#[rus...ruct)]': [Box; 1] + 755..756 'v': Vec, Global> + 776..793 '<[_]> ...to_vec': fn into_vec, Global>(Box<[Box], Global>) -> Vec, Global> + 776..850 '<[_]> ...ct)]))': Vec, Global> + 794..849 '#[rust...uct)])': Box<[Box; 1], Global> + 816..848 '[#[rus...ruct)]': [Box; 1] 817..847 '#[rust...truct)': Box 839..846 'Astruct': Astruct "#]], diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs index 2fb51acea873..14137605c9f2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs @@ -1475,26 +1475,26 @@ fn test(x: Box>, y: &dyn Trait) { expect![[r#" 29..33 'self': &'? Self 54..58 'self': &'? Self - 198..200 '{}': Box> - 210..211 'x': Box> - 234..235 'y': &'? dyn Trait + 198..200 '{}': Box + 'static> + 210..211 'x': Box + 'static> + 234..235 'y': &'? (dyn Trait + 'static) 254..371 '{ ...2(); }': () - 260..261 'x': Box> - 267..268 'y': &'? dyn Trait - 278..279 'z': Box> - 282..285 'bar': fn bar() -> Box> - 282..287 'bar()': Box> - 293..294 'x': Box> + 260..261 'x': Box + 'static> + 267..268 'y': &'? (dyn Trait + 'static) + 278..279 'z': Box + 'static> + 282..285 'bar': fn bar() -> Box + 'static> + 282..287 'bar()': Box + 'static> + 293..294 'x': Box + 'static> 293..300 'x.foo()': u64 - 306..307 'y': &'? dyn Trait + 306..307 'y': &'? (dyn Trait + 'static) 306..313 'y.foo()': u64 - 319..320 'z': Box> + 319..320 'z': Box + 'static> 319..326 'z.foo()': u64 - 332..333 'x': Box> + 332..333 'x': Box + 'static> 332..340 'x.foo2()': i64 - 346..347 'y': &'? dyn Trait + 346..347 'y': &'? (dyn Trait + 'static) 346..354 'y.foo2()': i64 - 360..361 'z': Box> + 360..361 'z': Box + 'static> 360..368 'z.foo2()': i64 "#]], ); @@ -1523,14 +1523,14 @@ fn test(s: S) { expect![[r#" 32..36 'self': &'? Self 102..106 'self': &'? S - 128..139 '{ loop {} }': &'? dyn Trait + 128..139 '{ loop {} }': &'? (dyn Trait + 'static) 130..137 'loop {}': ! 135..137 '{}': () 175..179 'self': &'? Self 251..252 's': S 267..289 '{ ...z(); }': () 273..274 's': S - 273..280 's.bar()': &'? dyn Trait + 273..280 's.bar()': &'? (dyn Trait + 'static) 273..286 's.bar().baz()': (u32, i32) "#]], ); @@ -1556,20 +1556,20 @@ fn test(x: Trait, y: &Trait) -> u64 { }"#, expect![[r#" 26..30 'self': &'? Self - 60..62 '{}': dyn Trait - 72..73 'x': dyn Trait - 82..83 'y': &'? dyn Trait + 60..62 '{}': dyn Trait + 'static + 72..73 'x': dyn Trait + 'static + 82..83 'y': &'? (dyn Trait + 'static) 100..175 '{ ...o(); }': u64 - 106..107 'x': dyn Trait - 113..114 'y': &'? dyn Trait - 124..125 'z': dyn Trait - 128..131 'bar': fn bar() -> dyn Trait - 128..133 'bar()': dyn Trait - 139..140 'x': dyn Trait + 106..107 'x': dyn Trait + 'static + 113..114 'y': &'? (dyn Trait + 'static) + 124..125 'z': dyn Trait + 'static + 128..131 'bar': fn bar() -> dyn Trait + 'static + 128..133 'bar()': dyn Trait + 'static + 139..140 'x': dyn Trait + 'static 139..146 'x.foo()': u64 - 152..153 'y': &'? dyn Trait + 152..153 'y': &'? (dyn Trait + 'static) 152..159 'y.foo()': u64 - 165..166 'z': dyn Trait + 165..166 'z': dyn Trait + 'static 165..172 'z.foo()': u64 "#]], ); @@ -1589,10 +1589,10 @@ fn main() { expect![[r#" 31..35 'self': &'? S 37..39 '{}': () - 47..48 '_': &'? dyn Fn(S) + 47..48 '_': &'? (dyn Fn(S) + 'static) 58..60 '{}': () 71..105 '{ ...()); }': () - 77..78 'f': fn f(&'? dyn Fn(S)) + 77..78 'f': fn f(&'? (dyn Fn(S) + 'static)) 77..102 'f(&|nu...foo())': () 79..101 '&|numb....foo()': &'? impl Fn(S) 80..101 '|numbe....foo()': impl Fn(S) @@ -2927,13 +2927,13 @@ fn test(x: &dyn Foo) { foo(x); }"#, expect![[r#" - 21..22 'x': &'? dyn Foo + 21..22 'x': &'? (dyn Foo + 'static) 34..36 '{}': () - 46..47 'x': &'? dyn Foo + 46..47 'x': &'? (dyn Foo + 'static) 59..74 '{ foo(x); }': () - 65..68 'foo': fn foo(&'? dyn Foo) + 65..68 'foo': fn foo(&'? (dyn Foo + 'static)) 65..71 'foo(x)': () - 69..70 'x': &'? dyn Foo + 69..70 'x': &'? (dyn Foo + 'static) "#]], ); } @@ -3210,13 +3210,13 @@ fn foo() { 218..324 '{ ...&s); }': () 228..229 's': Option 232..236 'None': Option - 246..247 'f': Box)> - 281..310 'Box { ... {}) }': Box)> + 246..247 'f': Box) + 'static> + 281..310 'Box { ... {}) }': Box) + 'static> 294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option) 300..307 '|ps| {}': impl FnOnce(&'? Option) 301..303 'ps': &'? Option 305..307 '{}': () - 316..317 'f': Box)> + 316..317 'f': Box) + 'static> 316..321 'f(&s)': () 318..320 '&s': &'? Option 319..320 's': Option @@ -4252,9 +4252,9 @@ fn f<'a>(v: &dyn Trait = &'a i32>) { "#, expect![[r#" 90..94 'self': &'? Self - 127..128 'v': &'? (dyn Trait = &'a i32>) + 127..128 'v': &'? (dyn Trait = &'a i32> + 'static) 164..195 '{ ...f(); }': () - 170..171 'v': &'? (dyn Trait = &'a i32>) + 170..171 'v': &'? (dyn Trait = &'a i32> + 'static) 170..184 'v.get::()': &'? i32 170..192 'v.get:...eref()': &'? i32 "#]], @@ -4735,7 +4735,7 @@ pub async fn foo_async<'a>() -> Box { fn foo() { foo_async(); - //^^^^^^^^^^^impl Future> + ?Sized + //^^^^^^^^^^^impl Future> + ?Sized } "#, ) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index a5c195d4086a..f9f8776cff7c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -8,10 +8,7 @@ use chalk_recursive::Cache; use chalk_solve::{Solver, logging_db::LoggingRustIrDatabase, rust_ir}; use base_db::Crate; -use hir_def::{ - BlockId, TraitId, - lang_item::{LangItem, LangItemTarget}, -}; +use hir_def::{BlockId, TraitId, lang_item::LangItem}; use hir_expand::name::Name; use intern::sym; use span::Edition; @@ -292,10 +289,6 @@ impl FnTrait { } pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option { - let target = db.lang_item(krate, self.lang_item())?; - match target { - LangItemTarget::Trait(t) => Some(t), - _ => None, - } + self.lang_item().resolve_trait(db, krate) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 198f715a6db2..1e0ff423ded6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -36,8 +36,7 @@ use crate::{ pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator + '_ { [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce] .into_iter() - .filter_map(move |lang| db.lang_item(krate, lang)) - .flat_map(|it| it.as_trait()) + .filter_map(move |lang| lang.resolve_trait(db, krate)) } /// Returns an iterator over the direct super traits (including the trait itself). diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index 4e9aa5610a52..6e1cd9a310f1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -22,7 +22,6 @@ use crate::{ use chalk_ir::Mutability; use hir_def::signatures::StructFlags; use hir_def::{AdtId, GenericDefId, GenericParamId, VariantId}; -use salsa::CycleRecoveryAction; use std::fmt; use std::ops::Not; use stdx::never; @@ -55,14 +54,14 @@ pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> Option>, - _count: u32, - _def: GenericDefId, -) -> CycleRecoveryAction>> { - CycleRecoveryAction::Iterate -} +// pub(crate) fn variances_of_cycle_fn( +// _db: &dyn HirDatabase, +// _result: &Option>, +// _count: u32, +// _def: GenericDefId, +// ) -> salsa::CycleRecoveryAction>> { +// salsa::CycleRecoveryAction::Iterate +// } pub(crate) fn variances_of_cycle_initial( db: &dyn HirDatabase, @@ -966,7 +965,7 @@ struct S3(S); struct FixedPoint(&'static FixedPoint<(), T, U>, V); "#, expect![[r#" - FixedPoint[T: covariant, U: covariant, V: covariant] + FixedPoint[T: bivariant, U: bivariant, V: bivariant] "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index 53817f37aa66..124ab8e274af 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -516,8 +516,7 @@ impl HirDisplay for TypeParam { return Ok(()); } - let sized_trait = - f.db.lang_item(krate, LangItem::Sized).and_then(|lang_item| lang_item.as_trait()); + let sized_trait = LangItem::Sized.resolve_trait(f.db, krate); let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() { WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait, _ => false, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 143c13069e42..3f1d5bb01f2a 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -53,7 +53,6 @@ use hir_def::{ generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, }, item_tree::{AttrOwner, FieldParent, ImportAlias, ItemTreeFieldId, ItemTreeNode}, - lang_item::LangItemTarget, layout::{self, ReprOptions, TargetDataLayout}, nameres::{self, diagnostics::DefDiagnostic}, per_ns::PerNs, @@ -137,7 +136,6 @@ pub use { HirFileRange, InFile, InFileWrapper, InMacroFile, InRealFile, MacroFilePosition, MacroFileRange, }, - hygiene::{SyntaxContextExt, marks_rev}, inert_attr_macro::AttributeTemplate, mod_path::{ModPath, PathKind, tool_path}, name::Name, @@ -781,7 +779,7 @@ impl Module { let drop_maybe_dangle = (|| { // FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper let trait_ = trait_?; - let drop_trait = db.lang_item(self.krate().into(), LangItem::Drop)?.as_trait()?; + let drop_trait = LangItem::Drop.resolve_trait(db, self.krate().into())?; if drop_trait != trait_.into() { return None; } @@ -2388,14 +2386,11 @@ impl Function { } let Some(impl_traits) = self.ret_type(db).as_impl_traits(db) else { return false }; - let Some(future_trait_id) = - db.lang_item(self.ty(db).env.krate, LangItem::Future).and_then(|t| t.as_trait()) + let Some(future_trait_id) = LangItem::Future.resolve_trait(db, self.ty(db).env.krate) else { return false; }; - let Some(sized_trait_id) = - db.lang_item(self.ty(db).env.krate, LangItem::Sized).and_then(|t| t.as_trait()) - else { + let Some(sized_trait_id) = LangItem::Sized.resolve_trait(db, self.ty(db).env.krate) else { return false; }; @@ -2861,9 +2856,7 @@ pub struct Trait { impl Trait { pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option { - db.lang_item(krate.into(), LangItem::from_name(name)?) - .and_then(LangItemTarget::as_trait) - .map(Into::into) + LangItem::from_name(name)?.resolve_trait(db, krate.into()).map(Into::into) } pub fn module(self, db: &dyn HirDatabase) -> Module { @@ -3692,24 +3685,16 @@ impl GenericDef { } let source_map = match def { - GenericDefId::AdtId(AdtId::EnumId(it)) => { - db.enum_signature_with_source_map(it).1.clone() - } - GenericDefId::AdtId(AdtId::StructId(it)) => { - db.struct_signature_with_source_map(it).1.clone() - } - GenericDefId::AdtId(AdtId::UnionId(it)) => { - db.union_signature_with_source_map(it).1.clone() - } + GenericDefId::AdtId(AdtId::EnumId(it)) => db.enum_signature_with_source_map(it).1, + GenericDefId::AdtId(AdtId::StructId(it)) => db.struct_signature_with_source_map(it).1, + GenericDefId::AdtId(AdtId::UnionId(it)) => db.union_signature_with_source_map(it).1, GenericDefId::ConstId(_) => return, - GenericDefId::FunctionId(it) => db.function_signature_with_source_map(it).1.clone(), - GenericDefId::ImplId(it) => db.impl_signature_with_source_map(it).1.clone(), + GenericDefId::FunctionId(it) => db.function_signature_with_source_map(it).1, + GenericDefId::ImplId(it) => db.impl_signature_with_source_map(it).1, GenericDefId::StaticId(_) => return, - GenericDefId::TraitAliasId(it) => { - db.trait_alias_signature_with_source_map(it).1.clone() - } - GenericDefId::TraitId(it) => db.trait_signature_with_source_map(it).1.clone(), - GenericDefId::TypeAliasId(it) => db.type_alias_signature_with_source_map(it).1.clone(), + GenericDefId::TraitAliasId(it) => db.trait_alias_signature_with_source_map(it).1, + GenericDefId::TraitId(it) => db.trait_signature_with_source_map(it).1, + GenericDefId::TypeAliasId(it) => db.type_alias_signature_with_source_map(it).1, }; expr_store_diagnostics(db, acc, &source_map); @@ -3809,7 +3794,7 @@ impl GenericSubstitution { container_params .chain(self_params) .filter_map(|(ty, name)| { - Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() })) + Some((name?.symbol().clone(), Type { ty, env: self.env.clone() })) }) .collect() } @@ -4989,18 +4974,14 @@ impl Type { /// `std::future::Future` and returns the `Output` associated type. /// This function is used in `.await` syntax completion. pub fn into_future_output(&self, db: &dyn HirDatabase) -> Option { - let trait_ = db - .lang_item(self.env.krate, LangItem::IntoFutureIntoFuture) - .and_then(|it| { - let into_future_fn = it.as_function()?; + let trait_ = LangItem::IntoFutureIntoFuture + .resolve_function(db, self.env.krate) + .and_then(|into_future_fn| { let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?; let into_future_trait = assoc_item.container_or_implemented_trait(db)?; Some(into_future_trait.id) }) - .or_else(|| { - let future_trait = db.lang_item(self.env.krate, LangItem::Future)?; - future_trait.as_trait() - })?; + .or_else(|| LangItem::Future.resolve_trait(db, self.env.krate))?; let canonical_ty = Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; @@ -5015,14 +4996,13 @@ impl Type { /// This does **not** resolve `IntoFuture`, only `Future`. pub fn future_output(self, db: &dyn HirDatabase) -> Option { - let future_output = - db.lang_item(self.env.krate, LangItem::FutureOutput)?.as_type_alias()?; + let future_output = LangItem::FutureOutput.resolve_type_alias(db, self.env.krate)?; self.normalize_trait_assoc_type(db, &[], future_output.into()) } /// This does **not** resolve `IntoIterator`, only `Iterator`. pub fn iterator_item(self, db: &dyn HirDatabase) -> Option { - let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?; + let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?; let iterator_item = db .trait_items(iterator_trait) .associated_type_by_name(&Name::new_symbol_root(sym::Item))?; @@ -5030,9 +5010,7 @@ impl Type { } pub fn impls_iterator(self, db: &dyn HirDatabase) -> bool { - let Some(iterator_trait) = - db.lang_item(self.env.krate, LangItem::Iterator).and_then(|it| it.as_trait()) - else { + let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else { return false; }; let canonical_ty = @@ -5042,12 +5020,13 @@ impl Type { /// Resolves the projection `::IntoIter` and returns the resulting type pub fn into_iterator_iter(self, db: &dyn HirDatabase) -> Option { - let trait_ = db.lang_item(self.env.krate, LangItem::IntoIterIntoIter).and_then(|it| { - let into_iter_fn = it.as_function()?; - let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?; - let into_iter_trait = assoc_item.container_or_implemented_trait(db)?; - Some(into_iter_trait.id) - })?; + let trait_ = LangItem::IntoIterIntoIter.resolve_function(db, self.env.krate).and_then( + |into_iter_fn| { + let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?; + let into_iter_trait = assoc_item.container_or_implemented_trait(db)?; + Some(into_iter_trait.id) + }, + )?; let canonical_ty = Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; @@ -5133,10 +5112,8 @@ impl Type { } pub fn is_copy(&self, db: &dyn HirDatabase) -> bool { - let lang_item = db.lang_item(self.env.krate, LangItem::Copy); - let copy_trait = match lang_item { - Some(LangItemTarget::Trait(it)) => it, - _ => return false, + let Some(copy_trait) = LangItem::Copy.resolve_trait(db, self.env.krate) else { + return false; }; self.impls_trait(db, copy_trait.into(), &[]) } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index f708f2e16673..4d092c1f0bb0 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -25,7 +25,6 @@ use hir_expand::{ builtin::{BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, files::{FileRangeWrapper, InRealFile}, - hygiene::SyntaxContextExt as _, inert_attr_macro::find_builtin_attr_idx, mod_path::{ModPath, PathKind}, name::AsName, @@ -927,7 +926,7 @@ impl<'db> SemanticsImpl<'db> { token: InRealFile, mut cb: impl FnMut(InFile, SyntaxContext) -> ControlFlow, ) -> Option { - self.descend_into_macros_impl(token.clone(), &mut cb) + self.descend_into_macros_impl(token, &mut cb) } /// Descends the token into expansions, returning the tokens that matches the input @@ -959,17 +958,13 @@ impl<'db> SemanticsImpl<'db> { let text = token.text(); let kind = token.kind(); if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() { - self.descend_into_macros_breakable( - token.clone(), - |InFile { value, file_id: _ }, _ctx| { - let mapped_kind = value.kind(); - let any_ident_match = - || kind.is_any_identifier() && value.kind().is_any_identifier(); - let matches = - (kind == mapped_kind || any_ident_match()) && text == value.text(); - if matches { ControlFlow::Break(value) } else { ControlFlow::Continue(()) } - }, - ) + self.descend_into_macros_breakable(token, |InFile { value, file_id: _ }, _ctx| { + let mapped_kind = value.kind(); + let any_ident_match = + || kind.is_any_identifier() && value.kind().is_any_identifier(); + let matches = (kind == mapped_kind || any_ident_match()) && text == value.text(); + if matches { ControlFlow::Break(value) } else { ControlFlow::Continue(()) } + }) } else { None } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 466bf7f6c826..587c51d8cc99 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -559,7 +559,7 @@ impl SourceToDefCtx<'_, '_> { let item = match ast::Item::cast(value.clone()) { Some(it) => it, None => { - let variant = ast::Variant::cast(value.clone())?; + let variant = ast::Variant::cast(value)?; return this .enum_variant_to_def(InFile::new(file_id, &variant)) .map(Into::into); diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 666efe8ec645..c1a75ce7e574 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -556,8 +556,8 @@ impl SourceAnalyzer { } } - let future_trait = db.lang_item(self.resolver.krate(), LangItem::Future)?.as_trait()?; - let poll_fn = db.lang_item(self.resolver.krate(), LangItem::FuturePoll)?.as_function()?; + let future_trait = LangItem::Future.resolve_trait(db, self.resolver.krate())?; + let poll_fn = LangItem::FuturePoll.resolve_function(db, self.resolver.krate())?; // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself // doesn't have any generic parameters, so we skip building another subst for `poll()`. let substs = hir_ty::TyBuilder::subst_for_def(db, future_trait, None).push(ty).build(); @@ -666,7 +666,7 @@ impl SourceAnalyzer { ) -> Option { let ty = self.ty_of_expr(try_expr.expr()?)?; - let op_fn = db.lang_item(self.resolver.krate(), LangItem::TryTraitBranch)?.as_function()?; + let op_fn = LangItem::TryTraitBranch.resolve_function(db, self.resolver.krate())?; let op_trait = match op_fn.lookup(db).container { ItemContainerId::TraitId(id) => id, _ => return None, @@ -1425,13 +1425,13 @@ impl SourceAnalyzer { lang_trait: LangItem, method_name: &Name, ) -> Option<(TraitId, FunctionId)> { - let trait_id = db.lang_item(self.resolver.krate(), lang_trait)?.as_trait()?; + let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?; let fn_id = db.trait_items(trait_id).method_by_name(method_name)?; Some((trait_id, fn_id)) } fn ty_of_expr(&self, expr: ast::Expr) -> Option<&Ty> { - self.infer()?.type_of_expr_or_pat(self.expr_id(expr.clone())?) + self.infer()?.type_of_expr_or_pat(self.expr_id(expr)?) } } diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index 41064d047a5a..e87ab87407ff 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -13,13 +13,13 @@ use hir_def::{ use hir_expand::{HirFileId, name::Name}; use hir_ty::{ db::HirDatabase, - display::{DisplayTarget, HirDisplay, hir_display_with_store}, + display::{HirDisplay, hir_display_with_store}, }; use intern::Symbol; use rustc_hash::FxHashMap; use syntax::{AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr, ast::HasName}; -use crate::{Module, ModuleDef, Semantics}; +use crate::{HasCrate, Module, ModuleDef, Semantics}; pub type FxIndexSet = indexmap::IndexSet>; @@ -66,7 +66,6 @@ pub struct SymbolCollector<'a> { symbols: FxIndexSet, work: Vec, current_container_name: Option, - display_target: DisplayTarget, } /// Given a [`ModuleId`] and a [`HirDatabase`], use the DefMap for the module's crate to collect @@ -78,10 +77,6 @@ impl<'a> SymbolCollector<'a> { symbols: Default::default(), work: Default::default(), current_container_name: None, - display_target: DisplayTarget::from_crate( - db, - *db.all_crates().last().expect("no crate graph present"), - ), } } @@ -93,8 +88,7 @@ impl<'a> SymbolCollector<'a> { pub fn collect(&mut self, module: Module) { let _p = tracing::info_span!("SymbolCollector::collect", ?module).entered(); - tracing::info!(?module, "SymbolCollector::collect",); - self.display_target = module.krate().to_display_target(self.db); + tracing::info!(?module, "SymbolCollector::collect"); // The initial work is the root module we're collecting, additional work will // be populated as we traverse the module's definitions. @@ -263,8 +257,9 @@ impl<'a> SymbolCollector<'a> { for (name, Item { def, vis, import }) in scope.macros() { if let Some(i) = import { match i { - ImportOrGlob::Import(i) => push_import(self, i, name, def.into(), vis), - ImportOrGlob::Glob(_) => (), + ImportOrExternCrate::Import(i) => push_import(self, i, name, def.into(), vis), + ImportOrExternCrate::Glob(_) => (), + ImportOrExternCrate::ExternCrate(_) => (), } continue; } @@ -320,7 +315,10 @@ impl<'a> SymbolCollector<'a> { let impl_data = self.db.impl_signature(impl_id); let impl_name = Some( hir_display_with_store(impl_data.self_ty, &impl_data.store) - .display(self.db, self.display_target) + .display( + self.db, + crate::Impl::from(impl_id).krate(self.db).to_display_target(self.db), + ) .to_smolstr(), ); self.with_container_name(impl_name, |s| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs index 2de0013bb126..fb569f8cdae0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs @@ -5,7 +5,7 @@ //! assists if we are allowed to. use hir::ImportPathConfig; -use ide_db::{SnippetCap, imports::insert_use::InsertUseConfig}; +use ide_db::{SnippetCap, assists::ExprFillDefaultMode, imports::insert_use::InsertUseConfig}; use crate::AssistKind; @@ -21,6 +21,7 @@ pub struct AssistConfig { pub term_search_fuel: u64, pub term_search_borrowck: bool, pub code_action_grouping: bool, + pub expr_fill_default: ExprFillDefaultMode, } impl AssistConfig { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 887ec5aeec9a..6a55f39e6934 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -150,6 +150,7 @@ fn add_missing_impl_members_inner( let new_impl_def = edit.make_mut(impl_def.clone()); let first_new_item = add_trait_assoc_items_to_impl( &ctx.sema, + ctx.config, &missing_items, trait_, &new_impl_def, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 8c1c83e3f716..858d4369914a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -3,6 +3,7 @@ use std::iter::{self, Peekable}; use either::Either; use hir::{Adt, Crate, HasAttrs, ImportPathConfig, ModuleDef, Semantics, sym}; use ide_db::RootDatabase; +use ide_db::assists::ExprFillDefaultMode; use ide_db::syntax_helpers::suggest_name; use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast}; use itertools::Itertools; @@ -216,7 +217,17 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) // filter out hidden patterns because they're handled by the catch-all arm !hidden }) - .map(|(pat, _)| make.match_arm(pat, None, make::ext::expr_todo())); + .map(|(pat, _)| { + make.match_arm( + pat, + None, + match ctx.config.expr_fill_default { + ExprFillDefaultMode::Todo => make::ext::expr_todo(), + ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), + ExprFillDefaultMode::Default => make::ext::expr_todo(), + }, + ) + }); let mut arms: Vec<_> = match_arm_list .arms() @@ -246,7 +257,15 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) if needs_catch_all_arm && !has_catch_all_arm { cov_mark::hit!(added_wildcard_pattern); - let arm = make.match_arm(make.wildcard_pat().into(), None, make::ext::expr_todo()); + let arm = make.match_arm( + make.wildcard_pat().into(), + None, + match ctx.config.expr_fill_default { + ExprFillDefaultMode::Todo => make::ext::expr_todo(), + ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), + ExprFillDefaultMode::Default => make::ext::expr_todo(), + }, + ); arms.push(arm); } @@ -474,8 +493,8 @@ fn build_pat( hir::StructKind::Record => { let fields = fields .into_iter() - .map(|f| make.name_ref(f.name(db).as_str())) - .map(|name_ref| make.record_pat_field_shorthand(name_ref)); + .map(|f| make.ident_pat(false, false, make.name(f.name(db).as_str()))) + .map(|ident| make.record_pat_field_shorthand(ident.into())); let fields = make.record_pat_field_list(fields, None); make.record_pat_with_fields(path, fields).into() } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs index cd23ad223729..bcd06c1ef725 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs @@ -196,7 +196,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_> // Wrap all tails in `Some(...)` let none_path = mapless_make.expr_path(mapless_make.ident_path("None")); let some_path = mapless_make.expr_path(mapless_make.ident_path("Some")); - for_each_tail_expr(&ast::Expr::BlockExpr(closure_body.clone()), &mut |e| { + for_each_tail_expr(&ast::Expr::BlockExpr(closure_body), &mut |e| { let e = match e { ast::Expr::BreakExpr(e) => e.expr(), ast::Expr::ReturnExpr(e) => e.expr(), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs index 1d3a2db3352b..43515de71e20 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs @@ -1066,7 +1066,7 @@ fn foo() { r#" fn foo() { let (mut a, b) = (0.1, "abc"); - fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&str) { + fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&'static str) { *a = 1.2; let c = *b; } @@ -1098,7 +1098,7 @@ fn foo() { r#" fn foo() { let (mut a, b) = (0.1, "abc"); - fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&str) { + fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&'static str) { let _: &mut bool = p2; *a = 1.2; let c = *b; @@ -1136,7 +1136,7 @@ fn foo() { r#" fn foo() { let (mut a, b) = (0.1, "abc"); - fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&str) { + fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&'static str) { let _: &mut bool = p2; *a = 1.2; let c = *b; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs index 24cc32d10d88..db41927f1df2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs @@ -80,7 +80,7 @@ pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_> let from_fn_name = builder.make_mut(from_fn_name); let tail_expr = builder.make_mut(tail_expr); let return_exprs = return_exprs.map(|r| builder.make_mut(r)).collect_vec(); - let associated_items = builder.make_mut(associated_items).clone(); + let associated_items = builder.make_mut(associated_items); ted::replace( trait_ty.syntax(), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs index df92b07cba7c..ebfed9f9ca99 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs @@ -1,8 +1,9 @@ -use hir::Semantics; -use ide_db::RootDatabase; use syntax::T; use syntax::ast::RangeItem; -use syntax::ast::{AstNode, HasName, LetStmt, Name, Pat, edit::AstNodeEdit}; +use syntax::ast::edit::IndentLevel; +use syntax::ast::edit_in_place::Indent; +use syntax::ast::syntax_factory::SyntaxFactory; +use syntax::ast::{self, AstNode, HasName, LetStmt, Pat}; use crate::{AssistContext, AssistId, Assists}; @@ -25,155 +26,205 @@ use crate::{AssistContext, AssistId, Assists}; // } // ``` pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - // should focus on else token to trigger + // Should focus on the `else` token to trigger let let_stmt = ctx .find_token_syntax_at_offset(T![else]) .and_then(|it| it.parent()?.parent()) .or_else(|| ctx.find_token_syntax_at_offset(T![let])?.parent())?; let let_stmt = LetStmt::cast(let_stmt)?; - let let_else_block = let_stmt.let_else()?.block_expr()?; - let let_init = let_stmt.initializer()?; + let else_block = let_stmt.let_else()?.block_expr()?; + let else_expr = if else_block.statements().next().is_none() { + else_block.tail_expr()? + } else { + else_block.into() + }; + let init = let_stmt.initializer()?; + // Ignore let stmt with type annotation if let_stmt.ty().is_some() { - // don't support let with type annotation return None; } let pat = let_stmt.pat()?; - let mut binders = Vec::new(); - binders_in_pat(&mut binders, &pat, &ctx.sema)?; - let target = let_stmt.syntax().text_range(); + let make = SyntaxFactory::with_mappings(); + let mut idents = Vec::default(); + let pat_without_mut = remove_mut_and_collect_idents(&make, &pat, &mut idents)?; + let bindings = idents + .into_iter() + .filter_map(|ref pat| { + // Identifiers which resolve to constants are not bindings + if ctx.sema.resolve_bind_pat_to_const(pat).is_none() { + Some((pat.name()?, pat.ref_token().is_none() && pat.mut_token().is_some())) + } else { + None + } + }) + .collect::>(); + acc.add( AssistId::refactor_rewrite("convert_let_else_to_match"), - "Convert let-else to let and match", - target, - |edit| { - let indent_level = let_stmt.indent_level().0 as usize; - let indent = " ".repeat(indent_level); - let indent1 = " ".repeat(indent_level + 1); + if bindings.is_empty() { + "Convert let-else to match" + } else { + "Convert let-else to let and match" + }, + let_stmt.syntax().text_range(), + |builder| { + let mut editor = builder.make_editor(let_stmt.syntax()); - let binders_str = binders_to_str(&binders, false); - let binders_str_mut = binders_to_str(&binders, true); + let binding_paths = bindings + .iter() + .map(|(name, _)| make.expr_path(make.ident_path(&name.to_string()))) + .collect::>(); - let init_expr = let_init.syntax().text(); - let mut pat_no_mut = pat.syntax().text().to_string(); - // remove the mut from the pattern - for (b, ismut) in binders.iter() { - if *ismut { - pat_no_mut = pat_no_mut.replace(&format!("mut {b}"), &b.to_string()); - } + let binding_arm = make.match_arm( + pat_without_mut, + None, + // There are three possible cases: + // + // - No bindings: `None => {}` + // - Single binding: `Some(it) => it` + // - Multiple bindings: `Foo::Bar { a, b, .. } => (a, b)` + match binding_paths.len() { + 0 => make.expr_empty_block().into(), + + 1 => binding_paths[0].clone(), + _ => make.expr_tuple(binding_paths).into(), + }, + ); + let else_arm = make.match_arm(make.wildcard_pat().into(), None, else_expr); + let match_ = make.expr_match(init, make.match_arm_list([binding_arm, else_arm])); + match_.reindent_to(IndentLevel::from_node(let_stmt.syntax())); + + if bindings.is_empty() { + editor.replace(let_stmt.syntax(), match_.syntax()); + } else { + let ident_pats = bindings + .into_iter() + .map(|(name, is_mut)| make.ident_pat(false, is_mut, name).into()) + .collect::>(); + let new_let_stmt = make.let_stmt( + if ident_pats.len() == 1 { + ident_pats[0].clone() + } else { + make.tuple_pat(ident_pats).into() + }, + None, + Some(match_.into()), + ); + editor.replace(let_stmt.syntax(), new_let_stmt.syntax()); } - let only_expr = let_else_block.statements().next().is_none(); - let branch2 = match &let_else_block.tail_expr() { - Some(tail) if only_expr => format!("{tail},"), - _ => let_else_block.syntax().text().to_string(), - }; - let replace = if binders.is_empty() { - format!( - "match {init_expr} {{ -{indent1}{pat_no_mut} => {binders_str} -{indent1}_ => {branch2} -{indent}}}" - ) - } else { - format!( - "let {binders_str_mut} = match {init_expr} {{ -{indent1}{pat_no_mut} => {binders_str}, -{indent1}_ => {branch2} -{indent}}};" - ) - }; - edit.replace(target, replace); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.vfs_file_id(), editor); }, ) } -/// Gets a list of binders in a pattern, and whether they are mut. -fn binders_in_pat( - acc: &mut Vec<(Name, bool)>, - pat: &Pat, - sem: &Semantics<'_, RootDatabase>, -) -> Option<()> { - use Pat::*; - match pat { - IdentPat(p) => { - let ident = p.name()?; - let ismut = p.ref_token().is_none() && p.mut_token().is_some(); - // check for const reference - if sem.resolve_bind_pat_to_const(p).is_none() { - acc.push((ident, ismut)); - } +fn remove_mut_and_collect_idents( + make: &SyntaxFactory, + pat: &ast::Pat, + acc: &mut Vec, +) -> Option { + Some(match pat { + ast::Pat::IdentPat(p) => { + acc.push(p.clone()); + let non_mut_pat = make.ident_pat( + p.ref_token().is_some(), + p.ref_token().is_some() && p.mut_token().is_some(), + p.name()?, + ); if let Some(inner) = p.pat() { - binders_in_pat(acc, &inner, sem)?; + non_mut_pat.set_pat(remove_mut_and_collect_idents(make, &inner, acc)); } - Some(()) + non_mut_pat.into() } - BoxPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)), - RestPat(_) | LiteralPat(_) | PathPat(_) | WildcardPat(_) | ConstBlockPat(_) => Some(()), - OrPat(p) => { - for p in p.pats() { - binders_in_pat(acc, &p, sem)?; - } - Some(()) + ast::Pat::BoxPat(p) => { + make.box_pat(remove_mut_and_collect_idents(make, &p.pat()?, acc)?).into() } - ParenPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)), - RangePat(p) => { - if let Some(st) = p.start() { - binders_in_pat(acc, &st, sem)? - } - if let Some(ed) = p.end() { - binders_in_pat(acc, &ed, sem)? - } - Some(()) + ast::Pat::OrPat(p) => make + .or_pat( + p.pats() + .map(|pat| remove_mut_and_collect_idents(make, &pat, acc)) + .collect::>>()?, + p.leading_pipe().is_some(), + ) + .into(), + ast::Pat::ParenPat(p) => { + make.paren_pat(remove_mut_and_collect_idents(make, &p.pat()?, acc)?).into() } - RecordPat(p) => { - for f in p.record_pat_field_list()?.fields() { - let pat = f.pat()?; - binders_in_pat(acc, &pat, sem)?; + ast::Pat::RangePat(p) => make + .range_pat( + if let Some(start) = p.start() { + Some(remove_mut_and_collect_idents(make, &start, acc)?) + } else { + None + }, + if let Some(end) = p.end() { + Some(remove_mut_and_collect_idents(make, &end, acc)?) + } else { + None + }, + ) + .into(), + ast::Pat::RecordPat(p) => make + .record_pat_with_fields( + p.path()?, + make.record_pat_field_list( + p.record_pat_field_list()? + .fields() + .map(|field| { + remove_mut_and_collect_idents(make, &field.pat()?, acc).map(|pat| { + if let Some(name_ref) = field.name_ref() { + make.record_pat_field(name_ref, pat) + } else { + make.record_pat_field_shorthand(pat) + } + }) + }) + .collect::>>()?, + p.record_pat_field_list()?.rest_pat(), + ), + ) + .into(), + ast::Pat::RefPat(p) => { + let inner = p.pat()?; + if let ast::Pat::IdentPat(ident) = inner { + acc.push(ident); + p.clone_for_update().into() + } else { + make.ref_pat(remove_mut_and_collect_idents(make, &inner, acc)?).into() } - Some(()) - } - RefPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)), - SlicePat(p) => { - for p in p.pats() { - binders_in_pat(acc, &p, sem)?; - } - Some(()) - } - TuplePat(p) => { - for p in p.fields() { - binders_in_pat(acc, &p, sem)?; - } - Some(()) - } - TupleStructPat(p) => { - for p in p.fields() { - binders_in_pat(acc, &p, sem)?; - } - Some(()) } + ast::Pat::SlicePat(p) => make + .slice_pat( + p.pats() + .map(|pat| remove_mut_and_collect_idents(make, &pat, acc)) + .collect::>>()?, + ) + .into(), + ast::Pat::TuplePat(p) => make + .tuple_pat( + p.fields() + .map(|field| remove_mut_and_collect_idents(make, &field, acc)) + .collect::>>()?, + ) + .into(), + ast::Pat::TupleStructPat(p) => make + .tuple_struct_pat( + p.path()?, + p.fields() + .map(|field| remove_mut_and_collect_idents(make, &field, acc)) + .collect::>>()?, + ) + .into(), + ast::Pat::RestPat(_) + | ast::Pat::LiteralPat(_) + | ast::Pat::PathPat(_) + | ast::Pat::WildcardPat(_) + | ast::Pat::ConstBlockPat(_) => pat.clone(), // don't support macro pat yet - MacroPat(_) => None, - } -} - -fn binders_to_str(binders: &[(Name, bool)], addmut: bool) -> String { - let vars = binders - .iter() - .map( - |(ident, ismut)| { - if *ismut && addmut { format!("mut {ident}") } else { ident.to_string() } - }, - ) - .collect::>() - .join(", "); - if binders.is_empty() { - String::from("{}") - } else if binders.len() == 1 { - vars - } else { - format!("({vars})") - } + ast::Pat::MacroPat(_) => return None, + }) } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs index 800ef89ac6ed..b8c647ac8b71 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs @@ -196,7 +196,9 @@ fn destructure_pat( let fields = field_names.iter().map(|(old_name, new_name)| { // Use shorthand syntax if possible if old_name == new_name && !is_mut { - make.record_pat_field_shorthand(make.name_ref(old_name)) + make.record_pat_field_shorthand( + make.ident_pat(false, false, make.name(old_name)).into(), + ) } else { make.record_pat_field( make.name_ref(old_name), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs index adf0f0997b39..f09389f8302f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs @@ -142,7 +142,7 @@ fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option name, - None => name_generator.suggest_name(&format!("_{}", id)), + None => name_generator.suggest_name(&format!("_{id}")), } .to_string() }) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs index 4e487e216264..b71de5e00c6a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs @@ -56,7 +56,12 @@ fn expand_record_rest_pattern( let new_field_list = make.record_pat_field_list(old_field_list.fields(), None); for (f, _) in missing_fields.iter() { let field = make.record_pat_field_shorthand( - make.name_ref(&f.name(ctx.sema.db).display_no_db(edition).to_smolstr()), + make.ident_pat( + false, + false, + make.name(&f.name(ctx.sema.db).display_no_db(edition).to_smolstr()), + ) + .into(), ); new_field_list.add_field(field); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index 046af71a9dc0..e977798c4fd0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -5033,7 +5033,7 @@ fn main() { fun_name(bar); } -fn $0fun_name(bar: &str) { +fn $0fun_name(bar: &'static str) { m!(bar); } "#, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index 3971b60f2532..31e84e9adcf4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -631,7 +631,7 @@ fn main() { "#, r#" fn main() { - const $0HELLO: &str = "hello"; + const $0HELLO: &'static str = "hello"; } "#, "Extract into constant", @@ -726,7 +726,7 @@ fn main() { "#, r#" fn main() { - static $0HELLO: &str = "hello"; + static $0HELLO: &'static str = "hello"; } "#, "Extract into static", @@ -2528,13 +2528,13 @@ fn foo() { check_assist_by_label( extract_variable, r#" -struct Entry(&str); +struct Entry<'a>(&'a str); fn foo() { let entry = Entry($0"Hello"$0); } "#, r#" -struct Entry(&str); +struct Entry<'a>(&'a str); fn foo() { let $0hello = "Hello"; let entry = Entry(hello); @@ -2546,13 +2546,13 @@ fn foo() { check_assist_by_label( extract_variable, r#" -struct Entry(&str); +struct Entry<'a>(&'a str); fn foo() { let entry = Entry($0"Hello"$0); } "#, r#" -struct Entry(&str); +struct Entry<'a>(&'a str); fn foo() { const $0HELLO: &str = "Hello"; let entry = Entry(HELLO); @@ -2564,13 +2564,13 @@ fn foo() { check_assist_by_label( extract_variable, r#" -struct Entry(&str); +struct Entry<'a>(&'a str); fn foo() { let entry = Entry($0"Hello"$0); } "#, r#" -struct Entry(&str); +struct Entry<'a>(&'a str); fn foo() { static $0HELLO: &str = "Hello"; let entry = Entry(HELLO); @@ -2587,13 +2587,13 @@ fn foo() { check_assist_by_label( extract_variable, r#" -struct Entry { message: &str } +struct Entry<'a> { message: &'a str } fn foo() { let entry = Entry { message: $0"Hello"$0 }; } "#, r#" -struct Entry { message: &str } +struct Entry<'a> { message: &'a str } fn foo() { let $0message = "Hello"; let entry = Entry { message }; @@ -2605,13 +2605,13 @@ fn foo() { check_assist_by_label( extract_variable, r#" -struct Entry { message: &str } +struct Entry<'a> { message: &'a str } fn foo() { let entry = Entry { message: $0"Hello"$0 }; } "#, r#" -struct Entry { message: &str } +struct Entry<'a> { message: &'a str } fn foo() { const $0HELLO: &str = "Hello"; let entry = Entry { message: HELLO }; @@ -2623,13 +2623,13 @@ fn foo() { check_assist_by_label( extract_variable, r#" -struct Entry { message: &str } +struct Entry<'a> { message: &'a str } fn foo() { let entry = Entry { message: $0"Hello"$0 }; } "#, r#" -struct Entry { message: &str } +struct Entry<'a> { message: &'a str } fn foo() { static $0HELLO: &str = "Hello"; let entry = Entry { message: HELLO }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs index 824380253ae5..30084d23d1fb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs @@ -4,6 +4,7 @@ use hir::{ }; use ide_db::{ FileId, FxHashMap, FxHashSet, RootDatabase, SnippetCap, + assists::ExprFillDefaultMode, defs::{Definition, NameRefClass}, famous_defs::FamousDefs, helpers::is_editable_crate, @@ -46,7 +47,7 @@ use crate::{ // bar("", baz()); // } // -// fn bar(arg: &str, baz: Baz) ${0:-> _} { +// fn bar(arg: &'static str, baz: Baz) ${0:-> _} { // todo!() // } // @@ -276,7 +277,11 @@ impl FunctionBuilder { target_module, &mut necessary_generic_params, ); - let placeholder_expr = make::ext::expr_todo(); + let placeholder_expr = match ctx.config.expr_fill_default { + ExprFillDefaultMode::Todo => make::ext::expr_todo(), + ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), + ExprFillDefaultMode::Default => make::ext::expr_todo(), + }; fn_body = make::block_expr(vec![], Some(placeholder_expr)); }; @@ -331,7 +336,11 @@ impl FunctionBuilder { let (generic_param_list, where_clause) = fn_generic_params(ctx, necessary_generic_params, &target)?; - let placeholder_expr = make::ext::expr_todo(); + let placeholder_expr = match ctx.config.expr_fill_default { + ExprFillDefaultMode::Todo => make::ext::expr_todo(), + ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), + ExprFillDefaultMode::Default => make::ext::expr_todo(), + }; let fn_body = make::block_expr(vec![], Some(placeholder_expr)); Some(Self { @@ -383,14 +392,14 @@ impl FunctionBuilder { // Focus the return type if there is one match ret_type { Some(ret_type) => { - edit.add_placeholder_snippet(cap, ret_type.clone()); + edit.add_placeholder_snippet(cap, ret_type); } None => { - edit.add_placeholder_snippet(cap, tail_expr.clone()); + edit.add_placeholder_snippet(cap, tail_expr); } } } else { - edit.add_placeholder_snippet(cap, tail_expr.clone()); + edit.add_placeholder_snippet(cap, tail_expr); } } @@ -444,7 +453,11 @@ fn make_fn_body_as_new_function( let adt_info = adt_info.as_ref()?; let path_self = make::ext::ident_path("Self"); - let placeholder_expr = make::ext::expr_todo(); + let placeholder_expr = match ctx.config.expr_fill_default { + ExprFillDefaultMode::Todo => make::ext::expr_todo(), + ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), + ExprFillDefaultMode::Default => make::ext::expr_todo(), + }; let tail_expr = if let Some(strukt) = adt_info.adt.as_struct() { match strukt.kind(ctx.db()) { StructKind::Record => { @@ -1505,7 +1518,7 @@ fn foo() { bar("bar") } -fn bar(arg: &str) { +fn bar(arg: &'static str) { ${0:todo!()} } "#, @@ -2122,7 +2135,7 @@ fn foo() { bar(baz(), baz(), "foo", "bar") } -fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) { +fn bar(baz_1: Baz, baz_2: Baz, arg_1: &'static str, arg_2: &'static str) { ${0:todo!()} } "#, @@ -3090,7 +3103,7 @@ pub struct Foo { field_2: String, } impl Foo { - fn new(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) -> Self { + fn new(baz_1: Baz, baz_2: Baz, arg_1: &'static str, arg_2: &'static str) -> Self { ${0:Self { field_1: todo!(), field_2: todo!() }} } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs index b7f7cb9cb01c..6bf7f5849148 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs @@ -1,14 +1,14 @@ use either::Either; use ide_db::imports::{ insert_use::{ImportGranularity, InsertUseConfig}, - merge_imports::{MergeBehavior, try_merge_imports, try_merge_trees, try_normalize_use_tree}, + merge_imports::{MergeBehavior, try_merge_imports, try_merge_trees}, }; -use itertools::Itertools; use syntax::{ AstNode, SyntaxElement, SyntaxNode, algo::neighbor, - ast::{self, edit_in_place::Removable}, - match_ast, ted, + ast::{self, syntax_factory::SyntaxFactory}, + match_ast, + syntax_editor::Removable, }; use crate::{ @@ -69,49 +69,32 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio (selection_range, edits?) }; - acc.add(AssistId::refactor_rewrite("merge_imports"), "Merge imports", target, |builder| { - let edits_mut: Vec = edits - .into_iter() - .map(|it| match it { - Remove(Either::Left(it)) => Remove(Either::Left(builder.make_mut(it))), - Remove(Either::Right(it)) => Remove(Either::Right(builder.make_mut(it))), - Replace(old, new) => Replace(builder.make_syntax_mut(old), new), - }) - .collect(); - for edit in edits_mut { - match edit { - Remove(it) => it.as_ref().either(Removable::remove, Removable::remove), - Replace(old, new) => { - ted::replace(old, &new); + let parent_node = match ctx.covering_element() { + SyntaxElement::Node(n) => n, + SyntaxElement::Token(t) => t.parent()?, + }; - // If there's a selection and we're replacing a use tree in a tree list, - // normalize the parent use tree if it only contains the merged subtree. - if !ctx.has_empty_selection() { - let normalized_use_tree = ast::UseTree::cast(new) - .as_ref() - .and_then(ast::UseTree::parent_use_tree_list) - .and_then(|use_tree_list| { - if use_tree_list.use_trees().collect_tuple::<(_,)>().is_some() { - Some(use_tree_list.parent_use_tree()) - } else { - None - } - }) - .and_then(|target_tree| { - try_normalize_use_tree( - &target_tree, - ctx.config.insert_use.granularity.into(), - ) - .map(|top_use_tree_flat| (target_tree, top_use_tree_flat)) - }); - if let Some((old_tree, new_tree)) = normalized_use_tree { - cov_mark::hit!(replace_parent_with_normalized_use_tree); - ted::replace(old_tree.syntax(), new_tree.syntax()); - } + acc.add(AssistId::refactor_rewrite("merge_imports"), "Merge imports", target, |builder| { + let make = SyntaxFactory::with_mappings(); + let mut editor = builder.make_editor(&parent_node); + + for edit in edits { + match edit { + Remove(it) => { + let node = it.as_ref(); + if let Some(left) = node.left() { + left.remove(&mut editor); + } else if let Some(right) = node.right() { + right.remove(&mut editor); } } + Replace(old, new) => { + editor.replace(old, &new); + } } } + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.vfs_file_id(), editor); }) } @@ -723,11 +706,10 @@ use std::{ ); cov_mark::check!(merge_with_selected_use_tree_neighbors); - cov_mark::check!(replace_parent_with_normalized_use_tree); check_assist( merge_imports, r"use std::$0{fmt::Display, fmt::Debug}$0;", - r"use std::fmt::{Debug, Display};", + r"use std::{fmt::{Debug, Display}};", ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index 6dcdf5edbd63..806c8fba9ea4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -9,7 +9,7 @@ use syntax::{ }; use crate::{ - AssistId, + AssistConfig, AssistId, assist_context::{AssistContext, Assists, SourceChangeBuilder}, utils::{ DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items, @@ -128,8 +128,14 @@ fn add_assist( acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| { let insert_after = ted::Position::after(builder.make_mut(adt.clone()).syntax()); let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false); - let impl_def_with_items = - impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path); + let impl_def_with_items = impl_def_from_trait( + &ctx.sema, + ctx.config, + adt, + &annotated_name, + trait_, + replace_trait_path, + ); update_attribute(builder, old_derives, old_tree, old_trait_path, attr); let trait_path = make::ty_path(replace_trait_path.clone()); @@ -217,6 +223,7 @@ fn add_assist( fn impl_def_from_trait( sema: &hir::Semantics<'_, ide_db::RootDatabase>, + config: &AssistConfig, adt: &ast::Adt, annotated_name: &ast::Name, trait_: Option, @@ -241,7 +248,7 @@ fn impl_def_from_trait( let impl_def = generate_trait_impl(adt, make::ty_path(trait_path.clone())); let first_assoc_item = - add_trait_assoc_items_to_impl(sema, &trait_items, trait_, &impl_def, &target_scope); + add_trait_assoc_items_to_impl(sema, config, &trait_items, trait_, &impl_def, &target_scope); // Generate a default `impl` function body for the derived trait. if let ast::AssocItem::Fn(ref func) = first_assoc_item { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_imports.rs similarity index 57% rename from src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs rename to src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_imports.rs index 805a7344494a..c066f41ca47b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_imports.rs @@ -1,7 +1,10 @@ use syntax::{ AstNode, SyntaxKind, - ast::{self, HasVisibility, edit_in_place::Removable, make}, - ted::{self, Position}, + ast::{ + self, HasAttrs, HasVisibility, edit::IndentLevel, edit_in_place::AttrsOwnerEdit, make, + syntax_factory::SyntaxFactory, + }, + syntax_editor::{Element, Position, Removable}, }; use crate::{ @@ -9,9 +12,9 @@ use crate::{ assist_context::{AssistContext, Assists}, }; -// Assist: unmerge_use +// Assist: unmerge_imports // -// Extracts single use item from use list. +// Extracts a use item from a use list into a standalone use list. // // ``` // use std::fmt::{Debug, Display$0}; @@ -21,21 +24,18 @@ use crate::{ // use std::fmt::{Debug}; // use std::fmt::Display; // ``` -pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let tree: ast::UseTree = ctx.find_node_at_offset::()?.clone_for_update(); +pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let tree = ctx.find_node_at_offset::()?; let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?; if tree_list.use_trees().count() < 2 { - cov_mark::hit!(skip_single_use_item); + cov_mark::hit!(skip_single_import); return None; } - let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?; + let use_ = tree_list.syntax().ancestors().find_map(ast::Use::cast)?; let path = resolve_full_path(&tree)?; - let old_parent_range = use_.syntax().parent()?.text_range(); - let new_parent = use_.syntax().parent()?; - // If possible, explain what is going to be done. let label = match tree.path().and_then(|path| path.first_segment()) { Some(name) => format!("Unmerge use of `{name}`"), @@ -43,17 +43,31 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< }; let target = tree.syntax().text_range(); - acc.add(AssistId::refactor_rewrite("unmerge_use"), label, target, |builder| { - let new_use = make::use_( + acc.add(AssistId::refactor_rewrite("unmerge_imports"), label, target, |builder| { + let make = SyntaxFactory::with_mappings(); + let new_use = make.use_( use_.visibility(), - make::use_tree(path, tree.use_tree_list(), tree.rename(), tree.star_token().is_some()), - ) - .clone_for_update(); + make.use_tree(path, tree.use_tree_list(), tree.rename(), tree.star_token().is_some()), + ); + // Add any attributes that are present on the use tree + use_.attrs().for_each(|attr| { + new_use.add_attr(attr.clone_for_update()); + }); - tree.remove(); - ted::insert(Position::after(use_.syntax()), new_use.syntax()); - - builder.replace(old_parent_range, new_parent.to_string()); + let mut editor = builder.make_editor(use_.syntax()); + // Remove the use tree from the current use item + tree.remove(&mut editor); + // Insert a newline and indentation, followed by the new use item + editor.insert_all( + Position::after(use_.syntax()), + vec![ + make.whitespace(&format!("\n{}", IndentLevel::from_node(use_.syntax()))) + .syntax_element(), + new_use.syntax().syntax_element(), + ], + ); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.vfs_file_id(), editor); }) } @@ -80,22 +94,22 @@ mod tests { use super::*; #[test] - fn skip_single_use_item() { - cov_mark::check!(skip_single_use_item); + fn skip_single_import() { + cov_mark::check!(skip_single_import); check_assist_not_applicable( - unmerge_use, + unmerge_imports, r" use std::fmt::Debug$0; ", ); check_assist_not_applicable( - unmerge_use, + unmerge_imports, r" use std::fmt::{Debug$0}; ", ); check_assist_not_applicable( - unmerge_use, + unmerge_imports, r" use std::fmt::Debug as Dbg$0; ", @@ -105,7 +119,7 @@ use std::fmt::Debug as Dbg$0; #[test] fn skip_single_glob_import() { check_assist_not_applicable( - unmerge_use, + unmerge_imports, r" use std::fmt::*$0; ", @@ -113,9 +127,9 @@ use std::fmt::*$0; } #[test] - fn unmerge_use_item() { + fn unmerge_import() { check_assist( - unmerge_use, + unmerge_imports, r" use std::fmt::{Debug, Display$0}; ", @@ -126,7 +140,7 @@ use std::fmt::Display; ); check_assist( - unmerge_use, + unmerge_imports, r" use std::fmt::{Debug, format$0, Display}; ", @@ -140,7 +154,7 @@ use std::fmt::format; #[test] fn unmerge_glob_import() { check_assist( - unmerge_use, + unmerge_imports, r" use std::fmt::{*$0, Display}; ", @@ -152,9 +166,9 @@ use std::fmt::*; } #[test] - fn unmerge_renamed_use_item() { + fn unmerge_renamed_import() { check_assist( - unmerge_use, + unmerge_imports, r" use std::fmt::{Debug, Display as Disp$0}; ", @@ -166,9 +180,9 @@ use std::fmt::Display as Disp; } #[test] - fn unmerge_indented_use_item() { + fn unmerge_indented_import() { check_assist( - unmerge_use, + unmerge_imports, r" mod format { use std::fmt::{Debug, Display$0 as Disp, format}; @@ -184,9 +198,9 @@ mod format { } #[test] - fn unmerge_nested_use_item() { + fn unmerge_nested_import() { check_assist( - unmerge_use, + unmerge_imports, r" use foo::bar::{baz::{qux$0, foobar}, barbaz}; ", @@ -196,7 +210,7 @@ use foo::bar::baz::qux; ", ); check_assist( - unmerge_use, + unmerge_imports, r" use foo::bar::{baz$0::{qux, foobar}, barbaz}; ", @@ -208,9 +222,9 @@ use foo::bar::baz::{qux, foobar}; } #[test] - fn unmerge_use_item_with_visibility() { + fn unmerge_import_with_visibility() { check_assist( - unmerge_use, + unmerge_imports, r" pub use std::fmt::{Debug, Display$0}; ", @@ -222,12 +236,27 @@ pub use std::fmt::Display; } #[test] - fn unmerge_use_item_on_self() { + fn unmerge_import_on_self() { check_assist( - unmerge_use, + unmerge_imports, r"use std::process::{Command, self$0};", r"use std::process::{Command}; use std::process;", ); } + + #[test] + fn unmerge_import_with_attributes() { + check_assist( + unmerge_imports, + r" +#[allow(deprecated)] +use foo::{bar, baz$0};", + r" +#[allow(deprecated)] +use foo::{bar}; +#[allow(deprecated)] +use foo::baz;", + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs index 31ff47a05492..5aedff5cc775 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs @@ -53,8 +53,14 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O |edit| { let pats_after = pipe_token .siblings_with_tokens(Direction::Next) - .filter_map(|it| ast::Pat::cast(it.into_node()?)); - let new_pat = make::or_pat(pats_after, or_pat.leading_pipe().is_some()); + .filter_map(|it| ast::Pat::cast(it.into_node()?)) + .collect::>(); + // It is guaranteed that `pats_after` has at least one element + let new_pat = if pats_after.len() == 1 { + pats_after[0].clone() + } else { + make::or_pat(pats_after, or_pat.leading_pipe().is_some()).into() + }; let new_match_arm = make::match_arm(new_pat, match_arm.guard(), match_arm_body).clone_for_update(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs index 1068d5d4cd57..e1b94673e775 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs @@ -116,7 +116,7 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) - (Some(attr), Some(ident)) if attr.simple_name().map(|v| v.eq("derive")).unwrap_or_default() => { - Some(attempt_get_derive(attr.clone(), ident)) + Some(attempt_get_derive(attr, ident)) } (Some(attr), _) => Some(WrapUnwrapOption::WrapAttr(attr)), @@ -128,7 +128,7 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) - NodeOrToken::Node(node) => ast::Attr::cast(node).map(WrapUnwrapOption::WrapAttr), NodeOrToken::Token(ident) if ident.kind() == syntax::T![ident] => { let attr = ident.parent_ancestors().find_map(ast::Attr::cast)?; - Some(attempt_get_derive(attr.clone(), ident)) + Some(attempt_get_derive(attr, ident)) } _ => None, } @@ -233,7 +233,7 @@ fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) -> if let Some(meta) = attr.meta() { if let (Some(eq), Some(expr)) = (meta.eq_token(), meta.expr()) { raw_tokens.push(NodeOrToken::Token(make::tokens::whitespace(" "))); - raw_tokens.push(NodeOrToken::Token(eq.clone())); + raw_tokens.push(NodeOrToken::Token(eq)); raw_tokens.push(NodeOrToken::Token(make::tokens::whitespace(" "))); expr.syntax().descendants_with_tokens().for_each(|it| { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index a157483a449c..627ed37b04e5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -222,8 +222,8 @@ mod handlers { mod toggle_async_sugar; mod toggle_ignore; mod toggle_macro_delimiter; + mod unmerge_imports; mod unmerge_match_arm; - mod unmerge_use; mod unnecessary_async; mod unqualify_method_call; mod unwrap_block; @@ -363,7 +363,7 @@ mod handlers { toggle_ignore::toggle_ignore, toggle_macro_delimiter::toggle_macro_delimiter, unmerge_match_arm::unmerge_match_arm, - unmerge_use::unmerge_use, + unmerge_imports::unmerge_imports, unnecessary_async::unnecessary_async, unqualify_method_call::unqualify_method_call, unwrap_block::unwrap_block, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index 0593e6930dca..5e6889792db6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -4,6 +4,7 @@ use expect_test::expect; use hir::Semantics; use ide_db::{ EditionedFileId, FileRange, RootDatabase, SnippetCap, + assists::ExprFillDefaultMode, base_db::SourceDatabase, imports::insert_use::{ImportGranularity, InsertUseConfig}, source_change::FileSystemEdit, @@ -35,6 +36,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { term_search_fuel: 400, term_search_borrowck: true, code_action_grouping: true, + expr_fill_default: ExprFillDefaultMode::Todo, }; pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig { @@ -54,6 +56,7 @@ pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig { term_search_fuel: 400, term_search_borrowck: true, code_action_grouping: false, + expr_fill_default: ExprFillDefaultMode::Todo, }; pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig { @@ -73,6 +76,7 @@ pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig { term_search_fuel: 400, term_search_borrowck: true, code_action_grouping: true, + expr_fill_default: ExprFillDefaultMode::Todo, }; pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig { @@ -92,6 +96,7 @@ pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig { term_search_fuel: 400, term_search_borrowck: true, code_action_grouping: true, + expr_fill_default: ExprFillDefaultMode::Todo, }; pub(crate) fn with_single_file(text: &str) -> (RootDatabase, EditionedFileId) { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 00a9d35c3107..01ab0be34b28 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -1737,7 +1737,7 @@ fn foo() { bar("", baz()); } -fn bar(arg: &str, baz: Baz) ${0:-> _} { +fn bar(arg: &'static str, baz: Baz) ${0:-> _} { todo!() } @@ -3339,6 +3339,20 @@ sth!{ } ) } +#[test] +fn doctest_unmerge_imports() { + check_doc_test( + "unmerge_imports", + r#####" +use std::fmt::{Debug, Display$0}; +"#####, + r#####" +use std::fmt::{Debug}; +use std::fmt::Display; +"#####, + ) +} + #[test] fn doctest_unmerge_match_arm() { check_doc_test( @@ -3365,20 +3379,6 @@ fn handle(action: Action) { ) } -#[test] -fn doctest_unmerge_use() { - check_doc_test( - "unmerge_use", - r#####" -use std::fmt::{Debug, Display$0}; -"#####, - r#####" -use std::fmt::{Debug}; -use std::fmt::Display; -"#####, - ) -} - #[test] fn doctest_unnecessary_async() { check_doc_test( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index 0471998f0b14..ef6914fda1d5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -8,6 +8,7 @@ use hir::{ }; use ide_db::{ RootDatabase, + assists::ExprFillDefaultMode, famous_defs::FamousDefs, path_transform::PathTransform, syntax_helpers::{node_ext::preorder_expr, prettify_macro_expansion}, @@ -27,7 +28,10 @@ use syntax::{ ted, }; -use crate::assist_context::{AssistContext, SourceChangeBuilder}; +use crate::{ + AssistConfig, + assist_context::{AssistContext, SourceChangeBuilder}, +}; mod gen_trait_fn_body; pub(crate) mod ref_field_expr; @@ -174,6 +178,7 @@ pub fn filter_assoc_items( /// inserted. pub fn add_trait_assoc_items_to_impl( sema: &Semantics<'_, RootDatabase>, + config: &AssistConfig, original_items: &[InFile], trait_: hir::Trait, impl_: &ast::Impl, @@ -219,7 +224,14 @@ pub fn add_trait_assoc_items_to_impl( match &item { ast::AssocItem::Fn(fn_) if fn_.body().is_none() => { let body = AstNodeEdit::indent( - &make::block_expr(None, Some(make::ext::expr_todo())), + &make::block_expr( + None, + Some(match config.expr_fill_default { + ExprFillDefaultMode::Todo => make::ext::expr_todo(), + ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), + ExprFillDefaultMode::Default => make::ext::expr_todo(), + }), + ), new_indent_level, ); ted::replace(fn_.get_or_create_body().syntax(), body.clone_for_update().syntax()) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index ee1a21f9a1a6..7fbd1fbc1af4 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -363,9 +363,14 @@ pub(crate) fn complete_expr_path( add_keyword("true", "true"); add_keyword("false", "false"); - if in_condition || in_block_expr { - add_keyword("letm", "let mut $0"); - add_keyword("let", "let $0"); + if in_condition { + add_keyword("letm", "let mut $1 = $0"); + add_keyword("let", "let $1 = $0"); + } + + if in_block_expr { + add_keyword("letm", "let mut $1 = $0;"); + add_keyword("let", "let $1 = $0;"); } if after_if_expr { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs index 039742463c81..64bb1fce6ba0 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs @@ -336,7 +336,7 @@ fn main() { } #[test] - fn completes_let_with_space() { + fn completes_let_in_block() { check_edit( "let", r#" @@ -346,7 +346,7 @@ fn main() { "#, r#" fn main() { - let $0 + let $1 = $0; } "#, ); @@ -359,7 +359,97 @@ fn main() { "#, r#" fn main() { - let mut $0 + let mut $1 = $0; +} +"#, + ); + } + + #[test] + fn completes_let_in_condition() { + check_edit( + "let", + r#" +fn main() { + if $0 {} +} +"#, + r#" +fn main() { + if let $1 = $0 {} +} +"#, + ); + check_edit( + "letm", + r#" +fn main() { + if $0 {} +} +"#, + r#" +fn main() { + if let mut $1 = $0 {} +} +"#, + ); + } + + #[test] + fn completes_let_in_no_empty_condition() { + check_edit( + "let", + r#" +fn main() { + if $0x {} +} +"#, + r#" +fn main() { + if let $1 = $0x {} +} +"#, + ); + check_edit( + "letm", + r#" +fn main() { + if $0x {} +} +"#, + r#" +fn main() { + if let mut $1 = $0x {} +} +"#, + ); + } + + #[test] + fn completes_let_in_condition_block() { + check_edit( + "let", + r#" +fn main() { + if { $0 } {} +} +"#, + r#" +fn main() { + if { let $1 = $0; } {} +} +"#, + ); + check_edit( + "letm", + r#" +fn main() { + if { $0 } {} +} +"#, + r#" +fn main() { + if { let mut $1 = $0; } {} } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs index b02f079b7213..8902cd09cec0 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs @@ -116,13 +116,13 @@ fn foo<'lifetime>(foo: &'a$0) {} check( r#" struct Foo; -impl<'impl> Foo { +impl<'r#impl> Foo { fn foo<'func>(&'a$0 self) {} } "#, expect![[r#" lt 'func - lt 'impl + lt 'r#impl lt 'static "#]], ); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index 595997358966..391e2379dcd5 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -387,11 +387,7 @@ fn expand( match ( sema.expand_macro_call(&actual_macro_call), - sema.speculative_expand_macro_call( - &actual_macro_call, - &speculative_args, - fake_ident_token.clone(), - ), + sema.speculative_expand_macro_call(&actual_macro_call, &speculative_args, fake_ident_token), ) { // successful expansions (Some(actual_expansion), Some((fake_expansion, fake_mapped_tokens))) => { @@ -661,9 +657,8 @@ fn expected_type_and_name( )) } else { cov_mark::hit!(expected_type_struct_field_without_leading_char); - let expr_field = token.prev_sibling_or_token()? - .into_node() - .and_then(ast::RecordExprField::cast)?; + cov_mark::hit!(expected_type_struct_field_followed_by_comma); + let expr_field = previous_non_trivia_token(token.clone())?.parent().and_then(ast::RecordExprField::cast)?; let (_, _, ty) = sema.resolve_record_field(&expr_field)?; Some(( Some(ty), @@ -681,7 +676,6 @@ fn expected_type_and_name( .or_else(|| sema.type_of_expr(&expr).map(TypeInfo::original)); (ty, field_name) } else { - cov_mark::hit!(expected_type_struct_field_followed_by_comma); (field_ty, field_name) } }, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index e208b9fd41ae..19cdef30bd96 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -135,7 +135,7 @@ impl fmt::Debug for CompletionItem { }, CompletionItemRefMode::Dereference => "*", }; - s.field("ref_match", &format!("{}@{offset:?}", prefix)); + s.field("ref_match", &format!("{prefix}@{offset:?}")); } if self.trigger_call_info { s.field("trigger_call_info", &true); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index b30ac43bf8fb..d5137949d42f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -1517,7 +1517,7 @@ fn main() { en Enum Enum fn function() fn() fn main() fn() - lc variable &str + lc variable &'static str ma helper!(…) macro_rules! helper ma m!(…) macro_rules! m ma makro!(…) macro_rules! makro @@ -2110,3 +2110,19 @@ fn foo() { "#]], ); } + +#[test] +fn escaped_label() { + check( + r#" +fn main() { + 'r#break: { + break '$0; + } +} + "#, + expect![[r#" + lb 'r#break + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index 15518e98370e..148203107c4c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -1358,7 +1358,7 @@ pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone, { 0u8 } fn main() { fo$0 } "#, CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), - expect!("fn(&mut T) -> u8"), + expect!("fn(&'x mut T) -> u8"), expect!("pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone,"), ); @@ -1391,7 +1391,7 @@ fn main() { } "#, CompletionItemKind::SymbolKind(SymbolKind::Method), - expect!("const fn(&'foo mut self, &Foo) -> !"), + expect!("const fn(&'foo mut self, &'foo Foo) -> !"), expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"), ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs index c7e2d058257e..125e11e9e358 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs @@ -429,18 +429,18 @@ trait Tr { impl Tr<$0 "#, expect![[r#" - en Enum Enum - ma makro!(…) macro_rules! makro + en Enum Enum + ma makro!(…) macro_rules! makro md module - sp Self dyn Tr<{unknown}> - st Record Record - st S S - st Tuple Tuple - st Unit Unit + sp Self dyn Tr<{unknown}> + 'static + st Record Record + st S S + st Tuple Tuple + st Unit Unit tt Tr tt Trait - un Union Union - bt u32 u32 + un Union Union + bt u32 u32 kw crate:: kw self:: "#]], diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml index f1d6b605b002..583318de26df 100644 --- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml @@ -24,6 +24,7 @@ arrayvec.workspace = true indexmap.workspace = true memchr = "2.7.4" salsa.workspace = true +salsa-macros.workspace = true query-group.workspace = true triomphe.workspace = true nohash-hasher.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs index 90ae4a3b5b3a..384eb57c0fd5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs @@ -169,3 +169,15 @@ impl AssistResolveStrategy { #[derive(Clone, Debug)] pub struct GroupLabel(pub String); + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum ExprFillDefaultMode { + Todo, + Default, + Underscore, +} +impl Default for ExprFillDefaultMode { + fn default() -> Self { + Self::Todo + } +} diff --git a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs index e9385253250a..4b0a84a559e2 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs @@ -86,7 +86,7 @@ pub fn items_with_name_in_module( let local_query = match name { NameToImport::Prefix(exact_name, case_sensitive) | NameToImport::Exact(exact_name, case_sensitive) => { - let mut local_query = symbol_index::Query::new(exact_name.clone()); + let mut local_query = symbol_index::Query::new(exact_name); local_query.assoc_search_mode(assoc_item_search); if prefix { local_query.prefix(); @@ -99,7 +99,7 @@ pub fn items_with_name_in_module( local_query } NameToImport::Fuzzy(fuzzy_search_string, case_sensitive) => { - let mut local_query = symbol_index::Query::new(fuzzy_search_string.clone()); + let mut local_query = symbol_index::Query::new(fuzzy_search_string); local_query.fuzzy(); local_query.assoc_search_mode(assoc_item_search); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index d3934e14abf9..63cc7cde2808 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -76,8 +76,10 @@ pub type FxIndexMap = pub type FilePosition = FilePositionWrapper; pub type FileRange = FileRangeWrapper; -#[salsa::db] +#[salsa_macros::db] pub struct RootDatabase { + // FIXME: Revisit this commit now that we migrated to the new salsa, given we store arcs in this + // db directly now // We use `ManuallyDrop` here because every codegen unit that contains a // `&RootDatabase -> &dyn OtherDatabase` cast will instantiate its drop glue in the vtable, // which duplicates `Weak::drop` and `Arc::drop` tens of thousands of times, which makes @@ -89,7 +91,7 @@ pub struct RootDatabase { impl std::panic::RefUnwindSafe for RootDatabase {} -#[salsa::db] +#[salsa_macros::db] impl salsa::Database for RootDatabase { fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {} } @@ -116,7 +118,7 @@ impl fmt::Debug for RootDatabase { } } -#[salsa::db] +#[salsa_macros::db] impl SourceDatabase for RootDatabase { fn file_text(&self, file_id: vfs::FileId) -> FileText { self.files.file_text(file_id) @@ -234,14 +236,6 @@ impl RootDatabase { // ); // hir::db::BodyWithSourceMapQuery.in_db_mut(self).set_lru_capacity(2048); } - - pub fn snapshot(&self) -> Self { - Self { - storage: self.storage.clone(), - files: self.files.clone(), - crates_map: self.crates_map.clone(), - } - } } #[query_group::query_group] diff --git a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs index 17c3f75ce173..cbe31405ab78 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs @@ -51,6 +51,7 @@ pub fn parallel_prime_caches( enum ParallelPrimeCacheWorkerProgress { BeginCrate { crate_id: Crate, crate_name: Symbol }, EndCrate { crate_id: Crate }, + Cancelled(Cancelled), } // We split off def map computation from other work, @@ -71,27 +72,35 @@ pub fn parallel_prime_caches( progress_sender .send(ParallelPrimeCacheWorkerProgress::BeginCrate { crate_id, crate_name })?; - match kind { + let cancelled = Cancelled::catch(|| match kind { PrimingPhase::DefMap => _ = db.crate_def_map(crate_id), PrimingPhase::ImportMap => _ = db.import_map(crate_id), PrimingPhase::CrateSymbols => _ = db.crate_symbols(crate_id.into()), - } + }); - progress_sender.send(ParallelPrimeCacheWorkerProgress::EndCrate { crate_id })?; + match cancelled { + Ok(()) => progress_sender + .send(ParallelPrimeCacheWorkerProgress::EndCrate { crate_id })?, + Err(cancelled) => progress_sender + .send(ParallelPrimeCacheWorkerProgress::Cancelled(cancelled))?, + } } Ok::<_, crossbeam_channel::SendError<_>>(()) }; for id in 0..num_worker_threads { - let worker = prime_caches_worker.clone(); - let db = db.snapshot(); - - stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .allow_leak(true) - .name(format!("PrimeCaches#{id}")) - .spawn(move || Cancelled::catch(|| worker(db.snapshot()))) - .expect("failed to spawn thread"); + stdx::thread::Builder::new( + stdx::thread::ThreadIntent::Worker, + format!("PrimeCaches#{id}"), + ) + .allow_leak(true) + .spawn({ + let worker = prime_caches_worker.clone(); + let db = db.clone(); + move || worker(db) + }) + .expect("failed to spawn thread"); } (work_sender, progress_receiver) @@ -142,9 +151,14 @@ pub fn parallel_prime_caches( continue; } Err(crossbeam_channel::RecvTimeoutError::Disconnected) => { - // our workers may have died from a cancelled task, so we'll check and re-raise here. - db.unwind_if_revision_cancelled(); - break; + // all our workers have exited, mark us as finished and exit + cb(ParallelPrimeCachesProgress { + crates_currently_indexing: vec![], + crates_done, + crates_total: crates_done, + work_type: "Indexing", + }); + return; } }; match worker_progress { @@ -156,6 +170,10 @@ pub fn parallel_prime_caches( crates_to_prime.mark_done(crate_id); crates_done += 1; } + ParallelPrimeCacheWorkerProgress::Cancelled(cancelled) => { + // Cancelled::throw should probably be public + std::panic::resume_unwind(Box::new(cancelled)); + } }; let progress = ParallelPrimeCachesProgress { @@ -186,9 +204,14 @@ pub fn parallel_prime_caches( continue; } Err(crossbeam_channel::RecvTimeoutError::Disconnected) => { - // our workers may have died from a cancelled task, so we'll check and re-raise here. - db.unwind_if_revision_cancelled(); - break; + // all our workers have exited, mark us as finished and exit + cb(ParallelPrimeCachesProgress { + crates_currently_indexing: vec![], + crates_done, + crates_total: crates_done, + work_type: "Populating symbols", + }); + return; } }; match worker_progress { @@ -199,6 +222,10 @@ pub fn parallel_prime_caches( crates_currently_indexing.swap_remove(&crate_id); crates_done += 1; } + ParallelPrimeCacheWorkerProgress::Cancelled(cancelled) => { + // Cancelled::throw should probably be public + std::panic::resume_unwind(Box::new(cancelled)); + } }; let progress = ParallelPrimeCachesProgress { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs index af25c2b2e332..a6da0fd9c5e3 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs @@ -31,7 +31,7 @@ fn foo() { x(); // ^^^ error: expected function, found i32 ""(); - // ^^^^ error: expected function, found &str + // ^^^^ error: expected function, found &'static str foo(); } "#, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs index b56255b1fde4..d72b21099ce3 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs @@ -166,7 +166,7 @@ fn main() { let _ = ptr as bool; //^^^^^^^^^^^ error: cannot cast `*const ()` as `bool` let v = "hello" as bool; - //^^^^^^^^^^^^^^^ error: casting `&str` as `bool` is invalid: needs casting through a raw pointer first + //^^^^^^^^^^^^^^^ error: casting `&'static str` as `bool` is invalid: needs casting through a raw pointer first } "#, ); @@ -956,7 +956,7 @@ fn main() { fn main() { let pointer: usize = &1_i32 as *const i32 as usize; let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `*const i32` as `&i32` + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `*const i32` as `&'static i32` } "#, ); @@ -992,7 +992,7 @@ impl Deref for Foo { fn main() { let _ = "foo" as bool; - //^^^^^^^^^^^^^ error: casting `&str` as `bool` is invalid: needs casting through a raw pointer first + //^^^^^^^^^^^^^ error: casting `&'static str` as `bool` is invalid: needs casting through a raw pointer first let _ = Foo as bool; //^^^^^^^^^^^ error: non-primitive cast: `Foo` as `bool` diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs index 6b02111016c0..a354d123f5ab 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -5,9 +5,13 @@ use hir::{ sym, }; use ide_db::{ - FxHashMap, assists::Assist, famous_defs::FamousDefs, - imports::import_assets::item_for_path_search, source_change::SourceChange, - syntax_helpers::tree_diff::diff, text_edit::TextEdit, + FxHashMap, + assists::{Assist, ExprFillDefaultMode}, + famous_defs::FamousDefs, + imports::import_assets::item_for_path_search, + source_change::SourceChange, + syntax_helpers::tree_diff::diff, + text_edit::TextEdit, use_trivial_constructor::use_trivial_constructor, }; use stdx::format_to; @@ -102,8 +106,9 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option make::ext::expr_todo(), - crate::ExprFillDefaultMode::Default => { + ExprFillDefaultMode::Todo => make::ext::expr_todo(), + ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), + ExprFillDefaultMode::Default => { get_default_constructor(ctx, d, ty).unwrap_or_else(make::ext::expr_todo) } }; @@ -158,9 +163,14 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option, d: &hir::MovedOutOf mod tests { use crate::tests::check_diagnostics; - // FIXME: spans are broken + #[test] + fn operand_field_span_respected() { + check_diagnostics( + r#" +struct NotCopy; +struct S { + field: NotCopy, +} + +fn f(s: &S) -> S { + S { field: s.field } + //^^^^^^^ error: cannot move `NotCopy` out of reference +} + "#, + ); + } #[test] fn move_by_explicit_deref() { @@ -85,7 +100,7 @@ fn consume(_: X) { fn main() { let a = &X(Y); consume(*a); - //^^^^^^^^^^^ error: cannot move `X` out of reference + //^^ error: cannot move `X` out of reference let a = &X(5); consume(*a); } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 8f6ed1a7bdbd..500c5de791dc 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -195,7 +195,7 @@ fn remove_unnecessary_wrapper( let db = ctx.sema.db; let root = db.parse_or_expand(expr_ptr.file_id); let expr = expr_ptr.value.to_node(&root); - let expr = ctx.sema.original_ast_node(expr.clone())?; + let expr = ctx.sema.original_ast_node(expr)?; let Expr::CallExpr(call_expr) = expr else { return None; @@ -306,10 +306,9 @@ fn str_ref_to_owned( acc: &mut Vec, ) -> Option<()> { let expected = d.expected.display(ctx.sema.db, ctx.display_target); - let actual = d.actual.display(ctx.sema.db, ctx.display_target); - // FIXME do this properly - if expected.to_string() != "String" || actual.to_string() != "&str" { + let is_applicable = d.actual.strip_reference().is_str() && expected.to_string() == "String"; + if !is_applicable { return None; } @@ -1176,7 +1175,7 @@ trait B {} fn test(a: &dyn A) -> &dyn B { a - //^ error: expected &dyn B, found &dyn A + //^ error: expected &(dyn B + 'static), found &(dyn A + 'static) } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs index 277aff2e08f4..a933f1b42611 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -1,3 +1,5 @@ +use std::ops::Not; + use hir::{ ClosureStyle, HirDisplay, ImportPathConfig, db::ExpandDatabase, @@ -60,9 +62,13 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option let mut formatter = |_: &hir::Type| String::from("_"); - let assists: Vec = paths + let assists: Vec = d + .expected + .is_unknown() + .not() + .then(|| "todo!()".to_owned()) .into_iter() - .filter_map(|path| { + .chain(paths.into_iter().filter_map(|path| { path.gen_source_code( &scope, &mut formatter, @@ -75,7 +81,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option ctx.display_target, ) .ok() - }) + })) .unique() .map(|code| Assist { id: AssistId::quick_fix("typed-hole"), @@ -95,9 +101,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option #[cfg(test)] mod tests { - use crate::tests::{ - check_diagnostics, check_fixes_unordered, check_has_fix, check_has_single_fix, - }; + use crate::tests::{check_diagnostics, check_fixes_unordered, check_has_fix}; #[test] fn unknown() { @@ -119,9 +123,9 @@ fn main() { if _ {} //^ 💡 error: invalid `_` expression, expected type `bool` let _: fn() -> i32 = _; - //^ error: invalid `_` expression, expected type `fn() -> i32` + //^ 💡 error: invalid `_` expression, expected type `fn() -> i32` let _: fn() -> () = _; // FIXME: This should trigger an assist because `main` matches via *coercion* - //^ error: invalid `_` expression, expected type `fn()` + //^ 💡 error: invalid `_` expression, expected type `fn()` } "#, ); @@ -147,7 +151,7 @@ fn main() { fn main() { let mut x = t(); x = _; - //^ error: invalid `_` expression, expected type `&str` + //^ 💡 error: invalid `_` expression, expected type `&'static str` x = ""; } fn t() -> T { loop {} } @@ -308,7 +312,7 @@ fn main() { #[test] fn ignore_impl_func_with_incorrect_return() { - check_has_single_fix( + check_fixes_unordered( r#" struct Bar {} trait Foo { @@ -323,7 +327,8 @@ fn main() { let a: i32 = 1; let c: Bar = _$0; }"#, - r#" + vec![ + r#" struct Bar {} trait Foo { type Res; @@ -337,6 +342,21 @@ fn main() { let a: i32 = 1; let c: Bar = Bar { }; }"#, + r#" +struct Bar {} +trait Foo { + type Res; + fn foo(&self) -> Self::Res; +} +impl Foo for i32 { + type Res = Self; + fn foo(&self) -> Self::Res { 1 } +} +fn main() { + let a: i32 = 1; + let c: Bar = todo!(); +}"#, + ], ); } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs index 4422d8f8262f..7f07009dc561 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -269,7 +269,7 @@ impl A { } fn main() { let a = A {a: 0, b: ""}; - A::::foo(); + A::::foo(); } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index 11efedd8a59d..607721d611d7 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -92,7 +92,7 @@ use hir::{ }; use ide_db::{ EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap, - assists::{Assist, AssistId, AssistResolveStrategy}, + assists::{Assist, AssistId, AssistResolveStrategy, ExprFillDefaultMode}, base_db::{ReleaseChannel, RootQueryDb as _}, generated::lints::{CLIPPY_LINT_GROUPS, DEFAULT_LINT_GROUPS, DEFAULT_LINTS, Lint, LintGroup}, imports::insert_use::InsertUseConfig, @@ -219,17 +219,6 @@ impl Diagnostic { } } -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum ExprFillDefaultMode { - Todo, - Default, -} -impl Default for ExprFillDefaultMode { - fn default() -> Self { - Self::Todo - } -} - #[derive(Debug, Clone)] pub struct DiagnosticsConfig { /// Whether native diagnostics are enabled. diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs index 13d08d46dedd..4e4bd47e1c2f 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs @@ -3,14 +3,16 @@ mod overly_long_real_world_cases; use ide_db::{ - LineIndexDatabase, RootDatabase, assists::AssistResolveStrategy, base_db::SourceDatabase, + LineIndexDatabase, RootDatabase, + assists::{AssistResolveStrategy, ExprFillDefaultMode}, + base_db::SourceDatabase, }; use itertools::Itertools; use stdx::trim_indent; use test_fixture::WithFixture; use test_utils::{MiniCore, assert_eq_text, extract_annotations}; -use crate::{DiagnosticsConfig, ExprFillDefaultMode, Severity}; +use crate::{DiagnosticsConfig, Severity}; /// Takes a multi-file input fixture with annotated cursor positions, /// and checks that: @@ -160,55 +162,6 @@ pub(crate) fn check_has_fix( assert!(fix.is_some(), "no diagnostic with desired fix"); } -#[track_caller] -pub(crate) fn check_has_single_fix( - #[rust_analyzer::rust_fixture] ra_fixture_before: &str, - #[rust_analyzer::rust_fixture] ra_fixture_after: &str, -) { - let after = trim_indent(ra_fixture_after); - - let (db, file_position) = RootDatabase::with_position(ra_fixture_before); - let mut conf = DiagnosticsConfig::test_sample(); - conf.expr_fill_default = ExprFillDefaultMode::Default; - let mut n_fixes = 0; - let fix = super::full_diagnostics( - &db, - &conf, - &AssistResolveStrategy::All, - file_position.file_id.file_id(&db), - ) - .into_iter() - .find(|d| { - d.fixes - .as_ref() - .and_then(|fixes| { - n_fixes += fixes.len(); - fixes.iter().find(|fix| { - if !fix.target.contains_inclusive(file_position.offset) { - return false; - } - let actual = { - let source_change = fix.source_change.as_ref().unwrap(); - let file_id = *source_change.source_file_edits.keys().next().unwrap(); - let mut actual = db.file_text(file_id).text(&db).to_string(); - - for (edit, snippet_edit) in source_change.source_file_edits.values() { - edit.apply(&mut actual); - if let Some(snippet_edit) = snippet_edit { - snippet_edit.apply(&mut actual); - } - } - actual - }; - after == actual - }) - }) - .is_some() - }); - assert!(fix.is_some(), "no diagnostic with desired fix"); - assert!(n_fixes == 1, "Too many fixes suggested"); -} - /// Checks that there's a diagnostic *without* fix at `$0`. pub(crate) fn check_no_fix(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (db, file_position) = RootDatabase::with_position(ra_fixture); diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index ebbd68bcdf74..f0247f32d7ec 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -599,7 +599,7 @@ fn filename_and_frag_for_def( Some(name) => { match m.attrs(db).by_key(sym::doc).find_string_value_in_tt(sym::keyword) { Some(kw) => { - format!("keyword.{}.html", kw) + format!("keyword.{kw}.html") } None => format!("{}/index.html", name.as_str()), } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 2f2d2252f844..075afcec019f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -634,9 +634,7 @@ fn walk_and_push_ty( } else if let Some(trait_) = t.as_associated_type_parent_trait(db) { push_new_def(trait_.into()); } else if let Some(tp) = t.as_type_param(db) { - let sized_trait = db - .lang_item(t.krate(db).into(), LangItem::Sized) - .and_then(|lang_item| lang_item.as_trait()); + let sized_trait = LangItem::Sized.resolve_trait(db, t.krate(db).into()); tp.trait_bounds(db) .into_iter() .filter(|&it| Some(it.into()) != sized_trait) diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index d469cd7c0cd5..7b7eef9d5793 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -7085,9 +7085,9 @@ fn foo() { } "#, expect![[r#" - ```rust - &str - ```"#]], + ```rust + &'static str + ```"#]], ); } @@ -8228,7 +8228,7 @@ format_args!("{aaaaa$0}"); *aaaaa* ```rust - let aaaaa: &str + let aaaaa: &'static str ``` "#]], ); @@ -8248,7 +8248,7 @@ format_args!("{$0aaaaa}"); *aaaaa* ```rust - let aaaaa: &str + let aaaaa: &'static str ``` "#]], ); @@ -8268,7 +8268,7 @@ format_args!(r"{$0aaaaa}"); *aaaaa* ```rust - let aaaaa: &str + let aaaaa: &'static str ``` "#]], ); @@ -8293,7 +8293,7 @@ foo!(r"{$0aaaaa}"); *aaaaa* ```rust - let aaaaa: &str + let aaaaa: &'static str ``` "#]], ); @@ -8337,7 +8337,7 @@ fn main() { expect![[r#" *"🦀\u{1f980}\\\x41"* ```rust - &str + &'static str ``` ___ @@ -8353,7 +8353,7 @@ fn main() { expect![[r#" *r"🦀\u{1f980}\\\x41"* ```rust - &str + &'static str ``` ___ @@ -8375,7 +8375,7 @@ fsdghs"; fsdghs"* ```rust - &str + &'static str ``` ___ @@ -8395,7 +8395,7 @@ fn main() { expect![[r#" *c"🦀\u{1f980}\\\x41"* ```rust - &{unknown} + &'static {unknown} ``` ___ @@ -8414,7 +8414,7 @@ fn main() { expect![[r#" *r"`[^`]*`"* ```rust - &str + &'static str ``` ___ @@ -8429,7 +8429,7 @@ fn main() { expect![[r#" *r"`"* ```rust - &str + &'static str ``` ___ @@ -8444,7 +8444,7 @@ fn main() { expect![[r#" *r" "* ```rust - &str + &'static str ``` ___ @@ -8460,12 +8460,12 @@ fn main() { expect![[r#" *r" Hello World "* ```rust - &str + &'static str ``` ___ value of literal: ` Hello World ` -"#]], + "#]], ) } @@ -8480,7 +8480,7 @@ fn main() { expect![[r#" *b"\xF0\x9F\xA6\x80\\"* ```rust - &[u8; 5] + &'static [u8; 5] ``` ___ @@ -8496,7 +8496,7 @@ fn main() { expect![[r#" *br"\xF0\x9F\xA6\x80\\"* ```rust - &[u8; 18] + &'static [u8; 18] ``` ___ @@ -9070,7 +9070,7 @@ struct Pedro$0<'a> { ```rust struct Pedro<'a> { - hola: &str, + hola: &'a str, } ``` @@ -9937,7 +9937,7 @@ fn baz() { --- - `U` = `i32`, `T` = `&str` + `U` = `i32`, `T` = `&'static str` "#]], ); } @@ -10030,7 +10030,7 @@ fn bar() { --- - `T` = `i8`, `U` = `&str` + `T` = `i8`, `U` = `&'static str` "#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index 52ea2e5ec58b..36fdd90e8aea 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -380,9 +380,9 @@ fn main() { let foo = foo3(); // ^^^ impl Fn(f64, f64) -> u32 let foo = foo4(); - // ^^^ &dyn Fn(f64, f64) -> u32 + // ^^^ &'static (dyn Fn(f64, f64) -> u32 + 'static) let foo = foo5(); - // ^^^ &dyn Fn(&dyn Fn(f64, f64) -> u32, f64) -> u32 + // ^^^ &'static (dyn Fn(&(dyn Fn(f64, f64) -> u32 + 'static), f64) -> u32 + 'static) let foo = foo6(); // ^^^ impl Fn(f64, f64) -> u32 let foo = foo7(); @@ -413,7 +413,7 @@ fn main() { let foo = foo3(); // ^^^ impl Fn(f64, f64) -> u32 let foo = foo4(); - // ^^^ &dyn Fn(f64, f64) -> u32 + // ^^^ &'static (dyn Fn(f64, f64) -> u32 + 'static) let foo = foo5(); let foo = foo6(); let foo = foo7(); @@ -528,7 +528,7 @@ fn main() { //^^^^ i32 let _ = 22; let test = "test"; - //^^^^ &str + //^^^^ &'static str let test = InnerStruct {}; //^^^^ InnerStruct @@ -618,12 +618,12 @@ impl Iterator for IntoIter { fn main() { let mut data = Vec::new(); - //^^^^ Vec<&str> + //^^^^ Vec<&'static str> data.push("foo"); for i in data { - //^ &str + //^ &'static str let z = i; - //^ &str + //^ &'static str } } "#, @@ -651,8 +651,8 @@ fn main() { //^^ Vec> let _v = { Vec::>::new() }; //^^ Vec> - let _v = { Vec::>::new() }; - //^^ Vec> + let _v = { Vec::>::new() }; + //^^ Vec> } "#, ); @@ -1017,7 +1017,7 @@ fn test(t: T) { "#, expect![[r#" fn test(t: T) { - let f = |a: i32, b: &str, c: T| {}; + let f = |a: i32, b: &'static str, c: T| {}; let result: () = f(42, "", t); } "#]], diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs index de9ca8c000f0..2ec85da4a429 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs @@ -194,7 +194,7 @@ impl Tr for () { //^ impl Tr for () impl dyn Tr { } -//^ impl dyn Tr +//^ impl dyn Tr + 'static static S0: () = 0; static S1: () = {}; diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index a13be6c4927f..aa525a86123d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -123,9 +123,9 @@ pub use ide_completion::{ CallableSnippets, CompletionConfig, CompletionFieldsToResolve, CompletionItem, CompletionItemKind, CompletionItemRefMode, CompletionRelevance, Snippet, SnippetScope, }; -pub use ide_db::text_edit::{Indel, TextEdit}; pub use ide_db::{ FileId, FilePosition, FileRange, RootDatabase, Severity, SymbolKind, + assists::ExprFillDefaultMode, base_db::{Crate, CrateGraphBuilder, FileChange, SourceRoot, SourceRootId}, documentation::Documentation, label::Label, @@ -134,8 +134,9 @@ pub use ide_db::{ search::{ReferenceCategory, SearchScope}, source_change::{FileSystemEdit, SnippetEdit, SourceChange}, symbol_index::Query, + text_edit::{Indel, TextEdit}, }; -pub use ide_diagnostics::{Diagnostic, DiagnosticCode, DiagnosticsConfig, ExprFillDefaultMode}; +pub use ide_diagnostics::{Diagnostic, DiagnosticCode, DiagnosticsConfig}; pub use ide_ssr::SsrError; pub use span::Edition; pub use syntax::{TextRange, TextSize}; @@ -181,7 +182,7 @@ impl AnalysisHost { /// Returns a snapshot of the current state, which you can query for /// semantic information. pub fn analysis(&self) -> Analysis { - Analysis { db: self.db.snapshot() } + Analysis { db: self.db.clone() } } /// Applies changes to the current state of the world. If there are @@ -863,7 +864,7 @@ impl Analysis { where F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, { - let snap = self.db.snapshot(); + let snap = self.db.clone(); Cancelled::catch(|| f(&snap)) } } diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs index 4a06cd919fc3..795c1f2ca3c0 100644 --- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs +++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs @@ -451,7 +451,7 @@ mod tests { assert_eq!(x.len(), 1); match x.into_iter().next().unwrap() { MonikerResult::Local { enclosing_moniker } => { - panic!("Unexpected local enclosed in {:?}", enclosing_moniker); + panic!("Unexpected local enclosed in {enclosing_moniker:?}"); } MonikerResult::Moniker(x) => { assert_eq!(identifier, x.identifier.to_string()); diff --git a/src/tools/rust-analyzer/crates/ide/src/status.rs b/src/tools/rust-analyzer/crates/ide/src/status.rs index 55a0db2d8204..cfcd76d2aa3b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/status.rs +++ b/src/tools/rust-analyzer/crates/ide/src/status.rs @@ -51,8 +51,8 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option) -> String { buf, "Crate: {}\n", match display_name { - Some(it) => format!("{it}({:?})", crate_id), - None => format!("{:?}", crate_id), + Some(it) => format!("{it}({crate_id:?})"), + None => format!("{crate_id:?}"), } ); format_to!(buf, " Root module file id: {}\n", root_file_id.index()); diff --git a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs index 4696fef3209a..7985279679c4 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs @@ -80,7 +80,7 @@ impl<'a> dot::Labeller<'a, Crate, Edge<'a>> for DotCrateGraph<'_> { fn node_id(&'a self, n: &Crate) -> Id<'a> { let id = n.as_id().as_u32(); - Id::new(format!("_{:?}", id)).unwrap() + Id::new(format!("_{id:?}")).unwrap() } fn node_shape(&'a self, _node: &Crate) -> Option> { diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index 89c3be96fcb9..8b2d6e8717d2 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -163,28 +163,28 @@ impl Symbol { pub fn integer(i: usize) -> Self { match i { - 0 => symbols::INTEGER_0.clone(), - 1 => symbols::INTEGER_1.clone(), - 2 => symbols::INTEGER_2.clone(), - 3 => symbols::INTEGER_3.clone(), - 4 => symbols::INTEGER_4.clone(), - 5 => symbols::INTEGER_5.clone(), - 6 => symbols::INTEGER_6.clone(), - 7 => symbols::INTEGER_7.clone(), - 8 => symbols::INTEGER_8.clone(), - 9 => symbols::INTEGER_9.clone(), - 10 => symbols::INTEGER_10.clone(), - 11 => symbols::INTEGER_11.clone(), - 12 => symbols::INTEGER_12.clone(), - 13 => symbols::INTEGER_13.clone(), - 14 => symbols::INTEGER_14.clone(), - 15 => symbols::INTEGER_15.clone(), + 0 => symbols::INTEGER_0, + 1 => symbols::INTEGER_1, + 2 => symbols::INTEGER_2, + 3 => symbols::INTEGER_3, + 4 => symbols::INTEGER_4, + 5 => symbols::INTEGER_5, + 6 => symbols::INTEGER_6, + 7 => symbols::INTEGER_7, + 8 => symbols::INTEGER_8, + 9 => symbols::INTEGER_9, + 10 => symbols::INTEGER_10, + 11 => symbols::INTEGER_11, + 12 => symbols::INTEGER_12, + 13 => symbols::INTEGER_13, + 14 => symbols::INTEGER_14, + 15 => symbols::INTEGER_15, i => Symbol::intern(&format!("{i}")), } } pub fn empty() -> Self { - symbols::__empty.clone() + symbols::__empty } #[inline] diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 3e52dbaea654..2686a75c7c86 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -292,7 +292,7 @@ impl ProjectFolders { }; let file_set_roots = vec![VfsPath::from(ratoml_path.to_owned())]; - let entry = vfs::loader::Entry::Files(vec![ratoml_path.to_owned()]); + let entry = vfs::loader::Entry::Files(vec![ratoml_path]); res.watch.push(res.load.len()); res.load.push(entry); diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs index 34dcf2a18229..0ac25da32941 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs @@ -4,7 +4,7 @@ use crate::grammar::attributes::ATTRIBUTE_FIRST; use super::*; -pub(super) use atom::{LITERAL_FIRST, literal}; +pub(super) use atom::{EXPR_RECOVERY_SET, LITERAL_FIRST, literal}; pub(crate) use atom::{block_expr, match_arm_list}; #[derive(PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs index c66afed91c51..5faf6fc2759e 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs @@ -46,7 +46,6 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = T!['['], T![|], T![async], - T![box], T![break], T![const], T![continue], @@ -68,7 +67,8 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = LIFETIME_IDENT, ])); -pub(super) const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[T![')'], T![']']]); +pub(in crate::grammar) const EXPR_RECOVERY_SET: TokenSet = + TokenSet::new(&[T!['}'], T![')'], T![']'], T![,]]); pub(super) fn atom_expr( p: &mut Parser<'_>, diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs index f5f003be4891..b9f4866574a6 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs @@ -32,6 +32,9 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[ T![impl], T![trait], T![const], + T![async], + T![unsafe], + T![extern], T![static], T![let], T![mod], diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs index 3410505cd46d..770827c6b0d4 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs @@ -81,7 +81,7 @@ fn path_for_qualifier( } const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet = - items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')'], T![,], T![let]])); + expressions::EXPR_RECOVERY_SET.union(items::ITEM_RECOVERY_SET); const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET; fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option { diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs index 460051a0f4a5..4dd44c030f30 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs @@ -199,8 +199,19 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) { } } -const PAT_RECOVERY_SET: TokenSet = - TokenSet::new(&[T![let], T![if], T![while], T![loop], T![match], T![')'], T![,], T![=]]); +const PAT_RECOVERY_SET: TokenSet = TokenSet::new(&[ + T![let], + T![if], + T![while], + T![loop], + T![match], + T![')'], + T![']'], + T!['}'], + T![,], + T![=], + T![&], +]); fn atom_pat(p: &mut Parser<'_>, recovery_set: TokenSet) -> Option { let m = match p.current() { diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs index 0133b7d5d820..9d31e435cf98 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs @@ -20,10 +20,15 @@ pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(TokenSet::new(&[ pub(super) const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[ T![')'], + // test_err type_in_array_recover + // const _: [&]; + T![']'], + T!['}'], T![>], T![,], // test_err struct_field_recover // struct S { f pub g: () } + // struct S { f: pub g: () } T![pub], ]); diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index 585e7ffb1aef..0a5c16dc4c49 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -179,6 +179,15 @@ impl<'a> Converter<'a> { COMMENT } + rustc_lexer::TokenKind::Frontmatter { has_invalid_preceding_whitespace, invalid_infostring } => { + if *has_invalid_preceding_whitespace { + err = "invalid preceding whitespace for frontmatter opening" + } else if *invalid_infostring { + err = "invalid infostring for frontmatter" + } + FRONTMATTER + } + rustc_lexer::TokenKind::Whitespace => WHITESPACE, rustc_lexer::TokenKind::Ident if token_text == "_" => UNDERSCORE, diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs index e6f93a1fbda5..b1727509b137 100644 --- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs +++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs @@ -150,6 +150,7 @@ pub enum SyntaxKind { STRING, COMMENT, ERROR, + FRONTMATTER, IDENT, LIFETIME_IDENT, NEWLINE, @@ -483,6 +484,7 @@ impl SyntaxKind { | YIELD_EXPR | COMMENT | ERROR + | FRONTMATTER | IDENT | LIFETIME_IDENT | NEWLINE @@ -994,7 +996,7 @@ impl SyntaxKind { } } #[macro_export] -macro_rules ! T_ { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [safe] => { $ crate :: SyntaxKind :: SAFE_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; } +macro_rules ! T_ { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [safe] => { $ crate :: SyntaxKind :: SAFE_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; [frontmatter] => { $ crate :: SyntaxKind :: FRONTMATTER } ; } impl ::core::marker::Copy for SyntaxKind {} impl ::core::clone::Clone for SyntaxKind { #[inline] diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs index 6c9d02aaa8f8..24db9478ee56 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs @@ -870,6 +870,10 @@ mod err { run_and_expect_errors("test_data/parser/inline/err/tuple_pat_leading_comma.rs"); } #[test] + fn type_in_array_recover() { + run_and_expect_errors("test_data/parser/inline/err/type_in_array_recover.rs"); + } + #[test] fn unsafe_block_in_mod() { run_and_expect_errors("test_data/parser/inline/err/unsafe_block_in_mod.rs"); } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast index d97fc6c72091..1a8e881dd9e0 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast @@ -35,8 +35,8 @@ SOURCE_FILE WHITESPACE " " LET_STMT LET_KW "let" - ERROR - R_BRACK "]" + ERROR + R_BRACK "]" WHITESPACE " " R_CURLY "}" WHITESPACE "\n" @@ -149,7 +149,8 @@ error 17: expected expression, item or let statement error 25: expected a name error 26: expected `;`, `{`, or `(` error 30: expected pattern -error 31: expected SEMICOLON +error 30: expected SEMICOLON +error 30: expected expression, item or let statement error 53: expected expression error 54: expected R_PAREN error 54: expected SEMICOLON diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast index feb617e1aa2a..b57066f2fb38 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast @@ -23,8 +23,7 @@ SOURCE_FILE L_CURLY "{" WHITESPACE " " DOT2 ".." - ERROR - COMMA "," + COMMA "," WHITESPACE " " R_CURLY "}" SEMICOLON ";" @@ -39,8 +38,7 @@ SOURCE_FILE L_CURLY "{" WHITESPACE " " DOT2 ".." - ERROR - COMMA "," + COMMA "," WHITESPACE " " RECORD_EXPR_FIELD NAME_REF @@ -55,5 +53,6 @@ SOURCE_FILE R_CURLY "}" WHITESPACE "\n" error 21: expected expression +error 21: cannot use a comma after the base struct error 36: expected expression -error 37: expected COMMA +error 36: cannot use a comma after the base struct diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast index 458d7f4e2fa2..5a12c21b647d 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast @@ -26,6 +26,36 @@ SOURCE_FILE WHITESPACE " " R_CURLY "}" WHITESPACE "\n" + STRUCT + STRUCT_KW "struct" + WHITESPACE " " + NAME + IDENT "S" + WHITESPACE " " + RECORD_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + RECORD_FIELD + NAME + IDENT "f" + COLON ":" + WHITESPACE " " + RECORD_FIELD + VISIBILITY + PUB_KW "pub" + WHITESPACE " " + NAME + IDENT "g" + COLON ":" + WHITESPACE " " + TUPLE_TYPE + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + R_CURLY "}" + WHITESPACE "\n" error 12: expected COLON error 12: expected type error 12: expected COMMA +error 38: expected type +error 38: expected COMMA diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs index da32227adcd7..5b1e5a5b8a21 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs @@ -1 +1,2 @@ struct S { f pub g: () } +struct S { f: pub g: () } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast new file mode 100644 index 000000000000..db76e8d7c88a --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast @@ -0,0 +1,15 @@ +SOURCE_FILE + CONST + CONST_KW "const" + WHITESPACE " " + UNDERSCORE "_" + COLON ":" + WHITESPACE " " + SLICE_TYPE + L_BRACK "[" + REF_TYPE + AMP "&" + R_BRACK "]" + SEMICOLON ";" + WHITESPACE "\n" +error 11: expected type diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs new file mode 100644 index 000000000000..039bf8299779 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs @@ -0,0 +1 @@ +const _: [&]; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs index 07a10aaae578..97c0c4bda7df 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs @@ -12,5 +12,5 @@ fn main() { let version_string = std::str::from_utf8(&output.stdout[..]) .expect("rustc --version output must be UTF-8") .trim(); - println!("cargo::rustc-env=RUSTC_VERSION={}", version_string); + println!("cargo::rustc-env=RUSTC_VERSION={version_string}"); } diff --git a/src/tools/rust-analyzer/crates/project-model/src/env.rs b/src/tools/rust-analyzer/crates/project-model/src/env.rs index f2e5df171ae3..e7293b0b2ef6 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/env.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/env.rs @@ -25,7 +25,7 @@ pub(crate) fn inject_cargo_package_env(env: &mut Env, package: &PackageData) { env.set("CARGO_PKG_VERSION_PATCH", package.version.patch.to_string()); env.set("CARGO_PKG_VERSION_PRE", package.version.pre.to_string()); - env.set("CARGO_PKG_AUTHORS", package.authors.join(":").clone()); + env.set("CARGO_PKG_AUTHORS", package.authors.join(":")); env.set("CARGO_PKG_NAME", package.name.clone()); env.set("CARGO_PKG_DESCRIPTION", package.description.as_deref().unwrap_or_default()); diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index c6e0cf36aff2..eec0077ea6e2 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -1370,7 +1370,7 @@ fn detached_file_to_crate_graph( Edition::CURRENT, display_name.clone(), None, - cfg_options.clone(), + cfg_options, None, Env::default(), CrateOrigin::Local { diff --git a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml index 8aeb26294231..8b03d8f8cc7a 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml +++ b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml @@ -20,3 +20,4 @@ syn = { version = "2.0", features = ["full", "extra-traits", "visit-mut"] } [dev-dependencies] expect-test = "1.5.1" salsa.workspace = true +salsa-macros.workspace = true diff --git a/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs b/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs index f4f316c1ac1e..ec4b6b2a4ac3 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs +++ b/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs @@ -178,7 +178,7 @@ pub(crate) fn query_group_impl( let supertraits = &item_trait.supertraits; let db_attr: Attribute = parse_quote! { - #[salsa::db] + #[salsa_macros::db] }; item_trait.attrs.push(db_attr); @@ -210,7 +210,7 @@ pub(crate) fn query_group_impl( .into_iter() .filter(|fn_arg| matches!(fn_arg, FnArg::Typed(_))) .map(|fn_arg| match fn_arg { - FnArg::Typed(pat_type) => pat_type.clone(), + FnArg::Typed(pat_type) => pat_type, FnArg::Receiver(_) => unreachable!("this should have been filtered out"), }) .collect::>(); @@ -407,7 +407,7 @@ pub(crate) fn query_group_impl( .collect::>(); let input_struct = quote! { - #[salsa::input] + #[salsa_macros::input] pub(crate) struct #input_struct_name { #(#fields),* } @@ -418,7 +418,7 @@ pub(crate) fn query_group_impl( let create_data_method = quote! { #[allow(non_snake_case)] - #[salsa::tracked] + #[salsa_macros::tracked] fn #create_data_ident(db: &dyn #trait_name_ident) -> #input_struct_name { #input_struct_name::new(db, #(#field_params),*) } @@ -443,7 +443,7 @@ pub(crate) fn query_group_impl( item_trait.items.append(&mut lookup_signatures); let trait_impl = quote! { - #[salsa::db] + #[salsa_macros::db] impl #trait_name_ident for DB where DB: #supertraits, diff --git a/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs b/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs index d4d40588bfc7..baac3e8bbfe7 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs +++ b/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs @@ -49,7 +49,7 @@ impl ToTokens for TrackedQuery { }) .into_iter() .chain(self.lru.map(|lru| quote!(lru = #lru))); - let annotation = quote!(#[salsa::tracked( #(#options),* )]); + let annotation = quote!(#[salsa_macros::tracked( #(#options),* )]); let pat_and_tys = &self.pat_and_tys; let params = self diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs index 26ed316122a5..f738185b1fe7 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs @@ -6,7 +6,7 @@ use salsa::plumbing::AsId; mod logger_db; use logger_db::LoggerDb; -#[salsa::interned(no_lifetime)] +#[salsa_macros::interned(no_lifetime)] pub struct InternedString { data: String, } diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs index 5cf9be36f70c..bade0c2cd6fa 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs @@ -1,6 +1,6 @@ use std::sync::{Arc, Mutex}; -#[salsa::db] +#[salsa_macros::db] #[derive(Default, Clone)] pub(crate) struct LoggerDb { storage: salsa::Storage, @@ -12,7 +12,7 @@ struct Logger { logs: Arc>>, } -#[salsa::db] +#[salsa_macros::db] impl salsa::Database for LoggerDb { fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { let event = event(); @@ -40,7 +40,7 @@ impl LoggerDb { /// it is meant to be run from outside any tracked functions. pub(crate) fn assert_logs(&self, expected: expect_test::Expect) { let logs = std::mem::take(&mut *self.logger.logs.lock().unwrap()); - expected.assert_eq(&format!("{:#?}", logs)); + expected.assert_eq(&format!("{logs:#?}")); } } diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs index a18b23a7d8a9..cc57ba78455f 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs @@ -4,7 +4,7 @@ mod logger_db; use logger_db::LoggerDb; use query_group_macro::query_group; -#[salsa::input] +#[salsa_macros::input] struct Input { str: String, } @@ -30,7 +30,7 @@ fn invoke_length_query_actual(db: &dyn PartialMigrationDatabase, input: Input) - input.str(db).len() } -#[salsa::tracked] +#[salsa_macros::tracked] fn invoke_length_tracked_actual(db: &dyn PartialMigrationDatabase, input: Input) -> usize { input.str(db).len() } @@ -87,12 +87,12 @@ fn invoke_tracked_query() { fn new_salsa_baseline() { let db = LoggerDb::default(); - #[salsa::input] + #[salsa_macros::input] struct Input { str: String, } - #[salsa::tracked] + #[salsa_macros::tracked] fn new_salsa_length_query(db: &dyn PartialMigrationDatabase, input: Input) -> usize { input.str(db).len() } diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs index 70073ac1de32..ad8ada3ef153 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs @@ -1,6 +1,6 @@ use query_group_macro::query_group; -#[salsa::db] +#[salsa_macros::db] pub trait SourceDb: salsa::Database { /// Text of the file. fn file_text(&self, id: usize) -> String; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs index ea5a5eaa6a44..4dba97c8ec49 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs @@ -182,10 +182,8 @@ fn with_extra_thread( thread_intent: stdx::thread::ThreadIntent, f: impl FnOnce() -> anyhow::Result<()> + Send + 'static, ) -> anyhow::Result<()> { - let handle = stdx::thread::Builder::new(thread_intent) - .name(thread_name.into()) - .stack_size(STACK_SIZE) - .spawn(f)?; + let handle = + stdx::thread::Builder::new(thread_intent, thread_name).stack_size(STACK_SIZE).spawn(f)?; handle.join()?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index a62005e3c085..a1e4adf0844a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -175,7 +175,7 @@ impl flags::AnalysisStats { UsizeWithUnderscore(dep_loc), UsizeWithUnderscore(dep_item_trees), ); - eprintln!(" dependency item stats: {}", dep_item_stats); + eprintln!(" dependency item stats: {dep_item_stats}"); // FIXME(salsa-transition): bring back stats for ParseQuery (file size) // and ParseMacroExpansionQuery (macro expansion "file") size whenever we implement @@ -295,7 +295,7 @@ impl flags::AnalysisStats { UsizeWithUnderscore(workspace_loc), UsizeWithUnderscore(workspace_item_trees), ); - eprintln!(" usages: {}", workspace_item_stats); + eprintln!(" usages: {workspace_item_stats}"); eprintln!(" Dependencies:"); eprintln!( @@ -303,7 +303,7 @@ impl flags::AnalysisStats { UsizeWithUnderscore(dep_loc), UsizeWithUnderscore(dep_item_trees), ); - eprintln!(" declarations: {}", dep_item_stats); + eprintln!(" declarations: {dep_item_stats}"); let crate_def_map_time = crate_def_map_sw.elapsed(); eprintln!("{:<20} {}", "Item Collection:", crate_def_map_time); @@ -701,10 +701,9 @@ impl flags::AnalysisStats { if self.parallel { let mut inference_sw = self.stop_watch(); - let snap = db.snapshot(); bodies .par_iter() - .map_with(snap, |snap, &body| { + .map_with(db.clone(), |snap, &body| { snap.body(body.into()); snap.infer(body.into()); }) @@ -1294,7 +1293,7 @@ impl fmt::Display for UsizeWithUnderscore { let num_str = self.0.to_string(); if num_str.len() <= 3 { - return write!(f, "{}", num_str); + return write!(f, "{num_str}"); } let mut result = String::new(); @@ -1307,7 +1306,7 @@ impl fmt::Display for UsizeWithUnderscore { } let result = result.chars().rev().collect::(); - write!(f, "{}", result) + write!(f, "{result}") } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs index 7c4eeebdfa31..7b12cb14009f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs @@ -15,11 +15,13 @@ impl flags::Diagnostics { pub fn run(self) -> anyhow::Result<()> { const STACK_SIZE: usize = 1024 * 1024 * 8; - let handle = stdx::thread::Builder::new(stdx::thread::ThreadIntent::LatencySensitive) - .name("BIG_STACK_THREAD".into()) - .stack_size(STACK_SIZE) - .spawn(|| self.run_()) - .unwrap(); + let handle = stdx::thread::Builder::new( + stdx::thread::ThreadIntent::LatencySensitive, + "BIG_STACK_THREAD", + ) + .stack_size(STACK_SIZE) + .spawn(|| self.run_()) + .unwrap(); handle.join() } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index c042c26bd188..e3b372c91494 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -7,6 +7,7 @@ use std::{cell::RefCell, fs::read_to_string, panic::AssertUnwindSafe, path::Path use hir::{ChangeWithProcMacros, Crate}; use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig}; +use ide_db::base_db; use itertools::Either; use paths::Utf8PathBuf; use profile::StopWatch; @@ -310,7 +311,7 @@ impl flags::RustcTests { let tester = AssertUnwindSafe(&mut tester); let p = p.clone(); move || { - let _guard = stdx::panic_context::enter(p.display().to_string()); + let _guard = base_db::DbPanicContext::enter(p.display().to_string()); { tester }.0.test(p); } }) { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index 2062294f807c..d258c5d8191f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs @@ -265,10 +265,10 @@ impl flags::Scip { }; if !duplicate_symbol_errors.is_empty() { - eprintln!("{}", DUPLICATE_SYMBOLS_MESSAGE); + eprintln!("{DUPLICATE_SYMBOLS_MESSAGE}"); for (source_location, symbol) in duplicate_symbol_errors { - eprintln!("{}", source_location); - eprintln!(" Duplicate symbol: {}", symbol); + eprintln!("{source_location}"); + eprintln!(" Duplicate symbol: {symbol}"); eprintln!(); } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs index bca7c8a098c2..0362e13b88b7 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs @@ -15,11 +15,13 @@ impl flags::UnresolvedReferences { pub fn run(self) -> anyhow::Result<()> { const STACK_SIZE: usize = 1024 * 1024 * 8; - let handle = stdx::thread::Builder::new(stdx::thread::ThreadIntent::LatencySensitive) - .name("BIG_STACK_THREAD".into()) - .stack_size(STACK_SIZE) - .spawn(|| self.run_()) - .unwrap(); + let handle = stdx::thread::Builder::new( + stdx::thread::ThreadIntent::LatencySensitive, + "BIG_STACK_THREAD", + ) + .stack_size(STACK_SIZE) + .spawn(|| self.run_()) + .unwrap(); handle.join() } @@ -28,7 +30,7 @@ impl flags::UnresolvedReferences { let root = vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(&self.path)).normalize(); let config = crate::config::Config::new( - root.clone(), + root, lsp_types::ClientCapabilities::default(), vec![], None, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs index 0035d941e2c6..d6c80c399ba2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs @@ -148,10 +148,10 @@ impl CommandHandle { let stderr = child.0.stderr().take().unwrap(); let actor = CargoActor::::new(parser, sender, stdout, stderr); - let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("CommandHandle".to_owned()) - .spawn(move || actor.run()) - .expect("failed to spawn thread"); + let thread = + stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "CommandHandle") + .spawn(move || actor.run()) + .expect("failed to spawn thread"); Ok(CommandHandle { program, arguments, current_dir, child, thread, _phantom: PhantomData }) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index dd827949a9c2..03e5b1f6f4b6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -9,13 +9,14 @@ use cfg::{CfgAtom, CfgDiff}; use hir::Symbol; use ide::{ AssistConfig, CallHierarchyConfig, CallableSnippets, CompletionConfig, - CompletionFieldsToResolve, DiagnosticsConfig, ExprFillDefaultMode, GenericParameterHints, - HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve, - InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, - Snippet, SnippetScope, SourceRootId, + CompletionFieldsToResolve, DiagnosticsConfig, GenericParameterHints, HighlightConfig, + HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve, InlayHintsConfig, + JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, Snippet, SnippetScope, + SourceRootId, }; use ide_db::{ SnippetCap, + assists::ExprFillDefaultMode, imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind}, }; use itertools::{Either, Itertools}; @@ -1182,7 +1183,7 @@ impl ConfigChange { source_root_map: Arc>, ) { assert!(self.source_map_change.is_none()); - self.source_map_change = Some(source_root_map.clone()); + self.source_map_change = Some(source_root_map); } } @@ -1493,6 +1494,11 @@ impl Config { term_search_fuel: self.assist_termSearch_fuel(source_root).to_owned() as u64, term_search_borrowck: self.assist_termSearch_borrowcheck(source_root).to_owned(), code_action_grouping: self.code_action_group(), + expr_fill_default: match self.assist_expressionFillDefault(source_root) { + ExprFillDefaultDef::Todo => ExprFillDefaultMode::Todo, + ExprFillDefaultDef::Default => ExprFillDefaultMode::Default, + ExprFillDefaultDef::Underscore => ExprFillDefaultMode::Underscore, + }, } } @@ -1577,6 +1583,7 @@ impl Config { expr_fill_default: match self.assist_expressionFillDefault(source_root) { ExprFillDefaultDef::Todo => ExprFillDefaultMode::Todo, ExprFillDefaultDef::Default => ExprFillDefaultMode::Default, + ExprFillDefaultDef::Underscore => ExprFillDefaultMode::Underscore, }, snippet_cap: self.snippet_cap(), insert_use: self.insert_use_config(source_root), @@ -2527,6 +2534,7 @@ where enum ExprFillDefaultDef { Todo, Default, + Underscore, } #[derive(Serialize, Deserialize, Debug, Clone)] diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs index 9b1463b1126b..438a2a0ba1ea 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs @@ -5,7 +5,7 @@ use std::mem; use cargo_metadata::PackageId; use ide::FileId; -use ide_db::FxHashMap; +use ide_db::{FxHashMap, base_db::DbPanicContext}; use itertools::Itertools; use rustc_hash::FxHashSet; use stdx::iter_eq_by; @@ -215,7 +215,7 @@ pub(crate) fn fetch_native_diagnostics( kind: NativeDiagnosticsFetchKind, ) -> Vec<(FileId, Vec)> { let _p = tracing::info_span!("fetch_native_diagnostics").entered(); - let _ctx = stdx::panic_context::enter("fetch_native_diagnostics".to_owned()); + let _ctx = DbPanicContext::enter("fetch_native_diagnostics".to_owned()); // the diagnostics produced may point to different files not requested by the concrete request, // put those into here and filter later diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs index 67ddc41f3b21..24c433610f1a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs @@ -126,10 +126,8 @@ impl CargoParser for DiscoverProjectParser { Some(msg) } Err(err) => { - let err = DiscoverProjectData::Error { - error: format!("{:#?}\n{}", err, line), - source: None, - }; + let err = + DiscoverProjectData::Error { error: format!("{err:#?}\n{line}"), source: None }; Some(DiscoverProjectMessage::new(err)) } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs index 2778b311e1e3..fc312439d58c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs @@ -133,10 +133,10 @@ impl FlycheckHandle { let actor = FlycheckActor::new(id, sender, config, sysroot_root, workspace_root, manifest_path); let (sender, receiver) = unbounded::(); - let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("Flycheck".to_owned()) - .spawn(move || actor.run(receiver)) - .expect("failed to spawn thread"); + let thread = + stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, format!("Flycheck{id}")) + .spawn(move || actor.run(receiver)) + .expect("failed to spawn thread"); FlycheckHandle { id, sender, _thread: thread } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 820276e8aea2..3b3b9c879754 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -511,7 +511,7 @@ impl GlobalState { self.fetch_workspaces_queue.request_op( format!("workspace vfs file change: {path}"), - FetchWorkspaceRequest { path: Some(path.to_owned()), force_crate_graph_reload }, + FetchWorkspaceRequest { path: Some(path), force_crate_graph_reload }, ); } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs index 3b76edf528b6..f04ada38893a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs @@ -4,7 +4,10 @@ use std::{ panic, thread, }; -use ide_db::base_db::salsa::{self, Cancelled}; +use ide_db::base_db::{ + DbPanicContext, + salsa::{self, Cancelled}, +}; use lsp_server::{ExtractError, Response, ResponseError}; use serde::{Serialize, de::DeserializeOwned}; use stdx::thread::ThreadIntent; @@ -56,7 +59,7 @@ impl RequestDispatcher<'_> { tracing::info_span!("request", method = ?req.method, "request_id" = ?req.id).entered(); tracing::debug!(?params); let result = { - let _pctx = stdx::panic_context::enter(panic_context); + let _pctx = DbPanicContext::enter(panic_context); f(self.global_state, params) }; if let Ok(response) = result_to_response::(req.id, result) { @@ -86,7 +89,7 @@ impl RequestDispatcher<'_> { let global_state_snapshot = self.global_state.snapshot(); let result = panic::catch_unwind(move || { - let _pctx = stdx::panic_context::enter(panic_context); + let _pctx = DbPanicContext::enter(panic_context); f(global_state_snapshot, params) }); @@ -257,7 +260,7 @@ impl RequestDispatcher<'_> { } .spawn(intent, move || { let result = panic::catch_unwind(move || { - let _pctx = stdx::panic_context::enter(panic_context); + let _pctx = DbPanicContext::enter(panic_context); f(world, params) }); match thread_result_to_response::(req.id.clone(), result) { @@ -421,11 +424,8 @@ impl NotificationDispatcher<'_> { tracing::debug!(?params); - let _pctx = stdx::panic_context::enter(format!( - "\nversion: {}\nnotification: {}", - version(), - N::METHOD - )); + let _pctx = + DbPanicContext::enter(format!("\nversion: {}\nnotification: {}", version(), N::METHOD)); if let Err(e) = f(self.global_state, params) { tracing::error!(handler = %N::METHOD, error = %e, "notification handler failed"); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index a30e5d8ce268..b7373f274f05 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -309,7 +309,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { let task = move || -> std::result::Result<(), Cancelled> { if invocation_strategy_once { let saved_file = vfs_path.as_path().map(|p| p.to_owned()); - world.flycheck[0].restart_workspace(saved_file.clone()); + world.flycheck[0].restart_workspace(saved_file); } let target = TargetSpec::for_file(&world, file_id)?.and_then(|it| { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index e08dd80973a7..69983a676261 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -2210,7 +2210,7 @@ fn runnable_action_links( let label = update_test.label(); if let Some(r) = to_proto::make_update_runnable(&r, update_test) { let update_command = to_proto::command::run_single(&r, label.unwrap().as_str()); - group.commands.push(to_command_link(update_command, r.label.clone())); + group.commands.push(to_command_link(update_command, r.label)); } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 96c2ceef6ba1..f6bcb5642c3b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -1064,7 +1064,7 @@ fn main() { ), work_done_progress_params: Default::default(), }); - assert!(res.to_string().contains("&str")); + assert!(res.to_string().contains("&'static str")); let res = server.send_request::(HoverParams { text_document_position_params: TextDocumentPositionParams::new( @@ -1073,7 +1073,7 @@ fn main() { ), work_done_progress_params: Default::default(), }); - assert!(res.to_string().contains("&str")); + assert!(res.to_string().contains("&'static str")); server.request::( GotoDefinitionParams { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs index 3f313b7e57fe..485f32281dde 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs @@ -82,11 +82,8 @@ impl RatomlTest { } Url::parse( - format!( - "file://{}", - path.into_string().to_owned().replace("C:\\", "/c:/").replace('\\', "/") - ) - .as_str(), + format!("file://{}", path.into_string().replace("C:\\", "/c:/").replace('\\', "/")) + .as_str(), ) .unwrap() } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs index 3f97952365f3..2bebb0c1b970 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs @@ -202,7 +202,7 @@ impl Project<'_> { } let mut config = Config::new( - tmp_dir_path.clone(), + tmp_dir_path, lsp_types::ClientCapabilities { workspace: Some(lsp_types::WorkspaceClientCapabilities { did_change_watched_files: Some( @@ -298,8 +298,7 @@ impl Server { ) -> Server { let (connection, client) = Connection::memory(); - let _thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("test server".to_owned()) + let _thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "test server") .spawn(move || main_loop(config, connection).unwrap()) .expect("failed to spawn a thread"); diff --git a/src/tools/rust-analyzer/crates/span/src/hygiene.rs b/src/tools/rust-analyzer/crates/span/src/hygiene.rs index b21102f2db71..7bb88ac3658c 100644 --- a/src/tools/rust-analyzer/crates/span/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/span/src/hygiene.rs @@ -94,16 +94,11 @@ const _: () = { } } impl zalsa_struct_::Configuration for SyntaxContext { + const LOCATION: salsa::plumbing::Location = + salsa::plumbing::Location { file: file!(), line: line!() }; const DEBUG_NAME: &'static str = "SyntaxContextData"; type Fields<'a> = SyntaxContextData; type Struct<'a> = SyntaxContext; - fn struct_from_id<'db>(id: salsa::Id) -> Self::Struct<'db> { - SyntaxContext::from_salsa_id(id) - } - fn deref_struct(s: Self::Struct<'_>) -> salsa::Id { - s.as_salsa_id() - .expect("`SyntaxContext::deref_structs()` called on a root `SyntaxContext`") - } } impl SyntaxContext { pub fn ingredient(db: &Db) -> &zalsa_struct_::IngredientImpl @@ -308,7 +303,7 @@ impl SyntaxContext { } #[cfg(feature = "salsa")] -impl SyntaxContext { +impl<'db> SyntaxContext { const MAX_ID: u32 = salsa::Id::MAX_U32 - 1; #[inline] @@ -340,6 +335,60 @@ impl SyntaxContext { // SAFETY: This comes from a Salsa ID. unsafe { Self::from_u32(id.as_u32()) } } + + #[inline] + pub fn outer_mark( + self, + db: &'db dyn salsa::Database, + ) -> (Option, Transparency) { + (self.outer_expn(db), self.outer_transparency(db)) + } + + #[inline] + pub fn normalize_to_macros_2_0(self, db: &'db dyn salsa::Database) -> SyntaxContext { + self.opaque(db) + } + + #[inline] + pub fn normalize_to_macro_rules(self, db: &'db dyn salsa::Database) -> SyntaxContext { + self.opaque_and_semitransparent(db) + } + + pub fn is_opaque(self, db: &'db dyn salsa::Database) -> bool { + !self.is_root() && self.outer_transparency(db).is_opaque() + } + + pub fn remove_mark( + &mut self, + db: &'db dyn salsa::Database, + ) -> (Option, Transparency) { + let data = *self; + *self = data.parent(db); + (data.outer_expn(db), data.outer_transparency(db)) + } + + pub fn marks( + self, + db: &'db dyn salsa::Database, + ) -> impl Iterator { + let mut marks = self.marks_rev(db).collect::>(); + marks.reverse(); + marks.into_iter() + } + + pub fn marks_rev( + self, + db: &'db dyn salsa::Database, + ) -> impl Iterator { + std::iter::successors(Some(self), move |&mark| Some(mark.parent(db))) + .take_while(|&it| !it.is_root()) + .map(|ctx| { + let mark = ctx.outer_mark(db); + // We stop before taking the root expansion, as such we cannot encounter a `None` outer + // expansion, as only the ROOT has it. + (mark.0.unwrap(), mark.1) + }) + } } #[cfg(not(feature = "salsa"))] #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] diff --git a/src/tools/rust-analyzer/crates/stdx/src/thread.rs b/src/tools/rust-analyzer/crates/stdx/src/thread.rs index 6c742fecf1b6..a34e9e4a6551 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/thread.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/thread.rs @@ -26,12 +26,12 @@ pub use pool::Pool; /// # Panics /// /// Panics if failed to spawn the thread. -pub fn spawn(intent: ThreadIntent, f: F) -> JoinHandle +pub fn spawn(intent: ThreadIntent, name: String, f: F) -> JoinHandle where F: (FnOnce() -> T) + Send + 'static, T: Send + 'static, { - Builder::new(intent).spawn(f).expect("failed to spawn thread") + Builder::new(intent, name).spawn(f).expect("failed to spawn thread") } pub struct Builder { @@ -42,13 +42,8 @@ pub struct Builder { impl Builder { #[must_use] - pub fn new(intent: ThreadIntent) -> Self { - Self { intent, inner: jod_thread::Builder::new(), allow_leak: false } - } - - #[must_use] - pub fn name(self, name: String) -> Self { - Self { inner: self.inner.name(name), ..self } + pub fn new(intent: ThreadIntent, name: impl Into) -> Self { + Self { intent, inner: jod_thread::Builder::new().name(name.into()), allow_leak: false } } #[must_use] @@ -56,6 +51,8 @@ impl Builder { Self { inner: self.inner.stack_size(size), ..self } } + /// Whether dropping should detach the thread + /// instead of joining it. #[must_use] pub fn allow_leak(self, allow_leak: bool) -> Self { Self { allow_leak, ..self } diff --git a/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs b/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs index 074cd747dacc..a8de4db624f1 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs @@ -50,10 +50,9 @@ impl Pool { let extant_tasks = Arc::new(AtomicUsize::new(0)); let mut handles = Vec::with_capacity(threads); - for _ in 0..threads { - let handle = Builder::new(INITIAL_INTENT) + for idx in 0..threads { + let handle = Builder::new(INITIAL_INTENT, format!("Worker{idx}",)) .stack_size(STACK_SIZE) - .name("Worker".into()) .allow_leak(true) .spawn({ let extant_tasks = Arc::clone(&extant_tasks); diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 510d44d00917..4c7704803ef3 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -14,7 +14,7 @@ rust-version.workspace = true [dependencies] either.workspace = true itertools.workspace = true -rowan = "=0.15.15" +rowan.workspace = true rustc-hash.workspace = true rustc-literal-escaper.workspace = true smol_str.workspace = true diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index a0ae0d68581a..10abca7d35d9 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -133,6 +133,7 @@ Meta = SourceFile = '#shebang'? + '#frontmatter'? Attr* Item* diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index 1243f6418fe2..cd9f4dba8908 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -1524,6 +1524,10 @@ impl ast::HasAttrs for SourceFile {} impl ast::HasDocComments for SourceFile {} impl ast::HasModuleItem for SourceFile {} impl SourceFile { + #[inline] + pub fn frontmatter_token(&self) -> Option { + support::token(&self.syntax, T![frontmatter]) + } #[inline] pub fn shebang_token(&self) -> Option { support::token(&self.syntax, T![shebang]) } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index d608a35effa1..596f73e0b103 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -69,6 +69,9 @@ pub mod ext { pub fn expr_todo() -> ast::Expr { expr_from_text("todo!()") } + pub fn expr_underscore() -> ast::Expr { + expr_from_text("_") + } pub fn expr_ty_default(ty: &ast::Type) -> ast::Expr { expr_from_text(&format!("{ty}::default()")) } @@ -706,7 +709,7 @@ pub fn wildcard_pat() -> ast::WildcardPat { } pub fn rest_pat() -> ast::RestPat { - ast_from_text("fn f(..)") + ast_from_text("fn f() { let ..; }") } pub fn literal_pat(lit: &str) -> ast::LiteralPat { @@ -785,8 +788,8 @@ pub fn record_pat_field(name_ref: ast::NameRef, pat: ast::Pat) -> ast::RecordPat ast_from_text(&format!("fn f(S {{ {name_ref}: {pat} }}: ()))")) } -pub fn record_pat_field_shorthand(name_ref: ast::NameRef) -> ast::RecordPatField { - ast_from_text(&format!("fn f(S {{ {name_ref} }}: ()))")) +pub fn record_pat_field_shorthand(pat: ast::Pat) -> ast::RecordPatField { + ast_from_text(&format!("fn f(S {{ {pat} }}: ()))")) } /// Returns a `IdentPat` if the path has just one segment, a `PathPat` otherwise. @@ -798,16 +801,38 @@ pub fn path_pat(path: ast::Path) -> ast::Pat { } /// Returns a `Pat` if the path has just one segment, an `OrPat` otherwise. -pub fn or_pat(pats: impl IntoIterator, leading_pipe: bool) -> ast::Pat { +/// +/// Invariant: `pats` must be length > 1. +pub fn or_pat(pats: impl IntoIterator, leading_pipe: bool) -> ast::OrPat { let leading_pipe = if leading_pipe { "| " } else { "" }; let pats = pats.into_iter().join(" | "); return from_text(&format!("{leading_pipe}{pats}")); - fn from_text(text: &str) -> ast::Pat { + fn from_text(text: &str) -> ast::OrPat { ast_from_text(&format!("fn f({text}: ())")) } } +pub fn box_pat(pat: ast::Pat) -> ast::BoxPat { + ast_from_text(&format!("fn f(box {pat}: ())")) +} + +pub fn paren_pat(pat: ast::Pat) -> ast::ParenPat { + ast_from_text(&format!("fn f(({pat}): ())")) +} + +pub fn range_pat(start: Option, end: Option) -> ast::RangePat { + ast_from_text(&format!( + "fn f({}..{}: ())", + start.map(|e| e.to_string()).unwrap_or_default(), + end.map(|e| e.to_string()).unwrap_or_default() + )) +} + +pub fn ref_pat(pat: ast::Pat) -> ast::RefPat { + ast_from_text(&format!("fn f(&{pat}: ())")) +} + pub fn match_arm(pat: ast::Pat, guard: Option, expr: ast::Expr) -> ast::MatchArm { return match guard { Some(guard) => from_text(&format!("{pat} {guard} => {expr}")), diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs index 1854000d3db2..8dee3964d448 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -3,7 +3,7 @@ use crate::{ AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken, ast::{ self, HasArgList, HasGenericArgs, HasGenericParams, HasLoopBody, HasName, HasTypeBounds, - HasVisibility, make, + HasVisibility, RangeItem, make, }, syntax_editor::SyntaxMappingBuilder, }; @@ -107,6 +107,20 @@ impl SyntaxFactory { ast } + pub fn use_(&self, visibility: Option, use_tree: ast::UseTree) -> ast::Use { + make::use_(visibility, use_tree).clone_for_update() + } + + pub fn use_tree( + &self, + path: ast::Path, + use_tree_list: Option, + alias: Option, + add_star: bool, + ) -> ast::UseTree { + make::use_tree(path, use_tree_list, alias, add_star).clone_for_update() + } + pub fn path_unqualified(&self, segment: ast::PathSegment) -> ast::Path { let ast = make::path_unqualified(segment.clone()).clone_for_update(); @@ -254,12 +268,12 @@ impl SyntaxFactory { ast } - pub fn record_pat_field_shorthand(&self, name_ref: ast::NameRef) -> ast::RecordPatField { - let ast = make::record_pat_field_shorthand(name_ref.clone()).clone_for_update(); + pub fn record_pat_field_shorthand(&self, pat: ast::Pat) -> ast::RecordPatField { + let ast = make::record_pat_field_shorthand(pat.clone()).clone_for_update(); if let Some(mut mapping) = self.mappings() { let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); - builder.map_node(name_ref.syntax().clone(), ast.pat().unwrap().syntax().clone()); + builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone()); builder.finish(&mut mapping); } @@ -294,6 +308,76 @@ impl SyntaxFactory { make::rest_pat().clone_for_update() } + pub fn or_pat( + &self, + pats: impl IntoIterator, + leading_pipe: bool, + ) -> ast::OrPat { + let (pats, input) = iterator_input(pats); + let ast = make::or_pat(pats, leading_pipe).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_children(input, ast.pats().map(|it| it.syntax().clone())); + builder.finish(&mut mapping); + } + + ast + } + + pub fn box_pat(&self, pat: ast::Pat) -> ast::BoxPat { + let ast = make::box_pat(pat.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn paren_pat(&self, pat: ast::Pat) -> ast::ParenPat { + let ast = make::paren_pat(pat.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn range_pat(&self, start: Option, end: Option) -> ast::RangePat { + let ast = make::range_pat(start.clone(), end.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + if let Some(start) = start { + builder.map_node(start.syntax().clone(), ast.start().unwrap().syntax().clone()); + } + if let Some(end) = end { + builder.map_node(end.syntax().clone(), ast.end().unwrap().syntax().clone()); + } + builder.finish(&mut mapping); + } + + ast + } + + pub fn ref_pat(&self, pat: ast::Pat) -> ast::RefPat { + let ast = make::ref_pat(pat.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + pub fn block_expr( &self, statements: impl IntoIterator, @@ -673,6 +757,38 @@ impl SyntaxFactory { ast } + pub fn let_else_stmt( + &self, + pattern: ast::Pat, + ty: Option, + initializer: ast::Expr, + diverging: ast::BlockExpr, + ) -> ast::LetStmt { + let ast = make::let_else_stmt( + pattern.clone(), + ty.clone(), + initializer.clone(), + diverging.clone(), + ) + .clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(pattern.syntax().clone(), ast.pat().unwrap().syntax().clone()); + if let Some(input) = ty { + builder.map_node(input.syntax().clone(), ast.ty().unwrap().syntax().clone()); + } + builder.map_node( + initializer.syntax().clone(), + ast.initializer().unwrap().syntax().clone(), + ); + builder.map_node(diverging.syntax().clone(), ast.let_else().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + pub fn type_arg(&self, ty: ast::Type) -> ast::TypeArg { let ast = make::type_arg(ty.clone()).clone_for_update(); diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 58200189c46b..31caf618be90 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -20,6 +20,7 @@ mod edit_algo; mod edits; mod mapping; +pub use edits::Removable; pub use mapping::{SyntaxMapping, SyntaxMappingBuilder}; #[derive(Debug)] diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs index 6a9c88b55d7e..01c1f0d49bfd 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -391,7 +391,7 @@ fn report_intersecting_changes( fn to_owning_node(element: &SyntaxElement) -> SyntaxNode { match element { SyntaxElement::Node(node) => node.clone(), - SyntaxElement::Token(token) => token.parent().unwrap().clone(), + SyntaxElement::Token(token) => token.parent().unwrap(), } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs index 350cb3e2544f..d66ea8aa28cf 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs @@ -1,7 +1,8 @@ //! Structural editing for ast using `SyntaxEditor` use crate::{ - Direction, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T, + AstToken, Direction, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T, + algo::neighbor, ast::{ self, AstNode, Fn, GenericParam, HasGenericParams, HasName, edit::IndentLevel, make, syntax_factory::SyntaxFactory, @@ -143,6 +144,53 @@ fn normalize_ws_between_braces(editor: &mut SyntaxEditor, node: &SyntaxNode) -> Some(()) } +pub trait Removable: AstNode { + fn remove(&self, editor: &mut SyntaxEditor); +} + +impl Removable for ast::Use { + fn remove(&self, editor: &mut SyntaxEditor) { + let make = SyntaxFactory::without_mappings(); + + let next_ws = self + .syntax() + .next_sibling_or_token() + .and_then(|it| it.into_token()) + .and_then(ast::Whitespace::cast); + if let Some(next_ws) = next_ws { + let ws_text = next_ws.syntax().text(); + if let Some(rest) = ws_text.strip_prefix('\n') { + if rest.is_empty() { + editor.delete(next_ws.syntax()); + } else { + editor.replace(next_ws.syntax(), make.whitespace(rest)); + } + } + } + + editor.delete(self.syntax()); + } +} + +impl Removable for ast::UseTree { + fn remove(&self, editor: &mut SyntaxEditor) { + for dir in [Direction::Next, Direction::Prev] { + if let Some(next_use_tree) = neighbor(self, dir) { + let separators = self + .syntax() + .siblings_with_tokens(dir) + .skip(1) + .take_while(|it| it.as_node() != Some(next_use_tree.syntax())); + for sep in separators { + editor.delete(sep); + } + break; + } + } + editor.delete(self.syntax()); + } +} + #[cfg(test)] mod tests { use parser::Edition; diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index 2f379d419e8f..f6ca5ab6c8c5 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -353,7 +353,7 @@ impl ChangeFixture { )]), CrateOrigin::Local { repo: None, name: None }, true, - proc_macro_cwd.clone(), + proc_macro_cwd, crate_ws_data, ); proc_macros.insert(proc_macros_crate, Ok(proc_macro)); diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs index 36ccb67f3b8d..1dbc07c0929c 100644 --- a/src/tools/rust-analyzer/crates/tt/src/lib.rs +++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs @@ -728,9 +728,9 @@ fn print_debug_subtree( }; write!(f, "{align}SUBTREE {delim} ",)?; - write!(f, "{:#?}", open)?; + write!(f, "{open:#?}")?; write!(f, " ")?; - write!(f, "{:#?}", close)?; + write!(f, "{close:#?}")?; for child in iter { writeln!(f)?; print_debug_token(f, level + 1, child)?; @@ -855,7 +855,7 @@ impl fmt::Display for Literal { } }?; if let Some(suffix) = &self.suffix { - write!(f, "{}", suffix)?; + write!(f, "{suffix}")?; } Ok(()) } diff --git a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs index e918fd0887db..a03337dbc51e 100644 --- a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs +++ b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs @@ -38,8 +38,7 @@ impl loader::Handle for NotifyHandle { fn spawn(sender: loader::Sender) -> NotifyHandle { let actor = NotifyActor::new(sender); let (sender, receiver) = unbounded::(); - let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("VfsLoader".to_owned()) + let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "VfsLoader") .spawn(move || actor.run(receiver)) .expect("failed to spawn thread"); NotifyHandle { sender, _thread: thread } diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index 09c127f6bcd8..90e4d65bf961 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -21079f53a359d9fc82668d4175d49dafdb600563 +6e23095adf9209614a45f7f75fea36dad7b92afb diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs index 82df78c1a898..824b38fc872d 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs @@ -414,7 +414,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { .map(|kind| to_pascal_case(kind)) .filter(|name| !defined_nodes.iter().any(|&it| it == name)) { - eprintln!("Warning: node {} not defined in AST source", node); + eprintln!("Warning: node {node} not defined in AST source"); drop(node); } @@ -670,6 +670,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String { [ident] => { $crate::SyntaxKind::IDENT }; [string] => { $crate::SyntaxKind::STRING }; [shebang] => { $crate::SyntaxKind::SHEBANG }; + [frontmatter] => { $crate::SyntaxKind::FRONTMATTER }; } impl ::core::marker::Copy for SyntaxKind {} diff --git a/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs b/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs index f3b786b9d867..ae53771fe8e5 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs @@ -159,7 +159,7 @@ fn collect_tests(s: &str) -> Vec { (name.to_owned(), Some(edition.to_owned())) } [name] => (name.to_owned(), None), - _ => panic!("invalid test name: {:?}", name), + _ => panic!("invalid test name: {name:?}"), }; let text: String = edition .as_ref() @@ -212,7 +212,7 @@ fn existing_tests(dir: &Path, ok: TestKind) -> Result( ) } -/// Decorates `ra_build_cmd` to add PGO instrumentation, and then runs the PGO instrumented -/// Rust Analyzer on itself to gather a PGO profile. -fn gather_pgo_profile<'a>( - sh: &'a Shell, - ra_build_cmd: Cmd<'a>, - target: &str, - train_crate: PgoTrainingCrate, -) -> anyhow::Result { - let pgo_dir = std::path::absolute("rust-analyzer-pgo")?; - // Clear out any stale profiles - if pgo_dir.is_dir() { - std::fs::remove_dir_all(&pgo_dir)?; - } - std::fs::create_dir_all(&pgo_dir)?; - - // Figure out a path to `llvm-profdata` - let target_libdir = cmd!(sh, "rustc --print=target-libdir") - .read() - .context("cannot resolve target-libdir from rustc")?; - let target_bindir = PathBuf::from(target_libdir).parent().unwrap().join("bin"); - let llvm_profdata = target_bindir.join("llvm-profdata").with_extension(EXE_EXTENSION); - - // Build RA with PGO instrumentation - let cmd_gather = - ra_build_cmd.env("RUSTFLAGS", format!("-Cprofile-generate={}", pgo_dir.to_str().unwrap())); - cmd_gather.run().context("cannot build rust-analyzer with PGO instrumentation")?; - - let (train_path, label) = match &train_crate { - PgoTrainingCrate::RustAnalyzer => (PathBuf::from("."), "itself"), - PgoTrainingCrate::GitHub(repo) => { - (download_crate_for_training(sh, &pgo_dir, repo)?, repo.as_str()) - } - }; - - // Run RA either on itself or on a downloaded crate - eprintln!("Training RA on {label}..."); - cmd!( - sh, - "target/{target}/release/rust-analyzer analysis-stats -q --run-all-ide-things {train_path}" - ) - .run() - .context("cannot generate PGO profiles")?; - - // Merge profiles into a single file - let merged_profile = pgo_dir.join("merged.profdata"); - let profile_files = std::fs::read_dir(pgo_dir)?.filter_map(|entry| { - let entry = entry.ok()?; - if entry.path().extension() == Some(OsStr::new("profraw")) { - Some(entry.path().to_str().unwrap().to_owned()) - } else { - None - } - }); - cmd!(sh, "{llvm_profdata} merge {profile_files...} -o {merged_profile}").run().context( - "cannot merge PGO profiles. Do you have the rustup `llvm-tools` component installed?", - )?; - - Ok(merged_profile) -} - -/// Downloads a crate from GitHub, stores it into `pgo_dir` and returns a path to it. -fn download_crate_for_training(sh: &Shell, pgo_dir: &Path, repo: &str) -> anyhow::Result { - let mut it = repo.splitn(2, '@'); - let repo = it.next().unwrap(); - let revision = it.next(); - - // FIXME: switch to `--revision` here around 2035 or so - let revision = - if let Some(revision) = revision { &["--branch", revision] as &[&str] } else { &[] }; - - let normalized_path = repo.replace("/", "-"); - let target_path = pgo_dir.join(normalized_path); - cmd!(sh, "git clone --depth 1 https://github.com/{repo} {revision...} {target_path}") - .run() - .with_context(|| "cannot download PGO training crate from {repo}")?; - - Ok(target_path) -} - fn gzip(src_path: &Path, dest_path: &Path) -> anyhow::Result<()> { let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best()); let mut input = io::BufReader::new(File::open(src_path)?); @@ -283,21 +201,8 @@ struct Target { } impl Target { - fn get(project_root: &Path) -> Self { - let name = match env::var("RA_TARGET") { - Ok(target) => target, - _ => { - if cfg!(target_os = "linux") { - "x86_64-unknown-linux-gnu".to_owned() - } else if cfg!(target_os = "windows") { - "x86_64-pc-windows-msvc".to_owned() - } else if cfg!(target_os = "macos") { - "x86_64-apple-darwin".to_owned() - } else { - panic!("Unsupported OS, maybe try setting RA_TARGET") - } - } - }; + fn get(project_root: &Path, sh: &Shell) -> Self { + let name = detect_target(sh); let (name, libc_suffix) = match name.split_once('.') { Some((l, r)) => (l.to_owned(), Some(r.to_owned())), None => (name, None), diff --git a/src/tools/rust-analyzer/xtask/src/flags.rs b/src/tools/rust-analyzer/xtask/src/flags.rs index 700806d178c3..2fd471b35c7e 100644 --- a/src/tools/rust-analyzer/xtask/src/flags.rs +++ b/src/tools/rust-analyzer/xtask/src/flags.rs @@ -4,6 +4,25 @@ use std::{fmt, str::FromStr}; use crate::install::{ClientOpt, ProcMacroServerOpt, ServerOpt}; +#[derive(Debug, Clone)] +pub enum PgoTrainingCrate { + // Use RA's own sources for PGO training + RustAnalyzer, + // Download a Rust crate from `https://github.com/{0}` and use it for PGO training. + GitHub(String), +} + +impl FromStr for PgoTrainingCrate { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "rust-analyzer" => Ok(Self::RustAnalyzer), + url => Ok(Self::GitHub(url.to_owned())), + } + } +} + xflags::xflags! { src "./src/flags.rs" @@ -29,6 +48,9 @@ xflags::xflags! { /// build in release with debug info set to 2. optional --dev-rel + + /// Apply PGO optimizations + optional --pgo pgo: PgoTrainingCrate } cmd fuzz-tests {} @@ -109,18 +131,16 @@ pub enum XtaskCmd { Tidy(Tidy), } -#[derive(Debug)] -pub struct Tidy {} - #[derive(Debug)] pub struct Install { pub client: bool, pub code_bin: Option, pub server: bool, - pub proc_macro_server: bool, pub mimalloc: bool, pub jemalloc: bool, + pub proc_macro_server: bool, pub dev_rel: bool, + pub pgo: Option, } #[derive(Debug)] @@ -143,25 +163,6 @@ pub struct RustcPush { pub branch: Option, } -#[derive(Debug)] -pub enum PgoTrainingCrate { - // Use RA's own sources for PGO training - RustAnalyzer, - // Download a Rust crate from `https://github.com/{0}` and use it for PGO training. - GitHub(String), -} - -impl FromStr for PgoTrainingCrate { - type Err = String; - - fn from_str(s: &str) -> Result { - match s { - "rust-analyzer" => Ok(Self::RustAnalyzer), - url => Ok(Self::GitHub(url.to_owned())), - } - } -} - #[derive(Debug)] pub struct Dist { pub mimalloc: bool, @@ -195,6 +196,9 @@ pub struct Codegen { pub check: bool, } +#[derive(Debug)] +pub struct Tidy; + impl Xtask { #[allow(dead_code)] pub fn from_env_or_exit() -> Self { @@ -324,7 +328,7 @@ impl Install { } else { Malloc::System }; - Some(ServerOpt { malloc, dev_rel: self.dev_rel }) + Some(ServerOpt { malloc, dev_rel: self.dev_rel, pgo: self.pgo.clone() }) } pub(crate) fn proc_macro_server(&self) -> Option { if !self.proc_macro_server { diff --git a/src/tools/rust-analyzer/xtask/src/install.rs b/src/tools/rust-analyzer/xtask/src/install.rs index 4e2093f0691b..f0cc445dfa23 100644 --- a/src/tools/rust-analyzer/xtask/src/install.rs +++ b/src/tools/rust-analyzer/xtask/src/install.rs @@ -5,7 +5,10 @@ use std::{env, path::PathBuf, str}; use anyhow::{Context, bail, format_err}; use xshell::{Shell, cmd}; -use crate::flags::{self, Malloc}; +use crate::{ + flags::{self, Malloc, PgoTrainingCrate}, + util::detect_target, +}; impl flags::Install { pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> { @@ -35,6 +38,7 @@ const VS_CODES: &[&str] = &["code", "code-exploration", "code-insiders", "codium pub(crate) struct ServerOpt { pub(crate) malloc: Malloc, pub(crate) dev_rel: bool, + pub(crate) pgo: Option, } pub(crate) struct ProcMacroServerOpt { @@ -135,21 +139,33 @@ fn install_server(sh: &Shell, opts: ServerOpt) -> anyhow::Result<()> { let features = opts.malloc.to_features(); let profile = if opts.dev_rel { "dev-rel" } else { "release" }; - let cmd = cmd!( + let mut install_cmd = cmd!( sh, "cargo install --path crates/rust-analyzer --profile={profile} --locked --force --features force-always-assert {features...}" ); - cmd.run()?; + + if let Some(train_crate) = opts.pgo { + let build_cmd = cmd!( + sh, + "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --profile={profile} --locked --features force-always-assert {features...}" + ); + + let target = detect_target(sh); + let profile = crate::pgo::gather_pgo_profile(sh, build_cmd, &target, train_crate)?; + install_cmd = crate::pgo::apply_pgo_to_cmd(install_cmd, &profile); + } + + install_cmd.run()?; Ok(()) } fn install_proc_macro_server(sh: &Shell, opts: ProcMacroServerOpt) -> anyhow::Result<()> { let profile = if opts.dev_rel { "dev-rel" } else { "release" }; - let cmd = cmd!( + cmd!( sh, "cargo +nightly install --path crates/proc-macro-srv-cli --profile={profile} --locked --force --features sysroot-abi" - ); - cmd.run()?; + ).run()?; + Ok(()) } diff --git a/src/tools/rust-analyzer/xtask/src/main.rs b/src/tools/rust-analyzer/xtask/src/main.rs index 52ea896c734d..aaa8d0e1d4d4 100644 --- a/src/tools/rust-analyzer/xtask/src/main.rs +++ b/src/tools/rust-analyzer/xtask/src/main.rs @@ -22,6 +22,7 @@ mod codegen; mod dist; mod install; mod metrics; +mod pgo; mod publish; mod release; mod tidy; diff --git a/src/tools/rust-analyzer/xtask/src/pgo.rs b/src/tools/rust-analyzer/xtask/src/pgo.rs new file mode 100644 index 000000000000..7f7b3311d962 --- /dev/null +++ b/src/tools/rust-analyzer/xtask/src/pgo.rs @@ -0,0 +1,105 @@ +//! PGO (Profile-Guided Optimization) utilities. + +use anyhow::Context; +use std::env::consts::EXE_EXTENSION; +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; +use xshell::{Cmd, Shell, cmd}; + +use crate::flags::PgoTrainingCrate; + +/// Decorates `ra_build_cmd` to add PGO instrumentation, and then runs the PGO instrumented +/// Rust Analyzer on itself to gather a PGO profile. +pub(crate) fn gather_pgo_profile<'a>( + sh: &'a Shell, + ra_build_cmd: Cmd<'a>, + target: &str, + train_crate: PgoTrainingCrate, +) -> anyhow::Result { + let pgo_dir = std::path::absolute("rust-analyzer-pgo")?; + // Clear out any stale profiles + if pgo_dir.is_dir() { + std::fs::remove_dir_all(&pgo_dir)?; + } + std::fs::create_dir_all(&pgo_dir)?; + + // Figure out a path to `llvm-profdata` + let target_libdir = cmd!(sh, "rustc --print=target-libdir") + .read() + .context("cannot resolve target-libdir from rustc")?; + let target_bindir = PathBuf::from(target_libdir).parent().unwrap().join("bin"); + let llvm_profdata = target_bindir.join("llvm-profdata").with_extension(EXE_EXTENSION); + + // Build RA with PGO instrumentation + let cmd_gather = + ra_build_cmd.env("RUSTFLAGS", format!("-Cprofile-generate={}", pgo_dir.to_str().unwrap())); + cmd_gather.run().context("cannot build rust-analyzer with PGO instrumentation")?; + + let (train_path, label) = match &train_crate { + PgoTrainingCrate::RustAnalyzer => (PathBuf::from("."), "itself"), + PgoTrainingCrate::GitHub(repo) => { + (download_crate_for_training(sh, &pgo_dir, repo)?, repo.as_str()) + } + }; + + // Run RA either on itself or on a downloaded crate + eprintln!("Training RA on {label}..."); + cmd!( + sh, + "target/{target}/release/rust-analyzer analysis-stats -q --run-all-ide-things {train_path}" + ) + .run() + .context("cannot generate PGO profiles")?; + + // Merge profiles into a single file + let merged_profile = pgo_dir.join("merged.profdata"); + let profile_files = std::fs::read_dir(pgo_dir)?.filter_map(|entry| { + let entry = entry.ok()?; + if entry.path().extension() == Some(OsStr::new("profraw")) { + Some(entry.path().to_str().unwrap().to_owned()) + } else { + None + } + }); + cmd!(sh, "{llvm_profdata} merge {profile_files...} -o {merged_profile}").run().context( + "cannot merge PGO profiles. Do you have the rustup `llvm-tools` component installed?", + )?; + + Ok(merged_profile) +} + +/// Downloads a crate from GitHub, stores it into `pgo_dir` and returns a path to it. +fn download_crate_for_training(sh: &Shell, pgo_dir: &Path, repo: &str) -> anyhow::Result { + let mut it = repo.splitn(2, '@'); + let repo = it.next().unwrap(); + let revision = it.next(); + + // FIXME: switch to `--revision` here around 2035 or so + let revision = + if let Some(revision) = revision { &["--branch", revision] as &[&str] } else { &[] }; + + let normalized_path = repo.replace("/", "-"); + let target_path = pgo_dir.join(normalized_path); + cmd!(sh, "git clone --depth 1 https://github.com/{repo} {revision...} {target_path}") + .run() + .with_context(|| "cannot download PGO training crate from {repo}")?; + + Ok(target_path) +} + +/// Helper function to create a build command for rust-analyzer +pub(crate) fn build_command<'a>( + sh: &'a Shell, + command: &str, + target_name: &str, + features: &[&str], +) -> Cmd<'a> { + cmd!( + sh, + "cargo {command} --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} {features...} --release" + ) +} + +pub(crate) fn apply_pgo_to_cmd<'a>(cmd: Cmd<'a>, profile_path: &Path) -> Cmd<'a> { + cmd.env("RUSTFLAGS", format!("-Cprofile-use={}", profile_path.to_str().unwrap())) +} diff --git a/src/tools/rust-analyzer/xtask/src/util.rs b/src/tools/rust-analyzer/xtask/src/util.rs index 39f52938c8c6..e5404d571717 100644 --- a/src/tools/rust-analyzer/xtask/src/util.rs +++ b/src/tools/rust-analyzer/xtask/src/util.rs @@ -1,5 +1,7 @@ use std::path::{Path, PathBuf}; +use xshell::{Shell, cmd}; + pub(crate) fn list_rust_files(dir: &Path) -> Vec { let mut res = list_files(dir); res.retain(|it| { @@ -29,3 +31,13 @@ pub(crate) fn list_files(dir: &Path) -> Vec { } res } + +pub(crate) fn detect_target(sh: &Shell) -> String { + match std::env::var("RA_TARGET") { + Ok(target) => target, + _ => match cmd!(sh, "rustc --print=host-tuple").read() { + Ok(target) => target, + Err(e) => panic!("Failed to detect target: {e}\nPlease set RA_TARGET explicitly"), + }, + } +} diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index fb584103df5d..3b5b31bed14a 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -19,13 +19,13 @@ dependencies = [ [[package]] name = "ammonia" -version = "4.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459" +checksum = "3ada2ee439075a3e70b6992fce18ac4e407cd05aea9ca3f75d2c0b0c20bbb364" dependencies = [ + "cssparser", "html5ever", "maplit", - "once_cell", "tendril", "url", ] @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "autocfg" @@ -156,9 +156,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "cc" -version = "1.2.19" +version = "1.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" +checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" dependencies = [ "shlex", ] @@ -171,9 +171,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", "clap_derive", @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.47" +version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06f5378ea264ad4f82bbc826628b5aad714a75abf6ece087e923010eb937fb6" +checksum = "be8c97f3a6f02b9e24cadc12aaba75201d18754b53ea0a9d99642f806ccdb4c9" dependencies = [ "clap", ] @@ -273,6 +273,29 @@ dependencies = [ "typenum", ] +[[package]] +name = "cssparser" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e901edd733a1472f944a45116df3f846f54d37e67e68640ac8bb69689aca2aa" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "darling" version = "0.20.11" @@ -389,6 +412,21 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "dtoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + [[package]] name = "elasticlunr-rs" version = "3.0.2" @@ -537,9 +575,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" [[package]] name = "heck" @@ -555,16 +593,14 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "html5ever" -version = "0.27.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +checksum = "953cbbe631aae7fc0a112702ad5d3aaf09da38beaf45ea84610d6e1c358f569c" dependencies = [ "log", "mac", "markup5ever", - "proc-macro2", - "quote", - "syn", + "match_token", ] [[package]] @@ -775,9 +811,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.6" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f33145a5cbea837164362c7bd596106eb7c5198f97d1ba6f6ebb3223952e488" +checksum = "d07d8d955d798e7a4d6f9c58cd1f1916e790b42b092758a9ef6e16fef9f1b3fd" dependencies = [ "jiff-static", "log", @@ -788,9 +824,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.6" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ce13c40ec6956157a3635d97a1ee2df323b263f09ea14165131289cb0f5c19" +checksum = "f244cfe006d98d26f859c7abd1318d85327e1882dc9cef80f62daeeb0adcf300" dependencies = [ "proc-macro2", "quote", @@ -815,9 +851,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libdbus-sys" @@ -880,23 +916,31 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "markup5ever" -version = "0.12.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +checksum = "d0a8096766c229e8c88a3900c9b44b7e06aa7f7343cc229158c3e58ef8f9973a" dependencies = [ "log", - "phf", - "phf_codegen", - "string_cache", - "string_cache_codegen", "tendril", + "web_atoms", +] + +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "mdbook" -version = "0.4.48" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6fbb4ac2d9fd7aa987c3510309ea3c80004a968d063c42f0d34fea070817c1" +checksum = "d1daacee059634081dee4250d2814763a365b92dfe14bfdef964bc27835209d4" dependencies = [ "ammonia", "anyhow", @@ -971,7 +1015,7 @@ dependencies = [ "pulldown-cmark-to-cmark 19.0.1", "serde_json", "thiserror 1.0.69", - "toml 0.8.20", + "toml 0.8.22", ] [[package]] @@ -1154,6 +1198,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ + "phf_macros", "phf_shared", ] @@ -1177,6 +1222,19 @@ dependencies = [ "rand", ] +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "phf_shared" version = "0.11.3" @@ -1224,9 +1282,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -1327,9 +1385,9 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ "bitflags 2.9.0", ] @@ -1377,9 +1435,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ "bitflags 2.9.0", "errno", @@ -1464,9 +1522,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -1530,9 +1588,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -1541,9 +1599,9 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", @@ -1671,9 +1729,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" dependencies = [ "serde", "serde_spanned", @@ -1683,26 +1741,33 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" + [[package]] name = "topological-sort" version = "0.2.2" @@ -1857,6 +1922,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "web_atoms" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bcbdcad8fb2e316072ba6bbe09419afdb550285668ac2534f4230a6f2da0ee" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2022,9 +2099,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.6" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3" dependencies = [ "memchr", ] diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index a0b220c3557d..10fde31306df 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -15,6 +15,6 @@ mdbook-i18n-helpers = "0.3.3" mdbook-spec = { path = "../../doc/reference/mdbook-spec" } [dependencies.mdbook] -version = "0.4.48" +version = "0.4.49" default-features = false features = ["search"] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3c3ebf556c52..4195258af885 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -175,6 +175,9 @@ const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[ const EXCEPTIONS_RUSTBOOK: ExceptionList = &[ // tidy-alphabetical-start + ("cssparser", "MPL-2.0"), + ("cssparser-macros", "MPL-2.0"), + ("dtoa-short", "MPL-2.0"), ("mdbook", "MPL-2.0"), ("ryu", "Apache-2.0 OR BSL-1.0"), // tidy-alphabetical-end @@ -459,7 +462,6 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[ // tidy-alphabetical-start "addr2line", "adler2", - "allocator-api2", "cc", "cfg-if", "compiler_builtins", @@ -473,8 +475,6 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[ "memchr", "miniz_oxide", "object", - "proc-macro2", - "quote", "r-efi", "r-efi-alloc", "rand", @@ -483,8 +483,6 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[ "rustc-demangle", "rustc-literal-escaper", "shlex", - "syn", - "unicode-ident", "unicode-width", "unwinding", "wasi", @@ -498,8 +496,6 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[ "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", - "zerocopy", - "zerocopy-derive", // tidy-alphabetical-end ]; diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index e6b5aa59622d..2f0158609e08 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -276,13 +276,7 @@ ui/auto-traits/issue-23080-2.rs ui/auto-traits/issue-23080.rs ui/auto-traits/issue-83857-ub.rs ui/auto-traits/issue-84075.rs -ui/auxiliary/issue-13560-1.rs -ui/auxiliary/issue-13560-2.rs -ui/auxiliary/issue-13560-3.rs ui/auxiliary/issue-16822.rs -ui/auxiliary/issue-18502.rs -ui/auxiliary/issue-24106.rs -ui/auxiliary/issue-76387.rs ui/bench/issue-32062.rs ui/binding/issue-40402-1.rs ui/binding/issue-40402-2.rs @@ -1378,12 +1372,8 @@ ui/intrinsics/issue-28575.rs ui/intrinsics/issue-84297-reifying-copy.rs ui/invalid/issue-114435-layout-type-err.rs ui/issue-11881.rs -ui/issue-13560.rs ui/issue-15924.rs ui/issue-16822.rs -ui/issue-18502.rs -ui/issue-24106.rs -ui/issue-76387-llvm-miscompile.rs ui/issues-71798.rs ui/issues/auxiliary/issue-11224.rs ui/issues/auxiliary/issue-11508.rs diff --git a/src/version b/src/version index 59be592144c2..636ea711ad96 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.88.0 +1.89.0 diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index 8e4e08503253..ad2770d43e37 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -86,10 +86,12 @@ pub unsafe fn sym_static() { // Regression test for #75761 // CHECK-LABEL: {{("#)?}}issue_75761{{"?}} -// CHECK: str {{.*}}x30 +// aarch64: str {{.*}}x30 +// arm64ec: stp {{.*}}x30 // CHECK: //APP // CHECK: //NO_APP -// CHECK: ldr {{.*}}x30 +// aarch64: ldr {{.*}}x30 +// arm64ec: ldp {{.*}}x30 #[no_mangle] pub unsafe fn issue_75761() { asm!("", out("v0") _, out("x30") _); diff --git a/tests/codegen/const-vector.rs b/tests/codegen/const-vector.rs index 289b67371ce4..42921442e039 100644 --- a/tests/codegen/const-vector.rs +++ b/tests/codegen/const-vector.rs @@ -1,4 +1,8 @@ -//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 +//@ revisions: OPT0 OPT0_S390X +//@ [OPT0] ignore-s390x +//@ [OPT0_S390X] only-s390x +//@ [OPT0] compile-flags: -C no-prepopulate-passes -Copt-level=0 +//@ [OPT0_S390X] compile-flags: -C no-prepopulate-passes -Copt-level=0 -C target-cpu=z13 // This test checks that constants of SIMD type are passed as immediate vectors. // We ensure that both vector representations (struct with fields and struct wrapping array) work. diff --git a/tests/codegen/simd/extract-insert-dyn.rs b/tests/codegen/simd/extract-insert-dyn.rs index 7d032c6bb3ef..729f0145314a 100644 --- a/tests/codegen/simd/extract-insert-dyn.rs +++ b/tests/codegen/simd/extract-insert-dyn.rs @@ -1,6 +1,12 @@ //@compile-flags: -C opt-level=3 -C no-prepopulate-passes -#![feature(core_intrinsics, repr_simd, arm_target_feature, mips_target_feature)] +#![feature( + core_intrinsics, + repr_simd, + arm_target_feature, + mips_target_feature, + s390x_target_feature +)] #![no_std] #![crate_type = "lib"] #![allow(non_camel_case_types)] @@ -25,6 +31,7 @@ pub struct i8x16([i8; 16]); #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] #[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] #[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] unsafe extern "C" fn dyn_simd_extract(x: i8x16, idx: u32) -> i8 { simd_extract_dyn(x, idx) } @@ -36,6 +43,7 @@ unsafe extern "C" fn dyn_simd_extract(x: i8x16, idx: u32) -> i8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] #[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] #[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] unsafe extern "C" fn literal_dyn_simd_extract(x: i8x16) -> i8 { simd_extract_dyn(x, 7) } @@ -47,6 +55,7 @@ unsafe extern "C" fn literal_dyn_simd_extract(x: i8x16) -> i8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] #[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] #[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] unsafe extern "C" fn const_dyn_simd_extract(x: i8x16) -> i8 { simd_extract_dyn(x, const { 3 + 4 }) } @@ -58,6 +67,7 @@ unsafe extern "C" fn const_dyn_simd_extract(x: i8x16) -> i8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] #[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] #[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] unsafe extern "C" fn const_simd_extract(x: i8x16) -> i8 { simd_extract(x, const { 3 + 4 }) } @@ -69,6 +79,7 @@ unsafe extern "C" fn const_simd_extract(x: i8x16) -> i8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] #[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] #[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] unsafe extern "C" fn dyn_simd_insert(x: i8x16, e: i8, idx: u32) -> i8x16 { simd_insert_dyn(x, idx, e) } @@ -80,6 +91,7 @@ unsafe extern "C" fn dyn_simd_insert(x: i8x16, e: i8, idx: u32) -> i8x16 { #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] #[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] #[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] unsafe extern "C" fn literal_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 { simd_insert_dyn(x, 7, e) } @@ -91,6 +103,7 @@ unsafe extern "C" fn literal_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 { #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] #[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] #[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] unsafe extern "C" fn const_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 { simd_insert_dyn(x, const { 3 + 4 }, e) } @@ -102,6 +115,7 @@ unsafe extern "C" fn const_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 { #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] #[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))] #[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))] +#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))] unsafe extern "C" fn const_simd_insert(x: i8x16, e: i8) -> i8x16 { simd_insert(x, const { 3 + 4 }, e) } diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map index 26536caeba52..4d8ea874bd79 100644 --- a/tests/coverage/abort.cov-map +++ b/tests/coverage/abort.cov-map @@ -1,7 +1,7 @@ Function name: abort::main -Raw bytes (83): 0x[01, 01, 07, 05, 01, 05, 0b, 01, 09, 05, 13, 01, 0d, 05, 1b, 01, 11, 0d, 01, 0d, 01, 01, 1b, 05, 02, 0b, 00, 18, 02, 01, 0c, 00, 19, 09, 00, 1a, 02, 0a, 06, 02, 09, 00, 0a, 02, 02, 0c, 00, 19, 0d, 00, 1a, 00, 31, 0e, 00, 30, 00, 31, 02, 04, 0c, 00, 19, 11, 00, 1a, 00, 31, 16, 00, 30, 00, 31, 02, 01, 09, 00, 17, 01, 02, 05, 01, 02] +Raw bytes (98): 0x[01, 01, 07, 05, 01, 05, 0b, 01, 09, 05, 13, 01, 0d, 05, 1b, 01, 11, 10, 01, 0d, 01, 00, 1c, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1b, 05, 01, 0b, 00, 18, 02, 01, 0c, 00, 19, 09, 00, 1a, 02, 0a, 06, 02, 09, 00, 0a, 02, 02, 0c, 00, 19, 0d, 00, 1a, 00, 31, 0e, 00, 30, 00, 31, 02, 04, 0c, 00, 19, 11, 00, 1a, 00, 31, 16, 00, 30, 00, 31, 02, 01, 09, 00, 17, 01, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/abort.rs Number of expressions: 7 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) @@ -10,9 +10,11 @@ Number of expressions: 7 - expression 4 operands: lhs = Counter(0), rhs = Counter(3) - expression 5 operands: lhs = Counter(1), rhs = Expression(6, Add) - expression 6 operands: lhs = Counter(0), rhs = Counter(4) -Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 13, 1) to (start + 1, 27) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 24) +Number of file 0 mappings: 16 +- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 27) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 24) - Code(Expression(0, Sub)) at (prev + 1, 12) to (start + 0, 25) = (c1 - c0) - Code(Counter(2)) at (prev + 0, 26) to (start + 2, 10) @@ -30,19 +32,25 @@ Number of file 0 mappings: 13 = (c1 - (c0 + c4)) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 23) = (c1 - c0) -- Code(Counter(0)) at (prev + 2, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c4 Function name: abort::might_abort -Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02] +Raw bytes (41): 0x[01, 01, 01, 01, 05, 07, 01, 03, 01, 00, 2e, 01, 01, 08, 00, 14, 05, 01, 09, 00, 11, 05, 00, 12, 00, 1f, 05, 01, 09, 00, 0f, 02, 01, 0c, 02, 06, 02, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/abort.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 3, 1) to (start + 1, 20) -- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15) -- Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 46) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 20) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 31) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 15) +- Code(Expression(0, Sub)) at (prev + 1, 12) to (start + 2, 6) + = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 3, 1) to (start + 0, 2) = (c0 - c1) Highest counter ID seen: c1 diff --git a/tests/coverage/assert-ne.cov-map b/tests/coverage/assert-ne.cov-map index 27d4b0382dec..fde0d5184d67 100644 --- a/tests/coverage/assert-ne.cov-map +++ b/tests/coverage/assert-ne.cov-map @@ -1,16 +1,23 @@ Function name: assert_ne::main -Raw bytes (28): 0x[01, 01, 02, 01, 05, 01, 09, 04, 01, 08, 01, 03, 15, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 06, 03, 05, 01, 02] +Raw bytes (55): 0x[01, 01, 03, 01, 05, 01, 09, 01, 09, 09, 01, 08, 01, 00, 0a, 01, 01, 05, 00, 0f, 01, 01, 09, 00, 12, 01, 00, 13, 00, 19, 01, 01, 0c, 00, 15, 05, 01, 0d, 00, 13, 02, 02, 0d, 00, 13, 0a, 03, 05, 00, 07, 0a, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 2 +- file 0 => $DIR/assert-ne.rs +Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 21) -- Code(Counter(1)) at (prev + 4, 13) to (start + 0, 19) +- expression 2 operands: lhs = Counter(0), rhs = Counter(2) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 25) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 21) +- Code(Counter(1)) at (prev + 1, 13) to (start + 0, 19) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) -- Code(Expression(1, Sub)) at (prev + 3, 5) to (start + 1, 2) +- Code(Expression(2, Sub)) at (prev + 3, 5) to (start + 0, 7) + = (c0 - c2) +- Code(Expression(2, Sub)) at (prev + 1, 1) to (start + 0, 2) = (c0 - c2) Highest counter ID seen: c1 diff --git a/tests/coverage/assert.cov-map b/tests/coverage/assert.cov-map index 903cccfe9cbc..07a0d4c8c27e 100644 --- a/tests/coverage/assert.cov-map +++ b/tests/coverage/assert.cov-map @@ -1,7 +1,7 @@ Function name: assert::main -Raw bytes (61): 0x[01, 01, 06, 05, 01, 05, 17, 01, 09, 05, 13, 17, 0d, 01, 09, 09, 01, 09, 01, 01, 1b, 05, 02, 0b, 00, 18, 02, 01, 0c, 00, 1a, 09, 00, 1b, 02, 0a, 06, 02, 13, 00, 20, 0d, 00, 21, 02, 0a, 0e, 02, 09, 00, 0a, 02, 01, 09, 00, 17, 01, 02, 05, 01, 02] +Raw bytes (76): 0x[01, 01, 06, 05, 01, 05, 17, 01, 09, 05, 13, 17, 0d, 01, 09, 0c, 01, 09, 01, 00, 1c, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1b, 05, 01, 0b, 00, 18, 02, 01, 0c, 00, 1a, 09, 00, 1b, 02, 0a, 06, 02, 13, 00, 20, 0d, 00, 21, 02, 0a, 0e, 02, 09, 00, 0a, 02, 01, 09, 00, 17, 01, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/assert.rs Number of expressions: 6 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) - expression 1 operands: lhs = Counter(1), rhs = Expression(5, Add) @@ -9,9 +9,11 @@ Number of expressions: 6 - expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) - expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3) - expression 5 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 9, 1) to (start + 1, 27) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 24) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 27) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 24) - Code(Expression(0, Sub)) at (prev + 1, 12) to (start + 0, 26) = (c1 - c0) - Code(Counter(2)) at (prev + 0, 27) to (start + 2, 10) @@ -22,18 +24,22 @@ Number of file 0 mappings: 9 = (c1 - ((c0 + c2) + c3)) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 23) = (c1 - c0) -- Code(Counter(0)) at (prev + 2, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 Function name: assert::might_fail_assert -Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 02, 0f, 02, 02, 25, 00, 3d, 05, 01, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 04, 01, 00, 28, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 20, 01, 01, 05, 00, 0f, 02, 00, 25, 00, 3d, 05, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/assert.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 15) -- Code(Expression(0, Sub)) at (prev + 2, 37) to (start + 0, 61) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 40) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Expression(0, Sub)) at (prev + 0, 37) to (start + 0, 61) = (c0 - c1) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map index 3aef4274edc3..e0ec3815244e 100644 --- a/tests/coverage/assert_not.cov-map +++ b/tests/coverage/assert_not.cov-map @@ -1,13 +1,18 @@ Function name: assert_not::main -Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 11, 01, 02, 05, 00, 13, 01, 01, 05, 00, 13, 01, 01, 05, 00, 15, 01, 01, 01, 00, 02] +Raw bytes (54): 0x[01, 01, 00, 0a, 01, 06, 01, 00, 0a, 01, 01, 05, 00, 0c, 01, 00, 0d, 00, 11, 01, 01, 05, 00, 0c, 01, 00, 0d, 00, 13, 01, 01, 05, 00, 0c, 01, 00, 0d, 00, 13, 01, 01, 05, 00, 0c, 01, 00, 0d, 00, 15, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/assert_not.rs Number of expressions: 0 -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 17) -- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 19) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 19) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 21) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 21) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map index 521562f6b912..c528ad525b5f 100644 --- a/tests/coverage/async.cov-map +++ b/tests/coverage/async.cov-map @@ -1,115 +1,125 @@ Function name: async::c -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 00, 18] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 24) Highest counter ID seen: c0 Function name: async::c::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0b, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 0b, 19, 00, 1a, 01, 01, 08, 00, 0e, 05, 01, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 11, 25) to (start + 1, 14) -- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 10) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 11, 25) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 14) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: async::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 13] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 19) Highest counter ID seen: c0 Function name: async::d::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 14, 00, 19] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 13, 14, 00, 15, 01, 00, 16, 00, 17, 01, 00, 18, 00, 19] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 20) to (start + 0, 25) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 19, 20) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 22) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 25) Highest counter ID seen: c0 Function name: async::e (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 13] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 1) to (start + 0, 20) +- Code(Zero) at (prev + 21, 1) to (start + 0, 19) Highest counter ID seen: (none) Function name: async::e::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 14, 00, 19] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 15, 14, 00, 15, 00, 00, 16, 00, 17, 00, 00, 18, 00, 19] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 20) to (start + 0, 25) +Number of file 0 mappings: 3 +- Code(Zero) at (prev + 21, 20) to (start + 0, 21) +- Code(Zero) at (prev + 0, 22) to (start + 0, 23) +- Code(Zero) at (prev + 0, 24) to (start + 0, 25) Highest counter ID seen: (none) Function name: async::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 13] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 19) Highest counter ID seen: c0 Function name: async::f::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 14, 00, 19] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 17, 14, 00, 15, 01, 00, 16, 00, 17, 01, 00, 18, 00, 19] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 23, 20) to (start + 0, 25) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 23, 20) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 22) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 25) Highest counter ID seen: c0 Function name: async::foo (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 00, 1d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 25, 1) to (start + 0, 30) +- Code(Zero) at (prev + 25, 1) to (start + 0, 29) Highest counter ID seen: (none) Function name: async::foo::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 1e, 00, 2d] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 19, 1e, 00, 1f, 00, 00, 20, 00, 2b, 00, 00, 2c, 00, 2d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 25, 30) to (start + 0, 45) +Number of file 0 mappings: 3 +- Code(Zero) at (prev + 25, 30) to (start + 0, 31) +- Code(Zero) at (prev + 0, 32) to (start + 0, 43) +- Code(Zero) at (prev + 0, 44) to (start + 0, 45) Highest counter ID seen: (none) Function name: async::g -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 00, 16] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 22) Highest counter ID seen: c0 Function name: async::g::{closure#0} (unused) -Raw bytes (59): 0x[01, 01, 00, 0b, 00, 1b, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (64): 0x[01, 01, 00, 0c, 00, 1b, 17, 00, 18, 00, 01, 0b, 00, 0c, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 11 -- Code(Zero) at (prev + 27, 23) to (start + 1, 12) -- Code(Zero) at (prev + 2, 9) to (start + 0, 10) +Number of file 0 mappings: 12 +- Code(Zero) at (prev + 27, 23) to (start + 0, 24) +- Code(Zero) at (prev + 1, 11) to (start + 0, 12) +- Code(Zero) at (prev + 1, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 23) - Code(Zero) at (prev + 0, 27) to (start + 0, 28) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) @@ -122,22 +132,23 @@ Number of file 0 mappings: 11 Highest counter ID seen: (none) Function name: async::h -Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 00, 16] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 00, 15] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 21) Highest counter ID seen: c0 Function name: async::h::{closure#0} (unused) -Raw bytes (39): 0x[01, 01, 00, 07, 00, 23, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (44): 0x[01, 01, 00, 08, 00, 23, 16, 00, 17, 00, 03, 0b, 00, 0c, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 7 -- Code(Zero) at (prev + 35, 22) to (start + 3, 12) -- Code(Zero) at (prev + 4, 9) to (start + 0, 10) +Number of file 0 mappings: 8 +- Code(Zero) at (prev + 35, 22) to (start + 0, 23) +- Code(Zero) at (prev + 3, 11) to (start + 0, 12) +- Code(Zero) at (prev + 1, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 25) - Code(Zero) at (prev + 0, 26) to (start + 0, 27) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) @@ -146,25 +157,27 @@ Number of file 0 mappings: 7 Highest counter ID seen: (none) Function name: async::i -Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 01, 00, 13] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 01, 00, 12] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 44, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 44, 1) to (start + 0, 18) Highest counter ID seen: c0 Function name: async::i::{closure#0} -Raw bytes (65): 0x[01, 01, 03, 05, 09, 11, 15, 0d, 11, 0b, 01, 2c, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 02, 00, 0e, 00, 17, 11, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 06, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] +Raw bytes (75): 0x[01, 01, 03, 05, 09, 11, 15, 0d, 11, 0d, 01, 2c, 13, 00, 14, 01, 04, 0b, 00, 0c, 09, 01, 09, 00, 0a, 01, 00, 0e, 00, 0f, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 02, 00, 0e, 00, 17, 11, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 06, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Counter(4), rhs = Counter(5) - expression 2 operands: lhs = Counter(3), rhs = Counter(4) -Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 44, 19) to (start + 4, 12) -- Code(Counter(2)) at (prev + 5, 9) to (start + 0, 10) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 44, 19) to (start + 0, 20) +- Code(Counter(0)) at (prev + 4, 11) to (start + 0, 12) +- Code(Counter(2)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 15) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 24) - Code(Counter(1)) at (prev + 0, 28) to (start + 0, 33) - Code(Counter(2)) at (prev + 0, 39) to (start + 0, 48) @@ -180,17 +193,18 @@ Number of file 0 mappings: 11 Highest counter ID seen: c5 Function name: async::j -Raw bytes (60): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 0a, 01, 37, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 02, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 06, 01, 0e, 00, 10, 01, 02, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 0b, 01, 37, 01, 00, 0c, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 0f, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 02, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 06, 01, 0e, 00, 10, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 55, 1) to (start + 0, 13) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 55, 1) to (start + 0, 12) - Code(Counter(0)) at (prev + 11, 11) to (start + 0, 12) - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 15) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 27) - Code(Counter(1)) at (prev + 0, 31) to (start + 0, 39) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 10) @@ -203,60 +217,67 @@ Number of file 0 mappings: 10 Highest counter ID seen: c2 Function name: async::j::c -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 39, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 39, 05, 00, 16, 01, 01, 0c, 00, 12, 05, 01, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 57, 5) to (start + 1, 18) -- Code(Counter(1)) at (prev + 2, 13) to (start + 0, 14) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 57, 5) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 18) +- Code(Counter(1)) at (prev + 1, 13) to (start + 0, 14) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) Highest counter ID seen: c1 Function name: async::j::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 40, 05, 00, 17] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 40, 05, 00, 11, 01, 00, 14, 00, 15, 01, 00, 16, 00, 17] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 64, 5) to (start + 0, 23) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 64, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 22) to (start + 0, 23) Highest counter ID seen: c0 Function name: async::j::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 41, 05, 00, 17] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 41, 05, 00, 11, 01, 00, 14, 00, 15, 01, 00, 16, 00, 17] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 65, 5) to (start + 0, 23) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 65, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 22) to (start + 0, 23) Highest counter ID seen: c0 Function name: async::k (unused) -Raw bytes (29): 0x[01, 01, 00, 05, 00, 49, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 00, 49, 01, 00, 0c, 00, 01, 0b, 00, 0c, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 5 -- Code(Zero) at (prev + 73, 1) to (start + 1, 12) -- Code(Zero) at (prev + 2, 14) to (start + 0, 16) +Number of file 0 mappings: 6 +- Code(Zero) at (prev + 73, 1) to (start + 0, 12) +- Code(Zero) at (prev + 1, 11) to (start + 0, 12) +- Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: async::l -Raw bytes (33): 0x[01, 01, 02, 01, 07, 05, 09, 05, 01, 51, 01, 01, 0c, 02, 02, 0e, 00, 10, 09, 01, 0e, 00, 10, 05, 01, 0e, 00, 10, 01, 02, 01, 00, 02] +Raw bytes (38): 0x[01, 01, 02, 01, 07, 05, 09, 06, 01, 51, 01, 00, 0c, 01, 01, 0b, 00, 0c, 02, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 05, 01, 0e, 00, 10, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 81, 1) to (start + 1, 12) -- Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 81, 1) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 11) to (start + 0, 12) +- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 16) = (c0 - (c1 + c2)) - Code(Counter(2)) at (prev + 1, 14) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 16) @@ -264,29 +285,43 @@ Number of file 0 mappings: 5 Highest counter ID seen: c2 Function name: async::m -Raw bytes (9): 0x[01, 01, 00, 01, 01, 59, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 59, 01, 00, 18] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 89, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 89, 1) to (start + 0, 24) Highest counter ID seen: c0 Function name: async::m::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 59, 19, 00, 22] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 59, 19, 00, 1a, 00, 00, 1b, 00, 20, 00, 00, 21, 00, 22] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 89, 25) to (start + 0, 34) +Number of file 0 mappings: 3 +- Code(Zero) at (prev + 89, 25) to (start + 0, 26) +- Code(Zero) at (prev + 0, 27) to (start + 0, 32) +- Code(Zero) at (prev + 0, 33) to (start + 0, 34) Highest counter ID seen: (none) Function name: async::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 5b, 01, 08, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 01, 5b, 01, 00, 0a, 01, 01, 0d, 00, 12, 01, 01, 0d, 00, 11, 01, 01, 09, 00, 13, 01, 00, 16, 00, 1e, 01, 00, 1f, 00, 20, 01, 01, 05, 00, 06, 01, 01, 05, 00, 06, 01, 01, 0d, 00, 11, 01, 01, 05, 00, 17, 01, 00, 18, 00, 1e, 01, 00, 1f, 00, 25, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 91, 1) to (start + 8, 2) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 91, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 19) +- Code(Counter(0)) at (prev + 0, 22) to (start + 0, 30) +- Code(Counter(0)) at (prev + 0, 31) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 30) +- Code(Counter(0)) at (prev + 0, 31) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage index aee76b05fb74..9fca1b6997d0 100644 --- a/tests/coverage/async.coverage +++ b/tests/coverage/async.coverage @@ -25,6 +25,7 @@ LL| 0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()` LL| | LL| 1|pub async fn g(x: u8) { + ^0 LL| 0| match x { LL| 0| y if e().await == y => (), LL| 0| y if f().await == y => (), @@ -33,8 +34,9 @@ LL| 0|} LL| | LL| 1|async fn h(x: usize) { // The function signature is counted when called, but the body is not - LL| 0| // executed (not awaited) so the open brace has a `0` count (at least when - LL| 0| // displayed with `llvm-cov show` in color-mode). + ^0 + LL| | // executed (not awaited) so the open brace has a `0` count (at least when + LL| | // displayed with `llvm-cov show` in color-mode). LL| 0| match x { LL| 0| y if foo().await[y] => (), LL| 0| _ => (), @@ -42,9 +44,9 @@ LL| 0|} LL| | LL| 1|async fn i(x: u8) { // line coverage is 1, but there are 2 regions: - LL| 1| // (a) the function signature, counted when the function is called; and - LL| 1| // (b) the open brace for the function body, counted once when the body is - LL| 1| // executed asynchronously. + LL| | // (a) the function signature, counted when the function is called; and + LL| | // (b) the open brace for the function body, counted once when the body is + LL| | // executed asynchronously. LL| 1| match x { LL| 1| y if c(x).await == y + 1 => { d().await; } ^0 ^0 @@ -91,7 +93,7 @@ LL| 1|} LL| | LL| 1|async fn m(x: u8) -> u8 { x - 1 } - ^0 + ^0^0 ^0 LL| | LL| 1|fn main() { LL| 1| let _ = g(10); diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async2.cov-map index c2a0645ee9a8..cc6295170980 100644 --- a/tests/coverage/async2.cov-map +++ b/tests/coverage/async2.cov-map @@ -1,59 +1,80 @@ Function name: async2::async_func -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 16] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async2.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 22) Highest counter ID seen: c0 Function name: async2::async_func::{closure#0} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 0f, 17, 03, 09, 01, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (49): 0x[01, 01, 00, 09, 01, 0f, 17, 00, 18, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 26, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 11, 01, 01, 08, 00, 09, 01, 00, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async2.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 15, 23) to (start + 3, 9) -- Code(Counter(0)) at (prev + 3, 10) to (start + 2, 6) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 15, 23) to (start + 0, 24) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 38) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- Code(Counter(0)) at (prev + 0, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: async2::async_func_just_println -Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 24] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 23] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async2.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 36) +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 35) Highest counter ID seen: c0 Function name: async2::async_func_just_println::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 24, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 17, 24, 00, 25, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 33, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async2.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 23, 36) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 23, 36) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 51) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: async2::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 07, 02] +Raw bytes (49): 0x[01, 01, 00, 09, 01, 1b, 01, 00, 0a, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 23, 01, 02, 05, 00, 13, 01, 02, 05, 00, 17, 01, 00, 18, 00, 22, 01, 01, 05, 00, 17, 01, 00, 18, 00, 2f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async2.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 27, 1) to (start + 7, 2) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 35) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 19) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 34) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 47) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: async2::non_async_func -Raw bytes (24): 0x[01, 01, 00, 04, 01, 07, 01, 03, 09, 01, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (49): 0x[01, 01, 00, 09, 01, 07, 01, 00, 14, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 2a, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 11, 01, 01, 08, 00, 09, 01, 00, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async2.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 7, 1) to (start + 3, 9) -- Code(Counter(0)) at (prev + 3, 10) to (start + 2, 6) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 42) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- Code(Counter(0)) at (prev + 0, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/async2.coverage b/tests/coverage/async2.coverage index fa56072924bb..e9ed8253093d 100644 --- a/tests/coverage/async2.coverage +++ b/tests/coverage/async2.coverage @@ -28,9 +28,9 @@ LL| | LL| 1|fn main() { LL| 1| println!("codecovsample::main"); - LL| 1| + LL| | LL| 1| non_async_func(); - LL| 1| + LL| | LL| 1| executor::block_on(async_func()); LL| 1| executor::block_on(async_func_just_println()); LL| 1|} diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map index d9196f446f13..07d4c0eb3cd6 100644 --- a/tests/coverage/async_block.cov-map +++ b/tests/coverage/async_block.cov-map @@ -1,30 +1,33 @@ Function name: async_block::main -Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 01, 0d, 00, 13, 02, 07, 09, 00, 22, 01, 02, 01, 00, 02] +Raw bytes (41): 0x[01, 01, 01, 05, 01, 07, 01, 07, 01, 00, 0a, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 01, 0d, 00, 13, 02, 07, 09, 00, 1b, 02, 00, 1c, 00, 22, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async_block.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 11) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 10) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10) = (c1 - c0) - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 19) - Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 19) = (c1 - c0) -- Code(Expression(0, Sub)) at (prev + 7, 9) to (start + 0, 34) +- Code(Expression(0, Sub)) at (prev + 7, 9) to (start + 0, 27) + = (c1 - c0) +- Code(Expression(0, Sub)) at (prev + 0, 28) to (start + 0, 34) = (c1 - c0) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: async_block::main::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 09, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 09, 1c, 00, 1d, 01, 01, 10, 00, 17, 05, 00, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async_block.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 9, 28) to (start + 1, 23) -- Code(Counter(1)) at (prev + 1, 24) to (start + 2, 14) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 9, 28) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 16) to (start + 0, 23) +- Code(Counter(1)) at (prev + 0, 24) to (start + 2, 14) - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map index a4ef0ceeb6df..9f8dc8d6cbba 100644 --- a/tests/coverage/async_closure.cov-map +++ b/tests/coverage/async_closure.cov-map @@ -1,38 +1,45 @@ Function name: async_closure::call_once:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 06, 01, 00, 2b] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 06, 01, 00, 2a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async_closure.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 43) +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 42) Highest counter ID seen: c0 Function name: async_closure::call_once::::{closure#0} -Raw bytes (16): 0x[01, 01, 01, 05, 09, 02, 01, 06, 2b, 01, 0e, 02, 02, 01, 00, 02] +Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 2b, 00, 2c, 01, 01, 05, 00, 0e, 02, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async_closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 6, 43) to (start + 1, 14) -- Code(Expression(0, Sub)) at (prev + 2, 1) to (start + 0, 2) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 6, 43) to (start + 0, 44) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Expression(0, Sub)) at (prev + 1, 1) to (start + 0, 2) = (c1 - c2) Highest counter ID seen: c0 Function name: async_closure::main -Raw bytes (14): 0x[01, 01, 00, 02, 01, 0a, 01, 01, 16, 01, 02, 05, 02, 02] +Raw bytes (44): 0x[01, 01, 00, 08, 01, 0a, 01, 00, 0e, 01, 01, 09, 00, 16, 01, 01, 05, 00, 17, 01, 00, 18, 00, 27, 01, 01, 05, 00, 17, 01, 00, 18, 00, 21, 01, 00, 22, 00, 2f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async_closure.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 10, 1) to (start + 1, 22) -- Code(Counter(0)) at (prev + 2, 5) to (start + 2, 2) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 14) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 39) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 33) +- Code(Counter(0)) at (prev + 0, 34) to (start + 0, 47) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: async_closure::main::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async_closure.rs Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) @@ -42,7 +49,7 @@ Highest counter ID seen: c0 Function name: async_closure::main::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async_closure.rs Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) @@ -50,11 +57,12 @@ Number of file 0 mappings: 2 Highest counter ID seen: c0 Function name: async_closure::main::{closure#0}::{closure#0}:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/async_closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) +- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36) Highest counter ID seen: c0 diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage index 5aed131de2e5..14f043415eac 100644 --- a/tests/coverage/async_closure.coverage +++ b/tests/coverage/async_closure.coverage @@ -8,7 +8,8 @@ LL| 1|} LL| | LL| 1|pub fn main() { - LL| 2| let async_closure = async || {}; + LL| 3| let async_closure = async || {}; + ^1 ------------------ | async_closure::main::{closure#0}: | LL| 1| let async_closure = async || {}; diff --git a/tests/coverage/attr/impl.cov-map b/tests/coverage/attr/impl.cov-map index 8a23c082082e..0562c291e6c1 100644 --- a/tests/coverage/attr/impl.cov-map +++ b/tests/coverage/attr/impl.cov-map @@ -1,27 +1,30 @@ Function name: ::off_on (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 0f, 05, 00, 13] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 0f, 05, 00, 10, 00, 00, 12, 00, 13] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/impl.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 15, 5) to (start + 0, 19) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 15, 5) to (start + 0, 16) +- Code(Zero) at (prev + 0, 18) to (start + 0, 19) Highest counter ID seen: (none) Function name: ::on_inherit (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 05, 00, 17] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 17, 05, 00, 14, 00, 00, 16, 00, 17] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/impl.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 23, 5) to (start + 0, 23) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 23, 5) to (start + 0, 20) +- Code(Zero) at (prev + 0, 22) to (start + 0, 23) Highest counter ID seen: (none) Function name: ::on_on (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 05, 00, 12] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 1a, 05, 00, 0f, 00, 00, 11, 00, 12] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/impl.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 26, 5) to (start + 0, 18) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 26, 5) to (start + 0, 15) +- Code(Zero) at (prev + 0, 17) to (start + 0, 18) Highest counter ID seen: (none) diff --git a/tests/coverage/attr/module.cov-map b/tests/coverage/attr/module.cov-map index 81e20a2c2649..88f4915bfe8f 100644 --- a/tests/coverage/attr/module.cov-map +++ b/tests/coverage/attr/module.cov-map @@ -1,27 +1,30 @@ Function name: module::off::on (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 0d, 05, 00, 0f] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 0d, 05, 00, 0c, 00, 00, 0e, 00, 0f] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/module.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 13, 5) to (start + 0, 15) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 13, 5) to (start + 0, 12) +- Code(Zero) at (prev + 0, 14) to (start + 0, 15) Highest counter ID seen: (none) Function name: module::on::inherit (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 05, 00, 14] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 15, 05, 00, 11, 00, 00, 13, 00, 14] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/module.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 5) to (start + 0, 20) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 21, 5) to (start + 0, 17) +- Code(Zero) at (prev + 0, 19) to (start + 0, 20) Highest counter ID seen: (none) Function name: module::on::on (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 18, 05, 00, 0f] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 18, 05, 00, 0c, 00, 00, 0e, 00, 0f] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/module.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 24, 5) to (start + 0, 15) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 24, 5) to (start + 0, 12) +- Code(Zero) at (prev + 0, 14) to (start + 0, 15) Highest counter ID seen: (none) diff --git a/tests/coverage/attr/nested.cov-map b/tests/coverage/attr/nested.cov-map index 138b3159ea5c..8ca218f7267f 100644 --- a/tests/coverage/attr/nested.cov-map +++ b/tests/coverage/attr/nested.cov-map @@ -1,20 +1,24 @@ Function name: nested::closure_expr -Raw bytes (14): 0x[01, 01, 00, 02, 01, 40, 01, 01, 0f, 01, 0b, 05, 01, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 40, 01, 00, 12, 01, 01, 09, 00, 0f, 01, 0a, 05, 00, 0d, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/nested.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 64, 1) to (start + 1, 15) -- Code(Counter(0)) at (prev + 11, 5) to (start + 1, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 64, 1) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 10, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: nested::closure_tail -Raw bytes (14): 0x[01, 01, 00, 02, 01, 4f, 01, 01, 0f, 01, 11, 05, 01, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 4f, 01, 00, 12, 01, 01, 09, 00, 0f, 01, 10, 05, 00, 0d, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/nested.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 79, 1) to (start + 1, 15) -- Code(Counter(0)) at (prev + 17, 5) to (start + 1, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 79, 1) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 16, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/attr/off-on-sandwich.cov-map b/tests/coverage/attr/off-on-sandwich.cov-map index c55c5897d8ba..c0c6eab57108 100644 --- a/tests/coverage/attr/off-on-sandwich.cov-map +++ b/tests/coverage/attr/off-on-sandwich.cov-map @@ -1,30 +1,36 @@ Function name: off_on_sandwich::dense_a::dense_b -Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 05, 02, 10, 01, 07, 05, 00, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 10, 05, 00, 11, 01, 01, 09, 00, 10, 01, 01, 09, 00, 10, 01, 05, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/off-on-sandwich.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 16, 5) to (start + 2, 16) -- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 6) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 16, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c -Raw bytes (14): 0x[01, 01, 00, 02, 01, 22, 09, 02, 15, 01, 0b, 09, 00, 0a] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 22, 09, 00, 16, 01, 01, 0d, 00, 15, 01, 01, 0d, 00, 15, 01, 09, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/off-on-sandwich.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 34, 9) to (start + 2, 21) -- Code(Counter(0)) at (prev + 11, 9) to (start + 0, 10) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 34, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 21) +- Code(Counter(0)) at (prev + 9, 9) to (start + 0, 10) Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c::sparse_d -Raw bytes (14): 0x[01, 01, 00, 02, 01, 25, 0d, 02, 19, 01, 07, 0d, 00, 0e] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 25, 0d, 00, 1a, 01, 01, 11, 00, 19, 01, 01, 11, 00, 19, 01, 05, 0d, 00, 0e] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/off-on-sandwich.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 37, 13) to (start + 2, 25) -- Code(Counter(0)) at (prev + 7, 13) to (start + 0, 14) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 37, 13) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 17) to (start + 0, 25) +- Code(Counter(0)) at (prev + 1, 17) to (start + 0, 25) +- Code(Counter(0)) at (prev + 5, 13) to (start + 0, 14) Highest counter ID seen: c0 diff --git a/tests/coverage/attr/trait-impl-inherit.cov-map b/tests/coverage/attr/trait-impl-inherit.cov-map index eab9f926bb77..bf10083dd290 100644 --- a/tests/coverage/attr/trait-impl-inherit.cov-map +++ b/tests/coverage/attr/trait-impl-inherit.cov-map @@ -1,9 +1,12 @@ Function name: ::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 05, 02, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 11, 05, 00, 10, 01, 01, 09, 00, 11, 01, 00, 12, 00, 1a, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/trait-impl-inherit.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 5) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map index 61fd4c7814d8..a7eb051ff093 100644 --- a/tests/coverage/await_ready.cov-map +++ b/tests/coverage/await_ready.cov-map @@ -1,21 +1,22 @@ Function name: await_ready::await_ready -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0e, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0e, 01, 00, 1d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/await_ready.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 30) +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 29) Highest counter ID seen: c0 Function name: await_ready::await_ready::{closure#0} -Raw bytes (16): 0x[01, 01, 01, 05, 09, 02, 01, 0e, 1e, 03, 0f, 02, 04, 01, 00, 02] +Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 0e, 1e, 00, 1f, 01, 02, 05, 01, 0f, 02, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/await_ready.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 14, 30) to (start + 3, 15) -- Code(Expression(0, Sub)) at (prev + 4, 1) to (start + 0, 2) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 14, 30) to (start + 0, 31) +- Code(Counter(0)) at (prev + 2, 5) to (start + 1, 15) +- Code(Expression(0, Sub)) at (prev + 2, 1) to (start + 0, 2) = (c1 - c2) Highest counter ID seen: c0 diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/await_ready.coverage index 1150d807e763..9a2d8f5a4fdf 100644 --- a/tests/coverage/await_ready.coverage +++ b/tests/coverage/await_ready.coverage @@ -12,7 +12,7 @@ LL| |#[coverage(on)] LL| |#[rustfmt::skip] LL| 1|async fn await_ready() -> u8 { - LL| 1| // await should be covered even if the function never yields + LL| | // await should be covered even if the function never yields LL| 1| ready() LL| 1| .await LL| 1|} diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map index f08a70a899d0..8b1b177f906e 100644 --- a/tests/coverage/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map @@ -1,84 +1,108 @@ Function name: bad_counter_ids::eq_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 0f, 00, 03, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 24, 01, 00, 0c, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 11, 01, 01, 05, 00, 0f, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/bad_counter_ids.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 15) -- Code(Zero) at (prev + 3, 1) to (start + 0, 2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 36, 1) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: bad_counter_ids::eq_bad_message -Raw bytes (19): 0x[01, 01, 00, 03, 01, 29, 01, 02, 0f, 01, 02, 20, 00, 2b, 00, 01, 01, 00, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 29, 01, 00, 14, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 11, 01, 01, 05, 00, 0f, 01, 00, 20, 00, 2b, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/bad_counter_ids.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 41, 1) to (start + 2, 15) -- Code(Counter(0)) at (prev + 2, 32) to (start + 0, 43) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(0)) at (prev + 0, 32) to (start + 0, 43) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: bad_counter_ids::eq_good -Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 0f, 01, 03, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 10, 01, 00, 0d, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 11, 01, 01, 05, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/bad_counter_ids.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 15) -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: bad_counter_ids::eq_good_message -Raw bytes (19): 0x[01, 01, 00, 03, 01, 15, 01, 02, 0f, 00, 02, 20, 00, 2b, 01, 01, 01, 00, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 15, 01, 00, 15, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 11, 01, 01, 05, 00, 0f, 00, 00, 20, 00, 2b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/bad_counter_ids.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 21, 1) to (start + 2, 15) -- Code(Zero) at (prev + 2, 32) to (start + 0, 43) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Zero) at (prev + 0, 32) to (start + 0, 43) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: bad_counter_ids::ne_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 0f, 00, 03, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 2e, 01, 00, 0c, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 11, 01, 01, 05, 00, 0f, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/bad_counter_ids.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 15) -- Code(Zero) at (prev + 3, 1) to (start + 0, 2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 46, 1) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: bad_counter_ids::ne_bad_message -Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 02, 0f, 01, 02, 20, 00, 2b, 00, 01, 01, 00, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 33, 01, 00, 14, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 11, 01, 01, 05, 00, 0f, 01, 00, 20, 00, 2b, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/bad_counter_ids.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 51, 1) to (start + 2, 15) -- Code(Counter(0)) at (prev + 2, 32) to (start + 0, 43) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 51, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(0)) at (prev + 0, 32) to (start + 0, 43) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: bad_counter_ids::ne_good -Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 0f, 01, 03, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 1a, 01, 00, 0d, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 11, 01, 01, 05, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/bad_counter_ids.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 15) -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) -Highest counter ID seen: c0 - -Function name: bad_counter_ids::ne_good_message -Raw bytes (19): 0x[01, 01, 00, 03, 01, 1f, 01, 02, 0f, 00, 02, 20, 00, 2b, 01, 01, 01, 00, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 15) -- Code(Zero) at (prev + 2, 32) to (start + 0, 43) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 26, 1) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 + +Function name: bad_counter_ids::ne_good_message +Raw bytes (34): 0x[01, 01, 00, 06, 01, 1f, 01, 00, 15, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 11, 01, 01, 05, 00, 0f, 00, 00, 20, 00, 2b, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/bad_counter_ids.rs +Number of expressions: 0 +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 31, 1) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Zero) at (prev + 0, 32) to (start + 0, 43) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/bench.cov-map b/tests/coverage/bench.cov-map index 9ee6510f6904..f2b21ddb70bb 100644 --- a/tests/coverage/bench.cov-map +++ b/tests/coverage/bench.cov-map @@ -1,9 +1,10 @@ Function name: bench::my_bench -Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 00, 27] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 01, 00, 24, 01, 00, 26, 00, 27] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/bench.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 39) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 36) +- Code(Counter(0)) at (prev + 0, 38) to (start + 0, 39) Highest counter ID seen: c0 diff --git a/tests/coverage/branch/generics.cov-map b/tests/coverage/branch/generics.cov-map index 656890634ff4..cb03f2a79f76 100644 --- a/tests/coverage/branch/generics.cov-map +++ b/tests/coverage/branch/generics.cov-map @@ -1,12 +1,13 @@ Function name: generics::print_size::<()> -Raw bytes (33): 0x[01, 01, 01, 01, 05, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 06, 01, 00, 13, 01, 01, 08, 00, 24, 20, 05, 02, 00, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generics.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 8) to (start + 0, 36) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 36) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 36) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 37) to (start + 2, 6) @@ -16,14 +17,15 @@ Number of file 0 mappings: 5 Highest counter ID seen: c1 Function name: generics::print_size:: -Raw bytes (33): 0x[01, 01, 01, 01, 05, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 06, 01, 00, 13, 01, 01, 08, 00, 24, 20, 05, 02, 00, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generics.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 8) to (start + 0, 36) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 36) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 36) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 37) to (start + 2, 6) @@ -33,14 +35,15 @@ Number of file 0 mappings: 5 Highest counter ID seen: c1 Function name: generics::print_size:: -Raw bytes (33): 0x[01, 01, 01, 01, 05, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 06, 01, 00, 13, 01, 01, 08, 00, 24, 20, 05, 02, 00, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generics.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 8) to (start + 0, 36) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 36) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 36) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 37) to (start + 2, 6) diff --git a/tests/coverage/branch/guard.cov-map b/tests/coverage/branch/guard.cov-map index 46533df00f71..9c6a9bf40fd1 100644 --- a/tests/coverage/branch/guard.cov-map +++ b/tests/coverage/branch/guard.cov-map @@ -1,7 +1,7 @@ Function name: guard::branch_match_guard -Raw bytes (89): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0d, 01, 0c, 01, 01, 0e, 02, 03, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02] +Raw bytes (104): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 10, 01, 0c, 01, 00, 26, 01, 01, 05, 00, 0e, 02, 02, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 00, 1e, 0d, 00, 22, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 00, 1e, 11, 00, 22, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/guard.rs Number of expressions: 8 - expression 0 operands: lhs = Counter(1), rhs = Counter(3) - expression 1 operands: lhs = Counter(2), rhs = Counter(1) @@ -11,9 +11,10 @@ Number of expressions: 8 - expression 5 operands: lhs = Counter(0), rhs = Counter(1) - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4) - expression 7 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) -- Code(Expression(0, Sub)) at (prev + 3, 11) to (start + 0, 12) +Number of file 0 mappings: 16 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 38) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Expression(0, Sub)) at (prev + 2, 11) to (start + 0, 12) = (c1 - c3) - Code(Expression(1, Sub)) at (prev + 1, 20) to (start + 2, 10) = (c2 - c1) @@ -22,14 +23,16 @@ Number of file 0 mappings: 13 - Branch { true: Counter(3), false: Expression(0, Sub) } at (prev + 0, 20) to (start + 0, 30) true = c3 false = (c1 - c3) -- Code(Counter(3)) at (prev + 0, 29) to (start + 2, 10) +- Code(Counter(3)) at (prev + 0, 29) to (start + 0, 30) +- Code(Counter(3)) at (prev + 0, 34) to (start + 2, 10) - Code(Counter(4)) at (prev + 3, 14) to (start + 0, 15) - Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 0, 25) = (c1 - c3) - Branch { true: Counter(4), false: Expression(2, Sub) } at (prev + 0, 20) to (start + 0, 30) true = c4 false = (c1 - (c3 + c4)) -- Code(Counter(4)) at (prev + 0, 29) to (start + 2, 10) +- Code(Counter(4)) at (prev + 0, 29) to (start + 0, 30) +- Code(Counter(4)) at (prev + 0, 34) to (start + 2, 10) - Code(Expression(4, Sub)) at (prev + 3, 14) to (start + 2, 10) = ((c0 + c1) - ((c2 + c3) + c4)) - Code(Counter(0)) at (prev + 4, 1) to (start + 0, 2) diff --git a/tests/coverage/branch/guard.coverage b/tests/coverage/branch/guard.coverage index f89b965b5d0f..465aefbf0665 100644 --- a/tests/coverage/branch/guard.coverage +++ b/tests/coverage/branch/guard.coverage @@ -17,7 +17,7 @@ LL| 1| println!("zero"); LL| 1| } LL| 3| Some(x) if x % 2 == 0 => { - ^2 + ^2 ^2 ------------------ | Branch (LL:20): [True: 2, False: 1] ------------------ diff --git a/tests/coverage/branch/if-let.cov-map b/tests/coverage/branch/if-let.cov-map index 7f6b174615a9..86bfcadb1255 100644 --- a/tests/coverage/branch/if-let.cov-map +++ b/tests/coverage/branch/if-let.cov-map @@ -1,12 +1,13 @@ Function name: if_let::if_let -Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 01, 02] +Raw bytes (58): 0x[01, 01, 01, 01, 05, 0a, 01, 0c, 01, 00, 1f, 01, 01, 05, 00, 0e, 20, 02, 05, 02, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 00, 08, 01, 00, 09, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if-let.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) -- Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 12) to (start + 0, 19) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 31) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 2, 12) to (start + 0, 19) true = (c0 - c1) false = c1 - Code(Expression(0, Sub)) at (prev + 0, 17) to (start + 0, 18) @@ -15,41 +16,53 @@ Number of file 0 mappings: 7 - Code(Expression(0, Sub)) at (prev + 0, 28) to (start + 2, 6) = (c0 - c1) - Code(Counter(1)) at (prev + 2, 12) to (start + 2, 6) -- Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: if_let::if_let_chain -Raw bytes (74): 0x[01, 01, 08, 01, 05, 01, 1f, 05, 09, 01, 1f, 05, 09, 01, 1f, 05, 09, 05, 09, 0a, 01, 17, 01, 00, 33, 20, 02, 05, 01, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 17, 20, 16, 09, 01, 10, 00, 17, 16, 00, 15, 00, 16, 02, 00, 1a, 00, 1b, 16, 01, 05, 03, 06, 1f, 03, 0c, 02, 06, 01, 03, 05, 01, 02] +Raw bytes (102): 0x[01, 01, 0c, 01, 05, 01, 2f, 05, 09, 01, 2f, 05, 09, 01, 2f, 05, 09, 01, 2f, 05, 09, 01, 2f, 05, 09, 05, 09, 0e, 01, 17, 01, 00, 32, 20, 02, 05, 01, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 17, 20, 26, 09, 01, 10, 00, 17, 26, 00, 15, 00, 16, 02, 00, 1a, 00, 1b, 26, 01, 05, 03, 06, 26, 01, 09, 00, 0c, 26, 00, 0d, 00, 0e, 2f, 02, 0c, 02, 06, 01, 03, 05, 00, 08, 01, 00, 09, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 8 +- file 0 => $DIR/if-let.rs +Number of expressions: 12 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Counter(0), rhs = Expression(7, Add) +- expression 1 operands: lhs = Counter(0), rhs = Expression(11, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) -- expression 3 operands: lhs = Counter(0), rhs = Expression(7, Add) +- expression 3 operands: lhs = Counter(0), rhs = Expression(11, Add) - expression 4 operands: lhs = Counter(1), rhs = Counter(2) -- expression 5 operands: lhs = Counter(0), rhs = Expression(7, Add) +- expression 5 operands: lhs = Counter(0), rhs = Expression(11, Add) - expression 6 operands: lhs = Counter(1), rhs = Counter(2) -- expression 7 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 51) +- expression 7 operands: lhs = Counter(0), rhs = Expression(11, Add) +- expression 8 operands: lhs = Counter(1), rhs = Counter(2) +- expression 9 operands: lhs = Counter(0), rhs = Expression(11, Add) +- expression 10 operands: lhs = Counter(1), rhs = Counter(2) +- expression 11 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 50) - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 1, 12) to (start + 0, 19) true = (c0 - c1) false = c1 - Code(Expression(0, Sub)) at (prev + 0, 17) to (start + 0, 18) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 22) to (start + 0, 23) -- Branch { true: Expression(5, Sub), false: Counter(2) } at (prev + 1, 16) to (start + 0, 23) +- Branch { true: Expression(9, Sub), false: Counter(2) } at (prev + 1, 16) to (start + 0, 23) true = (c0 - (c1 + c2)) false = c2 -- Code(Expression(5, Sub)) at (prev + 0, 21) to (start + 0, 22) +- Code(Expression(9, Sub)) at (prev + 0, 21) to (start + 0, 22) = (c0 - (c1 + c2)) - Code(Expression(0, Sub)) at (prev + 0, 26) to (start + 0, 27) = (c0 - c1) -- Code(Expression(5, Sub)) at (prev + 1, 5) to (start + 3, 6) +- Code(Expression(9, Sub)) at (prev + 1, 5) to (start + 3, 6) = (c0 - (c1 + c2)) -- Code(Expression(7, Add)) at (prev + 3, 12) to (start + 2, 6) +- Code(Expression(9, Sub)) at (prev + 1, 9) to (start + 0, 12) + = (c0 - (c1 + c2)) +- Code(Expression(9, Sub)) at (prev + 0, 13) to (start + 0, 14) + = (c0 - (c1 + c2)) +- Code(Expression(11, Add)) at (prev + 2, 12) to (start + 2, 6) = (c1 + c2) -- Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c2 diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map index 1d40f032aa87..09a014ce8a1a 100644 --- a/tests/coverage/branch/if.cov-map +++ b/tests/coverage/branch/if.cov-map @@ -1,14 +1,15 @@ Function name: if::branch_and -Raw bytes (54): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 2b, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (59): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 09, 01, 2b, 01, 00, 20, 01, 01, 05, 00, 0e, 01, 02, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 43, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -23,9 +24,9 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::branch_not -Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (126): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 14, 01, 0c, 01, 00, 17, 01, 01, 05, 00, 0e, 01, 02, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 0c, 05, 00, 0d, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 7 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) @@ -34,13 +35,15 @@ Number of expressions: 7 - expression 4 operands: lhs = Counter(0), rhs = Counter(3) - expression 5 operands: lhs = Counter(0), rhs = Counter(4) - expression 6 operands: lhs = Counter(0), rhs = Counter(4) -Number of file 0 mappings: 18 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) +Number of file 0 mappings: 20 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) -- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 8) to (start + 0, 10) @@ -68,18 +71,19 @@ Number of file 0 mappings: 18 Highest counter ID seen: c4 Function name: if::branch_not_as -Raw bytes (90): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0e, 01, 1d, 01, 01, 0e, 01, 03, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (95): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0f, 01, 1d, 01, 00, 1a, 01, 01, 05, 00, 0e, 01, 02, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 5 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) - expression 3 operands: lhs = Counter(0), rhs = Counter(3) - expression 4 operands: lhs = Counter(0), rhs = Counter(3) -Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 20) +Number of file 0 mappings: 15 +- Code(Counter(0)) at (prev + 29, 1) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 20) - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 0, 8) to (start + 0, 20) true = (c0 - c1) false = c1 @@ -104,9 +108,9 @@ Number of file 0 mappings: 14 Highest counter ID seen: c3 Function name: if::branch_or -Raw bytes (60): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 08, 01, 35, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 09, 01, 35, 01, 00, 1f, 01, 01, 05, 00, 0e, 01, 02, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 6 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(5, Add) @@ -114,9 +118,10 @@ Number of expressions: 6 - expression 3 operands: lhs = Counter(1), rhs = Counter(2) - expression 4 operands: lhs = Counter(0), rhs = Expression(5, Add) - expression 5 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 53, 1) to (start + 0, 31) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map index 5d4fc57eb8f7..9ec7c9a7f42b 100644 --- a/tests/coverage/branch/lazy-boolean.cov-map +++ b/tests/coverage/branch/lazy-boolean.cov-map @@ -1,42 +1,48 @@ Function name: lazy_boolean::branch_and -Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 13, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (53): 0x[01, 01, 01, 01, 05, 09, 01, 13, 01, 00, 20, 01, 01, 05, 00, 0e, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/lazy-boolean.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: lazy_boolean::branch_or -Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 1b, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (53): 0x[01, 01, 01, 01, 05, 09, 01, 1b, 01, 00, 1f, 01, 01, 05, 00, 0e, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/lazy-boolean.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 27, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 31) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Expression(0, Sub)) at (prev + 0, 18) to (start + 0, 19) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: lazy_boolean::chain -Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02] +Raw bytes (161): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 17, 01, 24, 01, 00, 11, 01, 01, 05, 00, 0e, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/lazy-boolean.rs Number of expressions: 15 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) @@ -53,9 +59,10 @@ Number of expressions: 15 - expression 12 operands: lhs = Counter(0), rhs = Expression(13, Add) - expression 13 operands: lhs = Expression(14, Add), rhs = Counter(6) - expression 14 operands: lhs = Counter(4), rhs = Counter(5) -Number of file 0 mappings: 19 -- Code(Counter(0)) at (prev + 36, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) +Number of file 0 mappings: 23 +- Code(Counter(0)) at (prev + 36, 1) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 18) true = c1 @@ -69,7 +76,8 @@ Number of file 0 mappings: 19 true = c3 false = (c2 - c3) - Code(Counter(3)) at (prev + 0, 40) to (start + 0, 45) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18) - Branch { true: Counter(4), false: Expression(4, Sub) } at (prev + 0, 13) to (start + 0, 18) @@ -87,13 +95,15 @@ Number of file 0 mappings: 19 false = (c0 - ((c4 + c5) + c6)) - Code(Expression(12, Sub)) at (prev + 0, 40) to (start + 0, 45) = (c0 - ((c4 + c5) + c6)) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c6 Function name: lazy_boolean::nested_mixed -Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02] +Raw bytes (157): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 17, 01, 31, 01, 00, 18, 01, 01, 05, 00, 0e, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/lazy-boolean.rs Number of expressions: 13 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(7, Add) @@ -108,9 +118,10 @@ Number of expressions: 13 - expression 10 operands: lhs = Counter(0), rhs = Counter(5) - expression 11 operands: lhs = Counter(0), rhs = Expression(12, Add) - expression 12 operands: lhs = Counter(5), rhs = Counter(6) -Number of file 0 mappings: 19 -- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) +Number of file 0 mappings: 23 +- Code(Counter(0)) at (prev + 49, 1) to (start + 0, 24) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 14) to (start + 0, 19) true = c1 @@ -127,7 +138,8 @@ Number of file 0 mappings: 19 false = ((c1 + c2) - c3) - Code(Expression(6, Sub)) at (prev + 0, 44) to (start + 0, 51) = ((c1 + c2) - c3) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19) - Branch { true: Counter(4), false: Expression(8, Sub) } at (prev + 0, 14) to (start + 0, 19) @@ -143,6 +155,8 @@ Number of file 0 mappings: 19 true = c6 false = (c0 - (c5 + c6)) - Code(Counter(6)) at (prev + 0, 44) to (start + 0, 51) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c6 diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map index 78507a326388..61bedbfbff0c 100644 --- a/tests/coverage/branch/let-else.cov-map +++ b/tests/coverage/branch/let-else.cov-map @@ -1,19 +1,24 @@ Function name: let_else::let_else -Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0a, 01, 01, 01, 00, 02] +Raw bytes (63): 0x[01, 01, 01, 01, 05, 0b, 01, 0c, 01, 00, 21, 01, 01, 05, 00, 0e, 20, 02, 05, 02, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 00, 0c, 05, 00, 0d, 00, 13, 05, 01, 09, 00, 0f, 02, 03, 05, 00, 08, 02, 00, 09, 00, 0a, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/let-else.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) -- Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 9) to (start + 0, 16) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 2, 9) to (start + 0, 16) true = (c0 - c1) false = c1 - Code(Expression(0, Sub)) at (prev + 0, 14) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 19) to (start + 0, 24) -- Code(Counter(1)) at (prev + 1, 9) to (start + 1, 15) -- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 10) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 19) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 15) +- Code(Expression(0, Sub)) at (prev + 3, 5) to (start + 0, 8) + = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 0, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map index ef71d12c8af1..a2ed0d84ed61 100644 --- a/tests/coverage/branch/match-arms.cov-map +++ b/tests/coverage/branch/match-arms.cov-map @@ -1,7 +1,7 @@ Function name: match_arms::guards -Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 0e, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 28, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 28, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 28, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 28, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 15, 01, 03, 05, 01, 02] +Raw bytes (158): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 1a, 01, 30, 01, 00, 23, 01, 01, 05, 00, 0e, 21, 02, 0b, 00, 10, 05, 01, 11, 00, 12, 20, 05, 02, 00, 17, 00, 1b, 05, 00, 1a, 00, 1b, 05, 00, 1f, 00, 26, 05, 00, 27, 00, 28, 09, 01, 11, 00, 12, 20, 09, 06, 00, 17, 00, 1b, 09, 00, 1a, 00, 1b, 09, 00, 1f, 00, 26, 09, 00, 27, 00, 28, 0d, 01, 11, 00, 12, 20, 0d, 0a, 00, 17, 00, 1b, 0d, 00, 1a, 00, 1b, 0d, 00, 1f, 00, 26, 0d, 00, 27, 00, 28, 11, 01, 11, 00, 12, 20, 11, 0e, 00, 17, 00, 1b, 11, 00, 1a, 00, 1b, 11, 00, 1f, 00, 26, 11, 00, 27, 00, 28, 12, 01, 0e, 00, 15, 01, 03, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/match-arms.rs Number of expressions: 8 - expression 0 operands: lhs = Counter(5), rhs = Counter(1) - expression 1 operands: lhs = Counter(6), rhs = Counter(2) @@ -11,70 +11,103 @@ Number of expressions: 8 - expression 5 operands: lhs = Expression(6, Add), rhs = Counter(4) - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(3) - expression 7 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 12 -- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 14) -- Code(Counter(8)) at (prev + 3, 11) to (start + 0, 16) -- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 40) +Number of file 0 mappings: 26 +- Code(Counter(0)) at (prev + 48, 1) to (start + 0, 35) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(8)) at (prev + 2, 11) to (start + 0, 16) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c1 false = (c5 - c1) -- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 40) +- Code(Counter(1)) at (prev + 0, 26) to (start + 0, 27) +- Code(Counter(1)) at (prev + 0, 31) to (start + 0, 38) +- Code(Counter(1)) at (prev + 0, 39) to (start + 0, 40) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18) - Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c2 false = (c6 - c2) -- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 40) +- Code(Counter(2)) at (prev + 0, 26) to (start + 0, 27) +- Code(Counter(2)) at (prev + 0, 31) to (start + 0, 38) +- Code(Counter(2)) at (prev + 0, 39) to (start + 0, 40) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18) - Branch { true: Counter(3), false: Expression(2, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c3 false = (c7 - c3) -- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 40) +- Code(Counter(3)) at (prev + 0, 26) to (start + 0, 27) +- Code(Counter(3)) at (prev + 0, 31) to (start + 0, 38) +- Code(Counter(3)) at (prev + 0, 39) to (start + 0, 40) +- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 18) - Branch { true: Counter(4), false: Expression(3, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c4 false = (c8 - c4) +- Code(Counter(4)) at (prev + 0, 26) to (start + 0, 27) +- Code(Counter(4)) at (prev + 0, 31) to (start + 0, 38) +- Code(Counter(4)) at (prev + 0, 39) to (start + 0, 40) - Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 21) = (c0 - (((c1 + c2) + c3) + c4)) -- Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c8 Function name: match_arms::match_arms -Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 20, 09, 01, 11, 00, 20, 0d, 01, 11, 00, 20, 02, 01, 11, 00, 20, 01, 03, 05, 01, 02] +Raw bytes (95): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 11, 01, 18, 01, 00, 1b, 01, 01, 05, 00, 0e, 01, 02, 0b, 00, 10, 05, 01, 11, 00, 12, 05, 00, 17, 00, 1e, 05, 00, 1f, 00, 20, 09, 01, 11, 00, 12, 09, 00, 17, 00, 1e, 09, 00, 1f, 00, 20, 0d, 01, 11, 00, 12, 0d, 00, 17, 00, 1e, 0d, 00, 1f, 00, 20, 02, 01, 11, 00, 12, 02, 00, 17, 00, 1e, 02, 00, 1f, 00, 20, 01, 03, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/match-arms.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) - expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) -- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 32) -- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 32) -- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 32) -- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 32) +Number of file 0 mappings: 17 +- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 27) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 11) to (start + 0, 16) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18) +- Code(Counter(1)) at (prev + 0, 23) to (start + 0, 30) +- Code(Counter(1)) at (prev + 0, 31) to (start + 0, 32) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18) +- Code(Counter(2)) at (prev + 0, 23) to (start + 0, 30) +- Code(Counter(2)) at (prev + 0, 31) to (start + 0, 32) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18) +- Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30) +- Code(Counter(3)) at (prev + 0, 31) to (start + 0, 32) +- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 18) = (c0 - ((c1 + c2) + c3)) -- Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) +- Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 0, 30) + = (c0 - ((c1 + c2) + c3)) +- Code(Expression(0, Sub)) at (prev + 0, 31) to (start + 0, 32) + = (c0 - ((c1 + c2) + c3)) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 Function name: match_arms::or_patterns -Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2d, 01, 03, 05, 01, 02] +Raw bytes (79): 0x[01, 01, 05, 05, 09, 01, 0b, 03, 0d, 01, 03, 01, 03, 0d, 01, 25, 01, 00, 1c, 01, 01, 05, 00, 0e, 01, 02, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2b, 03, 00, 2c, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 12, 00, 24, 00, 2b, 12, 00, 2c, 00, 2d, 01, 03, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 4 +- file 0 => $DIR/match-arms.rs +Number of expressions: 5 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add) - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) - expression 3 operands: lhs = Counter(0), rhs = Expression(0, Add) -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) +- expression 4 operands: lhs = Counter(0), rhs = Expression(0, Add) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 11) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18) - Code(Counter(2)) at (prev + 0, 30) to (start + 0, 31) -- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 45) +- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 43) + = (c1 + c2) +- Code(Expression(0, Add)) at (prev + 0, 44) to (start + 0, 45) = (c1 + c2) - Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18) - Code(Expression(1, Sub)) at (prev + 0, 30) to (start + 0, 31) = (c0 - ((c1 + c2) + c3)) -- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 45) +- Code(Expression(4, Sub)) at (prev + 0, 36) to (start + 0, 43) = (c0 - (c1 + c2)) -- Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) +- Code(Expression(4, Sub)) at (prev + 0, 44) to (start + 0, 45) + = (c0 - (c1 + c2)) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 diff --git a/tests/coverage/branch/match-trivial.cov-map b/tests/coverage/branch/match-trivial.cov-map index 1b0c6d12e3dc..a88e89523ae2 100644 --- a/tests/coverage/branch/match-trivial.cov-map +++ b/tests/coverage/branch/match-trivial.cov-map @@ -1,19 +1,24 @@ Function name: match_trivial::_uninhabited (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 0e] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 16, 01, 00, 20, 00, 01, 05, 00, 0e] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/match-trivial.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 22, 1) to (start + 1, 14) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 22, 1) to (start + 0, 32) +- Code(Zero) at (prev + 1, 5) to (start + 0, 14) Highest counter ID seen: (none) Function name: match_trivial::trivial -Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 0e, 01, 03, 0b, 05, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 1e, 01, 00, 17, 01, 01, 05, 00, 0e, 01, 02, 0b, 00, 0c, 01, 01, 1b, 00, 22, 01, 03, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/match-trivial.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 11) to (start + 5, 2) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 30, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 11) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 27) to (start + 0, 34) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/branch/match-trivial.coverage b/tests/coverage/branch/match-trivial.coverage index 4ffb172e1b67..6e7bf2d29abc 100644 --- a/tests/coverage/branch/match-trivial.coverage +++ b/tests/coverage/branch/match-trivial.coverage @@ -32,8 +32,8 @@ LL| | LL| 1| match x { LL| 1| Trivial::Value => consume("trivial"), - LL| 1| } - LL| 1| + LL| | } + LL| | LL| 1| consume("done"); LL| 1|} LL| | diff --git a/tests/coverage/branch/no-mir-spans.cov-map b/tests/coverage/branch/no-mir-spans.cov-map index 8fb44ef30fdb..4f893cba1f81 100644 --- a/tests/coverage/branch/no-mir-spans.cov-map +++ b/tests/coverage/branch/no-mir-spans.cov-map @@ -1,40 +1,40 @@ Function name: no_mir_spans::while_cond -Raw bytes (18): 0x[01, 01, 01, 05, 01, 02, 01, 10, 01, 00, 11, 20, 02, 01, 04, 0b, 00, 10] +Raw bytes (18): 0x[01, 01, 01, 05, 01, 02, 01, 10, 01, 00, 10, 20, 02, 01, 04, 0b, 00, 10] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no-mir-spans.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 17) +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 16) - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 4, 11) to (start + 0, 16) true = (c1 - c0) false = c0 Highest counter ID seen: c0 Function name: no_mir_spans::while_cond_not -Raw bytes (18): 0x[01, 01, 01, 05, 01, 02, 01, 19, 01, 00, 15, 20, 02, 01, 04, 0b, 00, 14] +Raw bytes (18): 0x[01, 01, 01, 05, 01, 02, 01, 19, 01, 00, 14, 20, 02, 01, 04, 0b, 00, 14] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no-mir-spans.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 25, 1) to (start + 0, 21) +- Code(Counter(0)) at (prev + 25, 1) to (start + 0, 20) - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 4, 11) to (start + 0, 20) true = (c1 - c0) false = c0 Highest counter ID seen: c0 Function name: no_mir_spans::while_op_and -Raw bytes (31): 0x[01, 01, 04, 09, 05, 09, 01, 0f, 09, 01, 05, 03, 01, 22, 01, 00, 13, 20, 05, 02, 05, 0b, 00, 10, 20, 06, 0a, 00, 14, 00, 19] +Raw bytes (31): 0x[01, 01, 04, 09, 05, 09, 01, 0f, 09, 01, 05, 03, 01, 22, 01, 00, 12, 20, 05, 02, 05, 0b, 00, 10, 20, 06, 0a, 00, 14, 00, 19] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no-mir-spans.rs Number of expressions: 4 - expression 0 operands: lhs = Counter(2), rhs = Counter(1) - expression 1 operands: lhs = Counter(2), rhs = Counter(0) - expression 2 operands: lhs = Expression(3, Add), rhs = Counter(2) - expression 3 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 34, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 34, 1) to (start + 0, 18) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 5, 11) to (start + 0, 16) true = c1 false = (c2 - c1) @@ -44,15 +44,15 @@ Number of file 0 mappings: 3 Highest counter ID seen: c1 Function name: no_mir_spans::while_op_or -Raw bytes (29): 0x[01, 01, 03, 09, 05, 09, 0b, 01, 05, 03, 01, 2d, 01, 00, 12, 20, 05, 02, 05, 0b, 00, 10, 20, 06, 01, 00, 14, 00, 19] +Raw bytes (29): 0x[01, 01, 03, 09, 05, 09, 0b, 01, 05, 03, 01, 2d, 01, 00, 11, 20, 05, 02, 05, 0b, 00, 10, 20, 06, 01, 00, 14, 00, 19] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no-mir-spans.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(2), rhs = Counter(1) - expression 1 operands: lhs = Counter(2), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 45, 1) to (start + 0, 18) +- Code(Counter(0)) at (prev + 45, 1) to (start + 0, 17) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 5, 11) to (start + 0, 16) true = c1 false = (c2 - c1) diff --git a/tests/coverage/branch/while.cov-map b/tests/coverage/branch/while.cov-map index 67746af051b6..767a7e46495f 100644 --- a/tests/coverage/branch/while.cov-map +++ b/tests/coverage/branch/while.cov-map @@ -1,12 +1,14 @@ Function name: while::while_cond -Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 0c, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (48): 0x[01, 01, 01, 05, 01, 08, 01, 0c, 01, 00, 10, 01, 01, 05, 00, 0e, 01, 02, 09, 00, 0e, 01, 00, 11, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/while.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) - Code(Counter(1)) at (prev + 1, 11) to (start + 0, 16) - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 16) true = (c1 - c0) @@ -17,14 +19,16 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: while::while_cond_not -Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 15, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (48): 0x[01, 01, 01, 05, 01, 08, 01, 15, 01, 00, 14, 01, 01, 05, 00, 0e, 01, 02, 09, 00, 0e, 01, 00, 11, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/while.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) - Code(Counter(1)) at (prev + 1, 11) to (start + 0, 20) - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 20) true = (c1 - c0) @@ -35,19 +39,23 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: while::while_op_and -Raw bytes (58): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 08, 01, 1e, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 0c, 01, 1e, 01, 00, 12, 01, 01, 05, 00, 0e, 01, 02, 09, 00, 0e, 01, 00, 11, 00, 12, 01, 01, 09, 00, 0e, 01, 00, 11, 00, 12, 05, 01, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/while.rs Number of expressions: 5 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Counter(1), rhs = Counter(0) - expression 2 operands: lhs = Expression(3, Add), rhs = Counter(1) - expression 3 operands: lhs = Counter(0), rhs = Counter(2) - expression 4 operands: lhs = Counter(1), rhs = Counter(0) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 30, 1) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 16) - Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16) true = c2 false = (c1 - c2) @@ -61,18 +69,22 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: while::while_op_or -Raw bytes (56): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 08, 01, 29, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02] +Raw bytes (76): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 0c, 01, 29, 01, 00, 11, 01, 01, 05, 00, 0e, 01, 02, 09, 00, 0e, 01, 00, 11, 00, 12, 01, 01, 09, 00, 0e, 01, 00, 11, 00, 12, 05, 01, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/while.rs Number of expressions: 4 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) - expression 3 operands: lhs = Counter(1), rhs = Counter(0) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 14) -- Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 16) - Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16) true = c2 false = (c1 - c2) diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index 2d784ba09b60..5f7e4ce58e97 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -1,18 +1,56 @@ Function name: closure::main -Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0d, 1b, 01, 1a, 05, 02, 0a, 01, 0c, 05, 11, 1b, 01, 1e, 05, 02, 0a, 01, 0c, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02] +Raw bytes (336): 0x[01, 01, 01, 01, 05, 42, 01, 09, 01, 00, 0a, 01, 04, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 01, 09, 00, 11, 01, 00, 14, 00, 1c, 01, 02, 09, 00, 18, 01, 00, 1b, 00, 43, 01, 01, 05, 00, 0d, 01, 01, 09, 00, 20, 01, 02, 09, 00, 14, 01, 02, 0d, 00, 1b, 01, 0d, 05, 00, 10, 01, 00, 13, 00, 3b, 01, 02, 09, 00, 0a, 01, 0a, 05, 00, 0d, 01, 01, 09, 00, 20, 01, 02, 09, 00, 14, 01, 02, 0d, 00, 1b, 01, 02, 0d, 00, 0e, 01, 04, 05, 00, 10, 01, 00, 13, 00, 17, 01, 01, 05, 00, 0d, 01, 01, 09, 00, 20, 01, 02, 09, 00, 14, 01, 02, 0d, 00, 1b, 01, 0d, 05, 00, 10, 01, 00, 13, 00, 17, 01, 02, 09, 00, 0a, 01, 0a, 05, 00, 0d, 01, 01, 09, 00, 20, 01, 02, 09, 00, 14, 01, 02, 0d, 00, 1b, 01, 02, 0d, 00, 0e, 01, 05, 09, 00, 16, 01, 0a, 05, 00, 0d, 01, 01, 09, 00, 28, 01, 02, 09, 00, 1a, 01, 01, 0e, 00, 12, 01, 01, 0e, 00, 11, 01, 02, 0d, 00, 1a, 01, 02, 0e, 00, 15, 01, 04, 09, 00, 18, 01, 0c, 09, 00, 16, 01, 00, 19, 00, 1b, 01, 01, 09, 00, 1e, 01, 03, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 05, 01, 09, 00, 30, 02, 03, 05, 00, 06, 01, 01, 05, 00, 28, 01, 01, 05, 00, 46, 01, 01, 05, 00, 43, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 24 -- Code(Counter(0)) at (prev + 9, 1) to (start + 13, 27) -- Code(Counter(0)) at (prev + 26, 5) to (start + 2, 10) -- Code(Counter(0)) at (prev + 12, 5) to (start + 17, 27) -- Code(Counter(0)) at (prev + 30, 5) to (start + 2, 10) -- Code(Counter(0)) at (prev + 12, 5) to (start + 12, 22) -- Code(Counter(0)) at (prev + 22, 5) to (start + 13, 24) -- Code(Counter(0)) at (prev + 25, 9) to (start + 1, 30) -- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 41) +Number of file 0 mappings: 66 +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 28) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 24) +- Code(Counter(0)) at (prev + 0, 27) to (start + 0, 67) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 32) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 20) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 27) +- Code(Counter(0)) at (prev + 13, 5) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 59) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 10, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 32) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 20) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 27) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 32) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 20) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 27) +- Code(Counter(0)) at (prev + 13, 5) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 23) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 10, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 32) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 20) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 27) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 5, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 10, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 40) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 14) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 14) to (start + 0, 17) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 26) +- Code(Counter(0)) at (prev + 2, 14) to (start + 0, 21) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 24) +- Code(Counter(0)) at (prev + 12, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 27) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 30) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 41) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 45) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 36) - Code(Counter(0)) at (prev + 5, 9) to (start + 0, 36) @@ -27,238 +65,277 @@ Number of file 0 mappings: 24 - Code(Counter(0)) at (prev + 8, 9) to (start + 0, 68) - Code(Counter(0)) at (prev + 10, 8) to (start + 0, 16) - Code(Counter(1)) at (prev + 0, 17) to (start + 4, 6) -- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 6) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 48) +- Code(Expression(0, Sub)) at (prev + 3, 5) to (start + 0, 6) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 5) to (start + 3, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 40) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 70) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 67) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: closure::main::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 28, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 01, 06] +Raw bytes (51): 0x[01, 01, 01, 01, 05, 09, 01, 28, 05, 00, 06, 01, 01, 0d, 00, 1a, 01, 00, 1d, 00, 1e, 01, 01, 0c, 00, 14, 05, 00, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 00, 17, 01, 00, 18, 00, 20, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 40, 5) to (start + 2, 20) -- Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 40, 5) to (start + 0, 6) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 26) +- Code(Counter(0)) at (prev + 0, 29) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 20) +- Code(Counter(1)) at (prev + 0, 21) to (start + 2, 10) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c1 Function name: closure::main::{closure#10} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 9b, 01, 07, 00, 21] +Raw bytes (25): 0x[01, 01, 00, 04, 00, 9b, 01, 07, 00, 08, 00, 00, 09, 00, 11, 00, 00, 12, 00, 1e, 00, 00, 20, 00, 21] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 155, 7) to (start + 0, 33) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 155, 7) to (start + 0, 8) +- Code(Zero) at (prev + 0, 9) to (start + 0, 17) +- Code(Zero) at (prev + 0, 18) to (start + 0, 30) +- Code(Zero) at (prev + 0, 32) to (start + 0, 33) Highest counter ID seen: (none) Function name: closure::main::{closure#11} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 9f, 01, 07, 00, 21] +Raw bytes (25): 0x[01, 01, 00, 04, 00, 9f, 01, 07, 00, 08, 00, 00, 09, 00, 11, 00, 00, 12, 00, 1e, 00, 00, 20, 00, 21] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 159, 7) to (start + 0, 33) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 159, 7) to (start + 0, 8) +- Code(Zero) at (prev + 0, 9) to (start + 0, 17) +- Code(Zero) at (prev + 0, 18) to (start + 0, 30) +- Code(Zero) at (prev + 0, 32) to (start + 0, 33) Highest counter ID seen: (none) Function name: closure::main::{closure#12} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, a7, 01, 01, 00, 17] +Raw bytes (10): 0x[01, 01, 00, 01, 00, a7, 01, 0a, 00, 16] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 167, 1) to (start + 0, 23) +- Code(Zero) at (prev + 167, 10) to (start + 0, 22) Highest counter ID seen: (none) Function name: closure::main::{closure#13} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, ac, 01, 0d, 02, 0e] +Raw bytes (10): 0x[01, 01, 00, 01, 00, ad, 01, 11, 00, 1d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 172, 13) to (start + 2, 14) +- Code(Zero) at (prev + 173, 17) to (start + 0, 29) Highest counter ID seen: (none) Function name: closure::main::{closure#14} -Raw bytes (22): 0x[01, 01, 01, 01, 05, 03, 01, b3, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33] +Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, b4, 01, 11, 00, 21, 01, 01, 14, 00, 1b, 05, 00, 1e, 00, 25, 02, 00, 2f, 00, 33] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 179, 13) to (start + 2, 27) -- Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 180, 17) to (start + 0, 33) +- Code(Counter(0)) at (prev + 1, 20) to (start + 0, 27) +- Code(Counter(1)) at (prev + 0, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) Highest counter ID seen: c1 Function name: closure::main::{closure#15} -Raw bytes (37): 0x[01, 01, 01, 01, 05, 06, 01, bb, 01, 09, 00, 0a, 01, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 02, 09, 00, 0a] +Raw bytes (42): 0x[01, 01, 01, 01, 05, 07, 01, bb, 01, 09, 00, 0a, 01, 01, 0d, 00, 15, 01, 01, 11, 00, 21, 01, 01, 14, 00, 1b, 05, 00, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 02, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 +Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 187, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 21) -- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) -- Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 17) to (start + 0, 33) +- Code(Counter(0)) at (prev + 1, 20) to (start + 0, 27) +- Code(Counter(1)) at (prev + 0, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) Highest counter ID seen: c1 Function name: closure::main::{closure#16} -Raw bytes (22): 0x[01, 01, 01, 01, 05, 03, 01, c5, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33] +Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, c6, 01, 11, 00, 21, 01, 01, 14, 00, 1b, 05, 00, 1e, 00, 25, 02, 00, 2f, 00, 33] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 197, 13) to (start + 2, 27) -- Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 198, 17) to (start + 0, 33) +- Code(Counter(0)) at (prev + 1, 20) to (start + 0, 27) +- Code(Counter(1)) at (prev + 0, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) Highest counter ID seen: c1 Function name: closure::main::{closure#17} -Raw bytes (37): 0x[01, 01, 01, 01, 05, 06, 01, cd, 01, 09, 00, 0a, 01, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 02, 09, 00, 0a] +Raw bytes (42): 0x[01, 01, 01, 01, 05, 07, 01, cd, 01, 09, 00, 0a, 01, 01, 0d, 00, 15, 01, 01, 11, 00, 21, 01, 01, 14, 00, 1b, 05, 00, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 02, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 +Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 205, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 21) -- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) -- Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 17) to (start + 0, 33) +- Code(Counter(0)) at (prev + 1, 20) to (start + 0, 27) +- Code(Counter(1)) at (prev + 0, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) Highest counter ID seen: c1 Function name: closure::main::{closure#18} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 19, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] +Raw bytes (51): 0x[01, 01, 01, 01, 05, 09, 01, 19, 0d, 00, 0e, 01, 01, 15, 00, 22, 01, 00, 25, 00, 26, 01, 01, 14, 00, 1c, 05, 00, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 00, 1f, 01, 00, 20, 00, 28, 01, 01, 0d, 00, 0e] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 25, 13) to (start + 2, 28) -- Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 25, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 1, 21) to (start + 0, 34) +- Code(Counter(0)) at (prev + 0, 37) to (start + 0, 38) +- Code(Counter(0)) at (prev + 1, 20) to (start + 0, 28) +- Code(Counter(1)) at (prev + 0, 29) to (start + 2, 18) - Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 18) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14) +- Code(Counter(0)) at (prev + 1, 17) to (start + 0, 31) +- Code(Counter(0)) at (prev + 0, 32) to (start + 0, 40) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) Highest counter ID seen: c1 Function name: closure::main::{closure#19} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] +Raw bytes (51): 0x[01, 01, 01, 01, 05, 09, 01, 43, 0d, 00, 0e, 01, 01, 15, 00, 22, 01, 00, 25, 00, 26, 01, 01, 14, 00, 1c, 05, 00, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 00, 1f, 01, 00, 20, 00, 28, 01, 01, 0d, 00, 0e] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 67, 13) to (start + 2, 28) -- Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 67, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 1, 21) to (start + 0, 34) +- Code(Counter(0)) at (prev + 0, 37) to (start + 0, 38) +- Code(Counter(0)) at (prev + 1, 20) to (start + 0, 28) +- Code(Counter(1)) at (prev + 0, 29) to (start + 2, 18) - Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 18) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14) +- Code(Counter(0)) at (prev + 1, 17) to (start + 0, 31) +- Code(Counter(0)) at (prev + 0, 32) to (start + 0, 40) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) Highest counter ID seen: c1 Function name: closure::main::{closure#1} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 52, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 01, 06] +Raw bytes (51): 0x[01, 01, 01, 01, 05, 09, 01, 52, 05, 00, 06, 01, 01, 0d, 00, 1a, 01, 00, 1d, 00, 1e, 01, 01, 0c, 00, 14, 05, 00, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 00, 17, 01, 00, 18, 00, 20, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 82, 5) to (start + 2, 20) -- Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 82, 5) to (start + 0, 6) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 26) +- Code(Counter(0)) at (prev + 0, 29) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 20) +- Code(Counter(1)) at (prev + 0, 21) to (start + 2, 10) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c1 Function name: closure::main::{closure#2} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 68, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 01, 06] +Raw bytes (51): 0x[01, 01, 01, 01, 05, 09, 01, 68, 05, 00, 06, 01, 01, 0d, 00, 1a, 01, 00, 1d, 00, 1e, 01, 01, 0c, 00, 14, 05, 00, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 00, 10, 01, 00, 11, 00, 17, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 104, 5) to (start + 2, 20) -- Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 104, 5) to (start + 0, 6) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 26) +- Code(Counter(0)) at (prev + 0, 29) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 20) +- Code(Counter(1)) at (prev + 0, 21) to (start + 2, 10) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c1 Function name: closure::main::{closure#3} (unused) -Raw bytes (25): 0x[01, 01, 00, 04, 00, 81, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 09, 00, 0a, 00, 01, 09, 01, 06] +Raw bytes (40): 0x[01, 01, 00, 07, 00, 81, 01, 05, 00, 06, 00, 01, 0c, 00, 14, 00, 00, 15, 02, 0a, 00, 02, 09, 00, 0a, 00, 01, 09, 00, 23, 00, 00, 24, 00, 2c, 00, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Zero) at (prev + 129, 5) to (start + 1, 20) -- Code(Zero) at (prev + 1, 21) to (start + 2, 10) +Number of file 0 mappings: 7 +- Code(Zero) at (prev + 129, 5) to (start + 0, 6) +- Code(Zero) at (prev + 1, 12) to (start + 0, 20) +- Code(Zero) at (prev + 0, 21) to (start + 2, 10) - Code(Zero) at (prev + 2, 9) to (start + 0, 10) -- Code(Zero) at (prev + 1, 9) to (start + 1, 6) -Highest counter ID seen: (none) - -Function name: closure::main::{closure#4} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 89, 01, 35, 00, 43] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 137, 53) to (start + 0, 67) +- Code(Zero) at (prev + 1, 9) to (start + 0, 35) +- Code(Zero) at (prev + 0, 36) to (start + 0, 44) +- Code(Zero) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: (none) Function name: closure::main::{closure#5} -Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 3d, 00, 4f] +Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 46, 00, 4e] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 140, 61) to (start + 0, 79) +- Code(Counter(0)) at (prev + 140, 70) to (start + 0, 78) Highest counter ID seen: c0 Function name: closure::main::{closure#6} -Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 41, 00, 57] +Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 4a, 00, 56] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 141, 65) to (start + 0, 87) +- Code(Counter(0)) at (prev + 141, 74) to (start + 0, 86) Highest counter ID seen: c0 Function name: closure::main::{closure#7} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 8e, 01, 3b, 00, 51] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 8e, 01, 44, 00, 50] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 142, 59) to (start + 0, 81) +- Code(Zero) at (prev + 142, 68) to (start + 0, 80) Highest counter ID seen: (none) Function name: closure::main::{closure#8} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 93, 01, 3b, 00, 55] +Raw bytes (25): 0x[01, 01, 00, 04, 00, 93, 01, 3b, 00, 3c, 00, 00, 3d, 00, 45, 00, 00, 46, 00, 52, 00, 00, 54, 00, 55] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 147, 59) to (start + 0, 85) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 147, 59) to (start + 0, 60) +- Code(Zero) at (prev + 0, 61) to (start + 0, 69) +- Code(Zero) at (prev + 0, 70) to (start + 0, 82) +- Code(Zero) at (prev + 0, 84) to (start + 0, 85) Highest counter ID seen: (none) Function name: closure::main::{closure#9} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 95, 01, 38, 02, 06] +Raw bytes (25): 0x[01, 01, 00, 04, 00, 95, 01, 38, 00, 39, 00, 01, 09, 00, 11, 00, 00, 12, 00, 1e, 00, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 149, 56) to (start + 2, 6) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 149, 56) to (start + 0, 57) +- Code(Zero) at (prev + 1, 9) to (start + 0, 17) +- Code(Zero) at (prev + 0, 18) to (start + 0, 30) +- Code(Zero) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: (none) diff --git a/tests/coverage/closure.coverage b/tests/coverage/closure.coverage index 2deeb9806c4d..142852692289 100644 --- a/tests/coverage/closure.coverage +++ b/tests/coverage/closure.coverage @@ -7,18 +7,18 @@ LL| | LL| |#[rustfmt::skip] LL| 1|fn main() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; LL| 1| let is_false = !is_true; - LL| 1| + LL| | LL| 1| let mut some_string = Some(String::from("the string content")); LL| 1| println!( LL| 1| "The string or alt: {}" - LL| 1| , + LL| | , LL| 1| some_string - LL| 1| . + LL| | . LL| 1| unwrap_or_else LL| | ( LL| | || @@ -33,7 +33,7 @@ LL| | ); LL| | LL| 1| some_string = Some(String::from("the string content")); - LL| 1| let + LL| | let LL| 1| a LL| | = LL| | || @@ -46,21 +46,21 @@ LL| 0| }; LL| 1| println!( LL| 1| "The string or alt: {}" - LL| 1| , + LL| | , LL| 1| some_string - LL| 1| . + LL| | . LL| 1| unwrap_or_else - LL| 1| ( + LL| | ( LL| 1| a - LL| 1| ) - LL| 1| ); - LL| 1| + LL| | ) + LL| | ); + LL| | LL| 1| some_string = None; LL| 1| println!( LL| 1| "The string or alt: {}" - LL| 1| , + LL| | , LL| 1| some_string - LL| 1| . + LL| | . LL| 1| unwrap_or_else LL| | ( LL| | || @@ -75,7 +75,7 @@ LL| | ); LL| | LL| 1| some_string = None; - LL| 1| let + LL| | let LL| 1| a LL| | = LL| | || @@ -88,16 +88,16 @@ LL| 1| }; LL| 1| println!( LL| 1| "The string or alt: {}" - LL| 1| , + LL| | , LL| 1| some_string - LL| 1| . + LL| | . LL| 1| unwrap_or_else - LL| 1| ( + LL| | ( LL| 1| a - LL| 1| ) - LL| 1| ); - LL| 1| - LL| 1| let + LL| | ) + LL| | ); + LL| | + LL| | let LL| 1| quote_closure LL| | = LL| | |val| @@ -110,17 +110,17 @@ LL| 5| }; LL| 1| println!( LL| 1| "Repeated, quoted string: {:?}" - LL| 1| , + LL| | , LL| 1| std::iter::repeat("repeat me") LL| 1| .take(5) LL| 1| .map - LL| 1| ( + LL| | ( LL| 1| quote_closure - LL| 1| ) + LL| | ) LL| 1| .collect::>() - LL| 1| ); - LL| 1| - LL| 1| let + LL| | ); + LL| | + LL| | let LL| 1| _unused_closure LL| | = LL| | | @@ -135,22 +135,22 @@ LL| | LL| 1| let mut countdown = 10; LL| 1| let _short_unused_closure = | _unused_arg: u8 | countdown += 1; - ^0 LL| | LL| | LL| 1| let short_used_covered_closure_macro = | used_arg: u8 | println!("called"); LL| 1| let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called"); - ^0 + ^0 LL| 1| let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called"); - ^0 + ^0 LL| | LL| | LL| | LL| | LL| 1| let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") }; - ^0 + ^0^0 ^0 ^0 LL| | LL| 1| let _shortish_unused_closure = | _unused_arg: u8 | { + ^0 LL| 0| println!("not called") LL| 0| }; LL| | @@ -173,14 +173,14 @@ LL| | LL| 1| let _short_unused_closure_line_break_no_block2 = LL| | | _unused_arg: u8 | - LL| 0| println!( + LL| | println!( LL| 0| "not called" - LL| 0| ) + LL| | ) LL| | ; LL| | LL| 1| let short_used_not_covered_closure_line_break_no_block_embedded_branch = LL| | | _unused_arg: u8 | - LL| 0| println!( + LL| | println!( LL| 0| "not called: {}", LL| 0| if is_true { "check" } else { "me" } LL| | ) @@ -198,7 +198,7 @@ LL| | LL| 1| let short_used_covered_closure_line_break_no_block_embedded_branch = LL| | | _unused_arg: u8 | - LL| 1| println!( + LL| | println!( LL| 1| "not called: {}", LL| 1| if is_true { "check" } else { "me" } ^0 diff --git a/tests/coverage/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map index 40a8bdf9c1d6..a7087c69dcba 100644 --- a/tests/coverage/closure_bug.cov-map +++ b/tests/coverage/closure_bug.cov-map @@ -1,44 +1,51 @@ Function name: closure_bug::main -Raw bytes (97): 0x[01, 01, 04, 01, 05, 01, 09, 01, 0d, 01, 11, 11, 01, 07, 01, 03, 0a, 01, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, 02, 00, 16, 00, 17, 01, 02, 09, 00, 0a, 01, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, 06, 00, 16, 00, 17, 01, 02, 09, 00, 0a, 01, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, 0a, 00, 16, 00, 17, 01, 02, 09, 00, 0a, 01, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, 0e, 00, 16, 00, 17, 01, 01, 01, 00, 02] +Raw bytes (132): 0x[01, 01, 04, 01, 05, 01, 09, 01, 0d, 01, 11, 18, 01, 07, 01, 00, 0a, 01, 01, 09, 00, 0f, 01, 00, 12, 00, 2d, 01, 02, 09, 00, 0a, 01, 06, 05, 00, 08, 01, 01, 08, 00, 0e, 05, 00, 0f, 00, 17, 02, 00, 16, 00, 17, 01, 02, 09, 00, 0a, 01, 06, 05, 00, 08, 01, 01, 08, 00, 0e, 09, 00, 0f, 00, 17, 06, 00, 16, 00, 17, 01, 02, 09, 00, 0a, 01, 06, 05, 00, 08, 01, 01, 08, 00, 0e, 0d, 00, 0f, 00, 17, 0a, 00, 16, 00, 17, 01, 02, 09, 00, 0a, 01, 06, 05, 00, 08, 01, 01, 08, 00, 0e, 11, 00, 0f, 00, 17, 0e, 00, 16, 00, 17, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_bug.rs Number of expressions: 4 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(3) - expression 3 operands: lhs = Counter(0), rhs = Counter(4) -Number of file 0 mappings: 17 -- Code(Counter(0)) at (prev + 7, 1) to (start + 3, 10) -- Code(Counter(0)) at (prev + 9, 5) to (start + 1, 14) -- Code(Counter(1)) at (prev + 1, 15) to (start + 0, 23) +Number of file 0 mappings: 24 +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 45) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 14) +- Code(Counter(1)) at (prev + 0, 15) to (start + 0, 23) - Code(Expression(0, Sub)) at (prev + 0, 22) to (start + 0, 23) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) -- Code(Counter(0)) at (prev + 6, 5) to (start + 1, 14) -- Code(Counter(2)) at (prev + 1, 15) to (start + 0, 23) +- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 14) +- Code(Counter(2)) at (prev + 0, 15) to (start + 0, 23) - Code(Expression(1, Sub)) at (prev + 0, 22) to (start + 0, 23) = (c0 - c2) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) -- Code(Counter(0)) at (prev + 6, 5) to (start + 1, 14) -- Code(Counter(3)) at (prev + 1, 15) to (start + 0, 23) +- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 14) +- Code(Counter(3)) at (prev + 0, 15) to (start + 0, 23) - Code(Expression(2, Sub)) at (prev + 0, 22) to (start + 0, 23) = (c0 - c3) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) -- Code(Counter(0)) at (prev + 6, 5) to (start + 1, 14) -- Code(Counter(4)) at (prev + 1, 15) to (start + 0, 23) +- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 14) +- Code(Counter(4)) at (prev + 0, 15) to (start + 0, 23) - Code(Expression(3, Sub)) at (prev + 0, 22) to (start + 0, 23) = (c0 - c4) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c4 Function name: closure_bug::main::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 0c, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_bug.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 14, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 14, 12) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) @@ -46,13 +53,13 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: closure_bug::main::{closure#1} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 17, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 17, 0c, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_bug.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 23, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 23, 12) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) @@ -60,13 +67,13 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: closure_bug::main::{closure#2} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 20, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 20, 0c, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_bug.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 32, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 32, 12) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) @@ -74,13 +81,13 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: closure_bug::main::{closure#3} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 29, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 29, 0c, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_bug.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 41, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 41, 12) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) diff --git a/tests/coverage/closure_bug.coverage b/tests/coverage/closure_bug.coverage index cc64470baa77..b85375d1850b 100644 --- a/tests/coverage/closure_bug.coverage +++ b/tests/coverage/closure_bug.coverage @@ -6,7 +6,7 @@ LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| let truthy = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| let a LL| | = LL| | | diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index 9dd99c8fab3f..3ab1d7f5fba8 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -1,41 +1,57 @@ Function name: closure_macro::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 1d, 01, 00, 38, 01, 01, 05, 00, 1f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_macro.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 29, 1) to (start + 0, 56) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 31) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: closure_macro::main -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (66): 0x[01, 01, 01, 01, 05, 0c, 01, 21, 01, 00, 24, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 20, 02, 01, 09, 00, 0f, 01, 00, 12, 00, 1b, 01, 00, 1c, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 00, 1f, 02, 00, 22, 00, 2e, 02, 01, 0d, 00, 2d, 02, 01, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_macro.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 32) -- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 36) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 32) +- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c0 - c1) -- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 27) +- Code(Counter(0)) at (prev + 0, 28) to (start + 0, 52) - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) -- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 31) = (c0 - c1) -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +- Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 46) + = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 45) + = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 11) + = (c0 - c1) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: closure_macro::main::{closure#0} -Raw bytes (35): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 06, 00, 17, 00, 1e, 01, 02, 09, 00, 0a] +Raw bytes (60): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 0a, 01, 10, 1c, 00, 1d, 01, 02, 11, 00, 18, 01, 00, 1b, 00, 22, 01, 01, 10, 00, 21, 05, 01, 11, 00, 19, 05, 00, 1a, 00, 1e, 05, 01, 11, 00, 27, 02, 02, 11, 00, 16, 06, 00, 17, 00, 1e, 01, 02, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_macro.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 16, 28) to (start + 3, 33) -- Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) -- Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 16, 28) to (start + 0, 29) +- Code(Counter(0)) at (prev + 2, 17) to (start + 0, 24) +- Code(Counter(0)) at (prev + 0, 27) to (start + 0, 34) +- Code(Counter(0)) at (prev + 1, 16) to (start + 0, 33) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 25) +- Code(Counter(1)) at (prev + 0, 26) to (start + 0, 30) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 39) +- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 22) = (c0 - c1) - Code(Expression(1, Sub)) at (prev + 0, 23) to (start + 0, 30) = (c0 - (c1 + c2)) diff --git a/tests/coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage index 00022bbff89f..b1d7a8327a4e 100644 --- a/tests/coverage/closure_macro.coverage +++ b/tests/coverage/closure_macro.coverage @@ -14,7 +14,7 @@ LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { LL| 0| $value.or_else(|e| { - LL| 0| // This closure, which is declared in a macro, should be instrumented. + LL| | // This closure, which is declared in a macro, should be instrumented. LL| 0| let message = format!($error_message, e); LL| 0| if message.len() > 0 { LL| 0| println!("{}", message); diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 2548754d754c..b5f4cee0ec44 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -1,50 +1,66 @@ Function name: closure_macro_async::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 21, 01, 00, 38, 01, 01, 05, 00, 1f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_macro_async.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 56) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 31) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: closure_macro_async::test -Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 00, 2b] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 00, 2a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_macro_async.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 43) +- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 42) Highest counter ID seen: c0 Function name: closure_macro_async::test::{closure#0} -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (66): 0x[01, 01, 01, 01, 05, 0c, 01, 25, 2b, 00, 2c, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 20, 02, 01, 09, 00, 0f, 01, 00, 12, 00, 1b, 01, 00, 1c, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 00, 1f, 02, 00, 22, 00, 2e, 02, 01, 0d, 00, 2d, 02, 01, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_macro_async.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 32) -- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 37, 43) to (start + 0, 44) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 32) +- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c0 - c1) -- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 27) +- Code(Counter(0)) at (prev + 0, 28) to (start + 0, 52) - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) -- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 31) = (c0 - c1) -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +- Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 46) + = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 45) + = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 11) + = (c0 - c1) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (35): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 05, 01, 14, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 06, 00, 17, 00, 1e, 01, 02, 09, 00, 0a] +Raw bytes (60): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 0a, 01, 14, 1c, 00, 1d, 01, 02, 11, 00, 18, 01, 00, 1b, 00, 22, 01, 01, 10, 00, 21, 05, 01, 11, 00, 19, 05, 00, 1a, 00, 1e, 05, 01, 11, 00, 27, 02, 02, 11, 00, 16, 06, 00, 17, 00, 1e, 01, 02, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_macro_async.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 20, 28) to (start + 3, 33) -- Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) -- Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 20, 28) to (start + 0, 29) +- Code(Counter(0)) at (prev + 2, 17) to (start + 0, 24) +- Code(Counter(0)) at (prev + 0, 27) to (start + 0, 34) +- Code(Counter(0)) at (prev + 1, 16) to (start + 0, 33) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 25) +- Code(Counter(1)) at (prev + 0, 26) to (start + 0, 30) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 39) +- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 22) = (c0 - c1) - Code(Expression(1, Sub)) at (prev + 0, 23) to (start + 0, 30) = (c0 - (c1 + c2)) diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index 1e1ffec9f761..7bfea3c9bb3b 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -18,7 +18,7 @@ LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { LL| 0| $value.or_else(|e| { - LL| 0| // This closure, which is declared in a macro, should be instrumented. + LL| | // This closure, which is declared in a macro, should be instrumented. LL| 0| let message = format!($error_message, e); LL| 0| if message.len() > 0 { LL| 0| println!("{}", message); diff --git a/tests/coverage/closure_unit_return.cov-map b/tests/coverage/closure_unit_return.cov-map index 9a66e0b0e772..f665d93e6e1c 100644 --- a/tests/coverage/closure_unit_return.cov-map +++ b/tests/coverage/closure_unit_return.cov-map @@ -1,38 +1,49 @@ Function name: closure_unit_return::explicit_unit -Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 01, 01, 10, 01, 05, 05, 02, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 07, 01, 00, 13, 01, 01, 09, 00, 10, 01, 04, 05, 00, 09, 01, 00, 0a, 00, 11, 01, 01, 05, 00, 07, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_unit_return.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 16) -- Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 9) +- Code(Counter(0)) at (prev + 0, 10) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 7) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: closure_unit_return::explicit_unit::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 08, 16, 02, 06] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 08, 16, 00, 17, 00, 01, 09, 00, 0b, 00, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_unit_return.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 8, 22) to (start + 2, 6) +Number of file 0 mappings: 3 +- Code(Zero) at (prev + 8, 22) to (start + 0, 23) +- Code(Zero) at (prev + 1, 9) to (start + 0, 11) +- Code(Zero) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: (none) Function name: closure_unit_return::implicit_unit -Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 01, 10, 01, 05, 05, 02, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 10, 01, 00, 13, 01, 01, 09, 00, 10, 01, 04, 05, 00, 09, 01, 00, 0a, 00, 11, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_unit_return.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 16) -- Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 9) +- Code(Counter(0)) at (prev + 0, 10) to (start + 0, 17) +- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: closure_unit_return::implicit_unit::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 16, 02, 06] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 11, 16, 00, 17, 00, 01, 09, 00, 0b, 00, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/closure_unit_return.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 17, 22) to (start + 2, 6) +Number of file 0 mappings: 3 +- Code(Zero) at (prev + 17, 22) to (start + 0, 23) +- Code(Zero) at (prev + 1, 9) to (start + 0, 11) +- Code(Zero) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: (none) diff --git a/tests/coverage/closure_unit_return.coverage b/tests/coverage/closure_unit_return.coverage index 5e57e0db1600..02ea63b6dc39 100644 --- a/tests/coverage/closure_unit_return.coverage +++ b/tests/coverage/closure_unit_return.coverage @@ -6,6 +6,7 @@ LL| | LL| 1|fn explicit_unit() { LL| 1| let closure = || { + ^0 LL| 0| (); LL| 0| }; LL| | @@ -15,11 +16,12 @@ LL| | LL| 1|fn implicit_unit() { LL| 1| let closure = || { + ^0 LL| 0| (); LL| 0| }; LL| | LL| 1| drop(closure); - LL| 1| // implicit return of `()` + LL| | // implicit return of `()` LL| 1|} LL| | LL| |#[coverage(off)] diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map index c34075a0bcfc..fda5dd1b97d1 100644 --- a/tests/coverage/condition/conditions.cov-map +++ b/tests/coverage/condition/conditions.cov-map @@ -1,15 +1,15 @@ Function name: conditions::assign_3_and_or -Raw bytes (65): 0x[01, 01, 05, 01, 05, 05, 09, 01, 09, 01, 13, 09, 0d, 09, 01, 1c, 01, 00, 2f, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 06, 00, 12, 00, 13, 0a, 00, 17, 00, 18, 20, 0d, 0e, 00, 17, 00, 18, 01, 01, 05, 01, 02] +Raw bytes (75): 0x[01, 01, 05, 01, 05, 05, 09, 01, 09, 01, 13, 09, 0d, 0b, 01, 1c, 01, 00, 2e, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 06, 00, 12, 00, 13, 0a, 00, 17, 00, 18, 20, 0d, 0e, 00, 17, 00, 18, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/conditions.rs Number of expressions: 5 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) - expression 3 operands: lhs = Counter(0), rhs = Expression(4, Add) - expression 4 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 47) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 46) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) @@ -24,20 +24,22 @@ Number of file 0 mappings: 9 - Branch { true: Counter(3), false: Expression(3, Sub) } at (prev + 0, 23) to (start + 0, 24) true = c3 false = (c0 - (c2 + c3)) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 Function name: conditions::assign_3_or_and -Raw bytes (63): 0x[01, 01, 04, 01, 05, 01, 0b, 05, 09, 09, 0d, 09, 01, 17, 01, 00, 2f, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 20, 09, 06, 00, 12, 00, 13, 09, 00, 17, 00, 18, 20, 0d, 0e, 00, 17, 00, 18, 01, 01, 05, 01, 02] +Raw bytes (73): 0x[01, 01, 04, 01, 05, 01, 0b, 05, 09, 09, 0d, 0b, 01, 17, 01, 00, 2e, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 20, 09, 06, 00, 12, 00, 13, 09, 00, 17, 00, 18, 20, 0d, 0e, 00, 17, 00, 18, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/conditions.rs Number of expressions: 4 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) - expression 3 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 47) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 46) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) @@ -52,18 +54,20 @@ Number of file 0 mappings: 9 - Branch { true: Counter(3), false: Expression(3, Sub) } at (prev + 0, 23) to (start + 0, 24) true = c3 false = (c2 - c3) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 Function name: conditions::assign_and -Raw bytes (47): 0x[01, 01, 02, 01, 05, 05, 09, 07, 01, 0d, 01, 00, 21, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 06, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (57): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 0d, 01, 00, 20, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 06, 00, 12, 00, 13, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/conditions.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 33) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 32) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) @@ -73,19 +77,21 @@ Number of file 0 mappings: 7 - Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 18) to (start + 0, 19) true = c2 false = (c1 - c2) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c2 Function name: conditions::assign_or -Raw bytes (49): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 07, 01, 12, 01, 00, 20, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 20, 09, 06, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (59): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 09, 01, 12, 01, 00, 1f, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 20, 09, 06, 00, 12, 00, 13, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/conditions.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 18, 1) to (start + 0, 32) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 18, 1) to (start + 0, 31) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) @@ -96,27 +102,32 @@ Number of file 0 mappings: 7 - Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 18) to (start + 0, 19) true = c2 false = (c0 - (c1 + c2)) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c2 Function name: conditions::foo -Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 21, 01, 00, 18, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/conditions.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 24) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: conditions::func_call -Raw bytes (47): 0x[01, 01, 02, 01, 05, 05, 09, 07, 01, 25, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 20, 05, 02, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] +Raw bytes (47): 0x[01, 01, 02, 01, 05, 05, 09, 07, 01, 25, 01, 00, 1f, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 20, 05, 02, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/conditions.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 31) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) - Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 9) to (start + 0, 10) @@ -130,11 +141,16 @@ Number of file 0 mappings: 7 Highest counter ID seen: c2 Function name: conditions::simple_assign -Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 08, 01, 00, 1a, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/conditions.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/conditions.cov-map b/tests/coverage/conditions.cov-map index 2d12f4bf7744..29d9604085ed 100644 --- a/tests/coverage/conditions.cov-map +++ b/tests/coverage/conditions.cov-map @@ -1,8 +1,8 @@ Function name: conditions::main -Raw bytes (533): 0x[01, 01, 47, 05, 09, 01, 05, 09, 5d, 09, 27, 5d, 61, 27, 65, 5d, 61, 09, 23, 27, 65, 5d, 61, 01, 03, 03, 0d, 11, 51, 11, 4f, 51, 55, 4f, 59, 51, 55, 11, 4b, 4f, 59, 51, 55, 03, 97, 01, 0d, 11, 0d, 11, 0d, 11, 0d, 11, 0d, 11, 97, 01, 15, 0d, 11, 19, 45, 19, 8f, 01, 45, 49, 8f, 01, 4d, 45, 49, 19, 8b, 01, 8f, 01, 4d, 45, 49, 97, 01, db, 01, 0d, 11, 15, 19, 15, 19, 15, 19, 1d, 21, 15, 19, db, 01, 1d, 15, 19, 21, 39, 21, d3, 01, 39, 3d, d3, 01, 41, 39, 3d, 21, cf, 01, d3, 01, 41, 39, 3d, db, 01, 97, 02, 15, 19, 1d, 21, 25, 29, 1d, 21, 97, 02, 25, 1d, 21, 29, 2d, 29, 8f, 02, 2d, 31, 8f, 02, 35, 2d, 31, 29, 8b, 02, 8f, 02, 35, 2d, 31, 97, 02, 9b, 02, 1d, 21, 25, 29, 44, 01, 03, 01, 02, 0c, 01, 02, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 03, 09, 00, 0a, 01, 00, 10, 00, 1d, 05, 01, 09, 01, 0a, 06, 02, 0f, 00, 1c, 09, 01, 0c, 00, 19, 0a, 00, 1d, 00, 2a, 0e, 00, 2e, 00, 3c, 23, 00, 3d, 02, 0a, 1e, 02, 09, 00, 0a, 09, 01, 09, 01, 12, 2a, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 03, 01, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 02, 08, 00, 15, 0d, 00, 16, 02, 06, 2e, 02, 0f, 00, 1c, 11, 01, 0c, 00, 19, 32, 00, 1d, 00, 2a, 36, 00, 2e, 00, 3c, 4b, 00, 3d, 02, 0a, 46, 02, 09, 00, 0a, 11, 01, 09, 00, 17, 52, 02, 09, 00, 0f, 97, 01, 03, 08, 00, 0c, 97, 01, 01, 0d, 01, 10, 97, 01, 01, 11, 02, 0a, 00, 02, 09, 00, 0a, 97, 01, 02, 0c, 00, 19, 15, 00, 1a, 02, 0a, 6a, 04, 11, 00, 1e, 19, 01, 10, 00, 1d, 72, 00, 21, 00, 2e, 76, 00, 32, 00, 40, 8b, 01, 00, 41, 02, 0e, 86, 01, 02, 0d, 00, 0e, 19, 01, 0d, 00, 1b, 92, 01, 02, 0d, 00, 13, 00, 02, 05, 00, 06, db, 01, 02, 09, 01, 0c, db, 01, 01, 0d, 02, 06, 00, 02, 05, 00, 06, 97, 02, 02, 09, 00, 0a, db, 01, 00, 10, 00, 1d, 1d, 00, 1e, 02, 06, ae, 01, 02, 0f, 00, 1c, 21, 01, 0c, 00, 19, b6, 01, 00, 1d, 00, 2a, ba, 01, 00, 2e, 00, 3c, cf, 01, 00, 3d, 02, 0a, ca, 01, 02, 09, 00, 0a, 21, 01, 09, 00, 17, d6, 01, 02, 0d, 02, 0f, 9b, 02, 05, 09, 00, 0a, 97, 02, 00, 10, 00, 1d, 25, 00, 1e, 02, 06, ea, 01, 02, 0f, 00, 1c, 29, 01, 0c, 00, 19, f2, 01, 00, 1d, 00, 2a, f6, 01, 00, 2e, 00, 3c, 8b, 02, 00, 3d, 02, 0a, 86, 02, 02, 09, 00, 0a, 29, 01, 09, 00, 17, 92, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] +Raw bytes (656): 0x[01, 01, 57, 05, 09, 01, 05, 09, 5d, 09, 27, 5d, 61, 27, 65, 5d, 61, 09, 23, 27, 65, 5d, 61, 01, 03, 03, 0d, 11, 51, 11, 4f, 51, 55, 4f, 59, 51, 55, 11, 4b, 4f, 59, 51, 55, 03, 9f, 01, 0d, 11, 0d, 11, 0d, 11, 0d, 11, 0d, 11, 0d, 11, 0d, 11, 9f, 01, 15, 0d, 11, 19, 45, 19, 97, 01, 45, 49, 97, 01, 4d, 45, 49, 19, 93, 01, 97, 01, 4d, 45, 49, 9f, 01, 9b, 02, 0d, 11, 15, 19, 15, 19, 15, 19, 15, 19, 15, 19, 1d, 21, 15, 19, 9b, 02, 1d, 15, 19, 21, 39, 21, e3, 01, 39, 3d, e3, 01, 41, 39, 3d, 21, df, 01, e3, 01, 41, 39, 3d, 9b, 02, d7, 02, 15, 19, 1d, 21, 9b, 02, d7, 02, 15, 19, 1d, 21, 9b, 02, d7, 02, 15, 19, 1d, 21, 9b, 02, d7, 02, 15, 19, 1d, 21, 9b, 02, d7, 02, 15, 19, 1d, 21, 25, 29, 1d, 21, d7, 02, 25, 1d, 21, 29, 2d, 29, cf, 02, 2d, 31, cf, 02, 35, 2d, 31, 29, cb, 02, cf, 02, 35, 2d, 31, d7, 02, db, 02, 1d, 21, 25, 29, 53, 01, 03, 01, 00, 0a, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1a, 01, 01, 08, 00, 0c, 01, 00, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 03, 09, 00, 0a, 01, 00, 10, 00, 1d, 05, 01, 09, 00, 17, 05, 01, 09, 00, 0a, 06, 01, 0f, 00, 1c, 09, 01, 0c, 00, 19, 0a, 00, 1d, 00, 2a, 0e, 00, 2e, 00, 3c, 23, 00, 3d, 02, 0a, 1e, 02, 09, 00, 0a, 09, 01, 09, 00, 17, 09, 01, 09, 00, 12, 2a, 02, 09, 00, 0f, 03, 03, 09, 00, 16, 03, 00, 19, 00, 1a, 03, 01, 08, 00, 0c, 03, 00, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 02, 08, 00, 15, 0d, 00, 16, 02, 06, 2e, 02, 0f, 00, 1c, 11, 01, 0c, 00, 19, 32, 00, 1d, 00, 2a, 36, 00, 2e, 00, 3c, 4b, 00, 3d, 02, 0a, 46, 02, 09, 00, 0a, 11, 01, 09, 00, 17, 52, 02, 09, 00, 0f, 9f, 01, 03, 08, 00, 0c, 9f, 01, 01, 0d, 00, 1a, 9f, 01, 00, 1d, 00, 1e, 9f, 01, 01, 0c, 00, 10, 9f, 01, 00, 11, 02, 0a, 00, 02, 09, 00, 0a, 9f, 01, 02, 0c, 00, 19, 15, 00, 1a, 02, 0a, 72, 04, 11, 00, 1e, 19, 01, 10, 00, 1d, 7a, 00, 21, 00, 2e, 7e, 00, 32, 00, 40, 93, 01, 00, 41, 02, 0e, 8e, 01, 02, 0d, 00, 0e, 19, 01, 0d, 00, 1b, 9a, 01, 02, 0d, 00, 13, 00, 02, 05, 00, 06, 9b, 02, 02, 09, 00, 16, 9b, 02, 00, 19, 00, 1a, 9b, 02, 01, 08, 00, 0c, 9b, 02, 00, 0d, 02, 06, 00, 02, 05, 00, 06, d7, 02, 02, 09, 00, 0a, 9b, 02, 00, 10, 00, 1d, 1d, 00, 1e, 02, 06, be, 01, 02, 0f, 00, 1c, 21, 01, 0c, 00, 19, c6, 01, 00, 1d, 00, 2a, ca, 01, 00, 2e, 00, 3c, df, 01, 00, 3d, 02, 0a, da, 01, 02, 09, 00, 0a, 21, 01, 09, 00, 17, 96, 02, 02, 0d, 00, 20, 96, 02, 00, 23, 00, 2c, 96, 02, 01, 09, 00, 11, 96, 02, 00, 12, 00, 1b, 96, 02, 01, 09, 00, 0f, db, 02, 03, 09, 00, 0a, d7, 02, 00, 10, 00, 1d, 25, 00, 1e, 02, 06, aa, 02, 02, 0f, 00, 1c, 29, 01, 0c, 00, 19, b2, 02, 00, 1d, 00, 2a, b6, 02, 00, 2e, 00, 3c, cb, 02, 00, 3d, 02, 0a, c6, 02, 02, 09, 00, 0a, 29, 01, 09, 00, 17, d2, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 71 +- file 0 => $DIR/conditions.rs +Number of expressions: 87 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(2), rhs = Counter(23) @@ -23,66 +23,86 @@ Number of expressions: 71 - expression 17 operands: lhs = Counter(4), rhs = Expression(18, Add) - expression 18 operands: lhs = Expression(19, Add), rhs = Counter(22) - expression 19 operands: lhs = Counter(20), rhs = Counter(21) -- expression 20 operands: lhs = Expression(0, Add), rhs = Expression(37, Add) +- expression 20 operands: lhs = Expression(0, Add), rhs = Expression(39, Add) - expression 21 operands: lhs = Counter(3), rhs = Counter(4) - expression 22 operands: lhs = Counter(3), rhs = Counter(4) - expression 23 operands: lhs = Counter(3), rhs = Counter(4) - expression 24 operands: lhs = Counter(3), rhs = Counter(4) - expression 25 operands: lhs = Counter(3), rhs = Counter(4) -- expression 26 operands: lhs = Expression(37, Add), rhs = Counter(5) +- expression 26 operands: lhs = Counter(3), rhs = Counter(4) - expression 27 operands: lhs = Counter(3), rhs = Counter(4) -- expression 28 operands: lhs = Counter(6), rhs = Counter(17) -- expression 29 operands: lhs = Counter(6), rhs = Expression(35, Add) -- expression 30 operands: lhs = Counter(17), rhs = Counter(18) -- expression 31 operands: lhs = Expression(35, Add), rhs = Counter(19) +- expression 28 operands: lhs = Expression(39, Add), rhs = Counter(5) +- expression 29 operands: lhs = Counter(3), rhs = Counter(4) +- expression 30 operands: lhs = Counter(6), rhs = Counter(17) +- expression 31 operands: lhs = Counter(6), rhs = Expression(37, Add) - expression 32 operands: lhs = Counter(17), rhs = Counter(18) -- expression 33 operands: lhs = Counter(6), rhs = Expression(34, Add) -- expression 34 operands: lhs = Expression(35, Add), rhs = Counter(19) -- expression 35 operands: lhs = Counter(17), rhs = Counter(18) -- expression 36 operands: lhs = Expression(37, Add), rhs = Expression(54, Add) -- expression 37 operands: lhs = Counter(3), rhs = Counter(4) -- expression 38 operands: lhs = Counter(5), rhs = Counter(6) -- expression 39 operands: lhs = Counter(5), rhs = Counter(6) +- expression 33 operands: lhs = Expression(37, Add), rhs = Counter(19) +- expression 34 operands: lhs = Counter(17), rhs = Counter(18) +- expression 35 operands: lhs = Counter(6), rhs = Expression(36, Add) +- expression 36 operands: lhs = Expression(37, Add), rhs = Counter(19) +- expression 37 operands: lhs = Counter(17), rhs = Counter(18) +- expression 38 operands: lhs = Expression(39, Add), rhs = Expression(70, Add) +- expression 39 operands: lhs = Counter(3), rhs = Counter(4) - expression 40 operands: lhs = Counter(5), rhs = Counter(6) -- expression 41 operands: lhs = Counter(7), rhs = Counter(8) +- expression 41 operands: lhs = Counter(5), rhs = Counter(6) - expression 42 operands: lhs = Counter(5), rhs = Counter(6) -- expression 43 operands: lhs = Expression(54, Add), rhs = Counter(7) +- expression 43 operands: lhs = Counter(5), rhs = Counter(6) - expression 44 operands: lhs = Counter(5), rhs = Counter(6) -- expression 45 operands: lhs = Counter(8), rhs = Counter(14) -- expression 46 operands: lhs = Counter(8), rhs = Expression(52, Add) -- expression 47 operands: lhs = Counter(14), rhs = Counter(15) -- expression 48 operands: lhs = Expression(52, Add), rhs = Counter(16) -- expression 49 operands: lhs = Counter(14), rhs = Counter(15) -- expression 50 operands: lhs = Counter(8), rhs = Expression(51, Add) -- expression 51 operands: lhs = Expression(52, Add), rhs = Counter(16) -- expression 52 operands: lhs = Counter(14), rhs = Counter(15) -- expression 53 operands: lhs = Expression(54, Add), rhs = Expression(69, Add) -- expression 54 operands: lhs = Counter(5), rhs = Counter(6) -- expression 55 operands: lhs = Counter(7), rhs = Counter(8) -- expression 56 operands: lhs = Counter(9), rhs = Counter(10) -- expression 57 operands: lhs = Counter(7), rhs = Counter(8) -- expression 58 operands: lhs = Expression(69, Add), rhs = Counter(9) +- expression 45 operands: lhs = Counter(7), rhs = Counter(8) +- expression 46 operands: lhs = Counter(5), rhs = Counter(6) +- expression 47 operands: lhs = Expression(70, Add), rhs = Counter(7) +- expression 48 operands: lhs = Counter(5), rhs = Counter(6) +- expression 49 operands: lhs = Counter(8), rhs = Counter(14) +- expression 50 operands: lhs = Counter(8), rhs = Expression(56, Add) +- expression 51 operands: lhs = Counter(14), rhs = Counter(15) +- expression 52 operands: lhs = Expression(56, Add), rhs = Counter(16) +- expression 53 operands: lhs = Counter(14), rhs = Counter(15) +- expression 54 operands: lhs = Counter(8), rhs = Expression(55, Add) +- expression 55 operands: lhs = Expression(56, Add), rhs = Counter(16) +- expression 56 operands: lhs = Counter(14), rhs = Counter(15) +- expression 57 operands: lhs = Expression(70, Add), rhs = Expression(85, Add) +- expression 58 operands: lhs = Counter(5), rhs = Counter(6) - expression 59 operands: lhs = Counter(7), rhs = Counter(8) -- expression 60 operands: lhs = Counter(10), rhs = Counter(11) -- expression 61 operands: lhs = Counter(10), rhs = Expression(67, Add) -- expression 62 operands: lhs = Counter(11), rhs = Counter(12) -- expression 63 operands: lhs = Expression(67, Add), rhs = Counter(13) -- expression 64 operands: lhs = Counter(11), rhs = Counter(12) -- expression 65 operands: lhs = Counter(10), rhs = Expression(66, Add) -- expression 66 operands: lhs = Expression(67, Add), rhs = Counter(13) -- expression 67 operands: lhs = Counter(11), rhs = Counter(12) -- expression 68 operands: lhs = Expression(69, Add), rhs = Expression(70, Add) -- expression 69 operands: lhs = Counter(7), rhs = Counter(8) -- expression 70 operands: lhs = Counter(9), rhs = Counter(10) -Number of file 0 mappings: 68 -- Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) -- Code(Counter(0)) at (prev + 2, 13) to (start + 2, 6) +- expression 60 operands: lhs = Expression(70, Add), rhs = Expression(85, Add) +- expression 61 operands: lhs = Counter(5), rhs = Counter(6) +- expression 62 operands: lhs = Counter(7), rhs = Counter(8) +- expression 63 operands: lhs = Expression(70, Add), rhs = Expression(85, Add) +- expression 64 operands: lhs = Counter(5), rhs = Counter(6) +- expression 65 operands: lhs = Counter(7), rhs = Counter(8) +- expression 66 operands: lhs = Expression(70, Add), rhs = Expression(85, Add) +- expression 67 operands: lhs = Counter(5), rhs = Counter(6) +- expression 68 operands: lhs = Counter(7), rhs = Counter(8) +- expression 69 operands: lhs = Expression(70, Add), rhs = Expression(85, Add) +- expression 70 operands: lhs = Counter(5), rhs = Counter(6) +- expression 71 operands: lhs = Counter(7), rhs = Counter(8) +- expression 72 operands: lhs = Counter(9), rhs = Counter(10) +- expression 73 operands: lhs = Counter(7), rhs = Counter(8) +- expression 74 operands: lhs = Expression(85, Add), rhs = Counter(9) +- expression 75 operands: lhs = Counter(7), rhs = Counter(8) +- expression 76 operands: lhs = Counter(10), rhs = Counter(11) +- expression 77 operands: lhs = Counter(10), rhs = Expression(83, Add) +- expression 78 operands: lhs = Counter(11), rhs = Counter(12) +- expression 79 operands: lhs = Expression(83, Add), rhs = Counter(13) +- expression 80 operands: lhs = Counter(11), rhs = Counter(12) +- expression 81 operands: lhs = Counter(10), rhs = Expression(82, Add) +- expression 82 operands: lhs = Expression(83, Add), rhs = Counter(13) +- expression 83 operands: lhs = Counter(11), rhs = Counter(12) +- expression 84 operands: lhs = Expression(85, Add), rhs = Expression(86, Add) +- expression 85 operands: lhs = Counter(7), rhs = Counter(8) +- expression 86 operands: lhs = Counter(9), rhs = Counter(10) +Number of file 0 mappings: 83 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 10) = (c1 + c2) - Code(Counter(0)) at (prev + 0, 16) to (start + 0, 29) -- Code(Counter(1)) at (prev + 1, 9) to (start + 1, 10) -- Code(Expression(1, Sub)) at (prev + 2, 15) to (start + 0, 28) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 23) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) +- Code(Expression(1, Sub)) at (prev + 1, 15) to (start + 0, 28) = (c0 - c1) - Code(Counter(2)) at (prev + 1, 12) to (start + 0, 25) - Code(Expression(2, Sub)) at (prev + 0, 29) to (start + 0, 42) @@ -93,12 +113,17 @@ Number of file 0 mappings: 68 = ((c23 + c24) + c25) - Code(Expression(7, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c2 - ((c23 + c24) + c25)) -- Code(Counter(2)) at (prev + 1, 9) to (start + 1, 18) -- Code(Expression(10, Sub)) at (prev + 3, 9) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 9) to (start + 0, 23) +- Code(Counter(2)) at (prev + 1, 9) to (start + 0, 18) +- Code(Expression(10, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - (c1 + c2)) -- Code(Expression(0, Add)) at (prev + 3, 9) to (start + 1, 12) +- Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 22) = (c1 + c2) -- Code(Expression(0, Add)) at (prev + 1, 13) to (start + 2, 6) +- Code(Expression(0, Add)) at (prev + 0, 25) to (start + 0, 26) + = (c1 + c2) +- Code(Expression(0, Add)) at (prev + 1, 8) to (start + 0, 12) + = (c1 + c2) +- Code(Expression(0, Add)) at (prev + 0, 13) to (start + 2, 6) = (c1 + c2) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Expression(0, Add)) at (prev + 2, 8) to (start + 0, 21) @@ -118,73 +143,89 @@ Number of file 0 mappings: 68 - Code(Counter(4)) at (prev + 1, 9) to (start + 0, 23) - Code(Expression(20, Sub)) at (prev + 2, 9) to (start + 0, 15) = ((c1 + c2) - (c3 + c4)) -- Code(Expression(37, Add)) at (prev + 3, 8) to (start + 0, 12) +- Code(Expression(39, Add)) at (prev + 3, 8) to (start + 0, 12) = (c3 + c4) -- Code(Expression(37, Add)) at (prev + 1, 13) to (start + 1, 16) +- Code(Expression(39, Add)) at (prev + 1, 13) to (start + 0, 26) = (c3 + c4) -- Code(Expression(37, Add)) at (prev + 1, 17) to (start + 2, 10) +- Code(Expression(39, Add)) at (prev + 0, 29) to (start + 0, 30) + = (c3 + c4) +- Code(Expression(39, Add)) at (prev + 1, 12) to (start + 0, 16) + = (c3 + c4) +- Code(Expression(39, Add)) at (prev + 0, 17) to (start + 2, 10) = (c3 + c4) - Code(Zero) at (prev + 2, 9) to (start + 0, 10) -- Code(Expression(37, Add)) at (prev + 2, 12) to (start + 0, 25) +- Code(Expression(39, Add)) at (prev + 2, 12) to (start + 0, 25) = (c3 + c4) - Code(Counter(5)) at (prev + 0, 26) to (start + 2, 10) -- Code(Expression(26, Sub)) at (prev + 4, 17) to (start + 0, 30) +- Code(Expression(28, Sub)) at (prev + 4, 17) to (start + 0, 30) = ((c3 + c4) - c5) - Code(Counter(6)) at (prev + 1, 16) to (start + 0, 29) -- Code(Expression(28, Sub)) at (prev + 0, 33) to (start + 0, 46) +- Code(Expression(30, Sub)) at (prev + 0, 33) to (start + 0, 46) = (c6 - c17) -- Code(Expression(29, Sub)) at (prev + 0, 50) to (start + 0, 64) +- Code(Expression(31, Sub)) at (prev + 0, 50) to (start + 0, 64) = (c6 - (c17 + c18)) -- Code(Expression(34, Add)) at (prev + 0, 65) to (start + 2, 14) +- Code(Expression(36, Add)) at (prev + 0, 65) to (start + 2, 14) = ((c17 + c18) + c19) -- Code(Expression(33, Sub)) at (prev + 2, 13) to (start + 0, 14) +- Code(Expression(35, Sub)) at (prev + 2, 13) to (start + 0, 14) = (c6 - ((c17 + c18) + c19)) - Code(Counter(6)) at (prev + 1, 13) to (start + 0, 27) -- Code(Expression(36, Sub)) at (prev + 2, 13) to (start + 0, 19) +- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 19) = ((c3 + c4) - (c5 + c6)) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) -- Code(Expression(54, Add)) at (prev + 2, 9) to (start + 1, 12) +- Code(Expression(70, Add)) at (prev + 2, 9) to (start + 0, 22) = (c5 + c6) -- Code(Expression(54, Add)) at (prev + 1, 13) to (start + 2, 6) +- Code(Expression(70, Add)) at (prev + 0, 25) to (start + 0, 26) + = (c5 + c6) +- Code(Expression(70, Add)) at (prev + 1, 8) to (start + 0, 12) + = (c5 + c6) +- Code(Expression(70, Add)) at (prev + 0, 13) to (start + 2, 6) = (c5 + c6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) -- Code(Expression(69, Add)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(85, Add)) at (prev + 2, 9) to (start + 0, 10) = (c7 + c8) -- Code(Expression(54, Add)) at (prev + 0, 16) to (start + 0, 29) +- Code(Expression(70, Add)) at (prev + 0, 16) to (start + 0, 29) = (c5 + c6) - Code(Counter(7)) at (prev + 0, 30) to (start + 2, 6) -- Code(Expression(43, Sub)) at (prev + 2, 15) to (start + 0, 28) +- Code(Expression(47, Sub)) at (prev + 2, 15) to (start + 0, 28) = ((c5 + c6) - c7) - Code(Counter(8)) at (prev + 1, 12) to (start + 0, 25) -- Code(Expression(45, Sub)) at (prev + 0, 29) to (start + 0, 42) +- Code(Expression(49, Sub)) at (prev + 0, 29) to (start + 0, 42) = (c8 - c14) -- Code(Expression(46, Sub)) at (prev + 0, 46) to (start + 0, 60) +- Code(Expression(50, Sub)) at (prev + 0, 46) to (start + 0, 60) = (c8 - (c14 + c15)) -- Code(Expression(51, Add)) at (prev + 0, 61) to (start + 2, 10) +- Code(Expression(55, Add)) at (prev + 0, 61) to (start + 2, 10) = ((c14 + c15) + c16) -- Code(Expression(50, Sub)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(54, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c8 - ((c14 + c15) + c16)) - Code(Counter(8)) at (prev + 1, 9) to (start + 0, 23) -- Code(Expression(53, Sub)) at (prev + 2, 13) to (start + 2, 15) +- Code(Expression(69, Sub)) at (prev + 2, 13) to (start + 0, 32) = ((c5 + c6) - (c7 + c8)) -- Code(Expression(70, Add)) at (prev + 5, 9) to (start + 0, 10) +- Code(Expression(69, Sub)) at (prev + 0, 35) to (start + 0, 44) + = ((c5 + c6) - (c7 + c8)) +- Code(Expression(69, Sub)) at (prev + 1, 9) to (start + 0, 17) + = ((c5 + c6) - (c7 + c8)) +- Code(Expression(69, Sub)) at (prev + 0, 18) to (start + 0, 27) + = ((c5 + c6) - (c7 + c8)) +- Code(Expression(69, Sub)) at (prev + 1, 9) to (start + 0, 15) + = ((c5 + c6) - (c7 + c8)) +- Code(Expression(86, Add)) at (prev + 3, 9) to (start + 0, 10) = (c9 + c10) -- Code(Expression(69, Add)) at (prev + 0, 16) to (start + 0, 29) +- Code(Expression(85, Add)) at (prev + 0, 16) to (start + 0, 29) = (c7 + c8) - Code(Counter(9)) at (prev + 0, 30) to (start + 2, 6) -- Code(Expression(58, Sub)) at (prev + 2, 15) to (start + 0, 28) +- Code(Expression(74, Sub)) at (prev + 2, 15) to (start + 0, 28) = ((c7 + c8) - c9) - Code(Counter(10)) at (prev + 1, 12) to (start + 0, 25) -- Code(Expression(60, Sub)) at (prev + 0, 29) to (start + 0, 42) +- Code(Expression(76, Sub)) at (prev + 0, 29) to (start + 0, 42) = (c10 - c11) -- Code(Expression(61, Sub)) at (prev + 0, 46) to (start + 0, 60) +- Code(Expression(77, Sub)) at (prev + 0, 46) to (start + 0, 60) = (c10 - (c11 + c12)) -- Code(Expression(66, Add)) at (prev + 0, 61) to (start + 2, 10) +- Code(Expression(82, Add)) at (prev + 0, 61) to (start + 2, 10) = ((c11 + c12) + c13) -- Code(Expression(65, Sub)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(81, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c10 - ((c11 + c12) + c13)) - Code(Counter(10)) at (prev + 1, 9) to (start + 0, 23) -- Code(Expression(68, Sub)) at (prev + 2, 9) to (start + 0, 15) +- Code(Expression(84, Sub)) at (prev + 2, 9) to (start + 0, 15) = ((c7 + c8) - (c9 + c10)) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c10 diff --git a/tests/coverage/continue.cov-map b/tests/coverage/continue.cov-map index d926741cbcb3..1a839f19a0f5 100644 --- a/tests/coverage/continue.cov-map +++ b/tests/coverage/continue.cov-map @@ -1,75 +1,88 @@ Function name: continue::main -Raw bytes (198): 0x[01, 01, 16, 05, 01, 05, 0b, 01, 09, 0d, 01, 0d, 1f, 01, 11, 0d, 1f, 01, 11, 15, 01, 15, 2b, 01, 19, 1d, 01, 1d, 37, 01, 21, 25, 01, 25, 43, 01, 29, 25, 01, 2d, 01, 53, 2d, 01, 31, 2d, 01, 1e, 01, 03, 01, 03, 12, 05, 04, 0e, 00, 13, 02, 01, 0f, 00, 16, 09, 02, 11, 00, 19, 06, 02, 12, 04, 0e, 0d, 06, 0e, 00, 13, 0e, 01, 0f, 00, 16, 1a, 01, 16, 02, 0e, 11, 04, 11, 00, 19, 1a, 03, 09, 00, 0e, 15, 02, 0e, 00, 13, 22, 01, 0f, 00, 16, 19, 01, 15, 02, 0e, 26, 04, 11, 00, 19, 19, 03, 09, 00, 0e, 1d, 02, 0e, 00, 13, 2e, 01, 0c, 00, 13, 21, 01, 0d, 00, 15, 32, 01, 0a, 01, 0e, 25, 03, 0e, 00, 13, 46, 01, 0f, 00, 16, 3e, 01, 16, 02, 0e, 29, 03, 12, 02, 0e, 46, 04, 09, 00, 0e, 2d, 02, 0e, 00, 13, 31, 01, 0f, 00, 16, 56, 01, 16, 02, 0e, 4e, 04, 11, 00, 16, 56, 03, 09, 00, 0e, 01, 02, 0d, 01, 02] +Raw bytes (241): 0x[01, 01, 1a, 05, 01, 05, 13, 01, 09, 05, 13, 01, 09, 0d, 01, 0d, 27, 01, 11, 0d, 27, 01, 11, 15, 01, 15, 33, 01, 19, 1d, 01, 1d, 47, 01, 21, 1d, 47, 01, 21, 25, 01, 25, 53, 01, 29, 25, 01, 2d, 01, 63, 2d, 01, 31, 2d, 01, 25, 01, 03, 01, 00, 0a, 01, 01, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 02, 09, 00, 0e, 01, 00, 11, 00, 12, 05, 01, 0e, 00, 13, 02, 01, 0f, 00, 16, 09, 02, 11, 00, 19, 0e, 02, 12, 02, 0e, 0e, 04, 09, 00, 0e, 0d, 02, 0e, 00, 13, 16, 01, 0f, 00, 16, 22, 01, 16, 02, 0e, 11, 04, 11, 00, 19, 22, 03, 09, 00, 0e, 15, 02, 0e, 00, 13, 2a, 01, 0f, 00, 16, 19, 01, 15, 02, 0e, 2e, 04, 11, 00, 19, 19, 03, 09, 00, 0e, 1d, 02, 0e, 00, 13, 36, 01, 0c, 00, 13, 21, 01, 0d, 00, 15, 42, 01, 09, 00, 0a, 42, 01, 09, 00, 0e, 25, 02, 0e, 00, 13, 56, 01, 0f, 00, 16, 4e, 01, 16, 02, 0e, 29, 03, 12, 02, 0e, 56, 04, 09, 00, 0e, 2d, 02, 0e, 00, 13, 31, 01, 0f, 00, 16, 66, 01, 16, 02, 0e, 5e, 04, 11, 00, 16, 66, 03, 09, 00, 0e, 01, 02, 0d, 00, 0e, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 22 +- file 0 => $DIR/continue.rs +Number of expressions: 26 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) -- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) +- expression 1 operands: lhs = Counter(1), rhs = Expression(4, Add) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) -- expression 3 operands: lhs = Counter(3), rhs = Counter(0) -- expression 4 operands: lhs = Counter(3), rhs = Expression(7, Add) -- expression 5 operands: lhs = Counter(0), rhs = Counter(4) -- expression 6 operands: lhs = Counter(3), rhs = Expression(7, Add) +- expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) +- expression 4 operands: lhs = Counter(0), rhs = Counter(2) +- expression 5 operands: lhs = Counter(3), rhs = Counter(0) +- expression 6 operands: lhs = Counter(3), rhs = Expression(9, Add) - expression 7 operands: lhs = Counter(0), rhs = Counter(4) -- expression 8 operands: lhs = Counter(5), rhs = Counter(0) -- expression 9 operands: lhs = Counter(5), rhs = Expression(10, Add) -- expression 10 operands: lhs = Counter(0), rhs = Counter(6) -- expression 11 operands: lhs = Counter(7), rhs = Counter(0) -- expression 12 operands: lhs = Counter(7), rhs = Expression(13, Add) -- expression 13 operands: lhs = Counter(0), rhs = Counter(8) -- expression 14 operands: lhs = Counter(9), rhs = Counter(0) -- expression 15 operands: lhs = Counter(9), rhs = Expression(16, Add) -- expression 16 operands: lhs = Counter(0), rhs = Counter(10) -- expression 17 operands: lhs = Counter(9), rhs = Counter(0) -- expression 18 operands: lhs = Counter(11), rhs = Counter(0) -- expression 19 operands: lhs = Expression(20, Add), rhs = Counter(11) -- expression 20 operands: lhs = Counter(0), rhs = Counter(12) -- expression 21 operands: lhs = Counter(11), rhs = Counter(0) -Number of file 0 mappings: 30 -- Code(Counter(0)) at (prev + 3, 1) to (start + 3, 18) -- Code(Counter(1)) at (prev + 4, 14) to (start + 0, 19) +- expression 8 operands: lhs = Counter(3), rhs = Expression(9, Add) +- expression 9 operands: lhs = Counter(0), rhs = Counter(4) +- expression 10 operands: lhs = Counter(5), rhs = Counter(0) +- expression 11 operands: lhs = Counter(5), rhs = Expression(12, Add) +- expression 12 operands: lhs = Counter(0), rhs = Counter(6) +- expression 13 operands: lhs = Counter(7), rhs = Counter(0) +- expression 14 operands: lhs = Counter(7), rhs = Expression(17, Add) +- expression 15 operands: lhs = Counter(0), rhs = Counter(8) +- expression 16 operands: lhs = Counter(7), rhs = Expression(17, Add) +- expression 17 operands: lhs = Counter(0), rhs = Counter(8) +- expression 18 operands: lhs = Counter(9), rhs = Counter(0) +- expression 19 operands: lhs = Counter(9), rhs = Expression(20, Add) +- expression 20 operands: lhs = Counter(0), rhs = Counter(10) +- expression 21 operands: lhs = Counter(9), rhs = Counter(0) +- expression 22 operands: lhs = Counter(11), rhs = Counter(0) +- expression 23 operands: lhs = Expression(24, Add), rhs = Counter(11) +- expression 24 operands: lhs = Counter(0), rhs = Counter(12) +- expression 25 operands: lhs = Counter(11), rhs = Counter(0) +Number of file 0 mappings: 37 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 19) - Code(Expression(0, Sub)) at (prev + 1, 15) to (start + 0, 22) = (c1 - c0) - Code(Counter(2)) at (prev + 2, 17) to (start + 0, 25) -- Code(Expression(1, Sub)) at (prev + 2, 18) to (start + 4, 14) +- Code(Expression(3, Sub)) at (prev + 2, 18) to (start + 2, 14) = (c1 - (c0 + c2)) -- Code(Counter(3)) at (prev + 6, 14) to (start + 0, 19) -- Code(Expression(3, Sub)) at (prev + 1, 15) to (start + 0, 22) +- Code(Expression(3, Sub)) at (prev + 4, 9) to (start + 0, 14) + = (c1 - (c0 + c2)) +- Code(Counter(3)) at (prev + 2, 14) to (start + 0, 19) +- Code(Expression(5, Sub)) at (prev + 1, 15) to (start + 0, 22) = (c3 - c0) -- Code(Expression(6, Sub)) at (prev + 1, 22) to (start + 2, 14) +- Code(Expression(8, Sub)) at (prev + 1, 22) to (start + 2, 14) = (c3 - (c0 + c4)) - Code(Counter(4)) at (prev + 4, 17) to (start + 0, 25) -- Code(Expression(6, Sub)) at (prev + 3, 9) to (start + 0, 14) +- Code(Expression(8, Sub)) at (prev + 3, 9) to (start + 0, 14) = (c3 - (c0 + c4)) - Code(Counter(5)) at (prev + 2, 14) to (start + 0, 19) -- Code(Expression(8, Sub)) at (prev + 1, 15) to (start + 0, 22) +- Code(Expression(10, Sub)) at (prev + 1, 15) to (start + 0, 22) = (c5 - c0) - Code(Counter(6)) at (prev + 1, 21) to (start + 2, 14) -- Code(Expression(9, Sub)) at (prev + 4, 17) to (start + 0, 25) +- Code(Expression(11, Sub)) at (prev + 4, 17) to (start + 0, 25) = (c5 - (c0 + c6)) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 14) - Code(Counter(7)) at (prev + 2, 14) to (start + 0, 19) -- Code(Expression(11, Sub)) at (prev + 1, 12) to (start + 0, 19) +- Code(Expression(13, Sub)) at (prev + 1, 12) to (start + 0, 19) = (c7 - c0) - Code(Counter(8)) at (prev + 1, 13) to (start + 0, 21) -- Code(Expression(12, Sub)) at (prev + 1, 10) to (start + 1, 14) +- Code(Expression(16, Sub)) at (prev + 1, 9) to (start + 0, 10) = (c7 - (c0 + c8)) -- Code(Counter(9)) at (prev + 3, 14) to (start + 0, 19) -- Code(Expression(17, Sub)) at (prev + 1, 15) to (start + 0, 22) +- Code(Expression(16, Sub)) at (prev + 1, 9) to (start + 0, 14) + = (c7 - (c0 + c8)) +- Code(Counter(9)) at (prev + 2, 14) to (start + 0, 19) +- Code(Expression(21, Sub)) at (prev + 1, 15) to (start + 0, 22) = (c9 - c0) -- Code(Expression(15, Sub)) at (prev + 1, 22) to (start + 2, 14) +- Code(Expression(19, Sub)) at (prev + 1, 22) to (start + 2, 14) = (c9 - (c0 + c10)) - Code(Counter(10)) at (prev + 3, 18) to (start + 2, 14) -- Code(Expression(17, Sub)) at (prev + 4, 9) to (start + 0, 14) +- Code(Expression(21, Sub)) at (prev + 4, 9) to (start + 0, 14) = (c9 - c0) - Code(Counter(11)) at (prev + 2, 14) to (start + 0, 19) - Code(Counter(12)) at (prev + 1, 15) to (start + 0, 22) -- Code(Expression(21, Sub)) at (prev + 1, 22) to (start + 2, 14) +- Code(Expression(25, Sub)) at (prev + 1, 22) to (start + 2, 14) = (c11 - c0) -- Code(Expression(19, Sub)) at (prev + 4, 17) to (start + 0, 22) +- Code(Expression(23, Sub)) at (prev + 4, 17) to (start + 0, 22) = ((c0 + c12) - c11) -- Code(Expression(21, Sub)) at (prev + 3, 9) to (start + 0, 14) +- Code(Expression(25, Sub)) at (prev + 3, 9) to (start + 0, 14) = (c11 - c0) -- Code(Counter(0)) at (prev + 2, 13) to (start + 1, 2) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c12 diff --git a/tests/coverage/continue.coverage b/tests/coverage/continue.coverage index 4916cac0038e..17fe4874d151 100644 --- a/tests/coverage/continue.coverage +++ b/tests/coverage/continue.coverage @@ -2,7 +2,7 @@ LL| | LL| 1|fn main() { LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| let mut x = 0; LL| 11| for _ in 0..10 { LL| 10| match is_true { @@ -12,7 +12,7 @@ LL| 0| _ => { LL| 0| x = 1; LL| 0| } - LL| 0| } + LL| | } LL| 0| x = 3; LL| | } LL| 11| for _ in 0..10 { diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index fee32376d831..daa42915a4af 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -1,31 +1,40 @@ Function name: coroutine::get_u32 -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0b, 01, 01, 0b, 05, 02, 09, 00, 0e, 02, 02, 09, 00, 28, 01, 02, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 0b, 01, 00, 2d, 01, 01, 08, 00, 0b, 05, 01, 09, 00, 0e, 02, 02, 09, 00, 28, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/coroutine.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 11, 1) to (start + 1, 11) -- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 14) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 45) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 11) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 14) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: coroutine::main -Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 02, 01, 00, 02] +Raw bytes (93): 0x[01, 01, 02, 01, 05, 05, 09, 11, 01, 13, 01, 00, 0a, 01, 01, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 01, 09, 00, 16, 01, 06, 0b, 00, 13, 01, 00, 14, 00, 22, 01, 00, 24, 00, 2a, 01, 00, 2b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 13, 05, 00, 0b, 00, 2e, 05, 00, 14, 00, 22, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/coroutine.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22) -- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 45) +Number of file 0 mappings: 17 +- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 6, 11) to (start + 0, 19) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 34) +- Code(Counter(0)) at (prev + 0, 36) to (start + 0, 42) +- Code(Counter(0)) at (prev + 0, 43) to (start + 0, 45) - Code(Counter(1)) at (prev + 1, 43) to (start + 0, 45) - Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c0 - c1) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46) +- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 19) +- Code(Counter(1)) at (prev + 0, 11) to (start + 0, 46) +- Code(Counter(1)) at (prev + 0, 20) to (start + 0, 34) - Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39) - Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46) - Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20) @@ -34,12 +43,14 @@ Number of file 0 mappings: 9 Highest counter ID seen: c3 Function name: coroutine::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 16, 08, 01, 1f, 05, 02, 10, 01, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 08, 00, 09, 01, 01, 09, 00, 1f, 05, 01, 10, 00, 15, 05, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/coroutine.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 22, 8) to (start + 1, 31) -- Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 22, 8) to (start + 0, 9) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 31) +- Code(Counter(1)) at (prev + 1, 16) to (start + 0, 21) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c1 diff --git a/tests/coverage/coverage_attr_closure.cov-map b/tests/coverage/coverage_attr_closure.cov-map index fb861996a0d2..deba65f22cca 100644 --- a/tests/coverage/coverage_attr_closure.cov-map +++ b/tests/coverage/coverage_attr_closure.cov-map @@ -1,38 +1,48 @@ Function name: coverage_attr_closure::GLOBAL_CLOSURE_ON::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 06, 0f, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 06, 0f, 00, 10, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 17, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/coverage_attr_closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 6, 15) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 6, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: coverage_attr_closure::contains_closures_off::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1d, 13, 02, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 1d, 13, 00, 14, 00, 01, 09, 00, 11, 00, 00, 12, 00, 1b, 00, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/coverage_attr_closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 29, 19) to (start + 2, 6) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 29, 19) to (start + 0, 20) +- Code(Zero) at (prev + 1, 9) to (start + 0, 17) +- Code(Zero) at (prev + 0, 18) to (start + 0, 27) +- Code(Zero) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: (none) Function name: coverage_attr_closure::contains_closures_on -Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 01, 1a, 01, 05, 09, 00, 1b, 01, 04, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 0f, 01, 00, 1a, 01, 01, 09, 00, 1a, 01, 04, 09, 00, 1b, 01, 04, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/coverage_attr_closure.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 26) -- Code(Counter(0)) at (prev + 5, 9) to (start + 0, 27) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 26) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 27) - Code(Counter(0)) at (prev + 4, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: coverage_attr_closure::contains_closures_on::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 13, 02, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 11, 13, 00, 14, 00, 01, 09, 00, 11, 00, 00, 12, 00, 1b, 00, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/coverage_attr_closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 17, 19) to (start + 2, 6) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 17, 19) to (start + 0, 20) +- Code(Zero) at (prev + 1, 9) to (start + 0, 17) +- Code(Zero) at (prev + 0, 18) to (start + 0, 27) +- Code(Zero) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: (none) diff --git a/tests/coverage/dead_code.cov-map b/tests/coverage/dead_code.cov-map index 897372fe0b5e..ae4146dc2467 100644 --- a/tests/coverage/dead_code.cov-map +++ b/tests/coverage/dead_code.cov-map @@ -1,37 +1,52 @@ Function name: dead_code::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 1b, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (51): 0x[01, 01, 01, 01, 05, 09, 01, 1b, 01, 00, 0a, 01, 04, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 02, 09, 00, 16, 01, 00, 19, 00, 1a, 01, 01, 08, 00, 0f, 05, 00, 10, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/dead_code.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 27, 1) to (start + 7, 15) -- Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 15) +- Code(Counter(1)) at (prev + 0, 16) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: dead_code::unused_fn (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] +Raw bytes (49): 0x[01, 01, 00, 09, 00, 0f, 01, 00, 0f, 00, 04, 09, 00, 10, 00, 00, 13, 00, 2e, 00, 02, 09, 00, 16, 00, 00, 19, 00, 1a, 00, 01, 08, 00, 0f, 00, 00, 10, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/dead_code.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Zero) at (prev + 15, 1) to (start + 7, 15) -- Code(Zero) at (prev + 7, 16) to (start + 2, 6) +Number of file 0 mappings: 9 +- Code(Zero) at (prev + 15, 1) to (start + 0, 15) +- Code(Zero) at (prev + 4, 9) to (start + 0, 16) +- Code(Zero) at (prev + 0, 19) to (start + 0, 46) +- Code(Zero) at (prev + 2, 9) to (start + 0, 22) +- Code(Zero) at (prev + 0, 25) to (start + 0, 26) +- Code(Zero) at (prev + 1, 8) to (start + 0, 15) +- Code(Zero) at (prev + 0, 16) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: dead_code::unused_pub_fn_not_in_library (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] +Raw bytes (49): 0x[01, 01, 00, 09, 00, 03, 01, 00, 26, 00, 04, 09, 00, 10, 00, 00, 13, 00, 2e, 00, 02, 09, 00, 16, 00, 00, 19, 00, 1a, 00, 01, 08, 00, 0f, 00, 00, 10, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/dead_code.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Zero) at (prev + 3, 1) to (start + 7, 15) -- Code(Zero) at (prev + 7, 16) to (start + 2, 6) +Number of file 0 mappings: 9 +- Code(Zero) at (prev + 3, 1) to (start + 0, 38) +- Code(Zero) at (prev + 4, 9) to (start + 0, 16) +- Code(Zero) at (prev + 0, 19) to (start + 0, 46) +- Code(Zero) at (prev + 2, 9) to (start + 0, 22) +- Code(Zero) at (prev + 0, 25) to (start + 0, 26) +- Code(Zero) at (prev + 1, 8) to (start + 0, 15) +- Code(Zero) at (prev + 0, 16) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) diff --git a/tests/coverage/dead_code.coverage b/tests/coverage/dead_code.coverage index 55d196f81604..fbb4a001d959 100644 --- a/tests/coverage/dead_code.coverage +++ b/tests/coverage/dead_code.coverage @@ -1,11 +1,11 @@ LL| |#![allow(dead_code, unused_assignments, unused_variables)] LL| | LL| 0|pub fn unused_pub_fn_not_in_library() { - LL| 0| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 0| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 0| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 0| let is_true = std::env::args().len() == 1; - LL| 0| + LL| | LL| 0| let mut countdown = 0; LL| 0| if is_true { LL| 0| countdown = 10; @@ -13,11 +13,11 @@ LL| 0|} LL| | LL| 0|fn unused_fn() { - LL| 0| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 0| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 0| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 0| let is_true = std::env::args().len() == 1; - LL| 0| + LL| | LL| 0| let mut countdown = 0; LL| 0| if is_true { LL| 0| countdown = 10; @@ -25,11 +25,11 @@ LL| 0|} LL| | LL| 1|fn main() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| let mut countdown = 0; LL| 1| if is_true { LL| 1| countdown = 10; diff --git a/tests/coverage/drop_trait.cov-map b/tests/coverage/drop_trait.cov-map index 16facf2eddf2..dcf9dbd8c647 100644 --- a/tests/coverage/drop_trait.cov-map +++ b/tests/coverage/drop_trait.cov-map @@ -1,21 +1,33 @@ Function name: ::drop -Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 05, 02, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 09, 05, 00, 17, 01, 01, 09, 00, 11, 01, 00, 12, 00, 24, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/drop_trait.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 9, 5) to (start + 2, 6) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 36) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: drop_trait::main -Raw bytes (24): 0x[01, 01, 00, 04, 01, 0e, 01, 05, 0c, 01, 06, 09, 01, 16, 00, 02, 06, 04, 0b, 01, 05, 01, 00, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 01, 0e, 01, 00, 1c, 01, 01, 09, 00, 15, 01, 00, 18, 00, 30, 01, 02, 09, 00, 0d, 01, 00, 10, 00, 2a, 01, 02, 08, 00, 0c, 01, 01, 09, 00, 11, 01, 00, 12, 00, 29, 01, 01, 10, 00, 16, 00, 01, 05, 00, 06, 00, 02, 0d, 00, 28, 00, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/drop_trait.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 14, 1) to (start + 5, 12) -- Code(Counter(0)) at (prev + 6, 9) to (start + 1, 22) -- Code(Zero) at (prev + 2, 6) to (start + 4, 11) -- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 2) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 48) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 16) to (start + 0, 42) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 41) +- Code(Counter(0)) at (prev + 1, 16) to (start + 0, 22) +- Code(Zero) at (prev + 1, 5) to (start + 0, 6) +- Code(Zero) at (prev + 2, 13) to (start + 0, 40) +- Code(Zero) at (prev + 2, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/drop_trait.coverage b/tests/coverage/drop_trait.coverage index 85d557573cf3..10ed8c0f154f 100644 --- a/tests/coverage/drop_trait.coverage +++ b/tests/coverage/drop_trait.coverage @@ -13,16 +13,16 @@ LL| | LL| 1|fn main() -> Result<(), u8> { LL| 1| let _firecracker = Firework { strength: 1 }; - LL| 1| + LL| | LL| 1| let _tnt = Firework { strength: 100 }; - LL| 1| + LL| | LL| 1| if true { LL| 1| println!("Exiting with error..."); LL| 1| return Err(1); LL| 0| } - LL| 0| + LL| | LL| 0| let _ = Firework { strength: 1000 }; - LL| 0| + LL| | LL| 0| Ok(()) LL| 1|} LL| | diff --git a/tests/coverage/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map index 6d6034928c9a..fc57a4892be4 100644 --- a/tests/coverage/fn_sig_into_try.cov-map +++ b/tests/coverage/fn_sig_into_try.cov-map @@ -1,44 +1,52 @@ Function name: fn_sig_into_try::a -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 05, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 0a, 01, 00, 16, 01, 03, 05, 00, 0f, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/fn_sig_into_try.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 10, 1) to (start + 5, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: fn_sig_into_try::b -Raw bytes (24): 0x[01, 01, 00, 04, 01, 11, 01, 03, 0f, 00, 03, 0f, 00, 10, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 11, 01, 00, 16, 01, 03, 05, 00, 0f, 00, 00, 0f, 00, 10, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/fn_sig_into_try.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 17, 1) to (start + 3, 15) -- Code(Zero) at (prev + 3, 15) to (start + 0, 16) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 15) +- Code(Zero) at (prev + 0, 15) to (start + 0, 16) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: fn_sig_into_try::c -Raw bytes (24): 0x[01, 01, 00, 04, 01, 18, 01, 03, 17, 00, 03, 17, 00, 18, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 18, 01, 00, 16, 01, 03, 0d, 00, 17, 00, 00, 17, 00, 18, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/fn_sig_into_try.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 24, 1) to (start + 3, 23) -- Code(Zero) at (prev + 3, 23) to (start + 0, 24) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 3, 13) to (start + 0, 23) +- Code(Zero) at (prev + 0, 23) to (start + 0, 24) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: fn_sig_into_try::d -Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 01, 04, 0f, 00, 04, 0f, 00, 10, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] +Raw bytes (39): 0x[01, 01, 00, 07, 01, 1f, 01, 00, 16, 01, 03, 0c, 00, 0e, 01, 00, 11, 00, 13, 01, 01, 05, 00, 0f, 00, 00, 0f, 00, 10, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/fn_sig_into_try.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 31, 1) to (start + 4, 15) -- Code(Zero) at (prev + 4, 15) to (start + 0, 16) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 31, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 3, 12) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Zero) at (prev + 0, 15) to (start + 0, 16) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage index cabe747ce5ac..bc744db4b69c 100644 --- a/tests/coverage/fn_sig_into_try.coverage +++ b/tests/coverage/fn_sig_into_try.coverage @@ -8,31 +8,31 @@ LL| |// signature should be handled in the same way. LL| | LL| 1|fn a() -> Option - LL| 1|// - LL| 1|{ + LL| |// + LL| |{ LL| 1| Some(7i32); LL| 1| Some(0) LL| 1|} LL| | LL| 1|fn b() -> Option - LL| 1|// - LL| 1|{ + LL| |// + LL| |{ LL| 1| Some(7i32)?; ^0 LL| 1| Some(0) LL| 1|} LL| | LL| 1|fn c() -> Option - LL| 1|// - LL| 1|{ + LL| |// + LL| |{ LL| 1| let _ = Some(7i32)?; ^0 LL| 1| Some(0) LL| 1|} LL| | LL| 1|fn d() -> Option - LL| 1|// - LL| 1|{ + LL| |// + LL| |{ LL| 1| let _: () = (); LL| 1| Some(7i32)?; ^0 diff --git a/tests/coverage/generic-unused-impl.cov-map b/tests/coverage/generic-unused-impl.cov-map index 5878de231bad..da9e5495a72b 100644 --- a/tests/coverage/generic-unused-impl.cov-map +++ b/tests/coverage/generic-unused-impl.cov-map @@ -1,18 +1,23 @@ Function name: as core::convert::From<[<_ as generic_unused_impl::Foo>::Assoc; 1]>>::from (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 0b, 05, 03, 06] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 0b, 05, 00, 29, 00, 01, 0e, 00, 12, 00, 00, 16, 00, 1a, 00, 01, 09, 00, 1b, 00, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generic-unused-impl.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 11, 5) to (start + 3, 6) +Number of file 0 mappings: 5 +- Code(Zero) at (prev + 11, 5) to (start + 0, 41) +- Code(Zero) at (prev + 1, 14) to (start + 0, 18) +- Code(Zero) at (prev + 0, 22) to (start + 0, 26) +- Code(Zero) at (prev + 1, 9) to (start + 0, 27) +- Code(Zero) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: (none) Function name: generic_unused_impl::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 00, 0d] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 11, 01, 00, 0a, 01, 00, 0c, 00, 0d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generic-unused-impl.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 13) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 12) to (start + 0, 13) Highest counter ID seen: c0 diff --git a/tests/coverage/generics.cov-map b/tests/coverage/generics.cov-map index bc5661afdc19..7f9b7ee0f471 100644 --- a/tests/coverage/generics.cov-map +++ b/tests/coverage/generics.cov-map @@ -1,48 +1,73 @@ Function name: as core::ops::drop::Drop>::drop -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 05, 02, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 11, 05, 00, 17, 01, 01, 09, 00, 11, 01, 00, 12, 00, 24, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generics.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 36) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: >::set_strength -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 0a, 05, 00, 30, 01, 01, 09, 00, 25, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generics.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 10, 5) to (start + 0, 48) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: as core::ops::drop::Drop>::drop -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 05, 02, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 11, 05, 00, 17, 01, 01, 09, 00, 11, 01, 00, 12, 00, 24, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generics.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 36) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: >::set_strength -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 0a, 05, 00, 30, 01, 01, 09, 00, 25, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generics.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 10, 5) to (start + 0, 48) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: generics::main -Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 01, 08, 0c, 01, 09, 09, 01, 16, 00, 02, 06, 04, 0b, 01, 05, 01, 00, 02] +Raw bytes (99): 0x[01, 01, 00, 13, 01, 16, 01, 00, 1c, 01, 01, 09, 00, 18, 01, 00, 1b, 00, 33, 01, 01, 05, 00, 10, 01, 00, 11, 00, 1d, 01, 02, 09, 00, 10, 01, 00, 13, 00, 2f, 01, 01, 05, 00, 08, 01, 00, 09, 00, 15, 01, 01, 05, 00, 08, 01, 00, 09, 00, 15, 01, 02, 08, 00, 0c, 01, 01, 09, 00, 11, 01, 00, 12, 00, 29, 01, 01, 10, 00, 16, 00, 01, 05, 00, 06, 00, 02, 0d, 00, 28, 00, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/generics.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 22, 1) to (start + 8, 12) -- Code(Counter(0)) at (prev + 9, 9) to (start + 1, 22) -- Code(Zero) at (prev + 2, 6) to (start + 4, 11) -- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 2) +Number of file 0 mappings: 19 +- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 24) +- Code(Counter(0)) at (prev + 0, 27) to (start + 0, 51) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 29) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 47) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 21) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 12) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 41) +- Code(Counter(0)) at (prev + 1, 16) to (start + 0, 22) +- Code(Zero) at (prev + 1, 5) to (start + 0, 6) +- Code(Zero) at (prev + 2, 13) to (start + 0, 40) +- Code(Zero) at (prev + 2, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/generics.coverage b/tests/coverage/generics.coverage index a2cd1465d26f..43697cacb9a5 100644 --- a/tests/coverage/generics.coverage +++ b/tests/coverage/generics.coverage @@ -44,18 +44,18 @@ LL| 1|fn main() -> Result<(), u8> { LL| 1| let mut firecracker = Firework { strength: 1 }; LL| 1| firecracker.set_strength(2); - LL| 1| + LL| | LL| 1| let mut tnt = Firework { strength: 100.1 }; LL| 1| tnt.set_strength(200.1); LL| 1| tnt.set_strength(300.3); - LL| 1| + LL| | LL| 1| if true { LL| 1| println!("Exiting with error..."); LL| 1| return Err(1); LL| 0| } - LL| 0| + LL| | LL| 0| let _ = Firework { strength: 1000 }; - LL| 0| + LL| | LL| 0| Ok(()) LL| 1|} LL| | diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map index 6e2d243e8dd2..c2158c441506 100644 --- a/tests/coverage/holes.cov-map +++ b/tests/coverage/holes.cov-map @@ -1,57 +1,81 @@ Function name: ::_method (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 2b, 09, 00, 1d] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 2b, 09, 00, 1a, 00, 00, 1c, 00, 1d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/holes.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 43, 9) to (start + 0, 29) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 43, 9) to (start + 0, 26) +- Code(Zero) at (prev + 0, 28) to (start + 0, 29) Highest counter ID seen: (none) Function name: holes::main -Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 06, 27, 01, 13, 05, 01, 02] +Raw bytes (154): 0x[01, 01, 00, 1e, 01, 08, 01, 00, 0a, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 04, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 04, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 07, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 06, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 04, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 04, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 06, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 03, 09, 00, 0f, 01, 07, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 03, 09, 00, 0f, 01, 07, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 06, 09, 00, 27, 01, 0d, 05, 00, 0e, 01, 00, 0f, 00, 11, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/holes.rs Number of expressions: 0 -Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 17) -- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 17) +Number of file 0 mappings: 30 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) - Code(Counter(0)) at (prev + 7, 9) to (start + 0, 17) -- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 17) -- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) -- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 17) -- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 17) -- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) -- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) -- Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15) -- Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15) -- Code(Counter(0)) at (prev + 10, 5) to (start + 6, 39) -- Code(Counter(0)) at (prev + 19, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 6, 9) to (start + 0, 39) +- Code(Counter(0)) at (prev + 13, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: holes::main::_unused_fn (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1f, 05, 00, 17] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 1f, 05, 00, 14, 00, 00, 16, 00, 17] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/holes.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 31, 5) to (start + 0, 23) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 31, 5) to (start + 0, 20) +- Code(Zero) at (prev + 0, 22) to (start + 0, 23) Highest counter ID seen: (none) Function name: holes::main::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 18, 09, 02, 0a] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 18, 09, 00, 0a, 00, 01, 0d, 00, 16, 00, 00, 17, 00, 19, 00, 01, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/holes.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 24, 9) to (start + 2, 10) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 24, 9) to (start + 0, 10) +- Code(Zero) at (prev + 1, 13) to (start + 0, 22) +- Code(Zero) at (prev + 0, 23) to (start + 0, 25) +- Code(Zero) at (prev + 1, 9) to (start + 0, 10) Highest counter ID seen: (none) Function name: holes::main::{closure#1} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 4b, 09, 02, 0a] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 4b, 09, 00, 0a, 00, 01, 0d, 00, 12, 00, 01, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/holes.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 75, 9) to (start + 2, 10) +Number of file 0 mappings: 3 +- Code(Zero) at (prev + 75, 9) to (start + 0, 10) +- Code(Zero) at (prev + 1, 13) to (start + 0, 18) +- Code(Zero) at (prev + 1, 9) to (start + 0, 10) Highest counter ID seen: (none) diff --git a/tests/coverage/holes.coverage b/tests/coverage/holes.coverage index a6a02f1b9d08..1ea60491800d 100644 --- a/tests/coverage/holes.coverage +++ b/tests/coverage/holes.coverage @@ -58,8 +58,8 @@ LL| | } LL| | LL| 1| black_box(()); - LL| 1| - LL| 1| #[rustfmt::skip] + LL| | + LL| | #[rustfmt::skip] LL| 1| let _const = LL| | const LL| | { @@ -68,8 +68,8 @@ LL| | ; LL| | LL| 1| black_box(()); - LL| 1| - LL| 1| #[rustfmt::skip] + LL| | + LL| | #[rustfmt::skip] LL| 1| let _async = LL| | async LL| 0| { @@ -78,11 +78,11 @@ LL| | ; LL| | LL| 1| black_box(()); - LL| 1| - LL| 1| // This tests the edge case of a const block nested inside an "anon const", - LL| 1| // such as the length of an array literal. Handling this case requires - LL| 1| // `nested_filter::OnlyBodies` or equivalent. - LL| 1| #[rustfmt::skip] + LL| | + LL| | // This tests the edge case of a const block nested inside an "anon const", + LL| | // such as the length of an array literal. Handling this case requires + LL| | // `nested_filter::OnlyBodies` or equivalent. + LL| | #[rustfmt::skip] LL| 1| let _const_block_inside_anon_const = LL| | [ LL| | 0 diff --git a/tests/coverage/if.cov-map b/tests/coverage/if.cov-map index a77ba8194a44..044c0f2ba089 100644 --- a/tests/coverage/if.cov-map +++ b/tests/coverage/if.cov-map @@ -1,12 +1,17 @@ Function name: if::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 04, 01, 12, 10, 05, 13, 05, 05, 06, 02, 05, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (51): 0x[01, 01, 01, 01, 05, 09, 01, 04, 01, 00, 0a, 01, 05, 05, 00, 0c, 01, 02, 09, 02, 0a, 01, 05, 09, 01, 0e, 01, 03, 09, 00, 0a, 01, 03, 09, 00, 10, 05, 01, 05, 05, 06, 02, 05, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 4, 1) to (start + 18, 16) -- Code(Counter(1)) at (prev + 19, 5) to (start + 5, 6) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 2, 9) to (start + 2, 10) +- Code(Counter(0)) at (prev + 5, 9) to (start + 1, 14) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 16) +- Code(Counter(1)) at (prev + 1, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 5, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) diff --git a/tests/coverage/if.coverage b/tests/coverage/if.coverage index 0762418347c2..c3c8a1bf38a4 100644 --- a/tests/coverage/if.coverage +++ b/tests/coverage/if.coverage @@ -2,23 +2,23 @@ LL| | LL| |#[rustfmt::skip] LL| 1|fn main() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. - LL| 1| let + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. + LL| | let LL| 1| is_true - LL| 1| = + LL| | = LL| 1| std::env::args().len() LL| 1| == LL| 1| 1 - LL| 1| ; - LL| 1| let + LL| | ; + LL| | let LL| 1| mut LL| 1| countdown - LL| 1| = + LL| | = LL| 1| 0 - LL| 1| ; - LL| 1| if + LL| | ; + LL| | if LL| 1| is_true LL| 1| { LL| 1| countdown diff --git a/tests/coverage/if_else.cov-map b/tests/coverage/if_else.cov-map index 194ad6ca71f8..1d8ca1809532 100644 --- a/tests/coverage/if_else.cov-map +++ b/tests/coverage/if_else.cov-map @@ -1,13 +1,18 @@ Function name: if_else::main -Raw bytes (43): 0x[01, 01, 02, 01, 05, 01, 09, 07, 01, 04, 01, 08, 10, 05, 09, 05, 05, 06, 02, 08, 09, 02, 10, 01, 06, 09, 00, 10, 09, 01, 05, 05, 06, 06, 07, 05, 05, 06, 01, 06, 01, 00, 02] +Raw bytes (68): 0x[01, 01, 02, 01, 05, 01, 09, 0c, 01, 04, 01, 00, 0a, 01, 04, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 02, 09, 00, 16, 01, 00, 19, 00, 1a, 01, 02, 09, 00, 10, 05, 01, 05, 05, 06, 02, 08, 09, 02, 10, 01, 06, 09, 00, 10, 09, 01, 05, 05, 06, 06, 07, 05, 05, 06, 01, 06, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if_else.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 4, 1) to (start + 8, 16) -- Code(Counter(1)) at (prev + 9, 5) to (start + 5, 6) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 26) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 16) +- Code(Counter(1)) at (prev + 1, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 8, 9) to (start + 2, 16) = (c0 - c1) - Code(Counter(0)) at (prev + 6, 9) to (start + 0, 16) diff --git a/tests/coverage/if_else.coverage b/tests/coverage/if_else.coverage index 2bf93487cec2..148e2b195173 100644 --- a/tests/coverage/if_else.coverage +++ b/tests/coverage/if_else.coverage @@ -2,13 +2,13 @@ LL| | LL| |#[rustfmt::skip] LL| 1|fn main() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| let mut countdown = 0; - LL| 1| if + LL| | if LL| 1| is_true LL| 1| { LL| 1| countdown diff --git a/tests/coverage/if_not.cov-map b/tests/coverage/if_not.cov-map index f47139ce5a48..1b1a1b30e934 100644 --- a/tests/coverage/if_not.cov-map +++ b/tests/coverage/if_not.cov-map @@ -1,14 +1,15 @@ Function name: if_not::if_not -Raw bytes (60): 0x[01, 01, 03, 01, 05, 01, 09, 01, 0d, 0a, 01, 05, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 05, 00, 06, 01, 03, 09, 01, 0d, 06, 02, 05, 02, 06, 09, 02, 05, 00, 06, 01, 03, 09, 01, 0d, 0a, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 03, 01, 05, 01, 09, 01, 0d, 0b, 01, 05, 01, 00, 16, 01, 02, 09, 01, 0d, 02, 02, 05, 02, 06, 05, 02, 05, 00, 06, 01, 03, 09, 01, 0d, 06, 02, 05, 02, 06, 09, 02, 05, 00, 06, 01, 03, 09, 01, 0d, 0a, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if_not.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(3) -Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 5, 1) to (start + 3, 13) -- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 2, 6) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 2, 9) to (start + 1, 13) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 2, 6) = (c0 - c1) - Code(Counter(1)) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 13) diff --git a/tests/coverage/if_not.coverage b/tests/coverage/if_not.coverage index 678ccf9f2f85..8478e861a3aa 100644 --- a/tests/coverage/if_not.coverage +++ b/tests/coverage/if_not.coverage @@ -3,7 +3,7 @@ LL| | LL| |#[rustfmt::skip] LL| 12|fn if_not(cond: bool) { - LL| 12| if + LL| | if LL| 12| ! LL| 12| cond LL| 4| { diff --git a/tests/coverage/ignore_run.cov-map b/tests/coverage/ignore_run.cov-map index c8ad3821e16f..0d8245c54dc4 100644 --- a/tests/coverage/ignore_run.cov-map +++ b/tests/coverage/ignore_run.cov-map @@ -1,9 +1,10 @@ Function name: ignore_run::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 0d] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 03, 01, 00, 0a, 01, 00, 0c, 00, 0d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/ignore_run.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 12) to (start + 0, 13) Highest counter ID seen: c0 diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index 65cefe76c29a..95a5f6bf68b7 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -1,44 +1,53 @@ Function name: inline_dead::dead (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 01, 02, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 17, 01, 00, 11, 00, 01, 05, 00, 07, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline-dead.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 23, 1) to (start + 2, 2) +Number of file 0 mappings: 3 +- Code(Zero) at (prev + 23, 1) to (start + 0, 17) +- Code(Zero) at (prev + 1, 5) to (start + 0, 7) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: inline_dead::live:: -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0d, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 0e, 01, 00, 20, 01, 01, 08, 00, 09, 05, 01, 09, 00, 0d, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline-dead.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) -- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 13) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 13) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: inline_dead::main -Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0a, 01, 06, 05, 01, 02] +Raw bytes (39): 0x[01, 01, 00, 07, 01, 04, 01, 00, 0a, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 12, 01, 00, 14, 00, 21, 01, 02, 09, 00, 0a, 01, 03, 05, 00, 0d, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline-dead.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 10) -- Code(Counter(0)) at (prev + 6, 5) to (start + 1, 2) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 18) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 33) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: inline_dead::main::{closure#0} -Raw bytes (19): 0x[01, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 01, 01, 05, 00, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 07, 17, 00, 18, 01, 01, 09, 00, 16, 00, 00, 17, 00, 18, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline-dead.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 7, 23) to (start + 1, 22) -- Code(Zero) at (prev + 1, 23) to (start + 0, 24) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 7, 23) to (start + 0, 24) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Zero) at (prev + 0, 23) to (start + 0, 24) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 diff --git a/tests/coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage index c12668ce89a2..d75aaf300623 100644 --- a/tests/coverage/inline-dead.coverage +++ b/tests/coverage/inline-dead.coverage @@ -3,7 +3,7 @@ LL| | LL| 1|fn main() { LL| 1| println!("{}", live::()); - LL| 1| + LL| | LL| 1| let f = |x: bool| { LL| 1| debug_assert!(x); ^0 diff --git a/tests/coverage/inline.cov-map b/tests/coverage/inline.cov-map index 7264391baaf7..4c67dd96ac2f 100644 --- a/tests/coverage/inline.cov-map +++ b/tests/coverage/inline.cov-map @@ -1,86 +1,137 @@ Function name: inline::display:: -Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 29, 01, 00, 22, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 10, 02, 00, 11, 02, 06, 01, 03, 05, 01, 02] +Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 29, 01, 00, 21, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 10, 02, 00, 11, 02, 06, 01, 03, 05, 00, 0d, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 34) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 33) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10) = (c1 - c0) - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 0, 17) to (start + 2, 6) = (c1 - c0) -- Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: inline::error -Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 0b] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 31, 01, 00, 0b, 01, 01, 05, 00, 0b] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 11) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 49, 1) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 11) Highest counter ID seen: c0 Function name: inline::length:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1e, 01, 00, 20, 01, 01, 05, 00, 07, 01, 00, 08, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 30, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 7) +- Code(Counter(0)) at (prev + 0, 8) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: inline::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 05, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 05, 01, 00, 0a, 01, 01, 05, 00, 11, 01, 00, 12, 00, 22, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 5, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 34) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: inline::permutate:: -Raw bytes (54): 0x[01, 01, 05, 01, 05, 0d, 09, 0d, 09, 01, 13, 05, 09, 08, 01, 0f, 01, 02, 0e, 05, 02, 0f, 02, 06, 02, 02, 0f, 00, 14, 0a, 01, 0d, 00, 0e, 09, 00, 12, 00, 16, 0a, 00, 17, 04, 0a, 0e, 05, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (142): 0x[01, 01, 0e, 01, 05, 0d, 09, 0d, 09, 0d, 09, 0d, 09, 0d, 09, 0d, 09, 0d, 09, 0d, 09, 0d, 09, 0d, 09, 0d, 09, 01, 37, 05, 09, 16, 01, 0f, 01, 00, 38, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 13, 01, 00, 14, 00, 16, 01, 01, 08, 00, 0e, 05, 00, 0f, 02, 06, 02, 02, 0f, 00, 14, 2e, 01, 0d, 00, 0e, 09, 00, 12, 00, 13, 09, 00, 15, 00, 16, 2e, 00, 17, 04, 0a, 2e, 01, 0d, 00, 11, 2e, 00, 12, 00, 14, 2e, 00, 16, 00, 17, 2e, 00, 19, 00, 1a, 2e, 01, 0d, 00, 16, 2e, 00, 17, 00, 19, 2e, 00, 1b, 00, 20, 2e, 01, 0d, 00, 11, 2e, 00, 12, 00, 14, 32, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 5 +- file 0 => $DIR/inline.rs +Number of expressions: 14 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(3), rhs = Counter(2) - expression 2 operands: lhs = Counter(3), rhs = Counter(2) -- expression 3 operands: lhs = Counter(0), rhs = Expression(4, Add) -- expression 4 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 14) -- Code(Counter(1)) at (prev + 2, 15) to (start + 2, 6) +- expression 3 operands: lhs = Counter(3), rhs = Counter(2) +- expression 4 operands: lhs = Counter(3), rhs = Counter(2) +- expression 5 operands: lhs = Counter(3), rhs = Counter(2) +- expression 6 operands: lhs = Counter(3), rhs = Counter(2) +- expression 7 operands: lhs = Counter(3), rhs = Counter(2) +- expression 8 operands: lhs = Counter(3), rhs = Counter(2) +- expression 9 operands: lhs = Counter(3), rhs = Counter(2) +- expression 10 operands: lhs = Counter(3), rhs = Counter(2) +- expression 11 operands: lhs = Counter(3), rhs = Counter(2) +- expression 12 operands: lhs = Counter(0), rhs = Expression(13, Add) +- expression 13 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 22 +- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 56) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 19) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 14) +- Code(Counter(1)) at (prev + 0, 15) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 15) to (start + 0, 20) = (c0 - c1) -- Code(Expression(2, Sub)) at (prev + 1, 13) to (start + 0, 14) +- Code(Expression(11, Sub)) at (prev + 1, 13) to (start + 0, 14) = (c3 - c2) -- Code(Counter(2)) at (prev + 0, 18) to (start + 0, 22) -- Code(Expression(2, Sub)) at (prev + 0, 23) to (start + 4, 10) +- Code(Counter(2)) at (prev + 0, 18) to (start + 0, 19) +- Code(Counter(2)) at (prev + 0, 21) to (start + 0, 22) +- Code(Expression(11, Sub)) at (prev + 0, 23) to (start + 4, 10) = (c3 - c2) -- Code(Expression(3, Sub)) at (prev + 5, 12) to (start + 2, 6) +- Code(Expression(11, Sub)) at (prev + 1, 13) to (start + 0, 17) + = (c3 - c2) +- Code(Expression(11, Sub)) at (prev + 0, 18) to (start + 0, 20) + = (c3 - c2) +- Code(Expression(11, Sub)) at (prev + 0, 22) to (start + 0, 23) + = (c3 - c2) +- Code(Expression(11, Sub)) at (prev + 0, 25) to (start + 0, 26) + = (c3 - c2) +- Code(Expression(11, Sub)) at (prev + 1, 13) to (start + 0, 22) + = (c3 - c2) +- Code(Expression(11, Sub)) at (prev + 0, 23) to (start + 0, 25) + = (c3 - c2) +- Code(Expression(11, Sub)) at (prev + 0, 27) to (start + 0, 32) + = (c3 - c2) +- Code(Expression(11, Sub)) at (prev + 1, 13) to (start + 0, 17) + = (c3 - c2) +- Code(Expression(11, Sub)) at (prev + 0, 18) to (start + 0, 20) + = (c3 - c2) +- Code(Expression(12, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - (c1 + c2)) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c2 Function name: inline::permutations:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 03, 02] +Raw bytes (39): 0x[01, 01, 00, 07, 01, 0a, 01, 00, 2d, 01, 01, 09, 00, 0f, 01, 00, 12, 00, 14, 01, 00, 15, 00, 1d, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 16, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 10, 1) to (start + 3, 2) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 45) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 20) +- Code(Counter(0)) at (prev + 0, 21) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: inline::swap:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 04, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 23, 01, 00, 33, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 12, 01, 01, 05, 00, 12, 01, 01, 05, 00, 0e, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inline.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 35, 1) to (start + 4, 2) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 51) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/inline.coverage b/tests/coverage/inline.coverage index 3d322126a38b..5fe069d5389d 100644 --- a/tests/coverage/inline.coverage +++ b/tests/coverage/inline.coverage @@ -18,7 +18,7 @@ LL| 6| display(xs); LL| 10| } else if k < n { LL| 15| for i in k..n { - ^10 + ^10^10 LL| 15| swap(xs, i, k); LL| 15| permutate(xs, k + 1); LL| 15| swap(xs, i, k); diff --git a/tests/coverage/inner_items.cov-map b/tests/coverage/inner_items.cov-map index a12cce25b643..ca6ddfda2ddf 100644 --- a/tests/coverage/inner_items.cov-map +++ b/tests/coverage/inner_items.cov-map @@ -1,46 +1,70 @@ Function name: ::default_trait_func -Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 09, 03, 0a] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 21, 09, 00, 29, 01, 01, 0d, 00, 14, 01, 01, 0d, 00, 11, 01, 00, 12, 00, 1c, 01, 01, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inner_items.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 33, 9) to (start + 3, 10) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 33, 9) to (start + 0, 41) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) Highest counter ID seen: c0 Function name: ::trait_func -Raw bytes (9): 0x[01, 01, 00, 01, 01, 28, 09, 03, 0a] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 28, 09, 00, 2c, 01, 01, 0d, 00, 29, 01, 01, 0d, 00, 14, 01, 00, 15, 00, 29, 01, 01, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inner_items.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 40, 9) to (start + 3, 10) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 40, 9) to (start + 0, 44) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 41) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 20) +- Code(Counter(0)) at (prev + 0, 21) to (start + 0, 41) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) Highest counter ID seen: c0 Function name: inner_items::main -Raw bytes (43): 0x[01, 01, 02, 01, 05, 01, 09, 07, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 05, 00, 06, 01, 24, 08, 00, 0f, 09, 00, 10, 02, 06, 06, 02, 05, 00, 06, 01, 02, 09, 05, 02] +Raw bytes (88): 0x[01, 01, 02, 01, 05, 01, 09, 10, 01, 03, 01, 00, 0a, 01, 04, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 02, 09, 00, 16, 01, 00, 19, 00, 1a, 01, 01, 08, 00, 0f, 05, 00, 10, 02, 06, 02, 02, 05, 00, 06, 01, 24, 08, 00, 0f, 09, 00, 10, 02, 06, 06, 02, 05, 00, 06, 01, 02, 09, 00, 10, 01, 00, 13, 02, 06, 01, 04, 05, 00, 08, 01, 00, 09, 00, 1b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inner_items.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) -- Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) +Number of file 0 mappings: 16 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 15) +- Code(Counter(1)) at (prev + 0, 16) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 36, 8) to (start + 0, 15) - Code(Counter(2)) at (prev + 0, 16) to (start + 2, 6) - Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c2) -- Code(Counter(0)) at (prev + 2, 9) to (start + 5, 2) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 2, 6) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 27) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c2 Function name: inner_items::main::in_func -Raw bytes (9): 0x[01, 01, 00, 01, 01, 12, 05, 04, 06] +Raw bytes (44): 0x[01, 01, 00, 08, 01, 12, 05, 00, 17, 01, 01, 0d, 00, 0e, 01, 00, 11, 00, 12, 01, 01, 0d, 00, 0e, 01, 00, 11, 00, 16, 01, 01, 09, 00, 11, 01, 00, 12, 00, 1a, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inner_items.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 18, 5) to (start + 4, 6) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 18, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 diff --git a/tests/coverage/inner_items.coverage b/tests/coverage/inner_items.coverage index 8244d347b59c..8503cc12f233 100644 --- a/tests/coverage/inner_items.coverage +++ b/tests/coverage/inner_items.coverage @@ -1,11 +1,11 @@ LL| |#![allow(unused_assignments, unused_variables, dead_code)] LL| | LL| 1|fn main() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| let mut countdown = 0; LL| 1| if is_true { LL| 1| countdown = 10; @@ -54,7 +54,7 @@ LL| 1| let mut val = InStruct { LL| 1| in_struct_field: 101, // LL| 1| }; - LL| 1| + LL| | LL| 1| val.default_trait_func(); LL| 1|} diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map index f10231090089..d1d751ff24b8 100644 --- a/tests/coverage/issue-83601.cov-map +++ b/tests/coverage/issue-83601.cov-map @@ -1,13 +1,30 @@ Function name: issue_83601::main -Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 0f, 05, 03, 09, 01, 0f, 02, 02, 05, 03, 02] +Raw bytes (76): 0x[01, 01, 01, 05, 09, 0e, 01, 06, 01, 00, 0a, 01, 01, 09, 00, 0c, 01, 00, 0f, 00, 15, 01, 01, 05, 00, 0f, 05, 01, 09, 00, 0c, 05, 00, 0f, 00, 15, 05, 01, 05, 00, 0f, 02, 01, 05, 00, 0d, 02, 00, 0e, 00, 14, 02, 01, 05, 00, 0d, 02, 00, 0e, 00, 14, 02, 01, 05, 00, 0d, 02, 00, 0e, 00, 14, 02, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-83601.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 15) -- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 15) -- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 15) to (start + 0, 21) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 15) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 13) + = (c1 - c2) +- Code(Expression(0, Sub)) at (prev + 0, 14) to (start + 0, 20) + = (c1 - c2) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 13) + = (c1 - c2) +- Code(Expression(0, Sub)) at (prev + 0, 14) to (start + 0, 20) + = (c1 - c2) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 13) + = (c1 - c2) +- Code(Expression(0, Sub)) at (prev + 0, 14) to (start + 0, 20) + = (c1 - c2) +- Code(Expression(0, Sub)) at (prev + 1, 1) to (start + 0, 2) = (c1 - c2) Highest counter ID seen: c1 diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index 47e2922a805a..2b643ea599ed 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -1,67 +1,81 @@ Function name: ::fmt -Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, 8a, 01, 05, 01, 24, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (42): 0x[01, 01, 01, 01, 05, 07, 01, 8a, 01, 05, 00, 43, 01, 01, 09, 00, 0f, 01, 00, 10, 00, 11, 01, 00, 13, 00, 24, 05, 00, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-84561.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 36) -- Code(Counter(1)) at (prev + 1, 37) to (start + 0, 38) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 138, 5) to (start + 0, 67) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 0, 16) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 36) +- Code(Counter(1)) at (prev + 0, 37) to (start + 0, 38) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c1 Function name: issue_84561::main -Raw bytes (10): 0x[01, 01, 00, 01, 01, b4, 01, 01, 04, 02] +Raw bytes (30): 0x[01, 01, 00, 05, 01, b4, 01, 01, 00, 0a, 01, 01, 05, 00, 0a, 01, 01, 05, 00, 0a, 01, 01, 05, 00, 0a, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-84561.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 180, 1) to (start + 4, 2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 180, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: issue_84561::test1 -Raw bytes (50): 0x[01, 01, 00, 09, 01, 9a, 01, 01, 01, 0b, 05, 01, 0c, 00, 1e, 01, 01, 05, 00, 0b, 09, 00, 0c, 00, 1e, 01, 01, 0d, 01, 0b, 0d, 01, 0c, 00, 1e, 01, 01, 05, 03, 0b, 11, 03, 0c, 00, 1e, 01, 01, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 00, 0c, 01, 9a, 01, 01, 00, 0b, 01, 01, 05, 00, 0b, 05, 00, 0c, 00, 1e, 01, 01, 05, 00, 0b, 09, 00, 0c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 05, 00, 0b, 0d, 00, 0c, 00, 1e, 01, 01, 05, 02, 06, 01, 03, 05, 00, 0b, 11, 00, 0c, 00, 1e, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-84561.rs Number of expressions: 0 -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 154, 1) to (start + 1, 11) -- Code(Counter(1)) at (prev + 1, 12) to (start + 0, 30) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 154, 1) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 11) +- Code(Counter(1)) at (prev + 0, 12) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 11) - Code(Counter(2)) at (prev + 0, 12) to (start + 0, 30) -- Code(Counter(0)) at (prev + 1, 13) to (start + 1, 11) -- Code(Counter(3)) at (prev + 1, 12) to (start + 0, 30) -- Code(Counter(0)) at (prev + 1, 5) to (start + 3, 11) -- Code(Counter(4)) at (prev + 3, 12) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 11) +- Code(Counter(3)) at (prev + 0, 12) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 5) to (start + 2, 6) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 11) +- Code(Counter(4)) at (prev + 0, 12) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c4 Function name: issue_84561::test2 -Raw bytes (20): 0x[01, 01, 00, 03, 01, b0, 01, 01, 01, 10, 05, 01, 11, 00, 23, 01, 01, 01, 00, 02] +Raw bytes (25): 0x[01, 01, 00, 04, 01, b0, 01, 01, 00, 0b, 01, 01, 05, 00, 10, 05, 00, 11, 00, 23, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-84561.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 176, 1) to (start + 1, 16) -- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 35) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 176, 1) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16) +- Code(Counter(1)) at (prev + 0, 17) to (start + 0, 35) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: issue_84561::test2::call_print -Raw bytes (10): 0x[01, 01, 00, 01, 01, a7, 01, 09, 02, 0a] +Raw bytes (25): 0x[01, 01, 00, 04, 01, a7, 01, 09, 00, 1f, 01, 01, 0d, 00, 13, 01, 00, 14, 00, 18, 01, 01, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-84561.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 167, 9) to (start + 0, 31) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 19) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 24) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) Highest counter ID seen: c0 Function name: issue_84561::test3 -Raw bytes (279): 0x[01, 01, 0a, 0d, 11, 0d, 15, 0d, 19, 1d, 21, 29, 2d, 25, 29, 25, 29, 25, 29, 27, 31, 29, 2d, 33, 01, 08, 01, 03, 0f, 05, 04, 09, 01, 0f, 09, 02, 05, 04, 0f, 09, 05, 05, 00, 0f, 09, 01, 05, 00, 0f, 09, 01, 09, 01, 0f, 0d, 02, 05, 00, 0f, 0d, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 0d, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 0d, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 0d, 04, 09, 02, 0f, 0d, 06, 05, 00, 0f, 0d, 04, 05, 00, 0f, 0d, 04, 09, 01, 0f, 0d, 05, 08, 00, 0f, 11, 01, 09, 00, 13, 02, 05, 09, 00, 13, 0d, 05, 08, 00, 0f, 15, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 06, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 0d, 03, 05, 00, 0f, 0d, 01, 0c, 00, 13, 19, 01, 0d, 00, 13, 0a, 02, 0d, 00, 13, 1d, 04, 05, 02, 13, 21, 03, 0d, 00, 13, 0e, 02, 0d, 00, 13, 27, 03, 05, 00, 0f, 25, 01, 0c, 00, 13, 29, 01, 0d, 00, 17, 29, 04, 0d, 00, 13, 1e, 02, 0d, 00, 17, 1e, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 1e, 02, 15, 00, 1b, 2d, 04, 0d, 00, 13, 22, 03, 09, 00, 19, 31, 02, 05, 00, 0f, 31, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] +Raw bytes (409): 0x[01, 01, 0a, 0d, 11, 0d, 15, 0d, 19, 1d, 21, 29, 2d, 25, 29, 25, 29, 25, 29, 27, 31, 29, 2d, 4d, 01, 08, 01, 00, 0b, 01, 01, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 01, 09, 00, 0c, 01, 00, 0f, 00, 15, 01, 01, 05, 00, 0f, 05, 01, 09, 00, 0c, 05, 00, 0f, 00, 15, 05, 01, 05, 00, 0f, 09, 01, 05, 00, 0d, 09, 00, 0e, 00, 14, 09, 01, 05, 00, 0d, 09, 00, 0e, 00, 14, 09, 01, 05, 00, 0d, 09, 00, 0e, 00, 14, 09, 02, 05, 00, 0f, 09, 01, 05, 00, 0f, 09, 01, 05, 00, 0f, 09, 01, 09, 00, 0c, 09, 00, 0f, 00, 15, 09, 01, 05, 00, 0f, 0d, 01, 05, 00, 0f, 0d, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 0d, 01, 05, 00, 0d, 0d, 00, 0e, 00, 14, 0d, 01, 05, 00, 0d, 0d, 00, 0e, 00, 14, 0d, 02, 05, 00, 0f, 00, 00, 20, 00, 24, 00, 00, 29, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 0d, 01, 05, 00, 0f, 00, 05, 09, 00, 0d, 00, 03, 09, 00, 10, 00, 02, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 0d, 04, 09, 00, 10, 0d, 00, 13, 00, 2e, 0d, 02, 05, 00, 0f, 0d, 04, 05, 00, 0f, 0d, 04, 05, 00, 0f, 0d, 04, 09, 00, 0c, 0d, 00, 0f, 00, 15, 0d, 01, 05, 00, 0f, 0d, 04, 08, 00, 0f, 11, 01, 09, 00, 13, 02, 05, 09, 00, 13, 0d, 05, 08, 00, 0f, 15, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 06, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 0d, 03, 05, 00, 0f, 0d, 01, 0c, 00, 13, 19, 01, 0d, 00, 13, 0a, 02, 0d, 00, 13, 1d, 04, 05, 00, 0f, 1d, 02, 0c, 00, 13, 21, 01, 0d, 00, 13, 0e, 02, 0d, 00, 13, 27, 03, 05, 00, 0f, 25, 01, 0c, 00, 13, 29, 01, 0d, 00, 17, 29, 04, 0d, 00, 13, 1e, 02, 0d, 00, 17, 1e, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 1e, 02, 15, 00, 1b, 2d, 04, 0d, 00, 13, 22, 03, 09, 00, 19, 31, 02, 05, 00, 0f, 31, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-84561.rs Number of expressions: 10 - expression 0 operands: lhs = Counter(3), rhs = Counter(4) - expression 1 operands: lhs = Counter(3), rhs = Counter(5) @@ -73,29 +87,54 @@ Number of expressions: 10 - expression 7 operands: lhs = Counter(9), rhs = Counter(10) - expression 8 operands: lhs = Expression(9, Add), rhs = Counter(12) - expression 9 operands: lhs = Counter(10), rhs = Counter(11) -Number of file 0 mappings: 51 -- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 15) -- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 15) -- Code(Counter(2)) at (prev + 2, 5) to (start + 4, 15) -- Code(Counter(2)) at (prev + 5, 5) to (start + 0, 15) +Number of file 0 mappings: 77 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 15) to (start + 0, 21) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(2)) at (prev + 0, 14) to (start + 0, 20) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(2)) at (prev + 0, 14) to (start + 0, 20) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(2)) at (prev + 0, 14) to (start + 0, 20) +- Code(Counter(2)) at (prev + 2, 5) to (start + 0, 15) - Code(Counter(2)) at (prev + 1, 5) to (start + 0, 15) -- Code(Counter(2)) at (prev + 1, 9) to (start + 1, 15) -- Code(Counter(3)) at (prev + 2, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(2)) at (prev + 0, 15) to (start + 0, 21) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 15) - Code(Counter(3)) at (prev + 1, 5) to (start + 0, 15) - Code(Zero) at (prev + 0, 32) to (start + 0, 48) -- Code(Counter(3)) at (prev + 1, 5) to (start + 3, 15) -- Code(Zero) at (prev + 3, 32) to (start + 0, 48) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(3)) at (prev + 0, 14) to (start + 0, 20) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(3)) at (prev + 0, 14) to (start + 0, 20) +- Code(Counter(3)) at (prev + 2, 5) to (start + 0, 15) +- Code(Zero) at (prev + 0, 32) to (start + 0, 36) +- Code(Zero) at (prev + 0, 41) to (start + 0, 48) - Code(Zero) at (prev + 0, 51) to (start + 0, 65) - Code(Zero) at (prev + 0, 75) to (start + 0, 90) - Code(Counter(3)) at (prev + 1, 5) to (start + 0, 15) -- Code(Zero) at (prev + 5, 9) to (start + 3, 16) -- Code(Zero) at (prev + 5, 13) to (start + 0, 27) +- Code(Zero) at (prev + 5, 9) to (start + 0, 13) +- Code(Zero) at (prev + 3, 9) to (start + 0, 16) +- Code(Zero) at (prev + 2, 13) to (start + 0, 27) - Code(Zero) at (prev + 2, 13) to (start + 0, 28) -- Code(Counter(3)) at (prev + 4, 9) to (start + 2, 15) -- Code(Counter(3)) at (prev + 6, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(3)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(3)) at (prev + 2, 5) to (start + 0, 15) - Code(Counter(3)) at (prev + 4, 5) to (start + 0, 15) -- Code(Counter(3)) at (prev + 4, 9) to (start + 1, 15) -- Code(Counter(3)) at (prev + 5, 8) to (start + 0, 15) +- Code(Counter(3)) at (prev + 4, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 4, 9) to (start + 0, 12) +- Code(Counter(3)) at (prev + 0, 15) to (start + 0, 21) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 4, 8) to (start + 0, 15) - Code(Counter(4)) at (prev + 1, 9) to (start + 0, 19) - Code(Expression(0, Sub)) at (prev + 5, 9) to (start + 0, 19) = (c3 - c4) @@ -110,8 +149,9 @@ Number of file 0 mappings: 51 - Code(Counter(6)) at (prev + 1, 13) to (start + 0, 19) - Code(Expression(2, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c3 - c6) -- Code(Counter(7)) at (prev + 4, 5) to (start + 2, 19) -- Code(Counter(8)) at (prev + 3, 13) to (start + 0, 19) +- Code(Counter(7)) at (prev + 4, 5) to (start + 0, 15) +- Code(Counter(7)) at (prev + 2, 12) to (start + 0, 19) +- Code(Counter(8)) at (prev + 1, 13) to (start + 0, 19) - Code(Expression(3, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c7 - c8) - Code(Expression(9, Add)) at (prev + 3, 5) to (start + 0, 15) diff --git a/tests/coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage index a55f42a696e6..781f1e97f5ab 100644 --- a/tests/coverage/issue-84561.coverage +++ b/tests/coverage/issue-84561.coverage @@ -14,7 +14,7 @@ LL| 1| println!("{:?}", Foo(1)); LL| 1| println!("{:?}", bar); LL| 1| println!("{:?}", baz); - LL| 1| + LL| | LL| 1| assert_eq!(Foo(1), Foo(1)); LL| 1| assert_ne!(Foo(0), Foo(1)); LL| 1| assert_eq!(Foo(2), Foo(2)); @@ -25,17 +25,17 @@ ^0 LL| 1| println!("{:?}", bar); LL| 1| println!("{:?}", Foo(1)); - LL| 1| + LL| | LL| 1| assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" }); - ^0 ^0 ^0 + ^0 ^0 ^0 ^0 LL| 1| assert_ne!( LL| | Foo(0) LL| | , LL| | Foo(5) LL| | , LL| 0| "{}" - LL| 0| , - LL| 0| if + LL| | , + LL| | if LL| 0| is_true LL| | { LL| 0| "true message" @@ -45,7 +45,7 @@ LL| | ); LL| | LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| assert_eq!( LL| | Foo(1), LL| | Foo(1) @@ -96,7 +96,7 @@ LL| | Foo(5) LL| | ); LL| 1| assert_ne!( - LL| 1| Foo(5), + LL| | Foo(5), LL| 1| if is_true { LL| 1| Foo(0) LL| | } else { diff --git a/tests/coverage/issue-85461.cov-map b/tests/coverage/issue-85461.cov-map index 349bc2cab803..b08d70336930 100644 --- a/tests/coverage/issue-85461.cov-map +++ b/tests/coverage/issue-85461.cov-map @@ -1,9 +1,12 @@ Function name: issue_85461::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 08, 01, 00, 0a, 01, 01, 05, 00, 11, 01, 01, 05, 00, 11, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-85461.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map index 38cb70a3f97a..17f3dafce1d7 100644 --- a/tests/coverage/issue-93054.cov-map +++ b/tests/coverage/issue-93054.cov-map @@ -1,27 +1,30 @@ Function name: issue_93054::foo2 (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 1d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 1c] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-93054.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 1) to (start + 0, 29) +- Code(Zero) at (prev + 21, 1) to (start + 0, 28) Highest counter ID seen: (none) Function name: issue_93054::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 00, 0d] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 1d, 01, 00, 0a, 01, 00, 0c, 00, 0d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-93054.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 29, 1) to (start + 0, 13) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 29, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 12) to (start + 0, 13) Highest counter ID seen: c0 Function name: issue_93054::make (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 19, 01, 00, 1b, 00, 01, 05, 00, 09, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/issue-93054.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 25, 1) to (start + 2, 2) +Number of file 0 mappings: 3 +- Code(Zero) at (prev + 25, 1) to (start + 0, 27) +- Code(Zero) at (prev + 1, 5) to (start + 0, 9) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map index 3f7788da1ebc..cbbe6a89fb0f 100644 --- a/tests/coverage/lazy_boolean.cov-map +++ b/tests/coverage/lazy_boolean.cov-map @@ -1,7 +1,7 @@ Function name: lazy_boolean::main -Raw bytes (158): 0x[01, 01, 07, 01, 05, 01, 25, 01, 21, 01, 11, 01, 15, 01, 19, 01, 1d, 1c, 01, 04, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 05, 00, 06, 01, 02, 09, 00, 11, 01, 02, 0d, 00, 12, 06, 02, 0d, 00, 12, 01, 03, 09, 00, 11, 01, 02, 0d, 00, 12, 0a, 02, 0d, 00, 12, 01, 02, 09, 00, 11, 01, 00, 14, 00, 19, 09, 00, 1d, 00, 22, 01, 01, 09, 00, 11, 01, 00, 14, 00, 19, 0d, 00, 1d, 00, 22, 01, 03, 09, 01, 10, 0e, 02, 05, 03, 06, 11, 03, 05, 00, 06, 01, 03, 09, 00, 10, 15, 01, 05, 03, 06, 12, 05, 05, 03, 06, 01, 05, 08, 00, 10, 16, 00, 11, 02, 06, 19, 02, 05, 00, 06, 01, 02, 08, 00, 0f, 1d, 00, 10, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (198): 0x[01, 01, 07, 01, 05, 01, 25, 01, 21, 01, 11, 01, 15, 01, 19, 01, 1d, 24, 01, 04, 01, 00, 0a, 01, 04, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 02, 0a, 00, 0f, 01, 00, 11, 00, 16, 01, 00, 18, 00, 1d, 01, 00, 21, 00, 2a, 01, 01, 08, 00, 0f, 05, 00, 10, 04, 06, 05, 01, 09, 00, 0e, 02, 03, 05, 00, 06, 01, 02, 09, 00, 11, 01, 02, 0d, 00, 12, 06, 02, 0d, 00, 12, 01, 03, 09, 00, 11, 01, 02, 0d, 00, 12, 0a, 02, 0d, 00, 12, 01, 02, 09, 00, 11, 01, 00, 14, 00, 19, 09, 00, 1d, 00, 22, 01, 01, 09, 00, 11, 01, 00, 14, 00, 19, 0d, 00, 1d, 00, 22, 01, 03, 09, 01, 10, 0e, 02, 05, 03, 06, 11, 03, 05, 00, 06, 01, 03, 09, 00, 10, 15, 01, 05, 03, 06, 12, 05, 05, 03, 06, 01, 05, 08, 00, 10, 16, 00, 11, 02, 06, 19, 02, 05, 00, 06, 01, 02, 08, 00, 0f, 1d, 00, 10, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/lazy_boolean.rs Number of expressions: 7 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(9) @@ -10,10 +10,18 @@ Number of expressions: 7 - expression 4 operands: lhs = Counter(0), rhs = Counter(5) - expression 5 operands: lhs = Counter(0), rhs = Counter(6) - expression 6 operands: lhs = Counter(0), rhs = Counter(7) -Number of file 0 mappings: 28 -- Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15) -- Code(Counter(1)) at (prev + 7, 16) to (start + 4, 6) -- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 6) +Number of file 0 mappings: 36 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 2, 10) to (start + 0, 15) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 29) +- Code(Counter(0)) at (prev + 0, 33) to (start + 0, 42) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 15) +- Code(Counter(1)) at (prev + 0, 16) to (start + 4, 6) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 14) +- Code(Expression(0, Sub)) at (prev + 3, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 17) - Code(Counter(0)) at (prev + 2, 13) to (start + 0, 18) diff --git a/tests/coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage index 828ba2a58116..0a30038e02fa 100644 --- a/tests/coverage/lazy_boolean.coverage +++ b/tests/coverage/lazy_boolean.coverage @@ -2,11 +2,11 @@ LL| | LL| |#[rustfmt::skip] LL| 1|fn main() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| let (mut a, mut b, mut c) = (0, 0, 0); LL| 1| if is_true { LL| 1| a = 1; diff --git a/tests/coverage/let_else_loop.cov-map b/tests/coverage/let_else_loop.cov-map index 7789114c2395..169d4a5c0961 100644 --- a/tests/coverage/let_else_loop.cov-map +++ b/tests/coverage/let_else_loop.cov-map @@ -1,33 +1,36 @@ Function name: let_else_loop::_if (unused) -Raw bytes (19): 0x[01, 01, 00, 03, 00, 16, 01, 01, 0c, 00, 01, 0f, 00, 16, 00, 00, 20, 00, 27] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 16, 01, 00, 13, 00, 01, 08, 00, 0c, 00, 00, 0f, 00, 16, 00, 00, 20, 00, 27] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/let_else_loop.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Zero) at (prev + 22, 1) to (start + 1, 12) -- Code(Zero) at (prev + 1, 15) to (start + 0, 22) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 22, 1) to (start + 0, 19) +- Code(Zero) at (prev + 1, 8) to (start + 0, 12) +- Code(Zero) at (prev + 0, 15) to (start + 0, 22) - Code(Zero) at (prev + 0, 32) to (start + 0, 39) Highest counter ID seen: (none) Function name: let_else_loop::_loop_either_way (unused) -Raw bytes (19): 0x[01, 01, 00, 03, 00, 0f, 01, 01, 14, 00, 01, 1c, 00, 23, 00, 01, 05, 00, 0c] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 0f, 01, 00, 20, 00, 01, 10, 00, 14, 00, 00, 1c, 00, 23, 00, 01, 05, 00, 0c] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/let_else_loop.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Zero) at (prev + 15, 1) to (start + 1, 20) -- Code(Zero) at (prev + 1, 28) to (start + 0, 35) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 15, 1) to (start + 0, 32) +- Code(Zero) at (prev + 1, 16) to (start + 0, 20) +- Code(Zero) at (prev + 0, 28) to (start + 0, 35) - Code(Zero) at (prev + 1, 5) to (start + 0, 12) Highest counter ID seen: (none) Function name: let_else_loop::loopy -Raw bytes (19): 0x[01, 01, 00, 03, 01, 09, 01, 01, 14, 09, 01, 1c, 00, 23, 05, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 09, 01, 00, 15, 01, 01, 10, 00, 14, 09, 00, 1c, 00, 23, 05, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/let_else_loop.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 9, 1) to (start + 1, 20) -- Code(Counter(2)) at (prev + 1, 28) to (start + 0, 35) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 16) to (start + 0, 20) +- Code(Counter(2)) at (prev + 0, 28) to (start + 0, 35) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c2 diff --git a/tests/coverage/long_and_wide.cov-map b/tests/coverage/long_and_wide.cov-map index 032b7fe102e8..93466a98eaf3 100644 --- a/tests/coverage/long_and_wide.cov-map +++ b/tests/coverage/long_and_wide.cov-map @@ -1,36 +1,44 @@ Function name: long_and_wide::far_function -Raw bytes (10): 0x[01, 01, 00, 01, 01, 96, 01, 01, 00, 15] +Raw bytes (15): 0x[01, 01, 00, 02, 01, 96, 01, 01, 00, 12, 01, 00, 14, 00, 15] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/long_and_wide.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 150, 1) to (start + 0, 21) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 150, 1) to (start + 0, 18) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 21) Highest counter ID seen: c0 Function name: long_and_wide::long_function -Raw bytes (10): 0x[01, 01, 00, 01, 01, 10, 01, 84, 01, 02] +Raw bytes (15): 0x[01, 01, 00, 02, 01, 10, 01, 00, 13, 01, 84, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/long_and_wide.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 16, 1) to (start + 132, 2) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 132, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: long_and_wide::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 04, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 07, 01, 00, 0a, 01, 01, 05, 00, 12, 01, 01, 05, 00, 12, 01, 01, 05, 00, 11, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/long_and_wide.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 1) to (start + 4, 2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: long_and_wide::wide_function -Raw bytes (10): 0x[01, 01, 00, 01, 01, 0e, 01, 00, 8b, 01] +Raw bytes (23): 0x[01, 01, 00, 03, 01, 0e, 01, 00, 13, 01, 00, 86, 01, 00, 88, 01, 01, 00, 8a, 01, 00, 8b, 01] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/long_and_wide.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 139) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 0, 134) to (start + 0, 136) +- Code(Counter(0)) at (prev + 0, 138) to (start + 0, 139) Highest counter ID seen: c0 diff --git a/tests/coverage/long_and_wide.coverage b/tests/coverage/long_and_wide.coverage index f0898d9f4662..d9bacdf9eed3 100644 --- a/tests/coverage/long_and_wide.coverage +++ b/tests/coverage/long_and_wide.coverage @@ -14,137 +14,137 @@ LL| 1|fn wide_function() { /* */ (); } LL| | LL| 1|fn long_function() { - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // - LL| 1| // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // + LL| | // LL| 1|} LL| | LL| 1|fn far_function() {} diff --git a/tests/coverage/loop-break.cov-map b/tests/coverage/loop-break.cov-map index fccc4d64395b..3981623550dd 100644 --- a/tests/coverage/loop-break.cov-map +++ b/tests/coverage/loop-break.cov-map @@ -1,11 +1,11 @@ Function name: loop_break::main -Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0b, 05, 02, 0c, 00, 21, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0a, 05, 02, 0c, 00, 21, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/loop-break.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 11) +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 10) - Code(Counter(1)) at (prev + 2, 12) to (start + 0, 33) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10) diff --git a/tests/coverage/loop_break_value.cov-map b/tests/coverage/loop_break_value.cov-map index e48d078f6722..cf355eceb2c1 100644 --- a/tests/coverage/loop_break_value.cov-map +++ b/tests/coverage/loop_break_value.cov-map @@ -1,9 +1,12 @@ Function name: loop_break_value::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 01, 0a, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 04, 01, 00, 0a, 01, 01, 09, 00, 0f, 01, 02, 0d, 05, 0a, 01, 07, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/loop_break_value.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 4, 1) to (start + 10, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 2, 13) to (start + 5, 10) +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/loop_break_value.coverage b/tests/coverage/loop_break_value.coverage index 7d4533987594..5e80168b958b 100644 --- a/tests/coverage/loop_break_value.coverage +++ b/tests/coverage/loop_break_value.coverage @@ -3,13 +3,13 @@ LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| let result - LL| 1| = + LL| | = LL| 1| loop LL| 1| { LL| 1| break LL| 1| 10 LL| 1| ; LL| 1| } - LL| 1| ; + LL| | ; LL| 1|} diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map index 2157cd6ee3f8..78fdaa53f46f 100644 --- a/tests/coverage/loops_branches.cov-map +++ b/tests/coverage/loops_branches.cov-map @@ -1,19 +1,22 @@ Function name: ::fmt -Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 14, 01, 09, 05, 01, 10, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 21, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (137): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 19, 01, 09, 05, 00, 43, 01, 01, 0c, 00, 10, 01, 01, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 13, 01, 00, 14, 00, 15, 01, 00, 17, 00, 1d, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 17, 0d, 00, 18, 00, 19, 0d, 00, 1b, 00, 21, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/loops_branches.rs Number of expressions: 4 - expression 0 operands: lhs = Expression(1, Add), rhs = Expression(2, Add) - expression 1 operands: lhs = Counter(0), rhs = Counter(3) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) - expression 3 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 20 -- Code(Counter(0)) at (prev + 9, 5) to (start + 1, 16) -- Code(Counter(0)) at (prev + 2, 16) to (start + 0, 21) +Number of file 0 mappings: 25 +- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 67) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 16) to (start + 0, 21) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 19) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 23) to (start + 0, 29) - Code(Counter(1)) at (prev + 0, 30) to (start + 0, 31) - Code(Zero) at (prev + 1, 16) to (start + 1, 10) - Code(Counter(3)) at (prev + 3, 13) to (start + 0, 14) @@ -23,7 +26,9 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18) -- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 23) +- Code(Counter(3)) at (prev + 0, 24) to (start + 0, 25) +- Code(Counter(3)) at (prev + 0, 27) to (start + 0, 33) - Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35) = ((c0 + c3) - (c1 + c2)) - Code(Zero) at (prev + 1, 20) to (start + 1, 14) @@ -33,22 +38,25 @@ Number of file 0 mappings: 20 Highest counter ID seen: c3 Function name: ::fmt -Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 21, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (137): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 19, 01, 22, 05, 00, 43, 01, 01, 0c, 00, 11, 00, 00, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 13, 01, 00, 14, 00, 15, 01, 00, 17, 00, 1d, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 17, 09, 00, 18, 00, 19, 09, 00, 1b, 00, 21, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/loops_branches.rs Number of expressions: 4 - expression 0 operands: lhs = Expression(1, Add), rhs = Expression(2, Add) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) - expression 2 operands: lhs = Counter(1), rhs = Counter(3) - expression 3 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 20 -- Code(Counter(0)) at (prev + 34, 5) to (start + 1, 17) -- Code(Zero) at (prev + 1, 18) to (start + 1, 10) +Number of file 0 mappings: 25 +- Code(Counter(0)) at (prev + 34, 5) to (start + 0, 67) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 17) +- Code(Zero) at (prev + 0, 18) to (start + 1, 10) - Code(Counter(0)) at (prev + 2, 16) to (start + 0, 21) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 19) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 23) to (start + 0, 29) - Code(Counter(3)) at (prev + 0, 30) to (start + 0, 31) - Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 23) @@ -58,7 +66,9 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18) -- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 23) +- Code(Counter(2)) at (prev + 0, 24) to (start + 0, 25) +- Code(Counter(2)) at (prev + 0, 27) to (start + 0, 33) - Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35) = ((c0 + c2) - (c1 + c3)) - Code(Expression(3, Sub)) at (prev + 3, 9) to (start + 0, 15) @@ -67,11 +77,20 @@ Number of file 0 mappings: 20 Highest counter ID seen: c3 Function name: loops_branches::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 01, 05, 02] +Raw bytes (54): 0x[01, 01, 00, 0a, 01, 37, 01, 00, 0a, 01, 01, 09, 00, 13, 01, 00, 16, 00, 1f, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 14, 01, 01, 09, 00, 15, 01, 00, 18, 00, 23, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 12, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/loops_branches.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 55, 1) to (start + 5, 2) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 55, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 19) +- Code(Counter(0)) at (prev + 0, 22) to (start + 0, 31) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 35) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/macro_in_closure.cov-map b/tests/coverage/macro_in_closure.cov-map index 9614154a3668..4544aa50143e 100644 --- a/tests/coverage/macro_in_closure.cov-map +++ b/tests/coverage/macro_in_closure.cov-map @@ -1,18 +1,21 @@ Function name: macro_in_closure::NO_BLOCK::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 1c, 00, 2d] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 25, 00, 2c] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/macro_in_closure.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 28) to (start + 0, 45) +- Code(Counter(0)) at (prev + 7, 37) to (start + 0, 44) Highest counter ID seen: c0 Function name: macro_in_closure::WITH_BLOCK::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 1e, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 09, 1e, 00, 1f, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 15, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/macro_in_closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 9, 30) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 9, 30) to (start + 0, 31) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map index bd033faa5510..c96cb75846b2 100644 --- a/tests/coverage/macro_name_span.cov-map +++ b/tests/coverage/macro_name_span.cov-map @@ -1,18 +1,21 @@ Function name: macro_name_span::affected_function -Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 3e] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 16, 1c, 00, 1d, 01, 01, 09, 00, 3e] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/macro_name_span.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 62) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 22, 28) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 62) Highest counter ID seen: c0 Function name: macro_name_span::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 0b, 01, 00, 0a, 01, 01, 05, 00, 16, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/macro_name_span.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 1) to (start + 2, 2) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/match_or_pattern.cov-map b/tests/coverage/match_or_pattern.cov-map index ae77eedfe72e..0bb126bc09b1 100644 --- a/tests/coverage/match_or_pattern.cov-map +++ b/tests/coverage/match_or_pattern.cov-map @@ -1,7 +1,7 @@ Function name: match_or_pattern::main -Raw bytes (145): 0x[01, 01, 08, 01, 05, 01, 09, 01, 0d, 01, 11, 01, 15, 01, 19, 01, 1d, 01, 21, 19, 01, 01, 01, 08, 0f, 05, 08, 10, 03, 06, 02, 03, 05, 00, 06, 01, 01, 0b, 00, 11, 06, 03, 1b, 00, 1d, 09, 01, 0e, 00, 10, 01, 02, 08, 00, 0f, 0d, 00, 10, 03, 06, 0a, 03, 05, 00, 06, 01, 01, 0b, 00, 11, 0e, 01, 1b, 00, 1d, 11, 01, 0e, 00, 10, 01, 02, 08, 00, 0f, 15, 00, 10, 03, 06, 12, 03, 05, 00, 06, 01, 01, 0b, 00, 11, 16, 01, 1b, 00, 1d, 19, 01, 0e, 00, 10, 01, 02, 08, 00, 0f, 1d, 00, 10, 03, 06, 1a, 03, 05, 00, 06, 01, 01, 0b, 00, 11, 1e, 01, 1b, 00, 1d, 21, 01, 0e, 00, 10, 01, 02, 01, 00, 02] +Raw bytes (190): 0x[01, 01, 08, 01, 05, 01, 09, 01, 0d, 01, 11, 01, 15, 01, 19, 01, 1d, 01, 21, 22, 01, 01, 01, 00, 0a, 01, 04, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 02, 09, 00, 0e, 01, 00, 10, 00, 12, 01, 00, 15, 00, 16, 01, 01, 09, 00, 0e, 01, 00, 10, 00, 12, 01, 00, 15, 00, 16, 01, 01, 08, 00, 0f, 05, 00, 10, 03, 06, 02, 03, 05, 00, 06, 01, 01, 0b, 00, 11, 06, 03, 1b, 00, 1d, 09, 01, 0e, 00, 10, 01, 02, 08, 00, 0f, 0d, 00, 10, 03, 06, 0a, 03, 05, 00, 06, 01, 01, 0b, 00, 11, 0e, 01, 1b, 00, 1d, 11, 01, 0e, 00, 10, 01, 02, 08, 00, 0f, 15, 00, 10, 03, 06, 12, 03, 05, 00, 06, 01, 01, 0b, 00, 11, 16, 01, 1b, 00, 1d, 19, 01, 0e, 00, 10, 01, 02, 08, 00, 0f, 1d, 00, 10, 03, 06, 1a, 03, 05, 00, 06, 01, 01, 0b, 00, 11, 1e, 01, 1b, 00, 1d, 21, 01, 0e, 00, 10, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/match_or_pattern.rs Number of expressions: 8 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) @@ -11,9 +11,18 @@ Number of expressions: 8 - expression 5 operands: lhs = Counter(0), rhs = Counter(6) - expression 6 operands: lhs = Counter(0), rhs = Counter(7) - expression 7 operands: lhs = Counter(0), rhs = Counter(8) -Number of file 0 mappings: 25 -- Code(Counter(0)) at (prev + 1, 1) to (start + 8, 15) -- Code(Counter(1)) at (prev + 8, 16) to (start + 3, 6) +Number of file 0 mappings: 34 +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 16) to (start + 0, 18) +- Code(Counter(0)) at (prev + 0, 21) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 16) to (start + 0, 18) +- Code(Counter(0)) at (prev + 0, 21) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 15) +- Code(Counter(1)) at (prev + 0, 16) to (start + 3, 6) - Code(Expression(0, Sub)) at (prev + 3, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 11) to (start + 0, 17) diff --git a/tests/coverage/match_or_pattern.coverage b/tests/coverage/match_or_pattern.coverage index a65c226e5672..50540bc5614a 100644 --- a/tests/coverage/match_or_pattern.coverage +++ b/tests/coverage/match_or_pattern.coverage @@ -1,9 +1,9 @@ LL| 1|fn main() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| let mut a: u8 = 0; LL| 1| let mut b: u8 = 0; LL| 1| if is_true { diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map index befe8866a592..ffee97cfbc50 100644 --- a/tests/coverage/mcdc/condition-limit.cov-map +++ b/tests/coverage/mcdc/condition-limit.cov-map @@ -1,7 +1,7 @@ Function name: condition_limit::accept_7_conditions -Raw bytes (147): 0x[01, 01, 08, 01, 05, 05, 09, 09, 0d, 0d, 11, 11, 15, 15, 19, 19, 1d, 01, 1d, 12, 01, 06, 01, 02, 09, 28, 08, 07, 02, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 07, 06, 00, 00, 0d, 00, 0e, 09, 00, 12, 00, 13, 30, 0d, 0a, 06, 05, 00, 00, 12, 00, 13, 0d, 00, 17, 00, 18, 30, 11, 0e, 05, 04, 00, 00, 17, 00, 18, 11, 00, 1c, 00, 1d, 30, 15, 12, 04, 03, 00, 00, 1c, 00, 1d, 15, 00, 21, 00, 22, 30, 19, 16, 03, 02, 00, 00, 21, 00, 22, 19, 00, 26, 00, 27, 30, 1d, 1a, 02, 00, 00, 00, 26, 00, 27, 1d, 00, 28, 02, 06, 1e, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (192): 0x[01, 01, 08, 01, 05, 05, 09, 09, 0d, 0d, 11, 11, 15, 15, 19, 19, 1d, 01, 1d, 1b, 01, 06, 01, 00, 2c, 01, 01, 0a, 00, 0b, 01, 00, 0d, 00, 0e, 01, 00, 10, 00, 11, 01, 00, 13, 00, 14, 01, 00, 16, 00, 17, 01, 00, 19, 00, 1a, 01, 00, 1c, 00, 1d, 01, 00, 21, 00, 29, 01, 01, 08, 00, 09, 28, 08, 07, 00, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 07, 06, 00, 00, 0d, 00, 0e, 09, 00, 12, 00, 13, 30, 0d, 0a, 06, 05, 00, 00, 12, 00, 13, 0d, 00, 17, 00, 18, 30, 11, 0e, 05, 04, 00, 00, 17, 00, 18, 11, 00, 1c, 00, 1d, 30, 15, 12, 04, 03, 00, 00, 1c, 00, 1d, 15, 00, 21, 00, 22, 30, 19, 16, 03, 02, 00, 00, 21, 00, 22, 19, 00, 26, 00, 27, 30, 1d, 1a, 02, 00, 00, 00, 26, 00, 27, 1d, 00, 28, 02, 06, 1e, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/condition-limit.rs Number of expressions: 8 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) @@ -11,9 +11,18 @@ Number of expressions: 8 - expression 5 operands: lhs = Counter(5), rhs = Counter(6) - expression 6 operands: lhs = Counter(6), rhs = Counter(7) - expression 7 operands: lhs = Counter(0), rhs = Counter(7) -Number of file 0 mappings: 18 -- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 9) -- MCDCDecision { bitmap_idx: 8, conditions_num: 7 } at (prev + 2, 8) to (start + 0, 39) +Number of file 0 mappings: 27 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 44) +- Code(Counter(0)) at (prev + 1, 10) to (start + 0, 11) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 16) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 20) +- Code(Counter(0)) at (prev + 0, 22) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 26) +- Code(Counter(0)) at (prev + 0, 28) to (start + 0, 29) +- Code(Counter(0)) at (prev + 0, 33) to (start + 0, 41) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 8, conditions_num: 7 } at (prev + 0, 8) to (start + 0, 39) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 7, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map index 1b038f48429e..dac1eb4c94bd 100644 --- a/tests/coverage/mcdc/if.cov-map +++ b/tests/coverage/mcdc/if.cov-map @@ -1,14 +1,15 @@ Function name: if::mcdc_check_a -Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 0e, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (67): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 09, 01, 0e, 01, 00, 22, 01, 01, 08, 00, 09, 28, 03, 02, 00, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 34) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -23,16 +24,17 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::mcdc_check_b -Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 16, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (67): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 09, 01, 16, 01, 00, 22, 01, 01, 08, 00, 09, 28, 03, 02, 00, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 22, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 34) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -47,16 +49,17 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::mcdc_check_both -Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 1e, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (67): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 09, 01, 1e, 01, 00, 25, 01, 01, 08, 00, 09, 28, 03, 02, 00, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 30, 1) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -71,16 +74,17 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::mcdc_check_neither -Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 06, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (67): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 09, 01, 06, 01, 00, 28, 01, 01, 08, 00, 09, 28, 03, 02, 00, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 40) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -95,9 +99,9 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::mcdc_check_not_tree_decision -Raw bytes (85): 0x[01, 01, 07, 01, 05, 01, 17, 05, 09, 05, 09, 17, 0d, 05, 09, 01, 0d, 0a, 01, 30, 01, 03, 0a, 28, 05, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 06, 03, 02, 00, 00, 0e, 00, 0f, 17, 00, 14, 00, 15, 30, 0d, 12, 02, 00, 00, 00, 14, 00, 15, 0d, 00, 16, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (90): 0x[01, 01, 07, 01, 05, 01, 17, 05, 09, 05, 09, 17, 0d, 05, 09, 01, 0d, 0b, 01, 30, 01, 00, 3b, 28, 05, 03, 03, 08, 00, 15, 01, 00, 09, 00, 0a, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 06, 03, 02, 00, 00, 0e, 00, 0f, 17, 00, 14, 00, 15, 30, 0d, 12, 02, 00, 00, 00, 14, 00, 15, 0d, 00, 16, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 7 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(5, Add) @@ -106,9 +110,10 @@ Number of expressions: 7 - expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3) - expression 5 operands: lhs = Counter(1), rhs = Counter(2) - expression 6 operands: lhs = Counter(0), rhs = Counter(3) -Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 48, 1) to (start + 3, 10) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 48, 1) to (start + 0, 59) - MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 3 } at (prev + 0, 9) to (start + 0, 10) true = c1 false = (c0 - c1) @@ -129,9 +134,9 @@ Number of file 0 mappings: 10 Highest counter ID seen: c3 Function name: if::mcdc_check_tree_decision -Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 09, 05, 09, 05, 1f, 09, 0d, 09, 0d, 01, 1f, 09, 0d, 0a, 01, 26, 01, 03, 09, 28, 04, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 09, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 0d, 0e, 03, 00, 00, 00, 13, 00, 14, 1f, 00, 16, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (92): 0x[01, 01, 08, 01, 05, 05, 09, 05, 09, 05, 1f, 09, 0d, 09, 0d, 01, 1f, 09, 0d, 0b, 01, 26, 01, 00, 37, 01, 03, 08, 00, 09, 28, 04, 03, 00, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 09, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 0d, 0e, 03, 00, 00, 00, 13, 00, 14, 1f, 00, 16, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/if.rs Number of expressions: 8 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) @@ -141,9 +146,10 @@ Number of expressions: 8 - expression 5 operands: lhs = Counter(2), rhs = Counter(3) - expression 6 operands: lhs = Counter(0), rhs = Expression(7, Add) - expression 7 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 38, 1) to (start + 3, 9) -- MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 38, 1) to (start + 0, 55) +- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 0, 8) to (start + 0, 21) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -164,46 +170,53 @@ Number of file 0 mappings: 10 Highest counter ID seen: c3 Function name: if::mcdc_nested_if -Raw bytes (120): 0x[01, 01, 0b, 01, 05, 01, 2b, 05, 09, 05, 09, 2b, 0d, 05, 09, 0d, 11, 2b, 11, 05, 09, 01, 2b, 05, 09, 0e, 01, 3a, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 26, 02, 00, 00, 00, 0d, 00, 0e, 2b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 0d, 12, 01, 02, 00, 00, 0c, 00, 0d, 0d, 00, 11, 00, 12, 30, 11, 1a, 02, 00, 00, 00, 11, 00, 12, 11, 00, 13, 02, 0a, 1e, 02, 09, 00, 0a, 26, 01, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (139): 0x[01, 01, 0d, 01, 05, 01, 33, 05, 09, 05, 09, 05, 09, 05, 09, 33, 0d, 05, 09, 0d, 11, 33, 11, 05, 09, 01, 33, 05, 09, 11, 01, 3a, 01, 00, 2d, 01, 01, 08, 00, 09, 28, 03, 02, 00, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 2e, 02, 00, 00, 00, 0d, 00, 0e, 33, 01, 09, 00, 0c, 33, 00, 0d, 00, 15, 33, 01, 0c, 00, 0d, 28, 06, 02, 00, 0c, 00, 12, 30, 0d, 1a, 01, 02, 00, 00, 0c, 00, 0d, 0d, 00, 11, 00, 12, 30, 11, 22, 02, 00, 00, 00, 11, 00, 12, 11, 00, 13, 02, 0a, 26, 02, 09, 00, 0a, 2e, 01, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 11 +- file 0 => $DIR/if.rs +Number of expressions: 13 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Counter(0), rhs = Expression(10, Add) +- expression 1 operands: lhs = Counter(0), rhs = Expression(12, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) - expression 3 operands: lhs = Counter(1), rhs = Counter(2) -- expression 4 operands: lhs = Expression(10, Add), rhs = Counter(3) +- expression 4 operands: lhs = Counter(1), rhs = Counter(2) - expression 5 operands: lhs = Counter(1), rhs = Counter(2) -- expression 6 operands: lhs = Counter(3), rhs = Counter(4) -- expression 7 operands: lhs = Expression(10, Add), rhs = Counter(4) -- expression 8 operands: lhs = Counter(1), rhs = Counter(2) -- expression 9 operands: lhs = Counter(0), rhs = Expression(10, Add) +- expression 6 operands: lhs = Expression(12, Add), rhs = Counter(3) +- expression 7 operands: lhs = Counter(1), rhs = Counter(2) +- expression 8 operands: lhs = Counter(3), rhs = Counter(4) +- expression 9 operands: lhs = Expression(12, Add), rhs = Counter(4) - expression 10 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 58, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +- expression 11 operands: lhs = Counter(0), rhs = Expression(12, Add) +- expression 12 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 17 +- Code(Counter(0)) at (prev + 58, 1) to (start + 0, 45) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) - Code(Expression(0, Sub)) at (prev + 0, 13) to (start + 0, 14) = (c0 - c1) -- MCDCBranch { true: Counter(2), false: Expression(9, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) +- MCDCBranch { true: Counter(2), false: Expression(11, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) true = c2 false = (c0 - (c1 + c2)) -- Code(Expression(10, Add)) at (prev + 1, 9) to (start + 1, 13) +- Code(Expression(12, Add)) at (prev + 1, 9) to (start + 0, 12) = (c1 + c2) -- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 1, 12) to (start + 0, 18) -- MCDCBranch { true: Counter(3), false: Expression(4, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 12) to (start + 0, 13) +- Code(Expression(12, Add)) at (prev + 0, 13) to (start + 0, 21) + = (c1 + c2) +- Code(Expression(12, Add)) at (prev + 1, 12) to (start + 0, 13) + = (c1 + c2) +- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 0, 12) to (start + 0, 18) +- MCDCBranch { true: Counter(3), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 12) to (start + 0, 13) true = c3 false = ((c1 + c2) - c3) - Code(Counter(3)) at (prev + 0, 17) to (start + 0, 18) -- MCDCBranch { true: Counter(4), false: Expression(6, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 17) to (start + 0, 18) +- MCDCBranch { true: Counter(4), false: Expression(8, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 17) to (start + 0, 18) true = c4 false = (c3 - c4) - Code(Counter(4)) at (prev + 0, 19) to (start + 2, 10) -- Code(Expression(7, Sub)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(9, Sub)) at (prev + 2, 9) to (start + 0, 10) = ((c1 + c2) - c4) -- Code(Expression(9, Sub)) at (prev + 1, 12) to (start + 2, 6) +- Code(Expression(11, Sub)) at (prev + 1, 12) to (start + 2, 6) = (c0 - (c1 + c2)) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c4 diff --git a/tests/coverage/mcdc/if.coverage b/tests/coverage/mcdc/if.coverage index 51917d060454..fda5525c472c 100644 --- a/tests/coverage/mcdc/if.coverage +++ b/tests/coverage/mcdc/if.coverage @@ -123,8 +123,8 @@ LL| 3|} LL| | LL| 4|fn mcdc_check_tree_decision(a: bool, b: bool, c: bool) { - LL| 4| // This expression is intentionally written in a way - LL| 4| // where 100% branch coverage indicates 100% mcdc coverage. + LL| | // This expression is intentionally written in a way + LL| | // where 100% branch coverage indicates 100% mcdc coverage. LL| 4| if a && (b || c) { ^3 ^2 ------------------ @@ -160,8 +160,8 @@ LL| 4|} LL| | LL| 4|fn mcdc_check_not_tree_decision(a: bool, b: bool, c: bool) { - LL| 4| // Contradict to `mcdc_check_tree_decision`, - LL| 4| // 100% branch coverage of this expression does not indicate 100% mcdc coverage. + LL| | // Contradict to `mcdc_check_tree_decision`, + LL| | // 100% branch coverage of this expression does not indicate 100% mcdc coverage. LL| 4| if (a || b) && c { ^1 ------------------ diff --git a/tests/coverage/mcdc/inlined_expressions.cov-map b/tests/coverage/mcdc/inlined_expressions.cov-map index 7d78e572a3b0..d05ef368ba4a 100644 --- a/tests/coverage/mcdc/inlined_expressions.cov-map +++ b/tests/coverage/mcdc/inlined_expressions.cov-map @@ -1,13 +1,14 @@ Function name: inlined_expressions::inlined_instance -Raw bytes (50): 0x[01, 01, 02, 01, 05, 05, 09, 06, 01, 07, 01, 01, 06, 28, 03, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 06, 02, 00, 00, 00, 0a, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (55): 0x[01, 01, 02, 01, 05, 05, 09, 07, 01, 07, 01, 00, 2e, 01, 01, 05, 00, 06, 28, 03, 02, 00, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 06, 02, 00, 00, 00, 0a, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/inlined_expressions.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 6) -- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 46) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 5) to (start + 0, 11) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 5) to (start + 0, 6) true = c1 false = (c0 - c1) diff --git a/tests/coverage/mcdc/nested_if.cov-map b/tests/coverage/mcdc/nested_if.cov-map index 83d0739aaf59..853cdf2c5760 100644 --- a/tests/coverage/mcdc/nested_if.cov-map +++ b/tests/coverage/mcdc/nested_if.cov-map @@ -1,7 +1,7 @@ Function name: nested_if::doubly_nested_if_in_condition -Raw bytes (170): 0x[01, 01, 0f, 01, 05, 05, 11, 05, 09, 05, 37, 09, 0d, 05, 09, 05, 1f, 09, 15, 15, 19, 05, 2b, 09, 19, 09, 0d, 05, 37, 09, 0d, 01, 11, 14, 01, 0e, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 06, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 06, 02, 00, 10, 00, 36, 30, 09, 16, 01, 00, 02, 00, 10, 00, 11, 30, 0d, 32, 02, 00, 00, 00, 15, 00, 36, 16, 00, 18, 00, 19, 28, 03, 02, 00, 18, 00, 1e, 30, 15, 1a, 01, 02, 00, 00, 18, 00, 19, 15, 00, 1d, 00, 1e, 30, 19, 22, 02, 00, 00, 00, 1d, 00, 1e, 19, 00, 21, 00, 25, 26, 00, 2f, 00, 34, 37, 00, 39, 00, 3e, 32, 00, 48, 00, 4c, 11, 00, 4f, 02, 06, 3a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (175): 0x[01, 01, 0f, 01, 05, 05, 11, 05, 09, 05, 37, 09, 0d, 05, 09, 05, 1f, 09, 15, 15, 19, 05, 2b, 09, 19, 09, 0d, 05, 37, 09, 0d, 01, 11, 15, 01, 0e, 01, 00, 45, 01, 01, 08, 00, 09, 28, 09, 02, 00, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 06, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 06, 02, 00, 10, 00, 36, 30, 09, 16, 01, 00, 02, 00, 10, 00, 11, 30, 0d, 32, 02, 00, 00, 00, 15, 00, 36, 16, 00, 18, 00, 19, 28, 03, 02, 00, 18, 00, 1e, 30, 15, 1a, 01, 02, 00, 00, 18, 00, 19, 15, 00, 1d, 00, 1e, 30, 19, 22, 02, 00, 00, 00, 1d, 00, 1e, 19, 00, 21, 00, 25, 26, 00, 2f, 00, 34, 37, 00, 39, 00, 3e, 32, 00, 48, 00, 4c, 11, 00, 4f, 02, 06, 3a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/nested_if.rs Number of expressions: 15 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(4) @@ -18,9 +18,10 @@ Number of expressions: 15 - expression 12 operands: lhs = Counter(1), rhs = Expression(13, Add) - expression 13 operands: lhs = Counter(2), rhs = Counter(3) - expression 14 operands: lhs = Counter(0), rhs = Counter(4) -Number of file 0 mappings: 20 -- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78) +Number of file 0 mappings: 21 +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 69) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 0, 8) to (start + 0, 78) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -59,9 +60,9 @@ Number of file 0 mappings: 20 Highest counter ID seen: c6 Function name: nested_if::nested_if_in_condition -Raw bytes (118): 0x[01, 01, 0a, 01, 05, 05, 11, 05, 09, 05, 09, 05, 23, 09, 0d, 09, 0d, 05, 23, 09, 0d, 01, 11, 0e, 01, 06, 01, 01, 09, 28, 06, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 06, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0e, 01, 00, 02, 00, 10, 00, 11, 0e, 00, 15, 00, 16, 30, 0d, 1e, 02, 00, 00, 00, 15, 00, 16, 23, 00, 19, 00, 1d, 1e, 00, 27, 00, 2c, 11, 00, 2f, 02, 06, 26, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (123): 0x[01, 01, 0a, 01, 05, 05, 11, 05, 09, 05, 09, 05, 23, 09, 0d, 09, 0d, 05, 23, 09, 0d, 01, 11, 0f, 01, 06, 01, 00, 35, 01, 01, 08, 00, 09, 28, 06, 02, 00, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 06, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0e, 01, 00, 02, 00, 10, 00, 11, 0e, 00, 15, 00, 16, 30, 0d, 1e, 02, 00, 00, 00, 15, 00, 16, 23, 00, 19, 00, 1d, 1e, 00, 27, 00, 2c, 11, 00, 2f, 02, 06, 26, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/nested_if.rs Number of expressions: 10 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(4) @@ -73,9 +74,10 @@ Number of expressions: 10 - expression 7 operands: lhs = Counter(1), rhs = Expression(8, Add) - expression 8 operands: lhs = Counter(2), rhs = Counter(3) - expression 9 operands: lhs = Counter(0), rhs = Counter(4) -Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46) +Number of file 0 mappings: 15 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 53) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 0, 8) to (start + 0, 46) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -103,9 +105,9 @@ Number of file 0 mappings: 14 Highest counter ID seen: c4 Function name: nested_if::nested_in_then_block_in_condition -Raw bytes (170): 0x[01, 01, 0f, 01, 05, 05, 19, 05, 09, 05, 09, 05, 37, 09, 0d, 09, 0d, 37, 11, 09, 0d, 11, 15, 37, 15, 09, 0d, 05, 37, 09, 0d, 01, 19, 14, 01, 21, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 19, 06, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0e, 01, 00, 02, 00, 10, 00, 11, 0e, 00, 15, 00, 16, 30, 0d, 32, 02, 00, 00, 00, 15, 00, 16, 37, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 11, 1e, 01, 02, 00, 00, 1c, 00, 1d, 11, 00, 21, 00, 22, 30, 15, 26, 02, 00, 00, 00, 21, 00, 22, 15, 00, 25, 00, 29, 2a, 00, 33, 00, 38, 32, 00, 44, 00, 49, 19, 00, 4c, 02, 06, 3a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (175): 0x[01, 01, 0f, 01, 05, 05, 19, 05, 09, 05, 09, 05, 37, 09, 0d, 09, 0d, 37, 11, 09, 0d, 11, 15, 37, 15, 09, 0d, 05, 37, 09, 0d, 01, 19, 15, 01, 21, 01, 00, 52, 01, 01, 08, 00, 09, 28, 09, 02, 00, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 19, 06, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0e, 01, 00, 02, 00, 10, 00, 11, 0e, 00, 15, 00, 16, 30, 0d, 32, 02, 00, 00, 00, 15, 00, 16, 37, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 11, 1e, 01, 02, 00, 00, 1c, 00, 1d, 11, 00, 21, 00, 22, 30, 15, 26, 02, 00, 00, 00, 21, 00, 22, 15, 00, 25, 00, 29, 2a, 00, 33, 00, 38, 32, 00, 44, 00, 49, 19, 00, 4c, 02, 06, 3a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/nested_if.rs Number of expressions: 15 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(6) @@ -122,9 +124,10 @@ Number of expressions: 15 - expression 12 operands: lhs = Counter(1), rhs = Expression(13, Add) - expression 13 operands: lhs = Counter(2), rhs = Counter(3) - expression 14 operands: lhs = Counter(0), rhs = Counter(6) -Number of file 0 mappings: 20 -- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75) +Number of file 0 mappings: 21 +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 82) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 0, 8) to (start + 0, 75) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -163,18 +166,19 @@ Number of file 0 mappings: 20 Highest counter ID seen: c6 Function name: nested_if::nested_single_condition_decision -Raw bytes (83): 0x[01, 01, 05, 01, 05, 05, 0d, 05, 09, 05, 09, 01, 0d, 0b, 01, 16, 01, 04, 09, 28, 03, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 06, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 09, 0e, 00, 10, 00, 11, 09, 00, 14, 00, 19, 0e, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (88): 0x[01, 01, 05, 01, 05, 05, 0d, 05, 09, 05, 09, 01, 0d, 0c, 01, 16, 01, 00, 36, 01, 04, 08, 00, 09, 28, 03, 02, 00, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 06, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 09, 0e, 00, 10, 00, 11, 09, 00, 14, 00, 19, 0e, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/nested_if.rs Number of expressions: 5 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(3) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) - expression 3 operands: lhs = Counter(1), rhs = Counter(2) - expression 4 operands: lhs = Counter(0), rhs = Counter(3) -Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 22, 1) to (start + 4, 9) -- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 54) +- Code(Counter(0)) at (prev + 4, 8) to (start + 0, 9) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 8) to (start + 0, 41) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) diff --git a/tests/coverage/mcdc/nested_if.coverage b/tests/coverage/mcdc/nested_if.coverage index c3ac30d22bf8..8b5179b34fee 100644 --- a/tests/coverage/mcdc/nested_if.coverage +++ b/tests/coverage/mcdc/nested_if.coverage @@ -122,9 +122,9 @@ LL| 4|} LL| | LL| 3|fn nested_single_condition_decision(a: bool, b: bool) { - LL| 3| // Decision with only 1 decision should not be instrumented by MCDC because - LL| 3| // branch-coverage is equivalent to MCDC coverage in this case, and we don't - LL| 3| // want to waste bitmap space for this. + LL| | // Decision with only 1 decision should not be instrumented by MCDC because + LL| | // branch-coverage is equivalent to MCDC coverage in this case, and we don't + LL| | // want to waste bitmap space for this. LL| 3| if a && if b { false } else { true } { ^2 ^1 ^1 ------------------ diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map index 48a103b2c7d7..f06bc2ed8168 100644 --- a/tests/coverage/mcdc/non_control_flow.cov-map +++ b/tests/coverage/mcdc/non_control_flow.cov-map @@ -1,14 +1,14 @@ Function name: non_control_flow::assign_3 -Raw bytes (79): 0x[01, 01, 04, 01, 05, 01, 0b, 05, 09, 09, 0d, 0a, 01, 15, 01, 00, 28, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 04, 03, 00, 0d, 00, 18, 30, 05, 02, 01, 00, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 30, 09, 06, 02, 03, 00, 00, 12, 00, 13, 09, 00, 17, 00, 18, 30, 0d, 0e, 03, 00, 00, 00, 17, 00, 18, 01, 01, 05, 01, 02] +Raw bytes (89): 0x[01, 01, 04, 01, 05, 01, 0b, 05, 09, 09, 0d, 0c, 01, 15, 01, 00, 27, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 04, 03, 00, 0d, 00, 18, 30, 05, 02, 01, 00, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 30, 09, 06, 02, 03, 00, 00, 12, 00, 13, 09, 00, 17, 00, 18, 30, 0d, 0e, 03, 00, 00, 00, 17, 00, 18, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/non_control_flow.rs Number of expressions: 4 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) - expression 3 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 40) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 39) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) @@ -24,21 +24,23 @@ Number of file 0 mappings: 10 - MCDCBranch { true: Counter(3), false: Expression(3, Sub), condition_id: 3, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) true = c3 false = (c2 - c3) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 Function name: non_control_flow::assign_3_bis -Raw bytes (81): 0x[01, 01, 05, 01, 05, 05, 09, 01, 09, 01, 13, 09, 0d, 0a, 01, 1a, 01, 00, 2c, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 02, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 06, 03, 00, 02, 00, 12, 00, 13, 0a, 00, 17, 00, 18, 30, 0d, 0e, 02, 00, 00, 00, 17, 00, 18, 01, 01, 05, 01, 02] +Raw bytes (91): 0x[01, 01, 05, 01, 05, 05, 09, 01, 09, 01, 13, 09, 0d, 0c, 01, 1a, 01, 00, 2b, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 02, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 06, 03, 00, 02, 00, 12, 00, 13, 0a, 00, 17, 00, 18, 30, 0d, 0e, 02, 00, 00, 00, 17, 00, 18, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/non_control_flow.rs Number of expressions: 5 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) - expression 3 operands: lhs = Counter(0), rhs = Expression(4, Add) - expression 4 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 26, 1) to (start + 0, 44) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 26, 1) to (start + 0, 43) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) @@ -54,18 +56,20 @@ Number of file 0 mappings: 10 - MCDCBranch { true: Counter(3), false: Expression(3, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) true = c3 false = (c0 - (c2 + c3)) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 Function name: non_control_flow::assign_and -Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 0b, 01, 00, 21, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 02, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 06, 02, 00, 00, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (70): 0x[01, 01, 02, 01, 05, 05, 09, 0a, 01, 0b, 01, 00, 20, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 02, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 06, 02, 00, 00, 00, 12, 00, 13, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/non_control_flow.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 33) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 32) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) @@ -76,19 +80,21 @@ Number of file 0 mappings: 8 - MCDCBranch { true: Counter(2), false: Expression(1, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) true = c2 false = (c1 - c2) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c2 Function name: non_control_flow::assign_or -Raw bytes (62): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 08, 01, 10, 01, 00, 20, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 02, 01, 00, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 30, 09, 06, 02, 00, 00, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (72): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 0a, 01, 10, 01, 00, 1f, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 02, 01, 00, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 30, 09, 06, 02, 00, 00, 00, 12, 00, 13, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/non_control_flow.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 32) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 31) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) @@ -100,27 +106,32 @@ Number of file 0 mappings: 8 - MCDCBranch { true: Counter(2), false: Expression(1, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) true = c2 false = (c0 - (c1 + c2)) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c2 Function name: non_control_flow::foo -Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 24, 01, 00, 18, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/non_control_flow.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 36, 1) to (start + 0, 24) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: non_control_flow::func_call -Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 28, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 28, 03, 02, 00, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] +Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 28, 01, 00, 1f, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 28, 03, 02, 00, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/non_control_flow.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 40, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 40, 1) to (start + 0, 31) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) - Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 9) to (start + 0, 15) @@ -135,17 +146,17 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: non_control_flow::right_comb_tree -Raw bytes (111): 0x[01, 01, 05, 01, 05, 05, 09, 09, 0d, 0d, 11, 11, 15, 0e, 01, 1f, 01, 00, 41, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 02, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 09, 06, 02, 03, 00, 00, 13, 00, 14, 09, 00, 19, 00, 1a, 30, 0d, 0a, 03, 04, 00, 00, 19, 00, 1a, 0d, 00, 1f, 00, 20, 30, 11, 0e, 04, 05, 00, 00, 1f, 00, 20, 11, 00, 24, 00, 27, 30, 15, 12, 05, 00, 00, 00, 24, 00, 27, 01, 01, 05, 01, 02] +Raw bytes (121): 0x[01, 01, 05, 01, 05, 05, 09, 09, 0d, 0d, 11, 11, 15, 10, 01, 1f, 01, 00, 40, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 02, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 09, 06, 02, 03, 00, 00, 13, 00, 14, 09, 00, 19, 00, 1a, 30, 0d, 0a, 03, 04, 00, 00, 19, 00, 1a, 0d, 00, 1f, 00, 20, 30, 11, 0e, 04, 05, 00, 00, 1f, 00, 20, 11, 00, 24, 00, 27, 30, 15, 12, 05, 00, 00, 00, 24, 00, 27, 01, 01, 05, 00, 0e, 01, 00, 0f, 00, 10, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/non_control_flow.rs Number of expressions: 5 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(2), rhs = Counter(3) - expression 3 operands: lhs = Counter(3), rhs = Counter(4) - expression 4 operands: lhs = Counter(4), rhs = Counter(5) -Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 31, 1) to (start + 0, 65) +Number of file 0 mappings: 16 +- Code(Counter(0)) at (prev + 31, 1) to (start + 0, 64) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 6, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42) @@ -168,6 +179,8 @@ Number of file 0 mappings: 14 - MCDCBranch { true: Counter(5), false: Expression(4, Sub), condition_id: 5, true_next_id: 0, false_next_id: 0 } at (prev + 0, 36) to (start + 0, 39) true = c5 false = (c4 - c5) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c5 diff --git a/tests/coverage/nested_loops.cov-map b/tests/coverage/nested_loops.cov-map index e9e41bd53e78..649c65d8590b 100644 --- a/tests/coverage/nested_loops.cov-map +++ b/tests/coverage/nested_loops.cov-map @@ -1,40 +1,60 @@ Function name: nested_loops::main -Raw bytes (97): 0x[01, 01, 0e, 07, 2f, 05, 11, 01, 0d, 2f, 05, 01, 0d, 27, 05, 01, 09, 33, 27, 05, 15, 01, 09, 2f, 33, 01, 0d, 05, 15, 05, 01, 0d, 01, 01, 01, 02, 1b, 05, 04, 13, 00, 20, 09, 01, 0d, 01, 18, 0d, 02, 12, 00, 17, 11, 01, 10, 00, 16, 02, 01, 11, 00, 16, 0e, 01, 0e, 03, 16, 15, 04, 11, 01, 1b, 16, 02, 15, 00, 21, 1e, 01, 18, 02, 12, 2a, 03, 0d, 00, 0e, 36, 02, 09, 00, 17, 01, 02, 01, 00, 02] +Raw bytes (164): 0x[01, 01, 14, 07, 47, 05, 11, 01, 0d, 47, 05, 01, 0d, 47, 05, 01, 0d, 47, 05, 01, 0d, 47, 05, 01, 0d, 3f, 05, 01, 09, 4b, 3f, 05, 15, 01, 09, 47, 4b, 01, 0d, 05, 15, 05, 01, 18, 01, 01, 01, 00, 0a, 01, 01, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1b, 05, 02, 13, 00, 20, 09, 01, 0d, 00, 12, 09, 00, 15, 00, 18, 09, 01, 0d, 00, 12, 09, 00, 15, 00, 18, 0d, 01, 12, 00, 17, 11, 01, 10, 00, 16, 02, 01, 11, 00, 16, 26, 01, 0d, 00, 0e, 26, 01, 0d, 00, 13, 26, 01, 0d, 00, 13, 26, 01, 10, 00, 16, 15, 01, 11, 00, 18, 15, 01, 14, 00, 1b, 2e, 01, 15, 00, 21, 36, 01, 18, 02, 12, 42, 03, 0d, 00, 0e, 4e, 02, 09, 00, 17, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 14 -- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(11, Add) +- file 0 => $DIR/nested_loops.rs +Number of expressions: 20 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(17, Add) - expression 1 operands: lhs = Counter(1), rhs = Counter(4) - expression 2 operands: lhs = Counter(0), rhs = Counter(3) -- expression 3 operands: lhs = Expression(11, Add), rhs = Counter(1) +- expression 3 operands: lhs = Expression(17, Add), rhs = Counter(1) - expression 4 operands: lhs = Counter(0), rhs = Counter(3) -- expression 5 operands: lhs = Expression(9, Add), rhs = Counter(1) -- expression 6 operands: lhs = Counter(0), rhs = Counter(2) -- expression 7 operands: lhs = Expression(12, Add), rhs = Expression(9, Add) -- expression 8 operands: lhs = Counter(1), rhs = Counter(5) -- expression 9 operands: lhs = Counter(0), rhs = Counter(2) -- expression 10 operands: lhs = Expression(11, Add), rhs = Expression(12, Add) -- expression 11 operands: lhs = Counter(0), rhs = Counter(3) -- expression 12 operands: lhs = Counter(1), rhs = Counter(5) -- expression 13 operands: lhs = Counter(1), rhs = Counter(0) -Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 1, 1) to (start + 2, 27) -- Code(Counter(1)) at (prev + 4, 19) to (start + 0, 32) -- Code(Counter(2)) at (prev + 1, 13) to (start + 1, 24) -- Code(Counter(3)) at (prev + 2, 18) to (start + 0, 23) +- expression 5 operands: lhs = Expression(17, Add), rhs = Counter(1) +- expression 6 operands: lhs = Counter(0), rhs = Counter(3) +- expression 7 operands: lhs = Expression(17, Add), rhs = Counter(1) +- expression 8 operands: lhs = Counter(0), rhs = Counter(3) +- expression 9 operands: lhs = Expression(17, Add), rhs = Counter(1) +- expression 10 operands: lhs = Counter(0), rhs = Counter(3) +- expression 11 operands: lhs = Expression(15, Add), rhs = Counter(1) +- expression 12 operands: lhs = Counter(0), rhs = Counter(2) +- expression 13 operands: lhs = Expression(18, Add), rhs = Expression(15, Add) +- expression 14 operands: lhs = Counter(1), rhs = Counter(5) +- expression 15 operands: lhs = Counter(0), rhs = Counter(2) +- expression 16 operands: lhs = Expression(17, Add), rhs = Expression(18, Add) +- expression 17 operands: lhs = Counter(0), rhs = Counter(3) +- expression 18 operands: lhs = Counter(1), rhs = Counter(5) +- expression 19 operands: lhs = Counter(1), rhs = Counter(0) +Number of file 0 mappings: 24 +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 27) +- Code(Counter(1)) at (prev + 2, 19) to (start + 0, 32) +- Code(Counter(2)) at (prev + 1, 13) to (start + 0, 18) +- Code(Counter(2)) at (prev + 0, 21) to (start + 0, 24) +- Code(Counter(2)) at (prev + 1, 13) to (start + 0, 18) +- Code(Counter(2)) at (prev + 0, 21) to (start + 0, 24) +- Code(Counter(3)) at (prev + 1, 18) to (start + 0, 23) - Code(Counter(4)) at (prev + 1, 16) to (start + 0, 22) - Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 22) = ((c1 + c4) - (c0 + c3)) -- Code(Expression(3, Sub)) at (prev + 1, 14) to (start + 3, 22) +- Code(Expression(9, Sub)) at (prev + 1, 13) to (start + 0, 14) = ((c0 + c3) - c1) -- Code(Counter(5)) at (prev + 4, 17) to (start + 1, 27) -- Code(Expression(5, Sub)) at (prev + 2, 21) to (start + 0, 33) +- Code(Expression(9, Sub)) at (prev + 1, 13) to (start + 0, 19) + = ((c0 + c3) - c1) +- Code(Expression(9, Sub)) at (prev + 1, 13) to (start + 0, 19) + = ((c0 + c3) - c1) +- Code(Expression(9, Sub)) at (prev + 1, 16) to (start + 0, 22) + = ((c0 + c3) - c1) +- Code(Counter(5)) at (prev + 1, 17) to (start + 0, 24) +- Code(Counter(5)) at (prev + 1, 20) to (start + 0, 27) +- Code(Expression(11, Sub)) at (prev + 1, 21) to (start + 0, 33) = ((c0 + c2) - c1) -- Code(Expression(7, Sub)) at (prev + 1, 24) to (start + 2, 18) +- Code(Expression(13, Sub)) at (prev + 1, 24) to (start + 2, 18) = ((c1 + c5) - (c0 + c2)) -- Code(Expression(10, Sub)) at (prev + 3, 13) to (start + 0, 14) +- Code(Expression(16, Sub)) at (prev + 3, 13) to (start + 0, 14) = ((c0 + c3) - (c1 + c5)) -- Code(Expression(13, Sub)) at (prev + 2, 9) to (start + 0, 23) +- Code(Expression(19, Sub)) at (prev + 2, 9) to (start + 0, 23) = (c1 - c0) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c5 diff --git a/tests/coverage/no-core.cov-map b/tests/coverage/no-core.cov-map index 3a1ca4745c73..f2867008127b 100644 --- a/tests/coverage/no-core.cov-map +++ b/tests/coverage/no-core.cov-map @@ -1,9 +1,10 @@ Function name: no_core::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 01, 00, 0d] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0c, 01, 00, 0a, 01, 00, 0c, 00, 0d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no-core.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 13) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 12) to (start + 0, 13) Highest counter ID seen: c0 diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map index 244b0099544b..ca3c95fe84c4 100644 --- a/tests/coverage/no_cov_crate.cov-map +++ b/tests/coverage/no_cov_crate.cov-map @@ -1,68 +1,99 @@ Function name: no_cov_crate::add_coverage_1 -Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 01, 00, 14, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 22, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_cov_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 22, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 34) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: no_cov_crate::add_coverage_2 -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1a, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1a, 01, 00, 14, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 22, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_cov_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 26, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 34) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: no_cov_crate::add_coverage_not_called (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1f, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 1f, 01, 00, 1d, 00, 01, 05, 00, 0d, 00, 00, 0e, 00, 26, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_cov_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 31, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 31, 1) to (start + 0, 29) +- Code(Zero) at (prev + 1, 5) to (start + 0, 13) +- Code(Zero) at (prev + 0, 14) to (start + 0, 38) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: no_cov_crate::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 4f, 01, 0b, 02] +Raw bytes (74): 0x[01, 01, 00, 0e, 01, 4f, 01, 00, 0a, 01, 01, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 02, 05, 00, 1a, 01, 01, 05, 00, 1a, 01, 01, 05, 00, 13, 01, 01, 05, 00, 13, 01, 02, 05, 00, 22, 01, 00, 23, 00, 2a, 01, 01, 05, 00, 16, 01, 00, 17, 00, 1e, 01, 01, 05, 00, 23, 01, 00, 24, 00, 2b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_cov_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 79, 1) to (start + 11, 2) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 79, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 19) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 34) +- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 42) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 23) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 35) +- Code(Counter(0)) at (prev + 0, 36) to (start + 0, 43) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer -Raw bytes (14): 0x[01, 01, 00, 02, 01, 33, 05, 02, 22, 01, 0c, 05, 00, 06] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 33, 05, 00, 20, 01, 01, 09, 00, 11, 01, 00, 12, 00, 26, 01, 01, 09, 00, 1a, 01, 00, 1b, 00, 22, 01, 0a, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_cov_crate.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 51, 5) to (start + 2, 34) -- Code(Counter(0)) at (prev + 12, 5) to (start + 0, 6) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 51, 5) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 38) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 26) +- Code(Counter(0)) at (prev + 0, 27) to (start + 0, 34) +- Code(Counter(0)) at (prev + 10, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered -Raw bytes (14): 0x[01, 01, 00, 02, 01, 41, 05, 02, 16, 01, 0b, 05, 00, 06] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 41, 05, 00, 2d, 01, 01, 09, 00, 11, 01, 00, 12, 00, 26, 01, 01, 09, 00, 0e, 01, 00, 0f, 00, 16, 01, 09, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_cov_crate.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 65, 5) to (start + 2, 22) -- Code(Counter(0)) at (prev + 11, 5) to (start + 0, 6) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 65, 5) to (start + 0, 45) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 38) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 22) +- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered::inner -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 45, 09, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 45, 09, 00, 20, 01, 01, 10, 00, 17, 05, 00, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_cov_crate.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 69, 9) to (start + 1, 23) -- Code(Counter(1)) at (prev + 1, 24) to (start + 2, 14) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 69, 9) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 16) to (start + 0, 23) +- Code(Counter(1)) at (prev + 0, 24) to (start + 2, 14) - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) diff --git a/tests/coverage/no_cov_crate.coverage b/tests/coverage/no_cov_crate.coverage index 2a8961e6c93a..c6453e60a1a4 100644 --- a/tests/coverage/no_cov_crate.coverage +++ b/tests/coverage/no_cov_crate.coverage @@ -78,12 +78,12 @@ LL| | LL| 1|fn main() { LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| do_not_add_coverage_1(); LL| 1| do_not_add_coverage_2(); LL| 1| add_coverage_1(); LL| 1| add_coverage_2(); - LL| 1| + LL| | LL| 1| nested_fns::outer_not_covered(is_true); LL| 1| nested_fns::outer(is_true); LL| 1| nested_fns::outer_both_covered(is_true); diff --git a/tests/coverage/no_spans.cov-map b/tests/coverage/no_spans.cov-map index 7f43b68fa904..821976b0fab0 100644 --- a/tests/coverage/no_spans.cov-map +++ b/tests/coverage/no_spans.cov-map @@ -1,18 +1,20 @@ Function name: no_spans::affected_function -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1a, 1c, 00, 1d] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 1c, 00, 1d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_spans.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 26, 28) to (start + 0, 29) +- Code(Counter(0)) at (prev + 21, 28) to (start + 0, 29) Highest counter ID seen: c0 -Function name: no_spans::affected_function::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 0c, 00, 0e] +Function name: no_spans::main +Raw bytes (19): 0x[01, 01, 00, 03, 01, 0a, 01, 00, 0a, 01, 01, 05, 00, 1a, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_spans.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 27, 12) to (start + 0, 14) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/no_spans.coverage b/tests/coverage/no_spans.coverage index 19e8c2fe5b6b..cf0e47677e9a 100644 --- a/tests/coverage/no_spans.coverage +++ b/tests/coverage/no_spans.coverage @@ -1,20 +1,15 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 LL| | - LL| |// If the span extractor can't find any relevant spans for a function, the - LL| |// refinement loop will terminate with nothing in its `prev` slot. If the - LL| |// subsequent code tries to unwrap `prev`, it will panic. + LL| |// Test that coverage instrumentation can gracefully handle functions that end + LL| |// up having no relevant spans, without crashing the compiler or causing + LL| |// `llvm-cov` to fail. LL| |// - LL| |// This scenario became more likely after #118525 started discarding spans that - LL| |// can't be un-expanded back to within the function body. - LL| |// - LL| |// Regression test for "invalid attempt to unwrap a None some_prev", as seen - LL| |// in issues such as #118643 and #118662. + LL| |// This was originally a regression test for issues such as #118643 and #118662. LL| | - LL| |#[coverage(off)] - LL| |fn main() { - LL| | affected_function()(); - LL| |} + LL| 1|fn main() { + LL| 1| affected_function()(); + LL| 1|} LL| | LL| |macro_rules! macro_that_defines_a_function { LL| | (fn $name:ident () $body:tt) => { @@ -24,7 +19,7 @@ LL| | LL| |macro_that_defines_a_function! { LL| 1| fn affected_function() { - LL| 1| || () + LL| | || () LL| | } LL| |} diff --git a/tests/coverage/no_spans.rs b/tests/coverage/no_spans.rs index e5312406f8a1..979b40719277 100644 --- a/tests/coverage/no_spans.rs +++ b/tests/coverage/no_spans.rs @@ -1,17 +1,12 @@ #![feature(coverage_attribute)] //@ edition: 2021 -// If the span extractor can't find any relevant spans for a function, the -// refinement loop will terminate with nothing in its `prev` slot. If the -// subsequent code tries to unwrap `prev`, it will panic. +// Test that coverage instrumentation can gracefully handle functions that end +// up having no relevant spans, without crashing the compiler or causing +// `llvm-cov` to fail. // -// This scenario became more likely after #118525 started discarding spans that -// can't be un-expanded back to within the function body. -// -// Regression test for "invalid attempt to unwrap a None some_prev", as seen -// in issues such as #118643 and #118662. +// This was originally a regression test for issues such as #118643 and #118662. -#[coverage(off)] fn main() { affected_function()(); } diff --git a/tests/coverage/no_spans_if_not.cov-map b/tests/coverage/no_spans_if_not.cov-map index 6c389a243172..c8aa5c7527d2 100644 --- a/tests/coverage/no_spans_if_not.cov-map +++ b/tests/coverage/no_spans_if_not.cov-map @@ -1,20 +1,23 @@ Function name: no_spans_if_not::affected_function -Raw bytes (19): 0x[01, 01, 00, 03, 01, 16, 1c, 01, 12, 01, 02, 0d, 00, 0f, 00, 02, 0d, 00, 0f] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 1c, 00, 1d, 01, 01, 0c, 00, 12, 01, 01, 0d, 00, 0f, 00, 02, 0d, 00, 0f] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_spans_if_not.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 18) -- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 15) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 22, 28) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 15) - Code(Zero) at (prev + 2, 13) to (start + 0, 15) Highest counter ID seen: c0 Function name: no_spans_if_not::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 0b, 01, 00, 0a, 01, 01, 05, 00, 16, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/no_spans_if_not.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 1) to (start + 2, 2) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/overflow.cov-map b/tests/coverage/overflow.cov-map index 1178d65de102..18b0503b9e7c 100644 --- a/tests/coverage/overflow.cov-map +++ b/tests/coverage/overflow.cov-map @@ -1,7 +1,7 @@ Function name: overflow::main -Raw bytes (61): 0x[01, 01, 06, 05, 01, 05, 17, 01, 09, 05, 13, 17, 0d, 01, 09, 09, 01, 10, 01, 01, 1b, 05, 02, 0b, 00, 18, 02, 01, 0c, 00, 1a, 09, 00, 1b, 03, 0a, 06, 03, 13, 00, 20, 0d, 00, 21, 03, 0a, 0e, 03, 09, 00, 0a, 02, 01, 09, 00, 17, 01, 02, 05, 01, 02] +Raw bytes (96): 0x[01, 01, 06, 05, 01, 05, 17, 01, 09, 05, 13, 17, 0d, 01, 09, 10, 01, 10, 01, 00, 1c, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1b, 05, 01, 0b, 00, 18, 02, 01, 0c, 00, 1a, 09, 00, 1b, 03, 0a, 09, 01, 11, 00, 17, 09, 00, 1a, 00, 28, 06, 02, 13, 00, 20, 0d, 00, 21, 03, 0a, 0d, 01, 11, 00, 17, 0d, 00, 1a, 00, 28, 0e, 02, 09, 00, 0a, 02, 01, 09, 00, 17, 01, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/overflow.rs Number of expressions: 6 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) - expression 1 operands: lhs = Counter(1), rhs = Expression(5, Add) @@ -9,33 +9,50 @@ Number of expressions: 6 - expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) - expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3) - expression 5 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 27) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 24) +Number of file 0 mappings: 16 +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 27) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 24) - Code(Expression(0, Sub)) at (prev + 1, 12) to (start + 0, 26) = (c1 - c0) - Code(Counter(2)) at (prev + 0, 27) to (start + 3, 10) -- Code(Expression(1, Sub)) at (prev + 3, 19) to (start + 0, 32) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 23) +- Code(Counter(2)) at (prev + 0, 26) to (start + 0, 40) +- Code(Expression(1, Sub)) at (prev + 2, 19) to (start + 0, 32) = (c1 - (c0 + c2)) - Code(Counter(3)) at (prev + 0, 33) to (start + 3, 10) -- Code(Expression(3, Sub)) at (prev + 3, 9) to (start + 0, 10) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 23) +- Code(Counter(3)) at (prev + 0, 26) to (start + 0, 40) +- Code(Expression(3, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c1 - ((c0 + c2) + c3)) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 23) = (c1 - c0) -- Code(Counter(0)) at (prev + 2, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 Function name: overflow::might_overflow -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 05, 00, 06, 01, 01, 09, 05, 02] +Raw bytes (76): 0x[01, 01, 01, 01, 05, 0e, 01, 05, 01, 00, 26, 01, 01, 08, 00, 12, 05, 00, 13, 02, 06, 02, 02, 05, 00, 06, 01, 01, 09, 00, 0f, 01, 00, 12, 00, 1e, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 26, 01, 01, 09, 00, 0f, 01, 00, 12, 00, 21, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 2f, 01, 01, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/overflow.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 18) -- Code(Counter(1)) at (prev + 1, 19) to (start + 2, 6) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 38) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 18) +- Code(Counter(1)) at (prev + 0, 19) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 9) to (start + 5, 2) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 38) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 33) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 47) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map index 18b13919fe5e..ff656d3d8d58 100644 --- a/tests/coverage/panic_unwind.cov-map +++ b/tests/coverage/panic_unwind.cov-map @@ -1,7 +1,7 @@ Function name: panic_unwind::main -Raw bytes (61): 0x[01, 01, 06, 05, 01, 05, 17, 01, 09, 05, 13, 17, 0d, 01, 09, 09, 01, 0d, 01, 01, 1b, 05, 02, 0b, 00, 18, 02, 01, 0c, 00, 1a, 09, 00, 1b, 02, 0a, 06, 02, 13, 00, 20, 0d, 00, 21, 02, 0a, 0e, 02, 09, 00, 0a, 02, 01, 09, 00, 17, 01, 02, 05, 01, 02] +Raw bytes (76): 0x[01, 01, 06, 05, 01, 05, 17, 01, 09, 05, 13, 17, 0d, 01, 09, 0c, 01, 0d, 01, 00, 1c, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1b, 05, 01, 0b, 00, 18, 02, 01, 0c, 00, 1a, 09, 00, 1b, 02, 0a, 06, 02, 13, 00, 20, 0d, 00, 21, 02, 0a, 0e, 02, 09, 00, 0a, 02, 01, 09, 00, 17, 01, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/panic_unwind.rs Number of expressions: 6 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) - expression 1 operands: lhs = Counter(1), rhs = Expression(5, Add) @@ -9,9 +9,11 @@ Number of expressions: 6 - expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) - expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3) - expression 5 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 13, 1) to (start + 1, 27) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 24) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 27) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 24) - Code(Expression(0, Sub)) at (prev + 1, 12) to (start + 0, 26) = (c1 - c0) - Code(Counter(2)) at (prev + 0, 27) to (start + 2, 10) @@ -22,19 +24,25 @@ Number of file 0 mappings: 9 = (c1 - ((c0 + c2) + c3)) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 23) = (c1 - c0) -- Code(Counter(0)) at (prev + 2, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 Function name: panic_unwind::might_panic -Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02] +Raw bytes (41): 0x[01, 01, 01, 01, 05, 07, 01, 04, 01, 00, 23, 01, 01, 08, 00, 14, 05, 01, 09, 00, 11, 05, 00, 12, 00, 20, 05, 01, 09, 00, 0f, 02, 01, 0c, 02, 06, 02, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/panic_unwind.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) -- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15) -- Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 35) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 20) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 32) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 15) +- Code(Expression(0, Sub)) at (prev + 1, 12) to (start + 2, 6) + = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 3, 1) to (start + 0, 2) = (c0 - c1) Highest counter ID seen: c1 diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 21c8714ac99b..0a81be749128 100644 --- a/tests/coverage/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map @@ -1,18 +1,29 @@ Function name: ::new -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 05, 02, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 0c, 05, 00, 41, 01, 01, 09, 00, 25, 01, 00, 10, 00, 15, 01, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/partial_eq.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 12, 5) to (start + 2, 6) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 12, 5) to (start + 0, 65) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 37) +- Code(Counter(0)) at (prev + 0, 16) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: partial_eq::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 0a, 02] +Raw bytes (49): 0x[01, 01, 00, 09, 01, 11, 01, 00, 0a, 01, 01, 09, 00, 16, 01, 00, 19, 00, 25, 01, 01, 09, 00, 16, 01, 00, 19, 00, 25, 01, 02, 05, 00, 0d, 01, 01, 09, 00, 1b, 01, 03, 09, 00, 26, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/partial_eq.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 1) to (start + 10, 2) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 37) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 27) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 38) +- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage index dc5b82b3c5f1..0662ce2c3000 100644 --- a/tests/coverage/partial_eq.coverage +++ b/tests/coverage/partial_eq.coverage @@ -17,13 +17,13 @@ LL| 1|fn main() { LL| 1| let version_3_2_1 = Version::new(3, 2, 1); LL| 1| let version_3_3_0 = Version::new(3, 3, 0); - LL| 1| + LL| | LL| 1| println!( LL| 1| "{:?} < {:?} = {}", - LL| 1| version_3_2_1, - LL| 1| version_3_3_0, + LL| | version_3_2_1, + LL| | version_3_3_0, LL| 1| version_3_2_1 < version_3_3_0, // - LL| 1| ); + LL| | ); LL| 1|} LL| | LL| |/* diff --git a/tests/coverage/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map index 8e428b267d56..5447ffdb6e7c 100644 --- a/tests/coverage/simple_loop.cov-map +++ b/tests/coverage/simple_loop.cov-map @@ -1,19 +1,27 @@ Function name: simple_loop::main -Raw bytes (43): 0x[01, 01, 02, 01, 05, 09, 01, 07, 01, 04, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 05, 00, 06, 09, 05, 0d, 02, 0e, 01, 04, 0d, 00, 12, 06, 02, 0a, 03, 0a, 01, 06, 01, 00, 02] +Raw bytes (75): 0x[01, 01, 03, 01, 05, 09, 01, 09, 01, 0d, 01, 04, 01, 00, 0a, 01, 04, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 02, 09, 00, 16, 01, 00, 19, 00, 1a, 01, 03, 09, 00, 10, 05, 01, 05, 05, 06, 02, 05, 05, 00, 06, 09, 05, 0d, 02, 0e, 01, 04, 0d, 00, 12, 0a, 02, 09, 00, 0a, 0a, 01, 09, 02, 0a, 01, 05, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 2 +- file 0 => $DIR/simple_loop.rs +Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(2), rhs = Counter(0) -Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 4, 1) to (start + 9, 16) -- Code(Counter(1)) at (prev + 10, 5) to (start + 5, 6) +- expression 2 operands: lhs = Counter(2), rhs = Counter(0) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 26) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 16) +- Code(Counter(1)) at (prev + 1, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 5, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(2)) at (prev + 5, 13) to (start + 2, 14) - Code(Counter(0)) at (prev + 4, 13) to (start + 0, 18) -- Code(Expression(1, Sub)) at (prev + 2, 10) to (start + 3, 10) +- Code(Expression(2, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c2 - c0) -- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 2) +- Code(Expression(2, Sub)) at (prev + 1, 9) to (start + 2, 10) + = (c2 - c0) +- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 2) Highest counter ID seen: c2 diff --git a/tests/coverage/simple_loop.coverage b/tests/coverage/simple_loop.coverage index 237e509f42e1..a75263f633e5 100644 --- a/tests/coverage/simple_loop.coverage +++ b/tests/coverage/simple_loop.coverage @@ -2,14 +2,14 @@ LL| | LL| |#[rustfmt::skip] LL| 1|fn main() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| let mut countdown = 0; - LL| 1| - LL| 1| if + LL| | + LL| | if LL| 1| is_true LL| 1| { LL| 1| countdown diff --git a/tests/coverage/simple_match.cov-map b/tests/coverage/simple_match.cov-map index 15f114daa7fb..cbd6c7ca52fd 100644 --- a/tests/coverage/simple_match.cov-map +++ b/tests/coverage/simple_match.cov-map @@ -1,16 +1,21 @@ Function name: simple_match::main -Raw bytes (64): 0x[01, 01, 05, 01, 05, 09, 01, 09, 01, 09, 13, 01, 0d, 0a, 01, 04, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 05, 00, 06, 09, 05, 09, 00, 0d, 0a, 05, 0d, 00, 16, 0d, 02, 0d, 00, 0e, 0a, 02, 11, 02, 12, 0d, 04, 0d, 07, 0e, 0e, 0a, 0d, 00, 0f, 01, 03, 01, 00, 02] +Raw bytes (99): 0x[01, 01, 05, 01, 05, 09, 01, 09, 01, 09, 13, 01, 0d, 11, 01, 04, 01, 00, 0a, 01, 04, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 02, 09, 00, 16, 01, 00, 19, 00, 1a, 01, 01, 08, 00, 0f, 05, 00, 10, 02, 06, 02, 02, 05, 00, 06, 09, 05, 09, 00, 0d, 0a, 05, 0d, 00, 16, 0d, 02, 0d, 00, 0e, 0a, 02, 11, 02, 12, 0d, 04, 0d, 07, 0e, 0d, 01, 11, 00, 1e, 0d, 02, 15, 00, 16, 0e, 07, 0d, 00, 0f, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/simple_match.rs Number of expressions: 5 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(2), rhs = Counter(0) - expression 2 operands: lhs = Counter(2), rhs = Counter(0) - expression 3 operands: lhs = Counter(2), rhs = Expression(4, Add) - expression 4 operands: lhs = Counter(0), rhs = Counter(3) -Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15) -- Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) +Number of file 0 mappings: 17 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 15) +- Code(Counter(1)) at (prev + 0, 16) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(2)) at (prev + 5, 9) to (start + 0, 13) @@ -20,7 +25,9 @@ Number of file 0 mappings: 10 - Code(Expression(2, Sub)) at (prev + 2, 17) to (start + 2, 18) = (c2 - c0) - Code(Counter(3)) at (prev + 4, 13) to (start + 7, 14) -- Code(Expression(3, Sub)) at (prev + 10, 13) to (start + 0, 15) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 30) +- Code(Counter(3)) at (prev + 2, 21) to (start + 0, 22) +- Code(Expression(3, Sub)) at (prev + 7, 13) to (start + 0, 15) = (c2 - (c0 + c3)) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c3 diff --git a/tests/coverage/simple_match.coverage b/tests/coverage/simple_match.coverage index e1d5e48a2bf1..0ed7e8dc7887 100644 --- a/tests/coverage/simple_match.coverage +++ b/tests/coverage/simple_match.coverage @@ -2,11 +2,11 @@ LL| | LL| |#[rustfmt::skip] LL| 1|fn main() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| + LL| | LL| 1| let mut countdown = 1; LL| 1| if is_true { LL| 1| countdown = 0; diff --git a/tests/coverage/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map index 898d68171c50..70cf7cff4b67 100644 --- a/tests/coverage/sort_groups.cov-map +++ b/tests/coverage/sort_groups.cov-map @@ -1,79 +1,98 @@ Function name: sort_groups::generic_fn::<&str> -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 11, 01, 00, 1d, 01, 01, 08, 00, 0c, 05, 00, 0d, 02, 06, 05, 01, 09, 00, 11, 02, 01, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/sort_groups.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) -- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 13) to (start + 2, 6) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: sort_groups::generic_fn::<()> -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 11, 01, 00, 1d, 01, 01, 08, 00, 0c, 05, 00, 0d, 02, 06, 05, 01, 09, 00, 11, 02, 01, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/sort_groups.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) -- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 13) to (start + 2, 6) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: sort_groups::generic_fn:: -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 11, 01, 00, 1d, 01, 01, 08, 00, 0c, 05, 00, 0d, 02, 06, 05, 01, 09, 00, 11, 02, 01, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/sort_groups.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) -- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 13) to (start + 2, 6) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: sort_groups::generic_fn:: -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 11, 01, 00, 1d, 01, 01, 08, 00, 0c, 05, 00, 0d, 02, 06, 05, 01, 09, 00, 11, 02, 01, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/sort_groups.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) -- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 13) to (start + 2, 6) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: sort_groups::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 1c, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02] +Raw bytes (76): 0x[01, 01, 01, 01, 05, 0e, 01, 06, 01, 00, 0a, 01, 01, 09, 00, 0d, 01, 00, 10, 00, 2a, 01, 01, 05, 00, 15, 01, 00, 16, 00, 1a, 01, 01, 05, 00, 1f, 01, 00, 20, 00, 25, 01, 01, 08, 00, 1c, 05, 00, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 00, 16, 01, 00, 17, 00, 1b, 01, 01, 05, 00, 0d, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/sort_groups.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 28) -- Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 16) to (start + 0, 42) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 21) +- Code(Counter(0)) at (prev + 0, 22) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 31) +- Code(Counter(0)) at (prev + 0, 32) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 28) +- Code(Counter(1)) at (prev + 0, 36) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 5) to (start + 2, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 23) to (start + 0, 27) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: sort_groups::other_fn -Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 11] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 17, 01, 00, 0e, 01, 00, 10, 00, 11] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/sort_groups.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 17) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 16) to (start + 0, 17) Highest counter ID seen: c0 diff --git a/tests/coverage/test_harness.cov-map b/tests/coverage/test_harness.cov-map index b513b3d05494..691332a1c420 100644 --- a/tests/coverage/test_harness.cov-map +++ b/tests/coverage/test_harness.cov-map @@ -1,18 +1,20 @@ Function name: test_harness::my_test -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 00, 10] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0a, 01, 00, 0d, 01, 00, 0f, 00, 10] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/test_harness.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 16) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) Highest counter ID seen: c0 Function name: test_harness::unused (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 07, 01, 00, 0f] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 07, 01, 00, 0c, 00, 00, 0e, 00, 0f] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/test_harness.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 7, 1) to (start + 0, 15) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 7, 1) to (start + 0, 12) +- Code(Zero) at (prev + 0, 14) to (start + 0, 15) Highest counter ID seen: (none) diff --git a/tests/coverage/tight_inf_loop.cov-map b/tests/coverage/tight_inf_loop.cov-map index 77a8ffb83581..c6bee3bd7ad9 100644 --- a/tests/coverage/tight_inf_loop.cov-map +++ b/tests/coverage/tight_inf_loop.cov-map @@ -1,11 +1,13 @@ Function name: tight_inf_loop::main -Raw bytes (19): 0x[01, 01, 00, 03, 01, 01, 01, 01, 0d, 00, 02, 09, 00, 10, 01, 01, 06, 01, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 01, 01, 00, 0a, 01, 01, 08, 00, 0d, 00, 01, 09, 00, 10, 01, 01, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/tight_inf_loop.rs Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 1, 1) to (start + 1, 13) -- Code(Zero) at (prev + 2, 9) to (start + 0, 16) -- Code(Counter(0)) at (prev + 1, 6) to (start + 1, 2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 13) +- Code(Zero) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/trivial.cov-map b/tests/coverage/trivial.cov-map index 05f64896d9ec..fff10df9aee5 100644 --- a/tests/coverage/trivial.cov-map +++ b/tests/coverage/trivial.cov-map @@ -1,9 +1,10 @@ Function name: trivial::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 0d] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 03, 01, 00, 0a, 01, 00, 0c, 00, 0d] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/trivial.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 12) to (start + 0, 13) Highest counter ID seen: c0 diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index e45f3de10815..e08f42961532 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -1,73 +1,83 @@ Function name: ::get_thing_2 -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 29, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 1a, 01, 02, 05, 00, 06] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 29, 05, 00, 44, 01, 01, 0c, 00, 18, 05, 01, 0d, 00, 14, 02, 02, 0d, 00, 1a, 01, 02, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/try_error_result.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 41, 5) to (start + 1, 24) -- Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 41, 5) to (start + 0, 68) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 24) +- Code(Counter(1)) at (prev + 1, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 26) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) Highest counter ID seen: c1 Function name: ::call -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 34, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 01, 02, 05, 00, 06] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 34, 05, 00, 3a, 01, 01, 0c, 00, 18, 05, 01, 0d, 00, 14, 02, 02, 0d, 00, 13, 01, 02, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/try_error_result.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 52, 5) to (start + 1, 24) -- Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 52, 5) to (start + 0, 58) +- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 24) +- Code(Counter(1)) at (prev + 1, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) Highest counter ID seen: c1 Function name: try_error_result::call -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 05, 01, 00, 2e, 01, 01, 08, 00, 14, 05, 01, 09, 00, 10, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/try_error_result.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 20) -- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 46) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 20) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: try_error_result::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0a, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (46): 0x[01, 01, 01, 01, 05, 08, 01, 71, 01, 00, 1c, 01, 01, 05, 00, 0a, 01, 00, 0d, 00, 17, 01, 00, 18, 00, 2b, 01, 01, 05, 00, 0a, 05, 01, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/try_error_result.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 10) -- Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 113, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 23) +- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 43) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 10) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: try_error_result::test1 -Raw bytes (67): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0b, 01, 0d, 01, 02, 17, 05, 07, 09, 00, 0e, 09, 02, 09, 04, 1a, 02, 06, 0d, 00, 11, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (82): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0e, 01, 0d, 01, 00, 1d, 01, 01, 09, 01, 12, 01, 01, 15, 00, 17, 05, 05, 09, 00, 0e, 09, 02, 09, 01, 11, 09, 04, 0d, 00, 1a, 02, 02, 0d, 00, 11, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/try_error_result.rs Number of expressions: 4 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) - expression 2 operands: lhs = Counter(1), rhs = Counter(0) - expression 3 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 13, 1) to (start + 2, 23) -- Code(Counter(1)) at (prev + 7, 9) to (start + 0, 14) -- Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26) -- Code(Expression(0, Sub)) at (prev + 6, 13) to (start + 0, 17) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 9) to (start + 1, 18) +- Code(Counter(0)) at (prev + 1, 21) to (start + 0, 23) +- Code(Counter(1)) at (prev + 5, 9) to (start + 0, 14) +- Code(Counter(2)) at (prev + 2, 9) to (start + 1, 17) +- Code(Counter(2)) at (prev + 4, 13) to (start + 0, 26) +- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 17) = ((c0 + c2) - c1) - Code(Expression(0, Sub)) at (prev + 0, 41) to (start + 0, 42) = ((c0 + c2) - c1) @@ -82,125 +92,157 @@ Number of file 0 mappings: 11 Highest counter ID seen: c2 Function name: try_error_result::test2 -Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 1c, 15, 04, 11, 00, 12, 1e, 02, 11, 03, 27, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 29, 19, 00, 41, 00, 42, 26, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 17, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 29, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 47, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 17, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 29, 29, 00, 42, 00, 43, 66, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 17, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 1d, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 17, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 1d, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 17, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02] +Raw bytes (443): 0x[01, 01, 3d, 0d, 11, 0d, 57, 11, 15, 0d, 57, 11, 15, 0d, 57, 11, 15, 0d, 4f, 53, 1d, 57, 19, 11, 15, 0d, 57, 11, 15, 0d, 57, 11, 15, 0d, 53, 57, 19, 11, 15, 0d, 4f, 53, 1d, 57, 19, 11, 15, 41, 6b, 21, 25, 41, 21, 41, 6b, 21, 25, 09, 8f, 01, 93, 01, 2d, 0d, 29, 09, 0d, 09, 0d, 09, 93, 01, 0d, 29, 09, 8f, 01, 93, 01, 2d, 0d, 29, 45, a7, 01, 31, 35, 45, 31, 45, a7, 01, 31, 35, 49, bb, 01, 39, 3d, 49, 39, 49, bb, 01, 39, 3d, 05, 09, c7, 01, 09, cb, 01, 3d, cf, 01, 39, d3, 01, 35, d7, 01, 31, db, 01, 2d, df, 01, 29, e3, 01, 25, e7, 01, 21, eb, 01, 1d, ef, 01, 19, f3, 01, 15, 05, 11, 39, 01, 3d, 01, 00, 1d, 01, 01, 09, 00, 0f, 01, 00, 12, 00, 1a, 01, 01, 09, 01, 12, 01, 01, 15, 00, 17, 05, 05, 09, 00, 0e, 09, 02, 09, 01, 11, 09, 04, 0d, 00, 1a, 0d, 02, 0d, 00, 13, 0d, 00, 14, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 00, 35, 02, 00, 45, 00, 4f, 02, 00, 50, 00, 62, 02, 01, 0d, 00, 13, 02, 02, 11, 00, 1c, 15, 01, 11, 00, 12, 36, 02, 11, 00, 15, 36, 02, 11, 00, 1b, 36, 01, 15, 00, 27, 4a, 02, 11, 00, 14, 36, 00, 17, 00, 1d, 36, 00, 1e, 00, 29, 19, 00, 41, 00, 42, 3e, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 4a, 01, 0d, 00, 17, 66, 01, 11, 00, 14, 41, 00, 17, 00, 1d, 41, 00, 1e, 00, 29, 21, 00, 41, 00, 42, 62, 00, 43, 00, 47, 25, 00, 60, 00, 61, 66, 01, 0d, 00, 17, 8a, 01, 04, 11, 00, 14, 7e, 00, 17, 00, 1d, 7e, 00, 1e, 00, 29, 29, 00, 42, 00, 43, 82, 01, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 8a, 01, 01, 0d, 00, 17, a2, 01, 01, 11, 00, 14, 45, 00, 17, 00, 1d, 45, 01, 12, 00, 1d, 31, 00, 36, 00, 37, 9e, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 17, b6, 01, 01, 11, 00, 14, 49, 00, 17, 00, 1d, 49, 01, 12, 00, 1d, 39, 01, 11, 00, 12, b2, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 17, be, 01, 03, 05, 00, 0b, c2, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 54 +- file 0 => $DIR/try_error_result.rs +Number of expressions: 61 - expression 0 operands: lhs = Counter(3), rhs = Counter(4) -- expression 1 operands: lhs = Counter(3), rhs = Expression(15, Add) +- expression 1 operands: lhs = Counter(3), rhs = Expression(21, Add) - expression 2 operands: lhs = Counter(4), rhs = Counter(5) -- expression 3 operands: lhs = Counter(3), rhs = Expression(13, Add) -- expression 4 operands: lhs = Expression(14, Add), rhs = Counter(7) -- expression 5 operands: lhs = Expression(15, Add), rhs = Counter(6) +- expression 3 operands: lhs = Counter(3), rhs = Expression(21, Add) +- expression 4 operands: lhs = Counter(4), rhs = Counter(5) +- expression 5 operands: lhs = Counter(3), rhs = Expression(21, Add) - expression 6 operands: lhs = Counter(4), rhs = Counter(5) -- expression 7 operands: lhs = Counter(3), rhs = Expression(15, Add) -- expression 8 operands: lhs = Counter(4), rhs = Counter(5) -- expression 9 operands: lhs = Counter(3), rhs = Expression(14, Add) -- expression 10 operands: lhs = Expression(15, Add), rhs = Counter(6) -- expression 11 operands: lhs = Counter(4), rhs = Counter(5) -- expression 12 operands: lhs = Counter(3), rhs = Expression(13, Add) -- expression 13 operands: lhs = Expression(14, Add), rhs = Counter(7) -- expression 14 operands: lhs = Expression(15, Add), rhs = Counter(6) -- expression 15 operands: lhs = Counter(4), rhs = Counter(5) -- expression 16 operands: lhs = Counter(16), rhs = Expression(20, Add) -- expression 17 operands: lhs = Counter(8), rhs = Counter(9) -- expression 18 operands: lhs = Counter(16), rhs = Counter(8) -- expression 19 operands: lhs = Counter(16), rhs = Expression(20, Add) -- expression 20 operands: lhs = Counter(8), rhs = Counter(9) -- expression 21 operands: lhs = Counter(2), rhs = Expression(28, Add) -- expression 22 operands: lhs = Expression(29, Add), rhs = Counter(11) -- expression 23 operands: lhs = Counter(3), rhs = Counter(10) -- expression 24 operands: lhs = Counter(2), rhs = Counter(3) -- expression 25 operands: lhs = Counter(2), rhs = Expression(29, Add) -- expression 26 operands: lhs = Counter(3), rhs = Counter(10) -- expression 27 operands: lhs = Counter(2), rhs = Expression(28, Add) -- expression 28 operands: lhs = Expression(29, Add), rhs = Counter(11) +- expression 7 operands: lhs = Counter(3), rhs = Expression(19, Add) +- expression 8 operands: lhs = Expression(20, Add), rhs = Counter(7) +- expression 9 operands: lhs = Expression(21, Add), rhs = Counter(6) +- expression 10 operands: lhs = Counter(4), rhs = Counter(5) +- expression 11 operands: lhs = Counter(3), rhs = Expression(21, Add) +- expression 12 operands: lhs = Counter(4), rhs = Counter(5) +- expression 13 operands: lhs = Counter(3), rhs = Expression(21, Add) +- expression 14 operands: lhs = Counter(4), rhs = Counter(5) +- expression 15 operands: lhs = Counter(3), rhs = Expression(20, Add) +- expression 16 operands: lhs = Expression(21, Add), rhs = Counter(6) +- expression 17 operands: lhs = Counter(4), rhs = Counter(5) +- expression 18 operands: lhs = Counter(3), rhs = Expression(19, Add) +- expression 19 operands: lhs = Expression(20, Add), rhs = Counter(7) +- expression 20 operands: lhs = Expression(21, Add), rhs = Counter(6) +- expression 21 operands: lhs = Counter(4), rhs = Counter(5) +- expression 22 operands: lhs = Counter(16), rhs = Expression(26, Add) +- expression 23 operands: lhs = Counter(8), rhs = Counter(9) +- expression 24 operands: lhs = Counter(16), rhs = Counter(8) +- expression 25 operands: lhs = Counter(16), rhs = Expression(26, Add) +- expression 26 operands: lhs = Counter(8), rhs = Counter(9) +- expression 27 operands: lhs = Counter(2), rhs = Expression(35, Add) +- expression 28 operands: lhs = Expression(36, Add), rhs = Counter(11) - expression 29 operands: lhs = Counter(3), rhs = Counter(10) -- expression 30 operands: lhs = Counter(17), rhs = Expression(34, Add) -- expression 31 operands: lhs = Counter(12), rhs = Counter(13) -- expression 32 operands: lhs = Counter(17), rhs = Counter(12) -- expression 33 operands: lhs = Counter(17), rhs = Expression(34, Add) -- expression 34 operands: lhs = Counter(12), rhs = Counter(13) -- expression 35 operands: lhs = Counter(18), rhs = Expression(39, Add) -- expression 36 operands: lhs = Counter(14), rhs = Counter(15) -- expression 37 operands: lhs = Counter(18), rhs = Counter(14) -- expression 38 operands: lhs = Counter(18), rhs = Expression(39, Add) -- expression 39 operands: lhs = Counter(14), rhs = Counter(15) -- expression 40 operands: lhs = Counter(1), rhs = Counter(2) -- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(2) -- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(15) -- expression 43 operands: lhs = Expression(44, Add), rhs = Counter(14) -- expression 44 operands: lhs = Expression(45, Add), rhs = Counter(13) -- expression 45 operands: lhs = Expression(46, Add), rhs = Counter(12) -- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(11) -- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(10) -- expression 48 operands: lhs = Expression(49, Add), rhs = Counter(9) -- expression 49 operands: lhs = Expression(50, Add), rhs = Counter(8) -- expression 50 operands: lhs = Expression(51, Add), rhs = Counter(7) -- expression 51 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 52 operands: lhs = Expression(53, Add), rhs = Counter(5) -- expression 53 operands: lhs = Counter(1), rhs = Counter(4) -Number of file 0 mappings: 40 -- Code(Counter(0)) at (prev + 61, 1) to (start + 3, 23) -- Code(Counter(1)) at (prev + 8, 9) to (start + 0, 14) -- Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26) -- Code(Counter(3)) at (prev + 6, 13) to (start + 0, 31) +- expression 30 operands: lhs = Counter(2), rhs = Counter(3) +- expression 31 operands: lhs = Counter(2), rhs = Counter(3) +- expression 32 operands: lhs = Counter(2), rhs = Expression(36, Add) +- expression 33 operands: lhs = Counter(3), rhs = Counter(10) +- expression 34 operands: lhs = Counter(2), rhs = Expression(35, Add) +- expression 35 operands: lhs = Expression(36, Add), rhs = Counter(11) +- expression 36 operands: lhs = Counter(3), rhs = Counter(10) +- expression 37 operands: lhs = Counter(17), rhs = Expression(41, Add) +- expression 38 operands: lhs = Counter(12), rhs = Counter(13) +- expression 39 operands: lhs = Counter(17), rhs = Counter(12) +- expression 40 operands: lhs = Counter(17), rhs = Expression(41, Add) +- expression 41 operands: lhs = Counter(12), rhs = Counter(13) +- expression 42 operands: lhs = Counter(18), rhs = Expression(46, Add) +- expression 43 operands: lhs = Counter(14), rhs = Counter(15) +- expression 44 operands: lhs = Counter(18), rhs = Counter(14) +- expression 45 operands: lhs = Counter(18), rhs = Expression(46, Add) +- expression 46 operands: lhs = Counter(14), rhs = Counter(15) +- expression 47 operands: lhs = Counter(1), rhs = Counter(2) +- expression 48 operands: lhs = Expression(49, Add), rhs = Counter(2) +- expression 49 operands: lhs = Expression(50, Add), rhs = Counter(15) +- expression 50 operands: lhs = Expression(51, Add), rhs = Counter(14) +- expression 51 operands: lhs = Expression(52, Add), rhs = Counter(13) +- expression 52 operands: lhs = Expression(53, Add), rhs = Counter(12) +- expression 53 operands: lhs = Expression(54, Add), rhs = Counter(11) +- expression 54 operands: lhs = Expression(55, Add), rhs = Counter(10) +- expression 55 operands: lhs = Expression(56, Add), rhs = Counter(9) +- expression 56 operands: lhs = Expression(57, Add), rhs = Counter(8) +- expression 57 operands: lhs = Expression(58, Add), rhs = Counter(7) +- expression 58 operands: lhs = Expression(59, Add), rhs = Counter(6) +- expression 59 operands: lhs = Expression(60, Add), rhs = Counter(5) +- expression 60 operands: lhs = Counter(1), rhs = Counter(4) +Number of file 0 mappings: 57 +- Code(Counter(0)) at (prev + 61, 1) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 9) to (start + 1, 18) +- Code(Counter(0)) at (prev + 1, 21) to (start + 0, 23) +- Code(Counter(1)) at (prev + 5, 9) to (start + 0, 14) +- Code(Counter(2)) at (prev + 2, 9) to (start + 1, 17) +- Code(Counter(2)) at (prev + 4, 13) to (start + 0, 26) +- Code(Counter(3)) at (prev + 2, 13) to (start + 0, 19) +- Code(Counter(3)) at (prev + 0, 20) to (start + 0, 31) - Code(Counter(4)) at (prev + 0, 47) to (start + 0, 48) -- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 3, 28) +- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 0, 53) = (c3 - c4) -- Code(Counter(5)) at (prev + 4, 17) to (start + 0, 18) -- Code(Expression(7, Sub)) at (prev + 2, 17) to (start + 3, 39) +- Code(Expression(0, Sub)) at (prev + 0, 69) to (start + 0, 79) + = (c3 - c4) +- Code(Expression(0, Sub)) at (prev + 0, 80) to (start + 0, 98) + = (c3 - c4) +- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 19) + = (c3 - c4) +- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 28) + = (c3 - c4) +- Code(Counter(5)) at (prev + 1, 17) to (start + 0, 18) +- Code(Expression(13, Sub)) at (prev + 2, 17) to (start + 0, 21) = (c3 - (c4 + c5)) -- Code(Expression(12, Sub)) at (prev + 5, 17) to (start + 0, 20) +- Code(Expression(13, Sub)) at (prev + 2, 17) to (start + 0, 27) + = (c3 - (c4 + c5)) +- Code(Expression(13, Sub)) at (prev + 1, 21) to (start + 0, 39) + = (c3 - (c4 + c5)) +- Code(Expression(18, Sub)) at (prev + 2, 17) to (start + 0, 20) = (c3 - (((c4 + c5) + c6) + c7)) -- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 41) +- Code(Expression(13, Sub)) at (prev + 0, 23) to (start + 0, 29) + = (c3 - (c4 + c5)) +- Code(Expression(13, Sub)) at (prev + 0, 30) to (start + 0, 41) = (c3 - (c4 + c5)) - Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66) -- Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 71) +- Code(Expression(15, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c3 - ((c4 + c5) + c6)) - Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96) -- Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 23) +- Code(Expression(18, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c3 - (((c4 + c5) + c6) + c7)) -- Code(Expression(19, Sub)) at (prev + 1, 17) to (start + 0, 20) +- Code(Expression(25, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c16 - (c8 + c9)) -- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 41) +- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 29) +- Code(Counter(16)) at (prev + 0, 30) to (start + 0, 41) - Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66) -- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 71) +- Code(Expression(24, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c16 - c8) - Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97) -- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 23) +- Code(Expression(25, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c16 - (c8 + c9)) -- Code(Expression(27, Sub)) at (prev + 4, 17) to (start + 0, 20) +- Code(Expression(34, Sub)) at (prev + 4, 17) to (start + 0, 20) = (c2 - ((c3 + c10) + c11)) -- Code(Expression(24, Sub)) at (prev + 0, 23) to (start + 0, 41) +- Code(Expression(31, Sub)) at (prev + 0, 23) to (start + 0, 29) + = (c2 - c3) +- Code(Expression(31, Sub)) at (prev + 0, 30) to (start + 0, 41) = (c2 - c3) - Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67) -- Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 72) +- Code(Expression(32, Sub)) at (prev + 0, 68) to (start + 0, 72) = (c2 - (c3 + c10)) - Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98) -- Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 23) +- Code(Expression(34, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c2 - ((c3 + c10) + c11)) -- Code(Expression(33, Sub)) at (prev + 1, 17) to (start + 0, 20) +- Code(Expression(40, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c17 - (c12 + c13)) -- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 29) -- Code(Counter(12)) at (prev + 1, 54) to (start + 0, 55) -- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 22) +- Code(Counter(17)) at (prev + 0, 23) to (start + 0, 29) +- Code(Counter(17)) at (prev + 1, 18) to (start + 0, 29) +- Code(Counter(12)) at (prev + 0, 54) to (start + 0, 55) +- Code(Expression(39, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c17 - c12) - Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48) -- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 23) +- Code(Expression(40, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c17 - (c12 + c13)) -- Code(Expression(38, Sub)) at (prev + 1, 17) to (start + 0, 20) +- Code(Expression(45, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c18 - (c14 + c15)) -- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 29) -- Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18) -- Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 22) +- Code(Counter(18)) at (prev + 0, 23) to (start + 0, 29) +- Code(Counter(18)) at (prev + 1, 18) to (start + 0, 29) +- Code(Counter(14)) at (prev + 1, 17) to (start + 0, 18) +- Code(Expression(44, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c18 - c14) - Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18) -- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 23) +- Code(Expression(45, Sub)) at (prev + 2, 13) to (start + 0, 23) = (c18 - (c14 + c15)) -- Code(Expression(40, Sub)) at (prev + 3, 5) to (start + 0, 11) +- Code(Expression(47, Sub)) at (prev + 3, 5) to (start + 0, 11) = (c1 - c2) -- Code(Expression(41, Sub)) at (prev + 1, 1) to (start + 0, 2) +- Code(Expression(48, Sub)) at (prev + 1, 1) to (start + 0, 2) = (((((((((((((c1 + c4) + c5) + c6) + c7) + c8) + c9) + c10) + c11) + c12) + c13) + c14) + c15) - c2) Highest counter ID seen: c18 diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage index 7a89c0452ac4..f2ec82f20fa2 100644 --- a/tests/coverage/try_error_result.coverage +++ b/tests/coverage/try_error_result.coverage @@ -21,8 +21,8 @@ LL| | { LL| 6| countdown LL| 6| -= 1 - LL| 6| ; - LL| 6| if + LL| | ; + LL| | if LL| 6| countdown < 5 LL| | { LL| 1| call(/*return_error=*/ true)?; @@ -71,19 +71,19 @@ LL| | { LL| 6| countdown LL| 6| -= 1 - LL| 6| ; - LL| 6| if + LL| | ; + LL| | if LL| 6| countdown < 5 LL| | { LL| 1| thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail"); ^0 LL| 1| thing1 - LL| 1| . + LL| | . LL| 1| get_thing_2(/*return_error=*/ false) LL| 0| ? LL| | . LL| 1| call(/*return_error=*/ true) - LL| 1| . + LL| | . LL| 1| expect_err( LL| 1| "call should fail" LL| | ); diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map index 29d40a055130..bbfa8b940c6d 100644 --- a/tests/coverage/unicode.cov-map +++ b/tests/coverage/unicode.cov-map @@ -1,12 +1,12 @@ Function name: unicode::main -Raw bytes (53): 0x[01, 01, 02, 05, 01, 01, 0d, 09, 01, 0e, 01, 00, 0b, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 23, 09, 00, 29, 00, 44, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 01, 02] +Raw bytes (58): 0x[01, 01, 02, 05, 01, 01, 0d, 0a, 01, 0e, 01, 00, 0a, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 23, 09, 00, 29, 00, 44, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unicode.rs Number of expressions: 2 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) - expression 1 operands: lhs = Counter(0), rhs = Counter(3) -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 11) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 10) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 12) = (c1 - c0) - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 27) @@ -17,24 +17,28 @@ Number of file 0 mappings: 9 - Code(Counter(3)) at (prev + 0, 71) to (start + 2, 6) - Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c3) -- Code(Counter(0)) at (prev + 2, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 Function name: unicode::他 (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 19, 00, 25] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 1e, 19, 00, 22, 00, 00, 24, 00, 25] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unicode.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 30, 25) to (start + 0, 37) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 30, 25) to (start + 0, 34) +- Code(Zero) at (prev + 0, 36) to (start + 0, 37) Highest counter ID seen: (none) Function name: unicode::申し訳ございません -Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 02, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 18, 01, 00, 29, 01, 01, 05, 00, 19, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unicode.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 24, 1) to (start + 2, 2) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 41) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 25) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/unicode.coverage b/tests/coverage/unicode.coverage index 443499545500..4646cc92e8e4 100644 --- a/tests/coverage/unicode.coverage +++ b/tests/coverage/unicode.coverage @@ -29,7 +29,7 @@ LL| | LL| |macro_rules! macro_that_defines_a_function { LL| | (fn $名:ident () $体:tt) => { - LL| 0| fn $名 () $体 fn 他 () {} + LL| 0| fn $名 () $体 fn 他 () {} LL| | } LL| |} LL| | diff --git a/tests/coverage/unreachable.cov-map b/tests/coverage/unreachable.cov-map index 0bc18bfcbd31..c38786ee664c 100644 --- a/tests/coverage/unreachable.cov-map +++ b/tests/coverage/unreachable.cov-map @@ -1,27 +1,29 @@ Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 27, 00, 45] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 30, 00, 45] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unreachable.rs Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 14, 39) to (start + 0, 69) +- Code(Zero) at (prev + 14, 48) to (start + 0, 69) Highest counter ID seen: (none) Function name: unreachable::unreachable_function (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 10, 01, 01, 23] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 10, 01, 00, 1a, 00, 01, 0e, 00, 23] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unreachable.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 16, 1) to (start + 1, 35) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 16, 1) to (start + 0, 26) +- Code(Zero) at (prev + 1, 14) to (start + 0, 35) Highest counter ID seen: (none) Function name: unreachable::unreachable_intrinsic (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 01, 2a] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 15, 01, 00, 1b, 00, 01, 0e, 00, 2a] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unreachable.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 1) to (start + 1, 42) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 21, 1) to (start + 0, 27) +- Code(Zero) at (prev + 1, 14) to (start + 0, 42) Highest counter ID seen: (none) diff --git a/tests/coverage/unused.cov-map b/tests/coverage/unused.cov-map index c18d331ec2e0..3380997b921e 100644 --- a/tests/coverage/unused.cov-map +++ b/tests/coverage/unused.cov-map @@ -1,14 +1,16 @@ Function name: unused::foo:: -Raw bytes (40): 0x[01, 01, 03, 05, 01, 05, 0b, 01, 09, 06, 01, 03, 01, 01, 12, 05, 02, 0b, 00, 11, 02, 01, 09, 00, 0f, 06, 00, 13, 00, 19, 02, 01, 09, 00, 0f, 01, 02, 01, 00, 02] +Raw bytes (50): 0x[01, 01, 03, 05, 01, 05, 0b, 01, 09, 08, 01, 03, 01, 00, 10, 01, 01, 09, 00, 0e, 01, 00, 11, 00, 12, 05, 01, 0b, 00, 11, 02, 01, 09, 00, 0f, 06, 00, 13, 00, 19, 02, 01, 09, 00, 0f, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unused.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 3, 1) to (start + 1, 18) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 17) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 17) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c1 - c0) - Code(Expression(1, Sub)) at (prev + 0, 19) to (start + 0, 25) @@ -19,16 +21,18 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: unused::foo:: -Raw bytes (40): 0x[01, 01, 03, 05, 01, 05, 0b, 01, 09, 06, 01, 03, 01, 01, 12, 05, 02, 0b, 00, 11, 02, 01, 09, 00, 0f, 06, 00, 13, 00, 19, 02, 01, 09, 00, 0f, 01, 02, 01, 00, 02] +Raw bytes (50): 0x[01, 01, 03, 05, 01, 05, 0b, 01, 09, 08, 01, 03, 01, 00, 10, 01, 01, 09, 00, 0e, 01, 00, 11, 00, 12, 05, 01, 0b, 00, 11, 02, 01, 09, 00, 0f, 06, 00, 13, 00, 19, 02, 01, 09, 00, 0f, 01, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unused.rs Number of expressions: 3 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 3, 1) to (start + 1, 18) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 17) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 17) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c1 - c0) - Code(Expression(1, Sub)) at (prev + 0, 19) to (start + 0, 25) @@ -39,58 +43,67 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: unused::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 04, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 25, 01, 00, 1c, 01, 01, 05, 00, 0f, 01, 01, 05, 00, 0f, 01, 01, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unused.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 37, 1) to (start + 4, 2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: unused::unused_func (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 13, 01, 00, 1b, 00, 01, 08, 00, 0e, 00, 00, 0f, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unused.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Zero) at (prev + 19, 1) to (start + 1, 14) -- Code(Zero) at (prev + 1, 15) to (start + 2, 6) +Number of file 0 mappings: 5 +- Code(Zero) at (prev + 19, 1) to (start + 0, 27) +- Code(Zero) at (prev + 1, 8) to (start + 0, 14) +- Code(Zero) at (prev + 0, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: unused::unused_func2 (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 19, 01, 00, 1c, 00, 01, 08, 00, 0e, 00, 00, 0f, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unused.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Zero) at (prev + 25, 1) to (start + 1, 14) -- Code(Zero) at (prev + 1, 15) to (start + 2, 6) +Number of file 0 mappings: 5 +- Code(Zero) at (prev + 25, 1) to (start + 0, 28) +- Code(Zero) at (prev + 1, 8) to (start + 0, 14) +- Code(Zero) at (prev + 0, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: unused::unused_func3 (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 1f, 01, 00, 1c, 00, 01, 08, 00, 0e, 00, 00, 0f, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unused.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Zero) at (prev + 31, 1) to (start + 1, 14) -- Code(Zero) at (prev + 1, 15) to (start + 2, 6) +Number of file 0 mappings: 5 +- Code(Zero) at (prev + 31, 1) to (start + 0, 28) +- Code(Zero) at (prev + 1, 8) to (start + 0, 14) +- Code(Zero) at (prev + 0, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: unused::unused_template_func::<_> (unused) -Raw bytes (34): 0x[01, 01, 00, 06, 00, 0b, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] +Raw bytes (44): 0x[01, 01, 00, 08, 00, 0b, 01, 00, 21, 00, 01, 09, 00, 0e, 00, 00, 11, 00, 12, 00, 01, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unused.rs Number of expressions: 0 -Number of file 0 mappings: 6 -- Code(Zero) at (prev + 11, 1) to (start + 1, 18) -- Code(Zero) at (prev + 2, 11) to (start + 0, 17) +Number of file 0 mappings: 8 +- Code(Zero) at (prev + 11, 1) to (start + 0, 33) +- Code(Zero) at (prev + 1, 9) to (start + 0, 14) +- Code(Zero) at (prev + 0, 17) to (start + 0, 18) +- Code(Zero) at (prev + 1, 11) to (start + 0, 17) - Code(Zero) at (prev + 1, 9) to (start + 0, 15) - Code(Zero) at (prev + 0, 19) to (start + 0, 25) - Code(Zero) at (prev + 1, 9) to (start + 0, 15) diff --git a/tests/coverage/unused_mod.cov-map b/tests/coverage/unused_mod.cov-map index 5e8b69fcdba9..ea419edbdafe 100644 --- a/tests/coverage/unused_mod.cov-map +++ b/tests/coverage/unused_mod.cov-map @@ -1,18 +1,24 @@ Function name: unused_mod::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 04, 01, 00, 0a, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 1c, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/unused_mod.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: unused_mod::unused_module::never_called_function (unused) -Raw bytes (9): 0x[01, 02, 00, 01, 00, 02, 01, 02, 02] +Raw bytes (24): 0x[01, 02, 00, 04, 00, 02, 01, 00, 1f, 00, 01, 05, 00, 0d, 00, 00, 0e, 00, 21, 00, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 2 +- file 0 => $DIR/auxiliary/unused_mod_helper.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 2, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Zero) at (prev + 2, 1) to (start + 0, 31) +- Code(Zero) at (prev + 1, 5) to (start + 0, 13) +- Code(Zero) at (prev + 0, 14) to (start + 0, 33) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) diff --git a/tests/coverage/uses_crate.cov-map b/tests/coverage/uses_crate.cov-map index 5c23f8826971..8f3c63aba5ce 100644 --- a/tests/coverage/uses_crate.cov-map +++ b/tests/coverage/uses_crate.cov-map @@ -1,45 +1,67 @@ Function name: used_crate::used_from_bin_crate_and_lib_crate_generic_function::> -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1b, 01, 00, 4c, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 4f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/auxiliary/used_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 27, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 76) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 79) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 13, 01, 00, 43, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 46, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/auxiliary/used_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 67) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 70) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: used_crate::used_only_from_bin_crate_generic_function::<&str> -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 13, 01, 00, 43, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 46, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/auxiliary/used_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 67) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 70) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 01, 00, 5b, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 5e, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/auxiliary/used_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 31, 1) to (start + 0, 91) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 94) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: uses_crate::main -Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 07, 02] +Raw bytes (59): 0x[01, 02, 00, 0b, 01, 0c, 01, 00, 0a, 01, 01, 05, 00, 1e, 01, 01, 09, 00, 11, 01, 00, 14, 00, 18, 01, 01, 05, 00, 3a, 01, 00, 3b, 00, 44, 01, 01, 05, 00, 3a, 01, 01, 05, 00, 43, 01, 00, 44, 00, 4c, 01, 01, 05, 00, 52, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 2 +- file 0 => $DIR/uses_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 12, 1) to (start + 7, 2) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 24) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 58) +- Code(Counter(0)) at (prev + 0, 59) to (start + 0, 68) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 58) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 67) +- Code(Counter(0)) at (prev + 0, 68) to (start + 0, 76) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 82) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage index d1b0dadda768..145c0649ac7b 100644 --- a/tests/coverage/uses_crate.coverage +++ b/tests/coverage/uses_crate.coverage @@ -6,9 +6,9 @@ $DIR/auxiliary/used_crate.rs: LL| |use std::fmt::Debug; LL| | LL| 1|pub fn used_function() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; LL| 1| let mut countdown = 0; LL| 1| if is_true { @@ -104,8 +104,8 @@ $DIR/auxiliary/used_crate.rs: LL| 1|fn use_this_lib_crate() { LL| 1| used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); LL| 1| used_with_same_type_from_bin_crate_and_lib_crate_generic_function( - LL| 1| "used from library used_crate.rs", - LL| 1| ); + LL| | "used from library used_crate.rs", + LL| | ); LL| 1| let some_vec = vec![5, 6, 7, 8]; LL| 1| used_only_from_this_lib_crate_generic_function(some_vec); LL| 1| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); diff --git a/tests/coverage/uses_inline_crate.cov-map b/tests/coverage/uses_inline_crate.cov-map index a482d20e3b4b..52f3f94ce642 100644 --- a/tests/coverage/uses_inline_crate.cov-map +++ b/tests/coverage/uses_inline_crate.cov-map @@ -1,59 +1,88 @@ Function name: used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::> -Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 2c, 01, 00, 4c, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 4f, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/auxiliary/used_inline_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 44, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 44, 1) to (start + 0, 76) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 79) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: used_inline_crate::used_inline_function -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 01, 02] +Raw bytes (56): 0x[01, 01, 01, 01, 05, 0a, 01, 14, 01, 00, 1e, 01, 04, 09, 00, 10, 01, 00, 13, 00, 2e, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1a, 01, 01, 08, 00, 0f, 05, 00, 10, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 00, 17, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/auxiliary/used_inline_crate.rs Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 20, 1) to (start + 6, 15) -- Code(Counter(1)) at (prev + 6, 16) to (start + 2, 6) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 20, 1) to (start + 0, 30) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 46) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 15) +- Code(Counter(1)) at (prev + 0, 16) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> -Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 21, 01, 00, 43, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 46, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/auxiliary/used_inline_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 67) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 70) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&str> -Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 21, 01, 00, 43, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 46, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/auxiliary/used_inline_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 67) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 70) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> -Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 02, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 31, 01, 00, 5b, 01, 01, 05, 00, 0d, 01, 00, 0e, 00, 5e, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/auxiliary/used_inline_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 49, 1) to (start + 2, 2) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 49, 1) to (start + 0, 91) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 94) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: uses_inline_crate::main -Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 0a, 02] +Raw bytes (64): 0x[01, 02, 00, 0c, 01, 0c, 01, 00, 0a, 01, 01, 05, 00, 25, 01, 01, 05, 00, 2c, 01, 01, 09, 00, 11, 01, 00, 14, 00, 18, 01, 01, 05, 00, 41, 01, 00, 42, 00, 4b, 01, 01, 05, 00, 41, 01, 01, 05, 00, 4a, 01, 00, 4b, 00, 53, 01, 01, 05, 00, 59, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 2 +- file 0 => $DIR/uses_inline_crate.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 12, 1) to (start + 10, 2) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 44) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 24) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 65) +- Code(Counter(0)) at (prev + 0, 66) to (start + 0, 75) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 65) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 74) +- Code(Counter(0)) at (prev + 0, 75) to (start + 0, 83) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 89) +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/uses_inline_crate.coverage b/tests/coverage/uses_inline_crate.coverage index 4671c95aefa4..15084bcf7ea9 100644 --- a/tests/coverage/uses_inline_crate.coverage +++ b/tests/coverage/uses_inline_crate.coverage @@ -6,9 +6,9 @@ $DIR/auxiliary/used_inline_crate.rs: LL| |use std::fmt::Debug; LL| | LL| 1|pub fn used_function() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; LL| 1| let mut countdown = 0; LL| 1| if is_true { @@ -20,9 +20,9 @@ $DIR/auxiliary/used_inline_crate.rs: LL| | LL| |#[inline(always)] LL| 1|pub fn used_inline_function() { - LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure - LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - LL| 1| // dependent conditions. + LL| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + LL| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + LL| | // dependent conditions. LL| 1| let is_true = std::env::args().len() == 1; LL| 1| let mut countdown = 0; LL| 1| if is_true { @@ -126,8 +126,8 @@ $DIR/auxiliary/used_inline_crate.rs: LL| 2|fn use_this_lib_crate() { LL| 2| used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); LL| 2| used_with_same_type_from_bin_crate_and_lib_crate_generic_function( - LL| 2| "used from library used_crate.rs", - LL| 2| ); + LL| | "used from library used_crate.rs", + LL| | ); LL| 2| let some_vec = vec![5, 6, 7, 8]; LL| 2| used_only_from_this_lib_crate_generic_function(some_vec); LL| 2| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); @@ -153,7 +153,7 @@ $DIR/uses_inline_crate.rs: LL| 1| used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); LL| 1| used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); LL| 1| used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function( - LL| 1| "interesting?", - LL| 1| ); + LL| | "interesting?", + LL| | ); LL| 1|} diff --git a/tests/coverage/while.cov-map b/tests/coverage/while.cov-map index 5a6698128cbd..c4183e18e021 100644 --- a/tests/coverage/while.cov-map +++ b/tests/coverage/while.cov-map @@ -1,11 +1,13 @@ Function name: while::main -Raw bytes (24): 0x[01, 01, 00, 04, 01, 01, 01, 01, 10, 01, 02, 0b, 00, 14, 00, 00, 15, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 01, 01, 00, 0a, 01, 01, 09, 00, 0c, 01, 00, 0f, 00, 10, 01, 01, 0b, 00, 14, 00, 00, 15, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/while.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 1, 1) to (start + 1, 16) -- Code(Counter(0)) at (prev + 2, 11) to (start + 0, 20) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 11) to (start + 0, 20) - Code(Zero) at (prev + 0, 21) to (start + 2, 6) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map index 69b51bf9ca34..b29b5d40c4df 100644 --- a/tests/coverage/while_early_ret.cov-map +++ b/tests/coverage/while_early_ret.cov-map @@ -1,27 +1,32 @@ Function name: while_early_ret::main -Raw bytes (63): 0x[01, 01, 07, 0f, 05, 01, 09, 0f, 13, 01, 09, 05, 0d, 05, 01, 05, 09, 09, 01, 05, 01, 01, 1b, 05, 03, 09, 02, 0a, 09, 05, 0d, 02, 0e, 02, 06, 15, 02, 16, 0d, 04, 15, 00, 1b, 0a, 04, 15, 00, 1b, 16, 03, 0a, 03, 0a, 1a, 06, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (80): 0x[01, 01, 08, 0f, 05, 01, 09, 0f, 13, 01, 09, 05, 0d, 05, 01, 05, 01, 05, 09, 0c, 01, 05, 01, 00, 1c, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1b, 05, 02, 09, 02, 0a, 09, 05, 0d, 02, 0e, 02, 06, 15, 02, 16, 0d, 04, 15, 00, 1b, 0a, 04, 15, 00, 1b, 1a, 03, 09, 00, 0a, 1a, 01, 09, 02, 0a, 1e, 05, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 -Number of expressions: 7 +- file 0 => $DIR/while_early_ret.rs +Number of expressions: 8 - expression 0 operands: lhs = Expression(3, Add), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) - expression 2 operands: lhs = Expression(3, Add), rhs = Expression(4, Add) - expression 3 operands: lhs = Counter(0), rhs = Counter(2) - expression 4 operands: lhs = Counter(1), rhs = Counter(3) - expression 5 operands: lhs = Counter(1), rhs = Counter(0) -- expression 6 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 27) -- Code(Counter(1)) at (prev + 3, 9) to (start + 2, 10) +- expression 6 operands: lhs = Counter(1), rhs = Counter(0) +- expression 7 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 27) +- Code(Counter(1)) at (prev + 2, 9) to (start + 2, 10) - Code(Counter(2)) at (prev + 5, 13) to (start + 2, 14) - Code(Expression(0, Sub)) at (prev + 6, 21) to (start + 2, 22) = ((c0 + c2) - c1) - Code(Counter(3)) at (prev + 4, 21) to (start + 0, 27) - Code(Expression(2, Sub)) at (prev + 4, 21) to (start + 0, 27) = ((c0 + c2) - (c1 + c3)) -- Code(Expression(5, Sub)) at (prev + 3, 10) to (start + 3, 10) +- Code(Expression(6, Sub)) at (prev + 3, 9) to (start + 0, 10) = (c1 - c0) -- Code(Expression(6, Sub)) at (prev + 6, 5) to (start + 0, 11) +- Code(Expression(6, Sub)) at (prev + 1, 9) to (start + 2, 10) + = (c1 - c0) +- Code(Expression(7, Sub)) at (prev + 5, 5) to (start + 0, 11) = (c1 - c2) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map index bf0916e5503a..87d0a0472615 100644 --- a/tests/coverage/yield.cov-map +++ b/tests/coverage/yield.cov-map @@ -1,30 +1,39 @@ Function name: yield::main -Raw bytes (94): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 2e, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 14, 11, 02, 0b, 00, 2e, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 14, 12, 02, 01, 00, 02] +Raw bytes (139): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 19, 01, 07, 01, 00, 0a, 01, 01, 09, 00, 16, 01, 06, 0b, 00, 13, 01, 00, 0b, 00, 2e, 01, 00, 14, 00, 22, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 13, 05, 00, 0b, 00, 2e, 05, 00, 14, 00, 22, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 13, 09, 00, 0b, 00, 2e, 09, 00, 14, 00, 22, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 14, 11, 02, 0b, 00, 13, 11, 00, 0b, 00, 2e, 11, 00, 14, 00, 22, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 14, 12, 02, 01, 00, 02] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/yield.rs Number of expressions: 5 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(2), rhs = Counter(4) - expression 3 operands: lhs = Counter(4), rhs = Counter(5) - expression 4 operands: lhs = Counter(4), rhs = Counter(5) -Number of file 0 mappings: 16 -- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22) -- Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) +Number of file 0 mappings: 25 +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 6, 11) to (start + 0, 19) +- Code(Counter(0)) at (prev + 0, 11) to (start + 0, 46) +- Code(Counter(0)) at (prev + 0, 20) to (start + 0, 34) - Code(Counter(1)) at (prev + 1, 39) to (start + 0, 41) - Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c0 - c1) -- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46) +- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 19) +- Code(Counter(1)) at (prev + 0, 11) to (start + 0, 46) +- Code(Counter(1)) at (prev + 0, 20) to (start + 0, 34) - Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39) - Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46) - Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c1 - c2) - Code(Counter(2)) at (prev + 3, 9) to (start + 0, 22) -- Code(Counter(2)) at (prev + 8, 11) to (start + 0, 46) +- Code(Counter(2)) at (prev + 8, 11) to (start + 0, 19) +- Code(Counter(2)) at (prev + 0, 11) to (start + 0, 46) +- Code(Counter(2)) at (prev + 0, 20) to (start + 0, 34) - Code(Counter(4)) at (prev + 1, 39) to (start + 0, 41) - Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c2 - c4) -- Code(Counter(4)) at (prev + 2, 11) to (start + 0, 46) +- Code(Counter(4)) at (prev + 2, 11) to (start + 0, 19) +- Code(Counter(4)) at (prev + 0, 11) to (start + 0, 46) +- Code(Counter(4)) at (prev + 0, 20) to (start + 0, 34) - Code(Expression(4, Sub)) at (prev + 1, 39) to (start + 0, 41) = (c4 - c5) - Code(Counter(5)) at (prev + 1, 14) to (start + 0, 20) @@ -33,24 +42,28 @@ Number of file 0 mappings: 16 Highest counter ID seen: c5 Function name: yield::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 09, 08, 01, 10, 05, 02, 10, 01, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 09, 08, 00, 09, 01, 01, 09, 00, 10, 05, 01, 10, 00, 15, 05, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/yield.rs Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 9, 8) to (start + 1, 16) -- Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 9, 8) to (start + 0, 9) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(1)) at (prev + 1, 16) to (start + 0, 21) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c1 Function name: yield::main::{closure#1} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 18, 08, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] +Raw bytes (34): 0x[01, 01, 00, 06, 01, 18, 08, 00, 09, 01, 01, 09, 00, 10, 05, 01, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 00, 15, 0d, 01, 05, 00, 06] Number of files: 1 -- file 0 => global file 1 +- file 0 => $DIR/yield.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 24, 8) to (start + 1, 16) -- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 24, 8) to (start + 0, 9) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 16) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 16) -- Code(Counter(3)) at (prev + 1, 16) to (start + 1, 6) +- Code(Counter(3)) at (prev + 1, 16) to (start + 0, 21) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c3 diff --git a/tests/crashes/127643.rs b/tests/crashes/127643.rs index a4db9397bdef..b5ec58b70e93 100644 --- a/tests/crashes/127643.rs +++ b/tests/crashes/127643.rs @@ -1,18 +1,18 @@ //@ known-bug: #127643 -#![feature(associated_const_equality)] +#![feature(generic_const_items, associated_const_equality)] +#![expect(incomplete_features)] -fn user() -> impl Owner {} - -trait Owner { - const C: K; -} -impl Owner for () { - const C: K = K::DEFAULT; +trait Foo { + const ASSOC: u32; } -trait ConstDefault { - const DEFAULT: Self; +impl Foo for () { + const ASSOC: u32 = N; } -fn main() {} +fn bar = { N }>>() {} + +fn main() { + bar::<10_u64, ()>(); +} diff --git a/tests/crashes/131758.rs b/tests/crashes/131758.rs deleted file mode 100644 index 942c5fd7a502..000000000000 --- a/tests/crashes/131758.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #131758 -#![feature(unboxed_closures)] -trait Foo {} - -impl> Foo for T {} - -fn baz(_: T) {} - -fn main() { - baz(|x| ()); -} diff --git a/tests/crashes/133066.rs b/tests/crashes/133066.rs deleted file mode 100644 index 732ebb7079fd..000000000000 --- a/tests/crashes/133066.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #133066 -trait Owner { - const C: u32; -} - -impl Owner for () {;} - -fn take0(_: impl Owner = { N }>) {} - -fn main() { - take0::(()); -} diff --git a/tests/debuginfo/step-into-match.rs b/tests/debuginfo/step-into-match.rs index 577e553c1198..d4b7ea201195 100644 --- a/tests/debuginfo/step-into-match.rs +++ b/tests/debuginfo/step-into-match.rs @@ -1,6 +1,10 @@ //@ compile-flags: -g //@ ignore-android: FIXME(#10381) +// On Arm64 Windows, stepping at the end of a function on goes to the callsite, not the instruction +// after it. +//@ ignore-aarch64-pc-windows-msvc: Stepping out of functions behaves differently. + // === GDB TESTS ============================================================== // gdb-command: r diff --git a/tests/debuginfo/type-names.rs b/tests/debuginfo/type-names.rs index 4df6daf7b6ef..3c7eab7e8d71 100644 --- a/tests/debuginfo/type-names.rs +++ b/tests/debuginfo/type-names.rs @@ -1,5 +1,7 @@ //@ ignore-lldb +//@ ignore-aarch64-pc-windows-msvc: Arm64 Windows cdb doesn't support JavaScript extensions. + // GDB changed the way that it formatted Foreign types //@ min-gdb-version: 9.2 diff --git a/tests/incremental/circular-dependencies.rs b/tests/incremental/circular-dependencies.rs index bd3b109b62c7..c7b5b931fbbe 100644 --- a/tests/incremental/circular-dependencies.rs +++ b/tests/incremental/circular-dependencies.rs @@ -15,7 +15,6 @@ pub struct Foo; pub fn consume_foo(_: Foo) {} //[cfail2]~^ NOTE function defined here -//[cfail2]~| NOTE pub fn produce_foo() -> Foo { Foo diff --git a/tests/incremental/ich_nested_items.rs b/tests/incremental/ich_nested_items.rs index 19628e0bce1b..c2a041ba268c 100644 --- a/tests/incremental/ich_nested_items.rs +++ b/tests/incremental/ich_nested_items.rs @@ -7,6 +7,7 @@ #![crate_type = "rlib"] #![feature(rustc_attrs)] +#![allow(dead_code)] #[rustc_clean(except = "opt_hir_owner_nodes", cfg = "cfail2")] pub fn foo() { diff --git a/tests/incremental/incremental_proc_macro.rs b/tests/incremental/incremental_proc_macro.rs index 3cf89cae6528..fc32aad5645c 100644 --- a/tests/incremental/incremental_proc_macro.rs +++ b/tests/incremental/incremental_proc_macro.rs @@ -12,5 +12,5 @@ extern crate incremental_proc_macro_aux; #[derive(IncrementalMacro)] pub struct Foo { - x: u32 + _x: u32 } diff --git a/tests/incremental/issue-49595/issue-49595.rs b/tests/incremental/issue-49595/issue-49595.rs index a291188f746e..7fe843135dfe 100644 --- a/tests/incremental/issue-49595/issue-49595.rs +++ b/tests/incremental/issue-49595/issue-49595.rs @@ -10,7 +10,7 @@ mod tests { #[cfg_attr(not(cfail1), test)] - fn test() { + fn _test() { } } diff --git a/tests/incremental/issue-84252-global-alloc.rs b/tests/incremental/issue-84252-global-alloc.rs index 8dc611df9d87..cd2cb2313bd3 100644 --- a/tests/incremental/issue-84252-global-alloc.rs +++ b/tests/incremental/issue-84252-global-alloc.rs @@ -1,5 +1,6 @@ //@ revisions: cfail1 cfail2 //@ build-pass +//@ needs-crate-type: cdylib #![crate_type="lib"] #![crate_type="cdylib"] diff --git a/tests/incremental/issue-85360-eval-obligation-ice.rs b/tests/incremental/issue-85360-eval-obligation-ice.rs index 70bb43f39ecf..2148e45bb387 100644 --- a/tests/incremental/issue-85360-eval-obligation-ice.rs +++ b/tests/incremental/issue-85360-eval-obligation-ice.rs @@ -4,6 +4,8 @@ //@ edition: 2021 //@ build-pass +#![allow(dead_code)] + use core::any::Any; use core::marker::PhantomData; diff --git a/tests/incremental/no_mangle.rs b/tests/incremental/no_mangle.rs index 1a01a40113a2..36b82a7b863c 100644 --- a/tests/incremental/no_mangle.rs +++ b/tests/incremental/no_mangle.rs @@ -1,6 +1,7 @@ //@ revisions:cfail1 cfail2 //@ check-pass //@ compile-flags: --crate-type cdylib +//@ needs-crate-type: cdylib #![deny(unused_attributes)] diff --git a/tests/incremental/thinlto/cgu_keeps_identical_fn.rs b/tests/incremental/thinlto/cgu_keeps_identical_fn.rs index 5751759223b9..d124a3498c4a 100644 --- a/tests/incremental/thinlto/cgu_keeps_identical_fn.rs +++ b/tests/incremental/thinlto/cgu_keeps_identical_fn.rs @@ -33,12 +33,12 @@ mod foo { // Trivial functions like this one are imported very reliably by ThinLTO. - #[cfg(any(cfail1, cfail4))] + #[cfg(cfail1)] pub fn inlined_fn() -> u32 { 1234 } - #[cfg(not(any(cfail1, cfail4)))] + #[cfg(not(cfail1))] pub fn inlined_fn() -> u32 { 1234 } diff --git a/tests/incremental/unrecoverable_query.rs b/tests/incremental/unrecoverable_query.rs index e17236bebd25..798a418f7990 100644 --- a/tests/incremental/unrecoverable_query.rs +++ b/tests/incremental/unrecoverable_query.rs @@ -8,6 +8,8 @@ //@ compile-flags: --crate-type=lib //@ build-pass +#![allow(dead_code)] + pub trait P { type A; } diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index 542b70bcee96..d465b8bded22 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -26,11 +26,20 @@ debug a => _9; } -+ coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); -+ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:32 (#0); -+ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:32 (#0); -+ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:32 (#0); -+ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:32 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:14:1: 14:10 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:15:11: 15:21 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:18 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:23: 16:30 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:31: 16:32 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:18 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:23: 17:30 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:31: 17:32 (#0); ++ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:18 (#0); ++ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:23: 18:30 (#0); ++ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:31: 18:32 (#0); ++ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:18 (#0); ++ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:23: 19:30 (#0); ++ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:31: 19:32 (#0); + coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); + bb0: { diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index 06e5f011c761..cf6d85abd80e 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -4,7 +4,9 @@ fn bar() -> bool { let mut _0: bool; -+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:27:1: 29:2 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:27:1: 27:17 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:28:5: 28:9 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:2: 29:2 (#0); + bb0: { + Coverage::VirtualCounter(bcb0); diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index 30de92f3b868..980c5e202ffd 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -7,7 +7,7 @@ let mut _2: bool; let mut _3: !; -+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:11 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:10 (#0); + coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0); + coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index 1a22adeba6fc..b707cd41788a 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -7,7 +7,8 @@ coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0) - coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0); + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index b77969a3e169..239b845c2311 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -7,7 +7,8 @@ coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0) -+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); + coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); + coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff index f36157a762c2..39ba480d2033 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff @@ -8,9 +8,9 @@ let mut _3: u16; let mut _4: u32; + scope 1 (inlined core::num::::unchecked_shl) { -+ let mut _5: bool; -+ let _6: (); ++ let _5: (); + scope 2 (inlined core::ub_checks::check_language_ub) { ++ let mut _6: bool; + scope 3 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -22,20 +22,20 @@ StorageLive(_4); _4 = copy _2; - _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; -+ StorageLive(_6); + StorageLive(_5); -+ _5 = UbChecks(); -+ switchInt(move _5) -> [0: bb2, otherwise: bb1]; ++ StorageLive(_6); ++ _6 = UbChecks(); ++ switchInt(copy _6) -> [0: bb2, otherwise: bb1]; } bb1: { -+ _6 = core::num::::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; ++ _5 = core::num::::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { -+ StorageDead(_5); + _0 = ShlUnchecked(copy _3, copy _4); + StorageDead(_6); ++ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff index be1b066c6c1b..5a758d357406 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff @@ -8,9 +8,9 @@ let mut _3: u16; let mut _4: u32; + scope 1 (inlined core::num::::unchecked_shl) { -+ let mut _5: bool; -+ let _6: (); ++ let _5: (); + scope 2 (inlined core::ub_checks::check_language_ub) { ++ let mut _6: bool; + scope 3 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -22,20 +22,20 @@ StorageLive(_4); _4 = copy _2; - _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind continue]; -+ StorageLive(_6); + StorageLive(_5); -+ _5 = UbChecks(); -+ switchInt(move _5) -> [0: bb2, otherwise: bb1]; ++ StorageLive(_6); ++ _6 = UbChecks(); ++ switchInt(copy _6) -> [0: bb2, otherwise: bb1]; } bb1: { -+ _6 = core::num::::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; ++ _5 = core::num::::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { -+ StorageDead(_5); + _0 = ShlUnchecked(copy _3, copy _4); + StorageDead(_6); ++ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff index 360687f3c4e7..a0caf141f2d0 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff @@ -8,9 +8,9 @@ let mut _3: i64; let mut _4: u32; + scope 1 (inlined core::num::::unchecked_shr) { -+ let mut _5: bool; -+ let _6: (); ++ let _5: (); + scope 2 (inlined core::ub_checks::check_language_ub) { ++ let mut _6: bool; + scope 3 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -22,20 +22,20 @@ StorageLive(_4); _4 = copy _2; - _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; -+ StorageLive(_6); + StorageLive(_5); -+ _5 = UbChecks(); -+ switchInt(move _5) -> [0: bb2, otherwise: bb1]; ++ StorageLive(_6); ++ _6 = UbChecks(); ++ switchInt(copy _6) -> [0: bb2, otherwise: bb1]; } bb1: { -+ _6 = core::num::::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; ++ _5 = core::num::::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { -+ StorageDead(_5); + _0 = ShrUnchecked(copy _3, copy _4); + StorageDead(_6); ++ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff index 986df55df037..633089e7b2a2 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff @@ -8,9 +8,9 @@ let mut _3: i64; let mut _4: u32; + scope 1 (inlined core::num::::unchecked_shr) { -+ let mut _5: bool; -+ let _6: (); ++ let _5: (); + scope 2 (inlined core::ub_checks::check_language_ub) { ++ let mut _6: bool; + scope 3 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -22,20 +22,20 @@ StorageLive(_4); _4 = copy _2; - _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind continue]; -+ StorageLive(_6); + StorageLive(_5); -+ _5 = UbChecks(); -+ switchInt(move _5) -> [0: bb2, otherwise: bb1]; ++ StorageLive(_6); ++ _6 = UbChecks(); ++ switchInt(copy _6) -> [0: bb2, otherwise: bb1]; } bb1: { -+ _6 = core::num::::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; ++ _5 = core::num::::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { -+ StorageDead(_5); + _0 = ShrUnchecked(copy _3, copy _4); + StorageDead(_6); ++ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index 28878736ed7c..a5986a4315a2 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -10,9 +10,9 @@ + scope 2 { + } + scope 3 (inlined unreachable_unchecked) { -+ let mut _4: bool; -+ let _5: (); ++ let _4: (); + scope 4 (inlined core::ub_checks::check_language_ub) { ++ let mut _5: bool; + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -24,7 +24,7 @@ _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable]; + StorageLive(_3); -+ StorageLive(_5); ++ StorageLive(_4); + _3 = discriminant(_2); + switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; } @@ -34,15 +34,15 @@ + } + + bb2: { -+ StorageLive(_4); -+ _4 = UbChecks(); -+ assume(copy _4); -+ _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; ++ StorageLive(_5); ++ _5 = UbChecks(); ++ assume(copy _5); ++ _4 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; + } + + bb3: { + _0 = move ((_2 as Some).0: T); -+ StorageDead(_5); ++ StorageDead(_4); + StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index 27b6bb6a5bb2..12b03a6b6d92 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -10,9 +10,9 @@ + scope 2 { + } + scope 3 (inlined unreachable_unchecked) { -+ let mut _4: bool; -+ let _5: (); ++ let _4: (); + scope 4 (inlined core::ub_checks::check_language_ub) { ++ let mut _5: bool; + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -24,7 +24,7 @@ _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2]; + StorageLive(_3); -+ StorageLive(_5); ++ StorageLive(_4); + _3 = discriminant(_2); + switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; } @@ -38,15 +38,15 @@ - bb2 (cleanup): { - resume; + bb2: { -+ StorageLive(_4); -+ _4 = UbChecks(); -+ assume(copy _4); -+ _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; ++ StorageLive(_5); ++ _5 = UbChecks(); ++ assume(copy _5); ++ _4 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; + } + + bb3: { + _0 = move ((_2 as Some).0: T); -+ StorageDead(_5); ++ StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + return; diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff index 5fee9a6733dd..82353a2d5404 100644 --- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff @@ -10,9 +10,9 @@ scope 2 { } scope 3 (inlined unreachable_unchecked) { - let mut _4: bool; - let _5: (); + let _4: (); scope 4 (inlined core::ub_checks::check_language_ub) { + let mut _5: bool; scope 5 (inlined core::ub_checks::check_language_ub::runtime) { } } @@ -23,7 +23,7 @@ StorageLive(_2); _2 = copy _1; StorageLive(_3); - StorageLive(_5); + StorageLive(_4); _3 = discriminant(_2); switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; } @@ -33,16 +33,16 @@ } bb2: { - StorageLive(_4); -- _4 = UbChecks(); -+ _4 = const false; - assume(copy _4); - _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; + StorageLive(_5); +- _5 = UbChecks(); ++ _5 = const false; + assume(copy _5); + _4 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; } bb3: { _0 = move ((_2 as Some).0: i32); - StorageDead(_5); + StorageDead(_4); StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index 1ab9be966522..d8eace98d556 100644 --- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -5,23 +5,18 @@ debug bytes => _1; let mut _0: std::option::Option<[u8; 4]>; let _2: [u32; 4]; - let mut _3: [u8; 16]; - let mut _5: [u8; 4]; - let mut _6: u32; + let mut _4: [u8; 4]; scope 1 { debug dwords => _2; scope 2 { - debug ip => _4; - let _4: u32; + debug ip => _3; + let _3: u32; } } bb0: { StorageLive(_2); - StorageLive(_3); - _3 = copy _1; - _2 = move _3 as [u32; 4] (Transmute); - StorageDead(_3); + _2 = copy _1 as [u32; 4] (Transmute); switchInt(copy _2[0 of 4]) -> [0: bb1, otherwise: bb4]; } @@ -34,15 +29,10 @@ } bb3: { + _3 = copy _2[3 of 4]; StorageLive(_4); - _4 = copy _2[3 of 4]; - StorageLive(_5); - StorageLive(_6); - _6 = copy _4; - _5 = move _6 as [u8; 4] (Transmute); - StorageDead(_6); - _0 = Option::<[u8; 4]>::Some(move _5); - StorageDead(_5); + _4 = copy _3 as [u8; 4] (Transmute); + _0 = Option::<[u8; 4]>::Some(move _4); StorageDead(_4); goto -> bb5; } diff --git a/tests/mir-opt/pre-codegen/matchbr.match1.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/matchbr.match1.PreCodegen.after.mir new file mode 100644 index 000000000000..3a202728ea91 --- /dev/null +++ b/tests/mir-opt/pre-codegen/matchbr.match1.PreCodegen.after.mir @@ -0,0 +1,13 @@ +// MIR for `match1` after PreCodegen + +fn match1(_1: bool, _2: i32, _3: i32) -> i32 { + debug c => _1; + debug v1 => _2; + debug v2 => _3; + let mut _0: i32; + + bb0: { + _0 = Sub(copy _2, copy _3); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/matchbr.rs b/tests/mir-opt/pre-codegen/matchbr.rs new file mode 100644 index 000000000000..1822739da2c7 --- /dev/null +++ b/tests/mir-opt/pre-codegen/matchbr.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] + +// EMIT_MIR matchbr.match1.PreCodegen.after.mir +pub fn match1(c: bool, v1: i32, v2: i32) -> i32 { + // CHECK-LABEL: fn match1( + // CHECK: bb0: + // CHECK-NEXT: _0 = Sub + // CHECK-NEXT: return; + if c { v1 - v2 } else { v1 - v2 } +} diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff index c363dfcbf70b..ff1bc58524bc 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff @@ -8,6 +8,9 @@ let mut _3: std::option::Option; let mut _4: isize; let mut _5: isize; +- let mut _7: bool; +- let mut _8: u8; +- let mut _9: bool; scope 1 { debug a => _6; let _6: u8; @@ -32,9 +35,7 @@ } bb2: { - StorageLive(_6); _6 = copy (((_1.0: std::option::Option) as Some).0: u8); - StorageDead(_6); goto -> bb3; } diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff index 895b0067d2e6..2c289c664754 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff @@ -8,6 +8,9 @@ let mut _3: std::option::Option; let mut _4: isize; let mut _5: isize; +- let mut _7: bool; +- let mut _8: u8; +- let mut _9: bool; scope 1 { debug a => _6; let _6: u8; @@ -32,9 +35,7 @@ } bb2: { - StorageLive(_6); _6 = copy (((_1.0: std::option::Option) as Some).0: u8); - StorageDead(_6); goto -> bb3; } diff --git a/tests/pretty/hir-delegation.pp b/tests/pretty/hir-delegation.pp index 872a6a45aede..e452cee63659 100644 --- a/tests/pretty/hir-delegation.pp +++ b/tests/pretty/hir-delegation.pp @@ -2,7 +2,8 @@ //@ pretty-mode:hir //@ pp-exact:hir-delegation.pp -#![allow(incomplete_features)]#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![feature(fn_delegation)] #[prelude_import] use ::std::prelude::rust_2015::*; #[macro_use] diff --git a/tests/run-make/arm64ec-import-export-static/export.rs b/tests/run-make/arm64ec-import-export-static/export.rs new file mode 100644 index 000000000000..98b3a66d80c0 --- /dev/null +++ b/tests/run-make/arm64ec-import-export-static/export.rs @@ -0,0 +1,23 @@ +#![crate_type = "dylib"] +#![allow(internal_features)] +#![feature(no_core, lang_items)] +#![no_core] +#![no_std] + +// This is needed because of #![no_core]: +#[lang = "sized"] +trait Sized {} +#[lang = "sync"] +trait Sync {} +impl Sync for i32 {} +#[lang = "copy"] +pub trait Copy {} +impl Copy for i32 {} +#[lang = "drop_in_place"] +pub unsafe fn drop_in_place(_: *mut T) {} +#[no_mangle] +extern "system" fn _DllMainCRTStartup(_: *const u8, _: u32, _: *const u8) -> u32 { + 1 +} + +pub static VALUE: i32 = 42; diff --git a/tests/run-make/arm64ec-import-export-static/import.rs b/tests/run-make/arm64ec-import-export-static/import.rs new file mode 100644 index 000000000000..9d52db251250 --- /dev/null +++ b/tests/run-make/arm64ec-import-export-static/import.rs @@ -0,0 +1,12 @@ +#![crate_type = "cdylib"] +#![allow(internal_features)] +#![feature(no_core)] +#![no_std] +#![no_core] + +extern crate export; + +#[no_mangle] +pub extern "C" fn func() -> i32 { + export::VALUE +} diff --git a/tests/run-make/arm64ec-import-export-static/rmake.rs b/tests/run-make/arm64ec-import-export-static/rmake.rs new file mode 100644 index 000000000000..7fa31144810d --- /dev/null +++ b/tests/run-make/arm64ec-import-export-static/rmake.rs @@ -0,0 +1,15 @@ +// Test that a static can be exported from one crate and imported into another. +// +// This was broken for Arm64EC as only functions, not variables, should be +// decorated with `#`. +// See https://github.com/rust-lang/rust/issues/138541 + +//@ needs-llvm-components: aarch64 +//@ only-windows + +use run_make_support::rustc; + +fn main() { + rustc().input("export.rs").target("aarch64-pc-windows-msvc").panic("abort").run(); + rustc().input("import.rs").target("aarch64-pc-windows-msvc").panic("abort").run(); +} diff --git a/tests/run-make/export/compile-interface-error/app.rs b/tests/run-make/export/compile-interface-error/app.rs new file mode 100644 index 000000000000..f619745a7112 --- /dev/null +++ b/tests/run-make/export/compile-interface-error/app.rs @@ -0,0 +1,3 @@ +extern crate libr; + +fn main() {} diff --git a/tests/run-make/export/compile-interface-error/liblibr.rs b/tests/run-make/export/compile-interface-error/liblibr.rs new file mode 100644 index 000000000000..906d8d7be12c --- /dev/null +++ b/tests/run-make/export/compile-interface-error/liblibr.rs @@ -0,0 +1,5 @@ +#![feature(export_stable)] + +// interface file is broken(priv fn): +#[export_stable] +extern "C" fn foo(); diff --git a/tests/run-make/export/compile-interface-error/rmake.rs b/tests/run-make/export/compile-interface-error/rmake.rs new file mode 100644 index 000000000000..89474e9d4fbf --- /dev/null +++ b/tests/run-make/export/compile-interface-error/rmake.rs @@ -0,0 +1,9 @@ +use run_make_support::rustc; + +fn main() { + // Do not produce the interface, use the broken one. + rustc() + .input("app.rs") + .run_fail() + .assert_stderr_contains("couldn't compile interface"); +} diff --git a/tests/run-make/export/disambiguator/app.rs b/tests/run-make/export/disambiguator/app.rs new file mode 100644 index 000000000000..27e0e2280e54 --- /dev/null +++ b/tests/run-make/export/disambiguator/app.rs @@ -0,0 +1,7 @@ +extern crate libr; + +use libr::*; + +fn main() { + assert_eq!(S::::foo(), 2); +} diff --git a/tests/run-make/export/disambiguator/libr.rs b/tests/run-make/export/disambiguator/libr.rs new file mode 100644 index 000000000000..b294d5c9e8ed --- /dev/null +++ b/tests/run-make/export/disambiguator/libr.rs @@ -0,0 +1,27 @@ +// `S::::foo` and `S::::foo` have same `DefPath` modulo disambiguator. +// `libr.rs` interface may not contain `S::::foo` as private items aren't +// exportable. We should make sure that original `S::::foo` and the one +// produced during interface generation have same mangled names. + +#![feature(export_stable)] +#![crate_type = "sdylib"] + +#[export_stable] +#[repr(C)] +pub struct S(pub T); + +struct S1; +pub struct S2; + +impl S { + extern "C" fn foo() -> i32 { + 1 + } +} + +#[export_stable] +impl S { + pub extern "C" fn foo() -> i32 { + 2 + } +} diff --git a/tests/run-make/export/disambiguator/rmake.rs b/tests/run-make/export/disambiguator/rmake.rs new file mode 100644 index 000000000000..743db1933fb4 --- /dev/null +++ b/tests/run-make/export/disambiguator/rmake.rs @@ -0,0 +1,12 @@ +use run_make_support::rustc; + +fn main() { + rustc() + .env("RUSTC_FORCE_RUSTC_VERSION", "1") + .input("libr.rs") + .run(); + rustc() + .env("RUSTC_FORCE_RUSTC_VERSION", "2") + .input("app.rs") + .run(); +} diff --git a/tests/run-make/export/extern-opt/app.rs b/tests/run-make/export/extern-opt/app.rs new file mode 100644 index 000000000000..765c9925d5f7 --- /dev/null +++ b/tests/run-make/export/extern-opt/app.rs @@ -0,0 +1,6 @@ +extern crate libr; +use libr::*; + +fn main() { + assert_eq!(foo(1), 1); +} diff --git a/tests/run-make/export/extern-opt/libinterface.rs b/tests/run-make/export/extern-opt/libinterface.rs new file mode 100644 index 000000000000..313cfbe7d59c --- /dev/null +++ b/tests/run-make/export/extern-opt/libinterface.rs @@ -0,0 +1,4 @@ +#![feature(export_stable)] + +#[export_stable] +pub extern "C" fn foo(x: i32) -> i32; diff --git a/tests/run-make/export/extern-opt/libr.rs b/tests/run-make/export/extern-opt/libr.rs new file mode 100644 index 000000000000..026ebb4233df --- /dev/null +++ b/tests/run-make/export/extern-opt/libr.rs @@ -0,0 +1,5 @@ +#![feature(export_stable)] +#![crate_type = "sdylib"] + +#[export_stable] +pub extern "C" fn foo(x: i32) -> i32 { x } diff --git a/tests/run-make/export/extern-opt/rmake.rs b/tests/run-make/export/extern-opt/rmake.rs new file mode 100644 index 000000000000..821e2eb21491 --- /dev/null +++ b/tests/run-make/export/extern-opt/rmake.rs @@ -0,0 +1,23 @@ +use run_make_support::{rustc, dynamic_lib_name}; + +fn main() { + rustc() + .env("RUSTC_FORCE_RUSTC_VERSION", "1") + .input("libr.rs") + .run(); + + rustc() + .env("RUSTC_FORCE_RUSTC_VERSION", "2") + .input("app.rs") + .extern_("libr", "libinterface.rs") + .extern_("libr", dynamic_lib_name("libr")) + .run(); + + rustc() + .env("RUSTC_FORCE_RUSTC_VERSION", "2") + .input("app.rs") + .extern_("libr", "interface.rs") // wrong interface format + .extern_("libr", dynamic_lib_name("libr")) + .run_fail() + .assert_stderr_contains("extern location for libr does not exist"); +} diff --git a/tests/run-make/export/simple/app.rs b/tests/run-make/export/simple/app.rs new file mode 100644 index 000000000000..ba34bdd7b566 --- /dev/null +++ b/tests/run-make/export/simple/app.rs @@ -0,0 +1,8 @@ +extern crate libr; +use libr::*; + +fn main() { + let s = m::S { x: 42 }; + assert_eq!(m::foo1(s), 42); + assert_eq!(m::S::foo2(1), 1); +} diff --git a/tests/run-make/export/simple/libr.rs b/tests/run-make/export/simple/libr.rs new file mode 100644 index 000000000000..e10b76a6e52e --- /dev/null +++ b/tests/run-make/export/simple/libr.rs @@ -0,0 +1,22 @@ +#![feature(export_stable)] +#![crate_type = "sdylib"] + +#[export_stable] +pub mod m { + #[repr(C)] + pub struct S { + pub x: i32, + } + + pub extern "C" fn foo1(x: S) -> i32 { + x.x + } + + pub type Integer = i32; + + impl S { + pub extern "C" fn foo2(x: Integer) -> Integer { + x + } + } +} diff --git a/tests/run-make/export/simple/rmake.rs b/tests/run-make/export/simple/rmake.rs new file mode 100644 index 000000000000..743db1933fb4 --- /dev/null +++ b/tests/run-make/export/simple/rmake.rs @@ -0,0 +1,12 @@ +use run_make_support::rustc; + +fn main() { + rustc() + .env("RUSTC_FORCE_RUSTC_VERSION", "1") + .input("libr.rs") + .run(); + rustc() + .env("RUSTC_FORCE_RUSTC_VERSION", "2") + .input("app.rs") + .run(); +} diff --git a/tests/run-make/pointer-auth-link-with-c/test.rs b/tests/run-make/pointer-auth-link-with-c/test.rs index 1a3be80e898b..795c6a45f8e6 100644 --- a/tests/run-make/pointer-auth-link-with-c/test.rs +++ b/tests/run-make/pointer-auth-link-with-c/test.rs @@ -1,4 +1,4 @@ -#[link(name = "test")] +#[link(name = "test", kind = "static")] extern "C" { fn foo() -> i32; } diff --git a/tests/run-make/remap-path-prefix-dwarf/rmake.rs b/tests/run-make/remap-path-prefix-dwarf/rmake.rs index ede1d6157425..3d6ca014fc2a 100644 --- a/tests/run-make/remap-path-prefix-dwarf/rmake.rs +++ b/tests/run-make/remap-path-prefix-dwarf/rmake.rs @@ -91,6 +91,59 @@ fn main() { )), dwarf_test: DwarfDump::ParentTest, }); + + check_dwarf_deps("macro", DwarfDump::AvoidSrcPath); + check_dwarf_deps("diagnostics", DwarfDump::AvoidSrcPath); + check_dwarf_deps("macro,diagnostics", DwarfDump::AvoidSrcPath); + check_dwarf_deps("object", DwarfDump::ContainsSrcPath); +} + +#[track_caller] +fn check_dwarf_deps(scope: &str, dwarf_test: DwarfDump) { + // build some_value.rs + let mut rustc_sm = rustc(); + rustc_sm.input(cwd().join("src/some_value.rs")); + rustc_sm.arg("-Cdebuginfo=2"); + rustc_sm.arg(format!("-Zremap-path-scope={}", scope)); + rustc_sm.arg("--remap-path-prefix"); + rustc_sm.arg(format!("{}=/REMAPPED", cwd().display())); + rustc_sm.arg("-Csplit-debuginfo=off"); + rustc_sm.run(); + + // build print_value.rs + let print_value_rlib = rust_lib_name(&format!("print_value.{scope}")); + let mut rustc_pv = rustc(); + rustc_pv.input(cwd().join("src/print_value.rs")); + rustc_pv.output(&print_value_rlib); + rustc_pv.arg("-Cdebuginfo=2"); + rustc_pv.arg(format!("-Zremap-path-scope={}", scope)); + rustc_pv.arg("--remap-path-prefix"); + rustc_pv.arg(format!("{}=/REMAPPED", cwd().display())); + rustc_pv.arg("-Csplit-debuginfo=off"); + rustc_pv.run(); + + match dwarf_test { + DwarfDump::AvoidSrcPath => { + llvm_dwarfdump() + .input(print_value_rlib) + .run() + .assert_stdout_not_contains("REMAPPED/src/some_value.rs") + .assert_stdout_not_contains("REMAPPED/src/print_value.rs") + .assert_stdout_not_contains("REMAPPED/REMAPPED") + .assert_stdout_contains(cwd().join("src/some_value.rs").display().to_string()) + .assert_stdout_contains(cwd().join("src/print_value.rs").display().to_string()); + } + DwarfDump::ContainsSrcPath => { + llvm_dwarfdump() + .input(print_value_rlib) + .run() + .assert_stdout_contains("REMAPPED/src/some_value.rs") + .assert_stdout_contains("REMAPPED/src/print_value.rs") + .assert_stdout_not_contains(cwd().join("src/some_value.rs").display().to_string()) + .assert_stdout_not_contains(cwd().join("src/print_value.rs").display().to_string()); + } + _ => unreachable!(), + } } #[track_caller] diff --git a/tests/run-make/remap-path-prefix-dwarf/src/print_value.rs b/tests/run-make/remap-path-prefix-dwarf/src/print_value.rs new file mode 100644 index 000000000000..f7653025ba5a --- /dev/null +++ b/tests/run-make/remap-path-prefix-dwarf/src/print_value.rs @@ -0,0 +1,7 @@ +#![crate_type = "rlib"] + +extern crate some_value; + +pub fn print_value() { + println!("{}", some_value::get_some_value()); +} diff --git a/tests/run-make/remap-path-prefix-dwarf/src/some_value.rs b/tests/run-make/remap-path-prefix-dwarf/src/some_value.rs new file mode 100644 index 000000000000..aa95a1bdf73b --- /dev/null +++ b/tests/run-make/remap-path-prefix-dwarf/src/some_value.rs @@ -0,0 +1,6 @@ +#![crate_type = "rlib"] + +#[inline] +pub fn get_some_value() -> i32 { + 42 +} diff --git a/tests/run-make/remap-path-prefix/rmake.rs b/tests/run-make/remap-path-prefix/rmake.rs index aeb30e72d5bf..b4f7f4769b5b 100644 --- a/tests/run-make/remap-path-prefix/rmake.rs +++ b/tests/run-make/remap-path-prefix/rmake.rs @@ -47,10 +47,10 @@ fn main() { out_object.run(); rmeta_contains("/the/aux/lib.rs"); - rmeta_not_contains("auxiliary"); + rmeta_contains("auxiliary"); out_macro.run(); rmeta_contains("/the/aux/lib.rs"); - rmeta_not_contains("auxiliary"); + rmeta_contains("auxiliary"); out_diagobj.run(); rmeta_contains("/the/aux/lib.rs"); rmeta_not_contains("auxiliary"); @@ -58,6 +58,7 @@ fn main() { //FIXME(Oneirical): These could be generalized into run_make_support // helper functions. +#[track_caller] fn rmeta_contains(expected: &str) { // Normalize to account for path differences in Windows. if !bstr::BString::from(rfs::read("liblib.rmeta")).replace(b"\\", b"/").contains_str(expected) { @@ -69,6 +70,7 @@ fn rmeta_contains(expected: &str) { } } +#[track_caller] fn rmeta_not_contains(expected: &str) { // Normalize to account for path differences in Windows. if bstr::BString::from(rfs::read("liblib.rmeta")).replace(b"\\", b"/").contains_str(expected) { diff --git a/tests/run-make/rustdoc-tempdir-removal/compile-error.rs b/tests/run-make/rustdoc-tempdir-removal/compile-error.rs new file mode 100644 index 000000000000..66a3b3f270b7 --- /dev/null +++ b/tests/run-make/rustdoc-tempdir-removal/compile-error.rs @@ -0,0 +1,5 @@ +#![doc(test(attr(deny(warnings))))] + +//! ``` +//! let a = 12; +//! ``` diff --git a/tests/run-make/rustdoc-tempdir-removal/rmake.rs b/tests/run-make/rustdoc-tempdir-removal/rmake.rs new file mode 100644 index 000000000000..9ad369ae5b10 --- /dev/null +++ b/tests/run-make/rustdoc-tempdir-removal/rmake.rs @@ -0,0 +1,42 @@ +// This test ensures that no temporary folder is "left behind" when doctests fail for any reason. + +//@ ignore-cross-compile + +use std::path::Path; + +use run_make_support::{path, rfs, rustdoc}; + +fn run_doctest_and_check_tmpdir(tmp_dir: &Path, doctest: &str, edition: &str) { + let mut runner = rustdoc(); + runner.input(doctest).arg("--test").edition(edition); + let output = if cfg!(unix) { + runner.env("TMPDIR", tmp_dir) + } else if cfg!(windows) { + runner.env("TEMP", tmp_dir).env("TMP", tmp_dir) + } else { + panic!("unsupported OS") + } + .run_fail(); + + output.assert_exit_code(101).assert_stdout_contains( + "test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out", + ); + + rfs::read_dir_entries(tmp_dir, |entry| { + panic!("Found an item inside the temporary folder: {entry:?}"); + }); +} + +fn run_doctest_and_check_tmpdir_for_edition(tmp_dir: &Path, edition: &str) { + run_doctest_and_check_tmpdir(tmp_dir, "compile-error.rs", edition); + run_doctest_and_check_tmpdir(tmp_dir, "run-error.rs", edition); +} + +fn main() { + let tmp_dir = path("tmp"); + rfs::create_dir(&tmp_dir); + + run_doctest_and_check_tmpdir_for_edition(&tmp_dir, "2018"); + // We use the 2024 edition to check that it's also working for merged doctests. + run_doctest_and_check_tmpdir_for_edition(&tmp_dir, "2024"); +} diff --git a/tests/run-make/rustdoc-tempdir-removal/run-error.rs b/tests/run-make/rustdoc-tempdir-removal/run-error.rs new file mode 100644 index 000000000000..4ac95f6dd61a --- /dev/null +++ b/tests/run-make/rustdoc-tempdir-removal/run-error.rs @@ -0,0 +1,3 @@ +//! ``` +//! panic!(); +//! ``` diff --git a/tests/run-make/sanitizer-dylib-link/program.rs b/tests/run-make/sanitizer-dylib-link/program.rs index 1026c7f89ba9..dbf885d343fe 100644 --- a/tests/run-make/sanitizer-dylib-link/program.rs +++ b/tests/run-make/sanitizer-dylib-link/program.rs @@ -1,4 +1,4 @@ -#[cfg_attr(windows, link(name = "library.dll.lib", modifiers = "+verbatim"))] +#[cfg_attr(windows, link(name = "library", kind = "raw-dylib"))] #[cfg_attr(not(windows), link(name = "library"))] extern "C" { fn overflow(); diff --git a/tests/rustdoc-gui/sidebar.goml b/tests/rustdoc-gui/sidebar.goml index 38160cc49d08..9c66b84165f8 100644 --- a/tests/rustdoc-gui/sidebar.goml +++ b/tests/rustdoc-gui/sidebar.goml @@ -199,6 +199,42 @@ assert-position-false: (".sidebar-crate > h2 > a", {"x": -3}) drag-and-drop: ((205, 100), (108, 100)) assert-position: (".sidebar-crate > h2 > a", {"x": -3}) +// Check that the mobile sidebar and the source sidebar use the same icon. +store-css: (".mobile-topbar .sidebar-menu-toggle::before", {"content": image_url}) +// Then we go to a source page. +click: ".main-heading .src" +assert-css: ("#sidebar-button a::before", {"content": |image_url|}) +// Check that hover events work as expected. +store-css: ("#sidebar-button a", {"background-color": sidebar_background}) +move-cursor-to: "#sidebar-button a" +store-css: ("#sidebar-button a:hover", {"background-color": sidebar_background_hover}) +assert: |sidebar_background| != |sidebar_background_hover| +click: "#sidebar-button a" +wait-for: "html.src-sidebar-expanded" +assert-css: ("#sidebar-button a:hover", {"background-color": |sidebar_background_hover|}) +move-cursor-to: "#settings-menu" +assert-css: ("#sidebar-button a:not(:hover)", {"background-color": |sidebar_background|}) +// Closing sidebar. +click: "#sidebar-button a" +wait-for: "html:not(.src-sidebar-expanded)" +// Now we check the same when the sidebar button is moved alongside the search. +set-window-size: (500, 500) +store-css: ("#sidebar-button a:hover", {"background-color": not_sidebar_background_hover}) +move-cursor-to: "#settings-menu" +store-css: ("#sidebar-button a:not(:hover)", {"background-color": not_sidebar_background}) +// The sidebar background is supposed to be the same as the main background. +assert-css: ("body", {"background-color": |not_sidebar_background|}) +assert: |not_sidebar_background| != |not_sidebar_background_hover| && |not_sidebar_background| != |sidebar_background| +// The hover background is supposed to be the same as the sidebar background. +assert: |not_sidebar_background_hover| == |sidebar_background| +click: "#sidebar-button a" +wait-for: "html.src-sidebar-expanded" +// And now the background colors are supposed to be the same as the sidebar since the sidebar has +// been open. +assert-css: ("#sidebar-button a:hover", {"background-color": |sidebar_background_hover|}) +move-cursor-to: "h2" +assert-css: ("#sidebar-button a:not(:hover)", {"background-color": |sidebar_background|}) + // Configuration option to show TOC in sidebar. set-local-storage: {"rustdoc-hide-toc": "true"} go-to: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html" diff --git a/tests/rustdoc-js-std/path-maxeditdistance.js b/tests/rustdoc-js-std/path-maxeditdistance.js index fd12a0564966..6989e7d6488b 100644 --- a/tests/rustdoc-js-std/path-maxeditdistance.js +++ b/tests/rustdoc-js-std/path-maxeditdistance.js @@ -13,9 +13,9 @@ const EXPECTED = [ { 'path': 'std::vec', 'name': 'IntoIter' }, { 'path': 'std::vec::Vec', 'name': 'from_iter' }, { 'path': 'std::vec::Vec', 'name': 'into_iter' }, + { 'path': 'std::vec::ExtractIf', 'name': 'into_iter' }, { 'path': 'std::vec::Drain', 'name': 'into_iter' }, { 'path': 'std::vec::IntoIter', 'name': 'into_iter' }, - { 'path': 'std::vec::ExtractIf', 'name': 'into_iter' }, { 'path': 'std::vec::Splice', 'name': 'into_iter' }, { 'path': 'std::collections::VecDeque', 'name': 'iter' }, { 'path': 'std::collections::VecDeque', 'name': 'iter_mut' }, diff --git a/tests/rustdoc-ui/ice-bug-report-url.rs b/tests/rustdoc-ui/ice-bug-report-url.rs index 9260644e44f1..2e384fa1be62 100644 --- a/tests/rustdoc-ui/ice-bug-report-url.rs +++ b/tests/rustdoc-ui/ice-bug-report-url.rs @@ -1,8 +1,6 @@ //@ compile-flags: -Ztreat-err-as-bug //@ rustc-env:RUSTC_ICE=0 //@ failure-status: 101 -//@ error-pattern: aborting due to -//@ error-pattern: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md //@ normalize-stderr: "note: compiler flags.*\n\n" -> "" //@ normalize-stderr: "note: rustc.*running on.*" -> "note: rustc {version} running on {platform}" @@ -13,3 +11,6 @@ fn wrong() //~^ ERROR expected one of + +//~? RAW aborting due to +//~? RAW we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md diff --git a/tests/rustdoc-ui/ice-bug-report-url.stderr b/tests/rustdoc-ui/ice-bug-report-url.stderr index 14a961c2ce01..b6eb8a1792df 100644 --- a/tests/rustdoc-ui/ice-bug-report-url.stderr +++ b/tests/rustdoc-ui/ice-bug-report-url.stderr @@ -1,5 +1,5 @@ error: internal compiler error: expected one of `->`, `where`, or `{`, found `` - --> $DIR/ice-bug-report-url.rs:14:10 + --> $DIR/ice-bug-report-url.rs:12:10 | LL | fn wrong() | ^ expected one of `->`, `where`, or `{` diff --git a/tests/rustdoc-ui/issues/issue-81662-shortness.rs b/tests/rustdoc-ui/issues/issue-81662-shortness.rs index 8719442c34f9..5d1951dbe3ee 100644 --- a/tests/rustdoc-ui/issues/issue-81662-shortness.rs +++ b/tests/rustdoc-ui/issues/issue-81662-shortness.rs @@ -1,6 +1,5 @@ //@ compile-flags:--test --error-format=short //@ check-stdout -//@ error-pattern:cannot find function `foo` //@ normalize-stdout: "tests/rustdoc-ui/issues" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ failure-status: 101 @@ -11,3 +10,5 @@ fn foo() { println!("Hello, world!"); } + +//~? RAW cannot find function `foo` diff --git a/tests/rustdoc-ui/issues/issue-81662-shortness.stdout b/tests/rustdoc-ui/issues/issue-81662-shortness.stdout index 8fcc7ed272f0..94a82cf0afc4 100644 --- a/tests/rustdoc-ui/issues/issue-81662-shortness.stdout +++ b/tests/rustdoc-ui/issues/issue-81662-shortness.stdout @@ -1,16 +1,16 @@ running 1 test -test $DIR/issue-81662-shortness.rs - foo (line 8) ... FAILED +test $DIR/issue-81662-shortness.rs - foo (line 7) ... FAILED failures: ----- $DIR/issue-81662-shortness.rs - foo (line 8) stdout ---- -$DIR/issue-81662-shortness.rs:9:1: error[E0425]: cannot find function `foo` in this scope: not found in this scope +---- $DIR/issue-81662-shortness.rs - foo (line 7) stdout ---- +$DIR/issue-81662-shortness.rs:8:1: error[E0425]: cannot find function `foo` in this scope: not found in this scope error: aborting due to 1 previous error Couldn't compile the test. failures: - $DIR/issue-81662-shortness.rs - foo (line 8) + $DIR/issue-81662-shortness.rs - foo (line 7) test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/issues/issue-83883-describe-lints.rs b/tests/rustdoc-ui/issues/issue-83883-describe-lints.rs index 35d2fda45850..62a0942df1b1 100644 --- a/tests/rustdoc-ui/issues/issue-83883-describe-lints.rs +++ b/tests/rustdoc-ui/issues/issue-83883-describe-lints.rs @@ -1,10 +1,11 @@ //@ compile-flags: -W help //@ check-pass //@ check-stdout -//@ error-pattern:Lint checks provided -//@ error-pattern:rustdoc::broken-intra-doc-links // // ignore-tidy-linelength // //@ normalize-stdout: "( +name default meaning\n +---- ------- -------\n)?( *[[:word:]:-]+ (allow |warn |deny |forbid ) [^\n]+\n)+" -> " $$NAMES $$LEVELS $$MEANINGS" //@ normalize-stdout: " +name sub-lints\n +---- ---------\n( *[[:word:]:-]+ [^\n]+\n)+" -> " $$NAMES $$SUB_LINTS" + +//~? RAW Lint checks provided +//~? RAW rustdoc::broken-intra-doc-links diff --git a/tests/rustdoc-ui/unportable-markdown.rs b/tests/rustdoc-ui/unportable-markdown.rs deleted file mode 100644 index 105fc1e59d53..000000000000 --- a/tests/rustdoc-ui/unportable-markdown.rs +++ /dev/null @@ -1,62 +0,0 @@ -// https://internals.rust-lang.org/t/proposal-migrate-the-syntax-of-rustdoc-markdown-footnotes-to-be-compatible-with-the-syntax-used-in-github/18929 -// -// A series of test cases for CommonMark corner cases that pulldown-cmark 0.11 fixes. -// -// This version of the lint is targeted at two especially-common cases where docs got broken. -// Other differences in parsing should not warn. -#![allow(rustdoc::broken_intra_doc_links)] -#![deny(rustdoc::unportable_markdown)] - -/// -/// -/// Test footnote [^foot]. -/// -/// [^foot]: This is nested within the footnote now, but didn't used to be. -/// -/// This is a multi-paragraph footnote. -pub struct GfmFootnotes; - -/// -/// -/// test [^foo][^bar] -/// -/// [^foo]: test -/// [^bar]: test2 -pub struct FootnoteSmashedName; - -/// -/// -/// - _t -/// # test -/// t_ -pub struct NestingCornerCase; - -/// -/// -/// *~~__emphasis strike strong__~~* ~~*__strike emphasis strong__*~~ -pub struct Emphasis1; - -/// -/// -/// | -/// | -pub struct NotEnoughTable; - -/// -/// -/// foo -/// >bar -//~^ ERROR unportable markdown -pub struct BlockQuoteNoSpace; - -/// Negative test. -/// -/// foo -/// > bar -pub struct BlockQuoteSpace; - -/// Negative test. -/// -/// >bar -/// baz -pub struct BlockQuoteNoSpaceStart; diff --git a/tests/rustdoc-ui/unportable-markdown.stderr b/tests/rustdoc-ui/unportable-markdown.stderr deleted file mode 100644 index 952ae4bb6eec..000000000000 --- a/tests/rustdoc-ui/unportable-markdown.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: unportable markdown - --> $DIR/unportable-markdown.rs:48:5 - | -LL | /// >bar - | ^ - | - = help: confusing block quote with no space after the `>` marker -note: the lint level is defined here - --> $DIR/unportable-markdown.rs:8:9 - | -LL | #![deny(rustdoc::unportable_markdown)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: if the quote is intended, add a space - | -LL | /// > bar - | + -help: if it should not be a quote, escape it - | -LL | /// \>bar - | + - -error: aborting due to 1 previous error - diff --git a/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs b/tests/rustdoc/anchors/anchor-id-duplicate-method-name-25001.rs similarity index 100% rename from tests/rustdoc/anchor-id-duplicate-method-name-25001.rs rename to tests/rustdoc/anchors/anchor-id-duplicate-method-name-25001.rs diff --git a/tests/rustdoc/anchor-id-trait-method-15169.rs b/tests/rustdoc/anchors/anchor-id-trait-method-15169.rs similarity index 100% rename from tests/rustdoc/anchor-id-trait-method-15169.rs rename to tests/rustdoc/anchors/anchor-id-trait-method-15169.rs diff --git a/tests/rustdoc/anchor-id-trait-tymethod-28478.rs b/tests/rustdoc/anchors/anchor-id-trait-tymethod-28478.rs similarity index 100% rename from tests/rustdoc/anchor-id-trait-tymethod-28478.rs rename to tests/rustdoc/anchors/anchor-id-trait-tymethod-28478.rs diff --git a/tests/rustdoc/anchors.no_const_anchor.html b/tests/rustdoc/anchors/anchors.no_const_anchor.html similarity index 100% rename from tests/rustdoc/anchors.no_const_anchor.html rename to tests/rustdoc/anchors/anchors.no_const_anchor.html diff --git a/tests/rustdoc/anchors.no_const_anchor2.html b/tests/rustdoc/anchors/anchors.no_const_anchor2.html similarity index 100% rename from tests/rustdoc/anchors.no_const_anchor2.html rename to tests/rustdoc/anchors/anchors.no_const_anchor2.html diff --git a/tests/rustdoc/anchors.no_method_anchor.html b/tests/rustdoc/anchors/anchors.no_method_anchor.html similarity index 100% rename from tests/rustdoc/anchors.no_method_anchor.html rename to tests/rustdoc/anchors/anchors.no_method_anchor.html diff --git a/tests/rustdoc/anchors.no_trait_method_anchor.html b/tests/rustdoc/anchors/anchors.no_trait_method_anchor.html similarity index 100% rename from tests/rustdoc/anchors.no_trait_method_anchor.html rename to tests/rustdoc/anchors/anchors.no_trait_method_anchor.html diff --git a/tests/rustdoc/anchors.no_tymethod_anchor.html b/tests/rustdoc/anchors/anchors.no_tymethod_anchor.html similarity index 100% rename from tests/rustdoc/anchors.no_tymethod_anchor.html rename to tests/rustdoc/anchors/anchors.no_tymethod_anchor.html diff --git a/tests/rustdoc/anchors.no_type_anchor.html b/tests/rustdoc/anchors/anchors.no_type_anchor.html similarity index 100% rename from tests/rustdoc/anchors.no_type_anchor.html rename to tests/rustdoc/anchors/anchors.no_type_anchor.html diff --git a/tests/rustdoc/anchors.no_type_anchor2.html b/tests/rustdoc/anchors/anchors.no_type_anchor2.html similarity index 100% rename from tests/rustdoc/anchors.no_type_anchor2.html rename to tests/rustdoc/anchors/anchors.no_type_anchor2.html diff --git a/tests/rustdoc/anchors.rs b/tests/rustdoc/anchors/anchors.rs similarity index 100% rename from tests/rustdoc/anchors.rs rename to tests/rustdoc/anchors/anchors.rs diff --git a/tests/rustdoc/auxiliary/issue-86620-1.rs b/tests/rustdoc/anchors/auxiliary/issue-86620-1.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-86620-1.rs rename to tests/rustdoc/anchors/auxiliary/issue-86620-1.rs diff --git a/tests/rustdoc/disambiguate-anchors-32890.rs b/tests/rustdoc/anchors/disambiguate-anchors-32890.rs similarity index 100% rename from tests/rustdoc/disambiguate-anchors-32890.rs rename to tests/rustdoc/anchors/disambiguate-anchors-32890.rs diff --git a/tests/rustdoc/disambiguate-anchors-header-29449.rs b/tests/rustdoc/anchors/disambiguate-anchors-header-29449.rs similarity index 100% rename from tests/rustdoc/disambiguate-anchors-header-29449.rs rename to tests/rustdoc/anchors/disambiguate-anchors-header-29449.rs diff --git a/tests/rustdoc/method-anchor-in-blanket-impl-86620.rs b/tests/rustdoc/anchors/method-anchor-in-blanket-impl-86620.rs similarity index 100% rename from tests/rustdoc/method-anchor-in-blanket-impl-86620.rs rename to tests/rustdoc/anchors/method-anchor-in-blanket-impl-86620.rs diff --git a/tests/rustdoc/trait-impl-items-links-and-anchors.rs b/tests/rustdoc/anchors/trait-impl-items-links-and-anchors.rs similarity index 100% rename from tests/rustdoc/trait-impl-items-links-and-anchors.rs rename to tests/rustdoc/anchors/trait-impl-items-links-and-anchors.rs diff --git a/tests/rustdoc/assoc-fns.rs b/tests/rustdoc/assoc/assoc-fns.rs similarity index 100% rename from tests/rustdoc/assoc-fns.rs rename to tests/rustdoc/assoc/assoc-fns.rs diff --git a/tests/rustdoc/assoc-item-cast.rs b/tests/rustdoc/assoc/assoc-item-cast.rs similarity index 100% rename from tests/rustdoc/assoc-item-cast.rs rename to tests/rustdoc/assoc/assoc-item-cast.rs diff --git a/tests/rustdoc/assoc-type-bindings-20646.rs b/tests/rustdoc/assoc/assoc-type-bindings-20646.rs similarity index 100% rename from tests/rustdoc/assoc-type-bindings-20646.rs rename to tests/rustdoc/assoc/assoc-type-bindings-20646.rs diff --git a/tests/rustdoc/assoc-types.rs b/tests/rustdoc/assoc/assoc-types.rs similarity index 100% rename from tests/rustdoc/assoc-types.rs rename to tests/rustdoc/assoc/assoc-types.rs diff --git a/tests/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs b/tests/rustdoc/assoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs similarity index 100% rename from tests/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs rename to tests/rustdoc/assoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs diff --git a/tests/rustdoc/auxiliary/issue-20646.rs b/tests/rustdoc/assoc/auxiliary/issue-20646.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-20646.rs rename to tests/rustdoc/assoc/auxiliary/issue-20646.rs diff --git a/tests/rustdoc/auxiliary/issue-20727.rs b/tests/rustdoc/assoc/auxiliary/issue-20727.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-20727.rs rename to tests/rustdoc/assoc/auxiliary/issue-20727.rs diff --git a/tests/rustdoc/auxiliary/normalize-assoc-item.rs b/tests/rustdoc/assoc/auxiliary/normalize-assoc-item.rs similarity index 100% rename from tests/rustdoc/auxiliary/normalize-assoc-item.rs rename to tests/rustdoc/assoc/auxiliary/normalize-assoc-item.rs diff --git a/tests/rustdoc/cross-crate-hidden-assoc-trait-items.rs b/tests/rustdoc/assoc/cross-crate-hidden-assoc-trait-items.rs similarity index 100% rename from tests/rustdoc/cross-crate-hidden-assoc-trait-items.rs rename to tests/rustdoc/assoc/cross-crate-hidden-assoc-trait-items.rs diff --git a/tests/rustdoc/doc-assoc-item.rs b/tests/rustdoc/assoc/doc-assoc-item.rs similarity index 100% rename from tests/rustdoc/doc-assoc-item.rs rename to tests/rustdoc/assoc/doc-assoc-item.rs diff --git a/tests/rustdoc/inline-assoc-type-20727-bindings.rs b/tests/rustdoc/assoc/inline-assoc-type-20727-bindings.rs similarity index 100% rename from tests/rustdoc/inline-assoc-type-20727-bindings.rs rename to tests/rustdoc/assoc/inline-assoc-type-20727-bindings.rs diff --git a/tests/rustdoc/inline-assoc-type-20727-bounds-deref.rs b/tests/rustdoc/assoc/inline-assoc-type-20727-bounds-deref.rs similarity index 100% rename from tests/rustdoc/inline-assoc-type-20727-bounds-deref.rs rename to tests/rustdoc/assoc/inline-assoc-type-20727-bounds-deref.rs diff --git a/tests/rustdoc/inline-assoc-type-20727-bounds-index.rs b/tests/rustdoc/assoc/inline-assoc-type-20727-bounds-index.rs similarity index 100% rename from tests/rustdoc/inline-assoc-type-20727-bounds-index.rs rename to tests/rustdoc/assoc/inline-assoc-type-20727-bounds-index.rs diff --git a/tests/rustdoc/inline-assoc-type-20727-bounds.rs b/tests/rustdoc/assoc/inline-assoc-type-20727-bounds.rs similarity index 100% rename from tests/rustdoc/inline-assoc-type-20727-bounds.rs rename to tests/rustdoc/assoc/inline-assoc-type-20727-bounds.rs diff --git a/tests/rustdoc/normalize-assoc-item.rs b/tests/rustdoc/assoc/normalize-assoc-item.rs similarity index 100% rename from tests/rustdoc/normalize-assoc-item.rs rename to tests/rustdoc/assoc/normalize-assoc-item.rs diff --git a/tests/rustdoc/async-fn-opaque-item.rs b/tests/rustdoc/async/async-fn-opaque-item.rs similarity index 100% rename from tests/rustdoc/async-fn-opaque-item.rs rename to tests/rustdoc/async/async-fn-opaque-item.rs diff --git a/tests/rustdoc/async-fn.rs b/tests/rustdoc/async/async-fn.rs similarity index 100% rename from tests/rustdoc/async-fn.rs rename to tests/rustdoc/async/async-fn.rs diff --git a/tests/rustdoc/async-move-doctest.rs b/tests/rustdoc/async/async-move-doctest.rs similarity index 100% rename from tests/rustdoc/async-move-doctest.rs rename to tests/rustdoc/async/async-move-doctest.rs diff --git a/tests/rustdoc/async-trait-sig.rs b/tests/rustdoc/async/async-trait-sig.rs similarity index 100% rename from tests/rustdoc/async-trait-sig.rs rename to tests/rustdoc/async/async-trait-sig.rs diff --git a/tests/rustdoc/async-trait.rs b/tests/rustdoc/async/async-trait.rs similarity index 100% rename from tests/rustdoc/async-trait.rs rename to tests/rustdoc/async/async-trait.rs diff --git a/tests/rustdoc/auxiliary/async-trait-dep.rs b/tests/rustdoc/async/auxiliary/async-trait-dep.rs similarity index 100% rename from tests/rustdoc/auxiliary/async-trait-dep.rs rename to tests/rustdoc/async/auxiliary/async-trait-dep.rs diff --git a/tests/rustdoc/auto-impl-for-trait.rs b/tests/rustdoc/auto/auto-impl-for-trait.rs similarity index 100% rename from tests/rustdoc/auto-impl-for-trait.rs rename to tests/rustdoc/auto/auto-impl-for-trait.rs diff --git a/tests/rustdoc/auto-impl-primitive.rs b/tests/rustdoc/auto/auto-impl-primitive.rs similarity index 100% rename from tests/rustdoc/auto-impl-primitive.rs rename to tests/rustdoc/auto/auto-impl-primitive.rs diff --git a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs b/tests/rustdoc/auto/auto-trait-bounds-by-associated-type-50159.rs similarity index 100% rename from tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs rename to tests/rustdoc/auto/auto-trait-bounds-by-associated-type-50159.rs diff --git a/tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs b/tests/rustdoc/auto/auto-trait-bounds-inference-variables-54705.rs similarity index 100% rename from tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs rename to tests/rustdoc/auto/auto-trait-bounds-inference-variables-54705.rs diff --git a/tests/rustdoc/auto-trait-bounds-where-51236.rs b/tests/rustdoc/auto/auto-trait-bounds-where-51236.rs similarity index 100% rename from tests/rustdoc/auto-trait-bounds-where-51236.rs rename to tests/rustdoc/auto/auto-trait-bounds-where-51236.rs diff --git a/tests/rustdoc/auto-trait-negative-impl-55321.rs b/tests/rustdoc/auto/auto-trait-negative-impl-55321.rs similarity index 100% rename from tests/rustdoc/auto-trait-negative-impl-55321.rs rename to tests/rustdoc/auto/auto-trait-negative-impl-55321.rs diff --git a/tests/rustdoc/auto-trait-not-send.rs b/tests/rustdoc/auto/auto-trait-not-send.rs similarity index 100% rename from tests/rustdoc/auto-trait-not-send.rs rename to tests/rustdoc/auto/auto-trait-not-send.rs diff --git a/tests/rustdoc/auto-traits.rs b/tests/rustdoc/auto/auto-traits.rs similarity index 100% rename from tests/rustdoc/auto-traits.rs rename to tests/rustdoc/auto/auto-traits.rs diff --git a/tests/rustdoc/auto_aliases.rs b/tests/rustdoc/auto/auto_aliases.rs similarity index 100% rename from tests/rustdoc/auto_aliases.rs rename to tests/rustdoc/auto/auto_aliases.rs diff --git a/tests/rustdoc/auxiliary/auto-traits.rs b/tests/rustdoc/auto/auxiliary/auto-traits.rs similarity index 100% rename from tests/rustdoc/auxiliary/auto-traits.rs rename to tests/rustdoc/auto/auxiliary/auto-traits.rs diff --git a/tests/rustdoc/assoc-consts-underscore.rs b/tests/rustdoc/constant/assoc-consts-underscore.rs similarity index 100% rename from tests/rustdoc/assoc-consts-underscore.rs rename to tests/rustdoc/constant/assoc-consts-underscore.rs diff --git a/tests/rustdoc/assoc-consts-version.rs b/tests/rustdoc/constant/assoc-consts-version.rs similarity index 100% rename from tests/rustdoc/assoc-consts-version.rs rename to tests/rustdoc/constant/assoc-consts-version.rs diff --git a/tests/rustdoc/assoc-consts.rs b/tests/rustdoc/constant/assoc-consts.rs similarity index 100% rename from tests/rustdoc/assoc-consts.rs rename to tests/rustdoc/constant/assoc-consts.rs diff --git a/tests/rustdoc/associated-consts.rs b/tests/rustdoc/constant/associated-consts.rs similarity index 100% rename from tests/rustdoc/associated-consts.rs rename to tests/rustdoc/constant/associated-consts.rs diff --git a/tests/rustdoc/const-display.rs b/tests/rustdoc/constant/const-display.rs similarity index 100% rename from tests/rustdoc/const-display.rs rename to tests/rustdoc/constant/const-display.rs diff --git a/tests/rustdoc/const-doc.rs b/tests/rustdoc/constant/const-doc.rs similarity index 100% rename from tests/rustdoc/const-doc.rs rename to tests/rustdoc/constant/const-doc.rs diff --git a/tests/rustdoc/const-effect-param.rs b/tests/rustdoc/constant/const-effect-param.rs similarity index 100% rename from tests/rustdoc/const-effect-param.rs rename to tests/rustdoc/constant/const-effect-param.rs diff --git a/tests/rustdoc/const-underscore.rs b/tests/rustdoc/constant/const-underscore.rs similarity index 100% rename from tests/rustdoc/const-underscore.rs rename to tests/rustdoc/constant/const-underscore.rs diff --git a/tests/rustdoc/const-value-display.rs b/tests/rustdoc/constant/const-value-display.rs similarity index 100% rename from tests/rustdoc/const-value-display.rs rename to tests/rustdoc/constant/const-value-display.rs diff --git a/tests/rustdoc/const.rs b/tests/rustdoc/constant/const.rs similarity index 100% rename from tests/rustdoc/const.rs rename to tests/rustdoc/constant/const.rs diff --git a/tests/rustdoc/document-item-with-associated-const-in-where-clause.rs b/tests/rustdoc/constant/document-item-with-associated-const-in-where-clause.rs similarity index 100% rename from tests/rustdoc/document-item-with-associated-const-in-where-clause.rs rename to tests/rustdoc/constant/document-item-with-associated-const-in-where-clause.rs diff --git a/tests/rustdoc/generic-const-items.rs b/tests/rustdoc/constant/generic-const-items.rs similarity index 100% rename from tests/rustdoc/generic-const-items.rs rename to tests/rustdoc/constant/generic-const-items.rs diff --git a/tests/rustdoc/generic_const_exprs.rs b/tests/rustdoc/constant/generic_const_exprs.rs similarity index 100% rename from tests/rustdoc/generic_const_exprs.rs rename to tests/rustdoc/constant/generic_const_exprs.rs diff --git a/tests/rustdoc/glob-shadowing-const.rs b/tests/rustdoc/constant/glob-shadowing-const.rs similarity index 100% rename from tests/rustdoc/glob-shadowing-const.rs rename to tests/rustdoc/constant/glob-shadowing-const.rs diff --git a/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs b/tests/rustdoc/constant/hide-complex-unevaluated-const-arguments.rs similarity index 100% rename from tests/rustdoc/hide-complex-unevaluated-const-arguments.rs rename to tests/rustdoc/constant/hide-complex-unevaluated-const-arguments.rs diff --git a/tests/rustdoc/hide-complex-unevaluated-consts.rs b/tests/rustdoc/constant/hide-complex-unevaluated-consts.rs similarity index 100% rename from tests/rustdoc/hide-complex-unevaluated-consts.rs rename to tests/rustdoc/constant/hide-complex-unevaluated-consts.rs diff --git a/tests/rustdoc/ice-associated-const-equality-105952.rs b/tests/rustdoc/constant/ice-associated-const-equality-105952.rs similarity index 100% rename from tests/rustdoc/ice-associated-const-equality-105952.rs rename to tests/rustdoc/constant/ice-associated-const-equality-105952.rs diff --git a/tests/rustdoc/legacy-const-generic.rs b/tests/rustdoc/constant/legacy-const-generic.rs similarity index 100% rename from tests/rustdoc/legacy-const-generic.rs rename to tests/rustdoc/constant/legacy-const-generic.rs diff --git a/tests/rustdoc/link-assoc-const.rs b/tests/rustdoc/constant/link-assoc-const.rs similarity index 100% rename from tests/rustdoc/link-assoc-const.rs rename to tests/rustdoc/constant/link-assoc-const.rs diff --git a/tests/rustdoc/redirect-const.rs b/tests/rustdoc/constant/redirect-const.rs similarity index 100% rename from tests/rustdoc/redirect-const.rs rename to tests/rustdoc/constant/redirect-const.rs diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/constant/rfc-2632-const-trait-impl.rs similarity index 100% rename from tests/rustdoc/rfc-2632-const-trait-impl.rs rename to tests/rustdoc/constant/rfc-2632-const-trait-impl.rs diff --git a/tests/rustdoc/show-const-contents.rs b/tests/rustdoc/constant/show-const-contents.rs similarity index 100% rename from tests/rustdoc/show-const-contents.rs rename to tests/rustdoc/constant/show-const-contents.rs diff --git a/tests/rustdoc/doc-cfg-hide.rs b/tests/rustdoc/doc-cfg/doc-cfg-hide.rs similarity index 100% rename from tests/rustdoc/doc-cfg-hide.rs rename to tests/rustdoc/doc-cfg/doc-cfg-hide.rs diff --git a/tests/rustdoc/doc-cfg-implicit-gate.rs b/tests/rustdoc/doc-cfg/doc-cfg-implicit-gate.rs similarity index 100% rename from tests/rustdoc/doc-cfg-implicit-gate.rs rename to tests/rustdoc/doc-cfg/doc-cfg-implicit-gate.rs diff --git a/tests/rustdoc/doc-cfg-implicit.rs b/tests/rustdoc/doc-cfg/doc-cfg-implicit.rs similarity index 100% rename from tests/rustdoc/doc-cfg-implicit.rs rename to tests/rustdoc/doc-cfg/doc-cfg-implicit.rs diff --git a/tests/rustdoc/doc-cfg-inherit-from-module-79201.rs b/tests/rustdoc/doc-cfg/doc-cfg-inherit-from-module-79201.rs similarity index 100% rename from tests/rustdoc/doc-cfg-inherit-from-module-79201.rs rename to tests/rustdoc/doc-cfg/doc-cfg-inherit-from-module-79201.rs diff --git a/tests/rustdoc/doc-cfg-simplification.rs b/tests/rustdoc/doc-cfg/doc-cfg-simplification.rs similarity index 100% rename from tests/rustdoc/doc-cfg-simplification.rs rename to tests/rustdoc/doc-cfg/doc-cfg-simplification.rs diff --git a/tests/rustdoc/doc-cfg-target-feature.rs b/tests/rustdoc/doc-cfg/doc-cfg-target-feature.rs similarity index 100% rename from tests/rustdoc/doc-cfg-target-feature.rs rename to tests/rustdoc/doc-cfg/doc-cfg-target-feature.rs diff --git a/tests/rustdoc/doc-cfg-traits.rs b/tests/rustdoc/doc-cfg/doc-cfg-traits.rs similarity index 100% rename from tests/rustdoc/doc-cfg-traits.rs rename to tests/rustdoc/doc-cfg/doc-cfg-traits.rs diff --git a/tests/rustdoc/doc-cfg.rs b/tests/rustdoc/doc-cfg/doc-cfg.rs similarity index 100% rename from tests/rustdoc/doc-cfg.rs rename to tests/rustdoc/doc-cfg/doc-cfg.rs diff --git a/tests/rustdoc/auxiliary/enum-variant.rs b/tests/rustdoc/enum/auxiliary/enum-variant.rs similarity index 100% rename from tests/rustdoc/auxiliary/enum-variant.rs rename to tests/rustdoc/enum/auxiliary/enum-variant.rs diff --git a/tests/rustdoc/auxiliary/variant-struct.rs b/tests/rustdoc/enum/auxiliary/variant-struct.rs similarity index 100% rename from tests/rustdoc/auxiliary/variant-struct.rs rename to tests/rustdoc/enum/auxiliary/variant-struct.rs diff --git a/tests/rustdoc/enum-headings.rs b/tests/rustdoc/enum/enum-headings.rs similarity index 100% rename from tests/rustdoc/enum-headings.rs rename to tests/rustdoc/enum/enum-headings.rs diff --git a/tests/rustdoc/enum-non-exhaustive-108925.rs b/tests/rustdoc/enum/enum-non-exhaustive-108925.rs similarity index 100% rename from tests/rustdoc/enum-non-exhaustive-108925.rs rename to tests/rustdoc/enum/enum-non-exhaustive-108925.rs diff --git a/tests/rustdoc/enum-variant-doc-hidden-field-88600.rs b/tests/rustdoc/enum/enum-variant-doc-hidden-field-88600.rs similarity index 100% rename from tests/rustdoc/enum-variant-doc-hidden-field-88600.rs rename to tests/rustdoc/enum/enum-variant-doc-hidden-field-88600.rs diff --git a/tests/rustdoc/enum-variant-fields-heading.rs b/tests/rustdoc/enum/enum-variant-fields-heading.rs similarity index 100% rename from tests/rustdoc/enum-variant-fields-heading.rs rename to tests/rustdoc/enum/enum-variant-fields-heading.rs diff --git a/tests/rustdoc/enum-variant-fields-heading.variants.html b/tests/rustdoc/enum/enum-variant-fields-heading.variants.html similarity index 100% rename from tests/rustdoc/enum-variant-fields-heading.variants.html rename to tests/rustdoc/enum/enum-variant-fields-heading.variants.html diff --git a/tests/rustdoc/enum-variant-value.rs b/tests/rustdoc/enum/enum-variant-value.rs similarity index 100% rename from tests/rustdoc/enum-variant-value.rs rename to tests/rustdoc/enum/enum-variant-value.rs diff --git a/tests/rustdoc/render-enum-variant-structlike-32395.rs b/tests/rustdoc/enum/render-enum-variant-structlike-32395.rs similarity index 100% rename from tests/rustdoc/render-enum-variant-structlike-32395.rs rename to tests/rustdoc/enum/render-enum-variant-structlike-32395.rs diff --git a/tests/rustdoc/strip-enum-variant.no-not-shown.html b/tests/rustdoc/enum/strip-enum-variant.no-not-shown.html similarity index 100% rename from tests/rustdoc/strip-enum-variant.no-not-shown.html rename to tests/rustdoc/enum/strip-enum-variant.no-not-shown.html diff --git a/tests/rustdoc/strip-enum-variant.rs b/tests/rustdoc/enum/strip-enum-variant.rs similarity index 100% rename from tests/rustdoc/strip-enum-variant.rs rename to tests/rustdoc/enum/strip-enum-variant.rs diff --git a/tests/rustdoc/extern/auxiliary/empty.rs b/tests/rustdoc/extern/auxiliary/empty.rs new file mode 100644 index 000000000000..d11c69f812a8 --- /dev/null +++ b/tests/rustdoc/extern/auxiliary/empty.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/rustdoc/auxiliary/extern-links.rs b/tests/rustdoc/extern/auxiliary/extern-links.rs similarity index 100% rename from tests/rustdoc/auxiliary/extern-links.rs rename to tests/rustdoc/extern/auxiliary/extern-links.rs diff --git a/tests/rustdoc/auxiliary/external-cross-doc.md b/tests/rustdoc/extern/auxiliary/external-cross-doc.md similarity index 100% rename from tests/rustdoc/auxiliary/external-cross-doc.md rename to tests/rustdoc/extern/auxiliary/external-cross-doc.md diff --git a/tests/rustdoc/auxiliary/external-cross.rs b/tests/rustdoc/extern/auxiliary/external-cross.rs similarity index 100% rename from tests/rustdoc/auxiliary/external-cross.rs rename to tests/rustdoc/extern/auxiliary/external-cross.rs diff --git a/tests/rustdoc/auxiliary/external-doc.md b/tests/rustdoc/extern/auxiliary/external-doc.md similarity index 100% rename from tests/rustdoc/auxiliary/external-doc.md rename to tests/rustdoc/extern/auxiliary/external-doc.md diff --git a/tests/rustdoc/auxiliary/html_root.rs b/tests/rustdoc/extern/auxiliary/html_root.rs similarity index 100% rename from tests/rustdoc/auxiliary/html_root.rs rename to tests/rustdoc/extern/auxiliary/html_root.rs diff --git a/tests/rustdoc/auxiliary/issue-30109-1.rs b/tests/rustdoc/extern/auxiliary/issue-30109-1.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-30109-1.rs rename to tests/rustdoc/extern/auxiliary/issue-30109-1.rs diff --git a/tests/rustdoc/auxiliary/no_html_root.rs b/tests/rustdoc/extern/auxiliary/no_html_root.rs similarity index 100% rename from tests/rustdoc/auxiliary/no_html_root.rs rename to tests/rustdoc/extern/auxiliary/no_html_root.rs diff --git a/tests/rustdoc/auxiliary/panic-item.rs b/tests/rustdoc/extern/auxiliary/panic-item.rs similarity index 100% rename from tests/rustdoc/auxiliary/panic-item.rs rename to tests/rustdoc/extern/auxiliary/panic-item.rs diff --git a/tests/rustdoc/auxiliary/pub-extern-crate.rs b/tests/rustdoc/extern/auxiliary/pub-extern-crate.rs similarity index 100% rename from tests/rustdoc/auxiliary/pub-extern-crate.rs rename to tests/rustdoc/extern/auxiliary/pub-extern-crate.rs diff --git a/tests/rustdoc/auxiliary/rustdoc-extern-default-method.rs b/tests/rustdoc/extern/auxiliary/rustdoc-extern-default-method.rs similarity index 100% rename from tests/rustdoc/auxiliary/rustdoc-extern-default-method.rs rename to tests/rustdoc/extern/auxiliary/rustdoc-extern-default-method.rs diff --git a/tests/rustdoc/auxiliary/rustdoc-extern-method.rs b/tests/rustdoc/extern/auxiliary/rustdoc-extern-method.rs similarity index 100% rename from tests/rustdoc/auxiliary/rustdoc-extern-method.rs rename to tests/rustdoc/extern/auxiliary/rustdoc-extern-method.rs diff --git a/tests/rustdoc/extern/auxiliary/variant-struct.rs b/tests/rustdoc/extern/auxiliary/variant-struct.rs new file mode 100644 index 000000000000..0f3d2e5f1b7a --- /dev/null +++ b/tests/rustdoc/extern/auxiliary/variant-struct.rs @@ -0,0 +1,5 @@ +pub enum Foo { + Bar { + qux: (), + } +} diff --git a/tests/rustdoc/extern-default-method.no_href_on_anchor.html b/tests/rustdoc/extern/extern-default-method.no_href_on_anchor.html similarity index 100% rename from tests/rustdoc/extern-default-method.no_href_on_anchor.html rename to tests/rustdoc/extern/extern-default-method.no_href_on_anchor.html diff --git a/tests/rustdoc/extern-default-method.rs b/tests/rustdoc/extern/extern-default-method.rs similarity index 100% rename from tests/rustdoc/extern-default-method.rs rename to tests/rustdoc/extern/extern-default-method.rs diff --git a/tests/rustdoc/extern-fn-22038.rs b/tests/rustdoc/extern/extern-fn-22038.rs similarity index 100% rename from tests/rustdoc/extern-fn-22038.rs rename to tests/rustdoc/extern/extern-fn-22038.rs diff --git a/tests/rustdoc/extern-html-root-url-precedence.rs b/tests/rustdoc/extern/extern-html-root-url-precedence.rs similarity index 100% rename from tests/rustdoc/extern-html-root-url-precedence.rs rename to tests/rustdoc/extern/extern-html-root-url-precedence.rs diff --git a/tests/rustdoc/extern-html-root-url.rs b/tests/rustdoc/extern/extern-html-root-url.rs similarity index 100% rename from tests/rustdoc/extern-html-root-url.rs rename to tests/rustdoc/extern/extern-html-root-url.rs diff --git a/tests/rustdoc/extern-links.rs b/tests/rustdoc/extern/extern-links.rs similarity index 100% rename from tests/rustdoc/extern-links.rs rename to tests/rustdoc/extern/extern-links.rs diff --git a/tests/rustdoc/extern-method.rs b/tests/rustdoc/extern/extern-method.rs similarity index 100% rename from tests/rustdoc/extern-method.rs rename to tests/rustdoc/extern/extern-method.rs diff --git a/tests/rustdoc/external-cross.rs b/tests/rustdoc/extern/external-cross.rs similarity index 100% rename from tests/rustdoc/external-cross.rs rename to tests/rustdoc/extern/external-cross.rs diff --git a/tests/rustdoc/external-doc.rs b/tests/rustdoc/extern/external-doc.rs similarity index 100% rename from tests/rustdoc/external-doc.rs rename to tests/rustdoc/extern/external-doc.rs diff --git a/tests/rustdoc/hidden-extern-34025.rs b/tests/rustdoc/extern/hidden-extern-34025.rs similarity index 100% rename from tests/rustdoc/hidden-extern-34025.rs rename to tests/rustdoc/extern/hidden-extern-34025.rs diff --git a/tests/rustdoc/link-extern-crate-33178.rs b/tests/rustdoc/extern/link-extern-crate-33178.rs similarity index 100% rename from tests/rustdoc/link-extern-crate-33178.rs rename to tests/rustdoc/extern/link-extern-crate-33178.rs diff --git a/tests/rustdoc/link-extern-crate-item-30109.rs b/tests/rustdoc/extern/link-extern-crate-item-30109.rs similarity index 100% rename from tests/rustdoc/link-extern-crate-item-30109.rs rename to tests/rustdoc/extern/link-extern-crate-item-30109.rs diff --git a/tests/rustdoc/link-extern-crate-title-33178.rs b/tests/rustdoc/extern/link-extern-crate-title-33178.rs similarity index 100% rename from tests/rustdoc/link-extern-crate-title-33178.rs rename to tests/rustdoc/extern/link-extern-crate-title-33178.rs diff --git a/tests/rustdoc/pub-extern-crate.rs b/tests/rustdoc/extern/pub-extern-crate.rs similarity index 100% rename from tests/rustdoc/pub-extern-crate.rs rename to tests/rustdoc/extern/pub-extern-crate.rs diff --git a/tests/rustdoc/unsafe-extern-blocks.rs b/tests/rustdoc/extern/unsafe-extern-blocks.rs similarity index 100% rename from tests/rustdoc/unsafe-extern-blocks.rs rename to tests/rustdoc/extern/unsafe-extern-blocks.rs diff --git a/tests/rustdoc/unused-extern-crate.rs b/tests/rustdoc/extern/unused-extern-crate.rs similarity index 100% rename from tests/rustdoc/unused-extern-crate.rs rename to tests/rustdoc/extern/unused-extern-crate.rs diff --git a/tests/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs b/tests/rustdoc/impl/auxiliary/cross-crate-hidden-impl-parameter.rs similarity index 100% rename from tests/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs rename to tests/rustdoc/impl/auxiliary/cross-crate-hidden-impl-parameter.rs diff --git a/tests/rustdoc/auxiliary/extern-impl-trait.rs b/tests/rustdoc/impl/auxiliary/extern-impl-trait.rs similarity index 100% rename from tests/rustdoc/auxiliary/extern-impl-trait.rs rename to tests/rustdoc/impl/auxiliary/extern-impl-trait.rs diff --git a/tests/rustdoc/auxiliary/incoherent-impl-types.rs b/tests/rustdoc/impl/auxiliary/incoherent-impl-types.rs similarity index 100% rename from tests/rustdoc/auxiliary/incoherent-impl-types.rs rename to tests/rustdoc/impl/auxiliary/incoherent-impl-types.rs diff --git a/tests/rustdoc/auxiliary/issue-100204-aux.rs b/tests/rustdoc/impl/auxiliary/issue-100204-aux.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-100204-aux.rs rename to tests/rustdoc/impl/auxiliary/issue-100204-aux.rs diff --git a/tests/rustdoc/auxiliary/issue-17476.rs b/tests/rustdoc/impl/auxiliary/issue-17476.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-17476.rs rename to tests/rustdoc/impl/auxiliary/issue-17476.rs diff --git a/tests/rustdoc/auxiliary/issue-21092.rs b/tests/rustdoc/impl/auxiliary/issue-21092.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-21092.rs rename to tests/rustdoc/impl/auxiliary/issue-21092.rs diff --git a/tests/rustdoc/auxiliary/issue-22025.rs b/tests/rustdoc/impl/auxiliary/issue-22025.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-22025.rs rename to tests/rustdoc/impl/auxiliary/issue-22025.rs diff --git a/tests/rustdoc/auxiliary/issue-53689.rs b/tests/rustdoc/impl/auxiliary/issue-53689.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-53689.rs rename to tests/rustdoc/impl/auxiliary/issue-53689.rs diff --git a/tests/rustdoc/auxiliary/precise-capturing.rs b/tests/rustdoc/impl/auxiliary/precise-capturing.rs similarity index 100% rename from tests/rustdoc/auxiliary/precise-capturing.rs rename to tests/rustdoc/impl/auxiliary/precise-capturing.rs diff --git a/tests/rustdoc/auxiliary/real_gimli.rs b/tests/rustdoc/impl/auxiliary/real_gimli.rs similarity index 100% rename from tests/rustdoc/auxiliary/real_gimli.rs rename to tests/rustdoc/impl/auxiliary/real_gimli.rs diff --git a/tests/rustdoc/auxiliary/realcore.rs b/tests/rustdoc/impl/auxiliary/realcore.rs similarity index 100% rename from tests/rustdoc/auxiliary/realcore.rs rename to tests/rustdoc/impl/auxiliary/realcore.rs diff --git a/tests/rustdoc/auxiliary/rustdoc-default-impl.rs b/tests/rustdoc/impl/auxiliary/rustdoc-default-impl.rs similarity index 100% rename from tests/rustdoc/auxiliary/rustdoc-default-impl.rs rename to tests/rustdoc/impl/auxiliary/rustdoc-default-impl.rs diff --git a/tests/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs b/tests/rustdoc/impl/auxiliary/rustdoc-impl-parts-crosscrate.rs similarity index 100% rename from tests/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs rename to tests/rustdoc/impl/auxiliary/rustdoc-impl-parts-crosscrate.rs diff --git a/tests/rustdoc/blanket-impl-29503.rs b/tests/rustdoc/impl/blanket-impl-29503.rs similarity index 100% rename from tests/rustdoc/blanket-impl-29503.rs rename to tests/rustdoc/impl/blanket-impl-29503.rs diff --git a/tests/rustdoc/blanket-impl-78673.rs b/tests/rustdoc/impl/blanket-impl-78673.rs similarity index 100% rename from tests/rustdoc/blanket-impl-78673.rs rename to tests/rustdoc/impl/blanket-impl-78673.rs diff --git a/tests/rustdoc/cross-crate-hidden-impl-parameter.rs b/tests/rustdoc/impl/cross-crate-hidden-impl-parameter.rs similarity index 100% rename from tests/rustdoc/cross-crate-hidden-impl-parameter.rs rename to tests/rustdoc/impl/cross-crate-hidden-impl-parameter.rs diff --git a/tests/rustdoc/deduplicate-glob-import-impl-21474.rs b/tests/rustdoc/impl/deduplicate-glob-import-impl-21474.rs similarity index 100% rename from tests/rustdoc/deduplicate-glob-import-impl-21474.rs rename to tests/rustdoc/impl/deduplicate-glob-import-impl-21474.rs diff --git a/tests/rustdoc/deduplicate-trait-impl-22025.rs b/tests/rustdoc/impl/deduplicate-trait-impl-22025.rs similarity index 100% rename from tests/rustdoc/deduplicate-trait-impl-22025.rs rename to tests/rustdoc/impl/deduplicate-trait-impl-22025.rs diff --git a/tests/rustdoc/default-impl.rs b/tests/rustdoc/impl/default-impl.rs similarity index 100% rename from tests/rustdoc/default-impl.rs rename to tests/rustdoc/impl/default-impl.rs diff --git a/tests/rustdoc/deprecated-impls.rs b/tests/rustdoc/impl/deprecated-impls.rs similarity index 100% rename from tests/rustdoc/deprecated-impls.rs rename to tests/rustdoc/impl/deprecated-impls.rs diff --git a/tests/rustdoc/doc-hidden-trait-implementors-33069.rs b/tests/rustdoc/impl/doc-hidden-trait-implementors-33069.rs similarity index 100% rename from tests/rustdoc/doc-hidden-trait-implementors-33069.rs rename to tests/rustdoc/impl/doc-hidden-trait-implementors-33069.rs diff --git a/tests/rustdoc/doc_auto_cfg_nested_impl.rs b/tests/rustdoc/impl/doc_auto_cfg_nested_impl.rs similarity index 100% rename from tests/rustdoc/doc_auto_cfg_nested_impl.rs rename to tests/rustdoc/impl/doc_auto_cfg_nested_impl.rs diff --git a/tests/rustdoc/duplicated_impl.rs b/tests/rustdoc/impl/duplicated_impl.rs similarity index 100% rename from tests/rustdoc/duplicated_impl.rs rename to tests/rustdoc/impl/duplicated_impl.rs diff --git a/tests/rustdoc/empty-impl-block.rs b/tests/rustdoc/impl/empty-impl-block.rs similarity index 100% rename from tests/rustdoc/empty-impl-block.rs rename to tests/rustdoc/impl/empty-impl-block.rs diff --git a/tests/rustdoc/empty-impls.rs b/tests/rustdoc/impl/empty-impls.rs similarity index 100% rename from tests/rustdoc/empty-impls.rs rename to tests/rustdoc/impl/empty-impls.rs diff --git a/tests/rustdoc/extern-impl-trait.rs b/tests/rustdoc/impl/extern-impl-trait.rs similarity index 100% rename from tests/rustdoc/extern-impl-trait.rs rename to tests/rustdoc/impl/extern-impl-trait.rs diff --git a/tests/rustdoc/extern-impl.rs b/tests/rustdoc/impl/extern-impl.rs similarity index 100% rename from tests/rustdoc/extern-impl.rs rename to tests/rustdoc/impl/extern-impl.rs diff --git a/tests/rustdoc/foreign-implementors-js-43701.rs b/tests/rustdoc/impl/foreign-implementors-js-43701.rs similarity index 100% rename from tests/rustdoc/foreign-implementors-js-43701.rs rename to tests/rustdoc/impl/foreign-implementors-js-43701.rs diff --git a/tests/rustdoc/generic-impl.rs b/tests/rustdoc/impl/generic-impl.rs similarity index 100% rename from tests/rustdoc/generic-impl.rs rename to tests/rustdoc/impl/generic-impl.rs diff --git a/tests/rustdoc/hidden-implementors-90781.rs b/tests/rustdoc/impl/hidden-implementors-90781.rs similarity index 100% rename from tests/rustdoc/hidden-implementors-90781.rs rename to tests/rustdoc/impl/hidden-implementors-90781.rs diff --git a/tests/rustdoc/hidden-impls.rs b/tests/rustdoc/impl/hidden-impls.rs similarity index 100% rename from tests/rustdoc/hidden-impls.rs rename to tests/rustdoc/impl/hidden-impls.rs diff --git a/tests/rustdoc/hidden-trait-struct-impls.rs b/tests/rustdoc/impl/hidden-trait-struct-impls.rs similarity index 100% rename from tests/rustdoc/hidden-trait-struct-impls.rs rename to tests/rustdoc/impl/hidden-trait-struct-impls.rs diff --git a/tests/rustdoc/hide-mut-methods-if-no-derefmut-impl-74083.rs b/tests/rustdoc/impl/hide-mut-methods-if-no-derefmut-impl-74083.rs similarity index 100% rename from tests/rustdoc/hide-mut-methods-if-no-derefmut-impl-74083.rs rename to tests/rustdoc/impl/hide-mut-methods-if-no-derefmut-impl-74083.rs diff --git a/tests/rustdoc/impl-alias-substituted.rs b/tests/rustdoc/impl/impl-alias-substituted.rs similarity index 100% rename from tests/rustdoc/impl-alias-substituted.rs rename to tests/rustdoc/impl/impl-alias-substituted.rs diff --git a/tests/rustdoc/impl-assoc-type-21092.rs b/tests/rustdoc/impl/impl-assoc-type-21092.rs similarity index 100% rename from tests/rustdoc/impl-assoc-type-21092.rs rename to tests/rustdoc/impl/impl-assoc-type-21092.rs diff --git a/tests/rustdoc/impl-associated-items-order.rs b/tests/rustdoc/impl/impl-associated-items-order.rs similarity index 100% rename from tests/rustdoc/impl-associated-items-order.rs rename to tests/rustdoc/impl/impl-associated-items-order.rs diff --git a/tests/rustdoc/impl-associated-items-sidebar.rs b/tests/rustdoc/impl/impl-associated-items-sidebar.rs similarity index 100% rename from tests/rustdoc/impl-associated-items-sidebar.rs rename to tests/rustdoc/impl/impl-associated-items-sidebar.rs diff --git a/tests/rustdoc/impl-blanket-53689.rs b/tests/rustdoc/impl/impl-blanket-53689.rs similarity index 100% rename from tests/rustdoc/impl-blanket-53689.rs rename to tests/rustdoc/impl/impl-blanket-53689.rs diff --git a/tests/rustdoc/impl-box.rs b/tests/rustdoc/impl/impl-box.rs similarity index 100% rename from tests/rustdoc/impl-box.rs rename to tests/rustdoc/impl/impl-box.rs diff --git a/tests/rustdoc/impl-disambiguation.rs b/tests/rustdoc/impl/impl-disambiguation.rs similarity index 100% rename from tests/rustdoc/impl-disambiguation.rs rename to tests/rustdoc/impl/impl-disambiguation.rs diff --git a/tests/rustdoc/impl-everywhere.rs b/tests/rustdoc/impl/impl-everywhere.rs similarity index 100% rename from tests/rustdoc/impl-everywhere.rs rename to tests/rustdoc/impl/impl-everywhere.rs diff --git a/tests/rustdoc/impl-in-const-block.rs b/tests/rustdoc/impl/impl-in-const-block.rs similarity index 100% rename from tests/rustdoc/impl-in-const-block.rs rename to tests/rustdoc/impl/impl-in-const-block.rs diff --git a/tests/rustdoc/impl-on-ty-alias-issue-119015.rs b/tests/rustdoc/impl/impl-on-ty-alias-issue-119015.rs similarity index 100% rename from tests/rustdoc/impl-on-ty-alias-issue-119015.rs rename to tests/rustdoc/impl/impl-on-ty-alias-issue-119015.rs diff --git a/tests/rustdoc/impl-parts-crosscrate.rs b/tests/rustdoc/impl/impl-parts-crosscrate.rs similarity index 100% rename from tests/rustdoc/impl-parts-crosscrate.rs rename to tests/rustdoc/impl/impl-parts-crosscrate.rs diff --git a/tests/rustdoc/impl-parts.rs b/tests/rustdoc/impl/impl-parts.rs similarity index 100% rename from tests/rustdoc/impl-parts.rs rename to tests/rustdoc/impl/impl-parts.rs diff --git a/tests/rustdoc/impl-ref-20175.rs b/tests/rustdoc/impl/impl-ref-20175.rs similarity index 100% rename from tests/rustdoc/impl-ref-20175.rs rename to tests/rustdoc/impl/impl-ref-20175.rs diff --git a/tests/rustdoc/impl-trait-43869.rs b/tests/rustdoc/impl/impl-trait-43869.rs similarity index 100% rename from tests/rustdoc/impl-trait-43869.rs rename to tests/rustdoc/impl/impl-trait-43869.rs diff --git a/tests/rustdoc/impl-trait-alias.rs b/tests/rustdoc/impl/impl-trait-alias.rs similarity index 100% rename from tests/rustdoc/impl-trait-alias.rs rename to tests/rustdoc/impl/impl-trait-alias.rs diff --git a/tests/rustdoc/impl-trait-precise-capturing.rs b/tests/rustdoc/impl/impl-trait-precise-capturing.rs similarity index 100% rename from tests/rustdoc/impl-trait-precise-capturing.rs rename to tests/rustdoc/impl/impl-trait-precise-capturing.rs diff --git a/tests/rustdoc/impl-type-parameter-33592.rs b/tests/rustdoc/impl/impl-type-parameter-33592.rs similarity index 100% rename from tests/rustdoc/impl-type-parameter-33592.rs rename to tests/rustdoc/impl/impl-type-parameter-33592.rs diff --git a/tests/rustdoc/implementor-stable-version.rs b/tests/rustdoc/impl/implementor-stable-version.rs similarity index 100% rename from tests/rustdoc/implementor-stable-version.rs rename to tests/rustdoc/impl/implementor-stable-version.rs diff --git a/tests/rustdoc/implementors-unstable-75588.rs b/tests/rustdoc/impl/implementors-unstable-75588.rs similarity index 100% rename from tests/rustdoc/implementors-unstable-75588.rs rename to tests/rustdoc/impl/implementors-unstable-75588.rs diff --git a/tests/rustdoc/inline-impl-through-glob-import-100204.rs b/tests/rustdoc/impl/inline-impl-through-glob-import-100204.rs similarity index 100% rename from tests/rustdoc/inline-impl-through-glob-import-100204.rs rename to tests/rustdoc/impl/inline-impl-through-glob-import-100204.rs diff --git a/tests/rustdoc/manual_impl.rs b/tests/rustdoc/impl/manual_impl.rs similarity index 100% rename from tests/rustdoc/manual_impl.rs rename to tests/rustdoc/impl/manual_impl.rs diff --git a/tests/rustdoc/method-link-foreign-trait-impl-17476.rs b/tests/rustdoc/impl/method-link-foreign-trait-impl-17476.rs similarity index 100% rename from tests/rustdoc/method-link-foreign-trait-impl-17476.rs rename to tests/rustdoc/impl/method-link-foreign-trait-impl-17476.rs diff --git a/tests/rustdoc/module-impls.rs b/tests/rustdoc/impl/module-impls.rs similarity index 100% rename from tests/rustdoc/module-impls.rs rename to tests/rustdoc/impl/module-impls.rs diff --git a/tests/rustdoc/must_implement_one_of.rs b/tests/rustdoc/impl/must_implement_one_of.rs similarity index 100% rename from tests/rustdoc/must_implement_one_of.rs rename to tests/rustdoc/impl/must_implement_one_of.rs diff --git a/tests/rustdoc/negative-impl-no-items.rs b/tests/rustdoc/impl/negative-impl-no-items.rs similarity index 100% rename from tests/rustdoc/negative-impl-no-items.rs rename to tests/rustdoc/impl/negative-impl-no-items.rs diff --git a/tests/rustdoc/negative-impl-sidebar.rs b/tests/rustdoc/impl/negative-impl-sidebar.rs similarity index 100% rename from tests/rustdoc/negative-impl-sidebar.rs rename to tests/rustdoc/impl/negative-impl-sidebar.rs diff --git a/tests/rustdoc/negative-impl.rs b/tests/rustdoc/impl/negative-impl.rs similarity index 100% rename from tests/rustdoc/negative-impl.rs rename to tests/rustdoc/impl/negative-impl.rs diff --git a/tests/rustdoc/return-impl-trait.rs b/tests/rustdoc/impl/return-impl-trait.rs similarity index 100% rename from tests/rustdoc/return-impl-trait.rs rename to tests/rustdoc/impl/return-impl-trait.rs diff --git a/tests/rustdoc/rustc-incoherent-impls.rs b/tests/rustdoc/impl/rustc-incoherent-impls.rs similarity index 100% rename from tests/rustdoc/rustc-incoherent-impls.rs rename to tests/rustdoc/impl/rustc-incoherent-impls.rs diff --git a/tests/rustdoc/same-crate-hidden-impl-parameter.rs b/tests/rustdoc/impl/same-crate-hidden-impl-parameter.rs similarity index 100% rename from tests/rustdoc/same-crate-hidden-impl-parameter.rs rename to tests/rustdoc/impl/same-crate-hidden-impl-parameter.rs diff --git a/tests/rustdoc/sidebar-trait-impl-disambiguate-78701.rs b/tests/rustdoc/impl/sidebar-trait-impl-disambiguate-78701.rs similarity index 100% rename from tests/rustdoc/sidebar-trait-impl-disambiguate-78701.rs rename to tests/rustdoc/impl/sidebar-trait-impl-disambiguate-78701.rs diff --git a/tests/rustdoc/struct-implementations-title.rs b/tests/rustdoc/impl/struct-implementations-title.rs similarity index 100% rename from tests/rustdoc/struct-implementations-title.rs rename to tests/rustdoc/impl/struct-implementations-title.rs diff --git a/tests/rustdoc/trait-impl.rs b/tests/rustdoc/impl/trait-impl.rs similarity index 100% rename from tests/rustdoc/trait-impl.rs rename to tests/rustdoc/impl/trait-impl.rs diff --git a/tests/rustdoc/trait-implementations-duplicate-self-45584.rs b/tests/rustdoc/impl/trait-implementations-duplicate-self-45584.rs similarity index 100% rename from tests/rustdoc/trait-implementations-duplicate-self-45584.rs rename to tests/rustdoc/impl/trait-implementations-duplicate-self-45584.rs diff --git a/tests/rustdoc/underscore-type-in-trait-impl-96381.rs b/tests/rustdoc/impl/underscore-type-in-trait-impl-96381.rs similarity index 100% rename from tests/rustdoc/underscore-type-in-trait-impl-96381.rs rename to tests/rustdoc/impl/underscore-type-in-trait-impl-96381.rs diff --git a/tests/rustdoc/universal-impl-trait.rs b/tests/rustdoc/impl/universal-impl-trait.rs similarity index 100% rename from tests/rustdoc/universal-impl-trait.rs rename to tests/rustdoc/impl/universal-impl-trait.rs diff --git a/tests/rustdoc/unneeded-trait-implementations-title.rs b/tests/rustdoc/impl/unneeded-trait-implementations-title.rs similarity index 100% rename from tests/rustdoc/unneeded-trait-implementations-title.rs rename to tests/rustdoc/impl/unneeded-trait-implementations-title.rs diff --git a/tests/rustdoc/ice-intra-doc-links-107995.rs b/tests/rustdoc/intra-doc/ice-intra-doc-links-107995.rs similarity index 100% rename from tests/rustdoc/ice-intra-doc-links-107995.rs rename to tests/rustdoc/intra-doc/ice-intra-doc-links-107995.rs diff --git a/tests/rustdoc/intra-doc-link-method-trait-impl-72340.rs b/tests/rustdoc/intra-doc/intra-doc-link-method-trait-impl-72340.rs similarity index 100% rename from tests/rustdoc/intra-doc-link-method-trait-impl-72340.rs rename to tests/rustdoc/intra-doc/intra-doc-link-method-trait-impl-72340.rs diff --git a/tests/rustdoc/auxiliary/jump-to-def-macro.rs b/tests/rustdoc/jump-to-def/auxiliary/jump-to-def-macro.rs similarity index 100% rename from tests/rustdoc/auxiliary/jump-to-def-macro.rs rename to tests/rustdoc/jump-to-def/auxiliary/jump-to-def-macro.rs diff --git a/tests/rustdoc/jump-to-def-doc-links-calls.rs b/tests/rustdoc/jump-to-def/jump-to-def-doc-links-calls.rs similarity index 100% rename from tests/rustdoc/jump-to-def-doc-links-calls.rs rename to tests/rustdoc/jump-to-def/jump-to-def-doc-links-calls.rs diff --git a/tests/rustdoc/jump-to-def-doc-links.rs b/tests/rustdoc/jump-to-def/jump-to-def-doc-links.rs similarity index 100% rename from tests/rustdoc/jump-to-def-doc-links.rs rename to tests/rustdoc/jump-to-def/jump-to-def-doc-links.rs diff --git a/tests/rustdoc/jump-to-def-macro.rs b/tests/rustdoc/jump-to-def/jump-to-def-macro.rs similarity index 100% rename from tests/rustdoc/jump-to-def-macro.rs rename to tests/rustdoc/jump-to-def/jump-to-def-macro.rs diff --git a/tests/rustdoc/jump-to-def-pats.rs b/tests/rustdoc/jump-to-def/jump-to-def-pats.rs similarity index 100% rename from tests/rustdoc/jump-to-def-pats.rs rename to tests/rustdoc/jump-to-def/jump-to-def-pats.rs diff --git a/tests/rustdoc/jump-to-def-prelude-types.rs b/tests/rustdoc/jump-to-def/jump-to-def-prelude-types.rs similarity index 100% rename from tests/rustdoc/jump-to-def-prelude-types.rs rename to tests/rustdoc/jump-to-def/jump-to-def-prelude-types.rs diff --git a/tests/rustdoc/jump-to-non-local-method.rs b/tests/rustdoc/jump-to-def/jump-to-non-local-method.rs similarity index 100% rename from tests/rustdoc/jump-to-non-local-method.rs rename to tests/rustdoc/jump-to-def/jump-to-non-local-method.rs diff --git a/tests/rustdoc/auxiliary/external-macro-src.rs b/tests/rustdoc/macro/auxiliary/external-macro-src.rs similarity index 100% rename from tests/rustdoc/auxiliary/external-macro-src.rs rename to tests/rustdoc/macro/auxiliary/external-macro-src.rs diff --git a/tests/rustdoc/macro/auxiliary/issue-99221-aux.rs b/tests/rustdoc/macro/auxiliary/issue-99221-aux.rs new file mode 100644 index 000000000000..e061e42b29db --- /dev/null +++ b/tests/rustdoc/macro/auxiliary/issue-99221-aux.rs @@ -0,0 +1,20 @@ +pub struct Option; +impl Option { + pub fn unwrap(self) {} +} + +mod macros { + use crate::Option; + /// [`Option::unwrap`] + #[macro_export] + macro_rules! print { + () => () + } +} + +mod structs { + use crate::Option; + /// [`Option::unwrap`] + pub struct Print; +} +pub use structs::Print; diff --git a/tests/rustdoc/auxiliary/macro_pub_in_module.rs b/tests/rustdoc/macro/auxiliary/macro_pub_in_module.rs similarity index 100% rename from tests/rustdoc/auxiliary/macro_pub_in_module.rs rename to tests/rustdoc/macro/auxiliary/macro_pub_in_module.rs diff --git a/tests/rustdoc/auxiliary/pub-use-extern-macros.rs b/tests/rustdoc/macro/auxiliary/pub-use-extern-macros.rs similarity index 100% rename from tests/rustdoc/auxiliary/pub-use-extern-macros.rs rename to tests/rustdoc/macro/auxiliary/pub-use-extern-macros.rs diff --git a/tests/rustdoc/compiler-derive-proc-macro.rs b/tests/rustdoc/macro/compiler-derive-proc-macro.rs similarity index 100% rename from tests/rustdoc/compiler-derive-proc-macro.rs rename to tests/rustdoc/macro/compiler-derive-proc-macro.rs diff --git a/tests/rustdoc/const-rendering-macros-33302.rs b/tests/rustdoc/macro/const-rendering-macros-33302.rs similarity index 100% rename from tests/rustdoc/const-rendering-macros-33302.rs rename to tests/rustdoc/macro/const-rendering-macros-33302.rs diff --git a/tests/rustdoc/decl_macro.rs b/tests/rustdoc/macro/decl_macro.rs similarity index 100% rename from tests/rustdoc/decl_macro.rs rename to tests/rustdoc/macro/decl_macro.rs diff --git a/tests/rustdoc/decl_macro_priv.rs b/tests/rustdoc/macro/decl_macro_priv.rs similarity index 100% rename from tests/rustdoc/decl_macro_priv.rs rename to tests/rustdoc/macro/decl_macro_priv.rs diff --git a/tests/rustdoc/doc-proc-macro.rs b/tests/rustdoc/macro/doc-proc-macro.rs similarity index 100% rename from tests/rustdoc/doc-proc-macro.rs rename to tests/rustdoc/macro/doc-proc-macro.rs diff --git a/tests/rustdoc/external-macro-src.rs b/tests/rustdoc/macro/external-macro-src.rs similarity index 100% rename from tests/rustdoc/external-macro-src.rs rename to tests/rustdoc/macro/external-macro-src.rs diff --git a/tests/rustdoc/macro-const-display-115295.rs b/tests/rustdoc/macro/macro-const-display-115295.rs similarity index 100% rename from tests/rustdoc/macro-const-display-115295.rs rename to tests/rustdoc/macro/macro-const-display-115295.rs diff --git a/tests/rustdoc/macro-doc-comment-23812.rs b/tests/rustdoc/macro/macro-doc-comment-23812.rs similarity index 100% rename from tests/rustdoc/macro-doc-comment-23812.rs rename to tests/rustdoc/macro/macro-doc-comment-23812.rs diff --git a/tests/rustdoc/macro-export-crate-root-108231.rs b/tests/rustdoc/macro/macro-export-crate-root-108231.rs similarity index 100% rename from tests/rustdoc/macro-export-crate-root-108231.rs rename to tests/rustdoc/macro/macro-export-crate-root-108231.rs diff --git a/tests/rustdoc/macro-generated-macro.macro_linebreak_pre.html b/tests/rustdoc/macro/macro-generated-macro.macro_linebreak_pre.html similarity index 100% rename from tests/rustdoc/macro-generated-macro.macro_linebreak_pre.html rename to tests/rustdoc/macro/macro-generated-macro.macro_linebreak_pre.html diff --git a/tests/rustdoc/macro-generated-macro.macro_morestuff_pre.html b/tests/rustdoc/macro/macro-generated-macro.macro_morestuff_pre.html similarity index 100% rename from tests/rustdoc/macro-generated-macro.macro_morestuff_pre.html rename to tests/rustdoc/macro/macro-generated-macro.macro_morestuff_pre.html diff --git a/tests/rustdoc/macro-generated-macro.rs b/tests/rustdoc/macro/macro-generated-macro.rs similarity index 100% rename from tests/rustdoc/macro-generated-macro.rs rename to tests/rustdoc/macro/macro-generated-macro.rs diff --git a/tests/rustdoc/macro-higher-kinded-function.rs b/tests/rustdoc/macro/macro-higher-kinded-function.rs similarity index 100% rename from tests/rustdoc/macro-higher-kinded-function.rs rename to tests/rustdoc/macro/macro-higher-kinded-function.rs diff --git a/tests/rustdoc/macro-ice-16019.rs b/tests/rustdoc/macro/macro-ice-16019.rs similarity index 100% rename from tests/rustdoc/macro-ice-16019.rs rename to tests/rustdoc/macro/macro-ice-16019.rs diff --git a/tests/rustdoc/macro-in-async-block.rs b/tests/rustdoc/macro/macro-in-async-block.rs similarity index 100% rename from tests/rustdoc/macro-in-async-block.rs rename to tests/rustdoc/macro/macro-in-async-block.rs diff --git a/tests/rustdoc/macro-in-closure.rs b/tests/rustdoc/macro/macro-in-closure.rs similarity index 100% rename from tests/rustdoc/macro-in-closure.rs rename to tests/rustdoc/macro/macro-in-closure.rs diff --git a/tests/rustdoc/macro-indirect-use.rs b/tests/rustdoc/macro/macro-indirect-use.rs similarity index 100% rename from tests/rustdoc/macro-indirect-use.rs rename to tests/rustdoc/macro/macro-indirect-use.rs diff --git a/tests/rustdoc/macro_pub_in_module.rs b/tests/rustdoc/macro/macro_pub_in_module.rs similarity index 100% rename from tests/rustdoc/macro_pub_in_module.rs rename to tests/rustdoc/macro/macro_pub_in_module.rs diff --git a/tests/rustdoc/macro_rules-matchers.rs b/tests/rustdoc/macro/macro_rules-matchers.rs similarity index 100% rename from tests/rustdoc/macro_rules-matchers.rs rename to tests/rustdoc/macro/macro_rules-matchers.rs diff --git a/tests/rustdoc/macros.rs b/tests/rustdoc/macro/macros.rs similarity index 100% rename from tests/rustdoc/macros.rs rename to tests/rustdoc/macro/macros.rs diff --git a/tests/rustdoc/multiple-macro-rules-w-same-name-99221.rs b/tests/rustdoc/macro/multiple-macro-rules-w-same-name-99221.rs similarity index 100% rename from tests/rustdoc/multiple-macro-rules-w-same-name-99221.rs rename to tests/rustdoc/macro/multiple-macro-rules-w-same-name-99221.rs diff --git a/tests/rustdoc/multiple-macro-rules-w-same-name-submodule-99221.rs b/tests/rustdoc/macro/multiple-macro-rules-w-same-name-submodule-99221.rs similarity index 100% rename from tests/rustdoc/multiple-macro-rules-w-same-name-submodule-99221.rs rename to tests/rustdoc/macro/multiple-macro-rules-w-same-name-submodule-99221.rs diff --git a/tests/rustdoc/proc-macro.rs b/tests/rustdoc/macro/proc-macro.rs similarity index 100% rename from tests/rustdoc/proc-macro.rs rename to tests/rustdoc/macro/proc-macro.rs diff --git a/tests/rustdoc/pub-use-extern-macros.rs b/tests/rustdoc/macro/pub-use-extern-macros.rs similarity index 100% rename from tests/rustdoc/pub-use-extern-macros.rs rename to tests/rustdoc/macro/pub-use-extern-macros.rs diff --git a/tests/rustdoc/rustc-macro-crate.rs b/tests/rustdoc/macro/rustc-macro-crate.rs similarity index 100% rename from tests/rustdoc/rustc-macro-crate.rs rename to tests/rustdoc/macro/rustc-macro-crate.rs diff --git a/tests/rustdoc/auxiliary/issue-15318.rs b/tests/rustdoc/primitive/auxiliary/issue-15318.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-15318.rs rename to tests/rustdoc/primitive/auxiliary/issue-15318.rs diff --git a/tests/rustdoc/auxiliary/primitive-doc.rs b/tests/rustdoc/primitive/auxiliary/primitive-doc.rs similarity index 100% rename from tests/rustdoc/auxiliary/primitive-doc.rs rename to tests/rustdoc/primitive/auxiliary/primitive-doc.rs diff --git a/tests/rustdoc/cross-crate-primitive-doc.rs b/tests/rustdoc/primitive/cross-crate-primitive-doc.rs similarity index 100% rename from tests/rustdoc/cross-crate-primitive-doc.rs rename to tests/rustdoc/primitive/cross-crate-primitive-doc.rs diff --git a/tests/rustdoc/no_std-primitive.rs b/tests/rustdoc/primitive/no_std-primitive.rs similarity index 100% rename from tests/rustdoc/no_std-primitive.rs rename to tests/rustdoc/primitive/no_std-primitive.rs diff --git a/tests/rustdoc/primitive-link.rs b/tests/rustdoc/primitive/primitive-link.rs similarity index 100% rename from tests/rustdoc/primitive-link.rs rename to tests/rustdoc/primitive/primitive-link.rs diff --git a/tests/rustdoc/primitive-raw-pointer-dox-15318-3.rs b/tests/rustdoc/primitive/primitive-raw-pointer-dox-15318-3.rs similarity index 100% rename from tests/rustdoc/primitive-raw-pointer-dox-15318-3.rs rename to tests/rustdoc/primitive/primitive-raw-pointer-dox-15318-3.rs diff --git a/tests/rustdoc/primitive-raw-pointer-link-15318.rs b/tests/rustdoc/primitive/primitive-raw-pointer-link-15318.rs similarity index 100% rename from tests/rustdoc/primitive-raw-pointer-link-15318.rs rename to tests/rustdoc/primitive/primitive-raw-pointer-link-15318.rs diff --git a/tests/rustdoc/primitive-raw-pointer-link-no-inlined-15318-2.rs b/tests/rustdoc/primitive/primitive-raw-pointer-link-no-inlined-15318-2.rs similarity index 100% rename from tests/rustdoc/primitive-raw-pointer-link-no-inlined-15318-2.rs rename to tests/rustdoc/primitive/primitive-raw-pointer-link-no-inlined-15318-2.rs diff --git a/tests/rustdoc/primitive-reference.rs b/tests/rustdoc/primitive/primitive-reference.rs similarity index 100% rename from tests/rustdoc/primitive-reference.rs rename to tests/rustdoc/primitive/primitive-reference.rs diff --git a/tests/rustdoc/primitive-slice-auto-trait.rs b/tests/rustdoc/primitive/primitive-slice-auto-trait.rs similarity index 100% rename from tests/rustdoc/primitive-slice-auto-trait.rs rename to tests/rustdoc/primitive/primitive-slice-auto-trait.rs diff --git a/tests/rustdoc/primitive-tuple-auto-trait.rs b/tests/rustdoc/primitive/primitive-tuple-auto-trait.rs similarity index 100% rename from tests/rustdoc/primitive-tuple-auto-trait.rs rename to tests/rustdoc/primitive/primitive-tuple-auto-trait.rs diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive/primitive-tuple-variadic.rs similarity index 100% rename from tests/rustdoc/primitive-tuple-variadic.rs rename to tests/rustdoc/primitive/primitive-tuple-variadic.rs diff --git a/tests/rustdoc/primitive-unit-auto-trait.rs b/tests/rustdoc/primitive/primitive-unit-auto-trait.rs similarity index 100% rename from tests/rustdoc/primitive-unit-auto-trait.rs rename to tests/rustdoc/primitive/primitive-unit-auto-trait.rs diff --git a/tests/rustdoc/search-index-primitive-inherent-method-23511.rs b/tests/rustdoc/primitive/search-index-primitive-inherent-method-23511.rs similarity index 100% rename from tests/rustdoc/search-index-primitive-inherent-method-23511.rs rename to tests/rustdoc/primitive/search-index-primitive-inherent-method-23511.rs diff --git a/tests/rustdoc/doc-hidden-private-67851-both.rs b/tests/rustdoc/private/doc-hidden-private-67851-both.rs similarity index 100% rename from tests/rustdoc/doc-hidden-private-67851-both.rs rename to tests/rustdoc/private/doc-hidden-private-67851-both.rs diff --git a/tests/rustdoc/doc-hidden-private-67851-hidden.rs b/tests/rustdoc/private/doc-hidden-private-67851-hidden.rs similarity index 100% rename from tests/rustdoc/doc-hidden-private-67851-hidden.rs rename to tests/rustdoc/private/doc-hidden-private-67851-hidden.rs diff --git a/tests/rustdoc/doc-hidden-private-67851-neither.rs b/tests/rustdoc/private/doc-hidden-private-67851-neither.rs similarity index 100% rename from tests/rustdoc/doc-hidden-private-67851-neither.rs rename to tests/rustdoc/private/doc-hidden-private-67851-neither.rs diff --git a/tests/rustdoc/doc-hidden-private-67851-private.rs b/tests/rustdoc/private/doc-hidden-private-67851-private.rs similarity index 100% rename from tests/rustdoc/doc-hidden-private-67851-private.rs rename to tests/rustdoc/private/doc-hidden-private-67851-private.rs diff --git a/tests/rustdoc/empty-impl-block-private-with-doc.rs b/tests/rustdoc/private/empty-impl-block-private-with-doc.rs similarity index 100% rename from tests/rustdoc/empty-impl-block-private-with-doc.rs rename to tests/rustdoc/private/empty-impl-block-private-with-doc.rs diff --git a/tests/rustdoc/empty-impl-block-private.rs b/tests/rustdoc/private/empty-impl-block-private.rs similarity index 100% rename from tests/rustdoc/empty-impl-block-private.rs rename to tests/rustdoc/private/empty-impl-block-private.rs diff --git a/tests/rustdoc/empty-mod-private.rs b/tests/rustdoc/private/empty-mod-private.rs similarity index 100% rename from tests/rustdoc/empty-mod-private.rs rename to tests/rustdoc/private/empty-mod-private.rs diff --git a/tests/rustdoc/enum-variant-private-46767.rs b/tests/rustdoc/private/enum-variant-private-46767.rs similarity index 100% rename from tests/rustdoc/enum-variant-private-46767.rs rename to tests/rustdoc/private/enum-variant-private-46767.rs diff --git a/tests/rustdoc/files-creation-private.rs b/tests/rustdoc/private/files-creation-private.rs similarity index 100% rename from tests/rustdoc/files-creation-private.rs rename to tests/rustdoc/private/files-creation-private.rs diff --git a/tests/rustdoc/hidden-private.rs b/tests/rustdoc/private/hidden-private.rs similarity index 100% rename from tests/rustdoc/hidden-private.rs rename to tests/rustdoc/private/hidden-private.rs diff --git a/tests/rustdoc/inline-private-with-intermediate-doc-hidden.rs b/tests/rustdoc/private/inline-private-with-intermediate-doc-hidden.rs similarity index 100% rename from tests/rustdoc/inline-private-with-intermediate-doc-hidden.rs rename to tests/rustdoc/private/inline-private-with-intermediate-doc-hidden.rs diff --git a/tests/rustdoc/inner-private-110422.rs b/tests/rustdoc/private/inner-private-110422.rs similarity index 100% rename from tests/rustdoc/inner-private-110422.rs rename to tests/rustdoc/private/inner-private-110422.rs diff --git a/tests/rustdoc/macro-document-private-duplicate.rs b/tests/rustdoc/private/macro-document-private-duplicate.rs similarity index 100% rename from tests/rustdoc/macro-document-private-duplicate.rs rename to tests/rustdoc/private/macro-document-private-duplicate.rs diff --git a/tests/rustdoc/macro-document-private.rs b/tests/rustdoc/private/macro-document-private.rs similarity index 100% rename from tests/rustdoc/macro-document-private.rs rename to tests/rustdoc/private/macro-document-private.rs diff --git a/tests/rustdoc/macro-private-not-documented.rs b/tests/rustdoc/private/macro-private-not-documented.rs similarity index 100% rename from tests/rustdoc/macro-private-not-documented.rs rename to tests/rustdoc/private/macro-private-not-documented.rs diff --git a/tests/rustdoc/missing-private-inlining-109258.rs b/tests/rustdoc/private/missing-private-inlining-109258.rs similarity index 100% rename from tests/rustdoc/missing-private-inlining-109258.rs rename to tests/rustdoc/private/missing-private-inlining-109258.rs diff --git a/tests/rustdoc/private-fields-tuple-struct.rs b/tests/rustdoc/private/private-fields-tuple-struct.rs similarity index 100% rename from tests/rustdoc/private-fields-tuple-struct.rs rename to tests/rustdoc/private/private-fields-tuple-struct.rs diff --git a/tests/rustdoc/private-non-local-fields-2.rs b/tests/rustdoc/private/private-non-local-fields-2.rs similarity index 100% rename from tests/rustdoc/private-non-local-fields-2.rs rename to tests/rustdoc/private/private-non-local-fields-2.rs diff --git a/tests/rustdoc/private-non-local-fields.rs b/tests/rustdoc/private/private-non-local-fields.rs similarity index 100% rename from tests/rustdoc/private-non-local-fields.rs rename to tests/rustdoc/private/private-non-local-fields.rs diff --git a/tests/rustdoc/private-type-alias.rs b/tests/rustdoc/private/private-type-alias.rs similarity index 100% rename from tests/rustdoc/private-type-alias.rs rename to tests/rustdoc/private/private-type-alias.rs diff --git a/tests/rustdoc/private-type-cycle-110629.rs b/tests/rustdoc/private/private-type-cycle-110629.rs similarity index 100% rename from tests/rustdoc/private-type-cycle-110629.rs rename to tests/rustdoc/private/private-type-cycle-110629.rs diff --git a/tests/rustdoc/private-use-decl-macro-47038.rs b/tests/rustdoc/private/private-use-decl-macro-47038.rs similarity index 100% rename from tests/rustdoc/private-use-decl-macro-47038.rs rename to tests/rustdoc/private/private-use-decl-macro-47038.rs diff --git a/tests/rustdoc/private-use.rs b/tests/rustdoc/private/private-use.rs similarity index 100% rename from tests/rustdoc/private-use.rs rename to tests/rustdoc/private/private-use.rs diff --git a/tests/rustdoc/public-impl-mention-private-generic-46380-2.rs b/tests/rustdoc/private/public-impl-mention-private-generic-46380-2.rs similarity index 100% rename from tests/rustdoc/public-impl-mention-private-generic-46380-2.rs rename to tests/rustdoc/private/public-impl-mention-private-generic-46380-2.rs diff --git a/tests/rustdoc/traits-in-bodies-private.rs b/tests/rustdoc/private/traits-in-bodies-private.rs similarity index 100% rename from tests/rustdoc/traits-in-bodies-private.rs rename to tests/rustdoc/private/traits-in-bodies-private.rs diff --git a/tests/rustdoc/alias-reexport.rs b/tests/rustdoc/reexport/alias-reexport.rs similarity index 100% rename from tests/rustdoc/alias-reexport.rs rename to tests/rustdoc/reexport/alias-reexport.rs diff --git a/tests/rustdoc/alias-reexport2.rs b/tests/rustdoc/reexport/alias-reexport2.rs similarity index 100% rename from tests/rustdoc/alias-reexport2.rs rename to tests/rustdoc/reexport/alias-reexport2.rs diff --git a/tests/rustdoc/anonymous-reexport-108931.rs b/tests/rustdoc/reexport/anonymous-reexport-108931.rs similarity index 100% rename from tests/rustdoc/anonymous-reexport-108931.rs rename to tests/rustdoc/reexport/anonymous-reexport-108931.rs diff --git a/tests/rustdoc/anonymous-reexport.rs b/tests/rustdoc/reexport/anonymous-reexport.rs similarity index 100% rename from tests/rustdoc/anonymous-reexport.rs rename to tests/rustdoc/reexport/anonymous-reexport.rs diff --git a/tests/rustdoc/auxiliary/alias-reexport.rs b/tests/rustdoc/reexport/auxiliary/alias-reexport.rs similarity index 100% rename from tests/rustdoc/auxiliary/alias-reexport.rs rename to tests/rustdoc/reexport/auxiliary/alias-reexport.rs diff --git a/tests/rustdoc/auxiliary/alias-reexport2.rs b/tests/rustdoc/reexport/auxiliary/alias-reexport2.rs similarity index 100% rename from tests/rustdoc/auxiliary/alias-reexport2.rs rename to tests/rustdoc/reexport/auxiliary/alias-reexport2.rs diff --git a/tests/rustdoc/reexport/auxiliary/all-item-types.rs b/tests/rustdoc/reexport/auxiliary/all-item-types.rs new file mode 100644 index 000000000000..f94bd998717a --- /dev/null +++ b/tests/rustdoc/reexport/auxiliary/all-item-types.rs @@ -0,0 +1,22 @@ +#![feature(extern_types)] + +pub mod foo_mod {} +extern "C" { + pub fn foo_ffn(); + pub static FOO_FSTATIC: FooStruct; + pub type FooFType; +} +pub fn foo_fn() {} +pub trait FooTrait {} +pub struct FooStruct; +pub enum FooEnum {} +pub union FooUnion { + x: (), +} +pub type FooType = FooStruct; +pub static FOO_STATIC: FooStruct = FooStruct; +pub const FOO_CONSTANT: FooStruct = FooStruct; +#[macro_export] +macro_rules! foo_macro { + () => (); +} diff --git a/tests/rustdoc/auxiliary/issue-113982-doc_auto_cfg-reexport-foreign.rs b/tests/rustdoc/reexport/auxiliary/issue-113982-doc_auto_cfg-reexport-foreign.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-113982-doc_auto_cfg-reexport-foreign.rs rename to tests/rustdoc/reexport/auxiliary/issue-113982-doc_auto_cfg-reexport-foreign.rs diff --git a/tests/rustdoc/auxiliary/issue-28927-1.rs b/tests/rustdoc/reexport/auxiliary/issue-28927-1.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-28927-1.rs rename to tests/rustdoc/reexport/auxiliary/issue-28927-1.rs diff --git a/tests/rustdoc/auxiliary/issue-28927-2.rs b/tests/rustdoc/reexport/auxiliary/issue-28927-2.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-28927-2.rs rename to tests/rustdoc/reexport/auxiliary/issue-28927-2.rs diff --git a/tests/rustdoc/auxiliary/primitive-reexport.rs b/tests/rustdoc/reexport/auxiliary/primitive-reexport.rs similarity index 100% rename from tests/rustdoc/auxiliary/primitive-reexport.rs rename to tests/rustdoc/reexport/auxiliary/primitive-reexport.rs diff --git a/tests/rustdoc/auxiliary/reexport-check.rs b/tests/rustdoc/reexport/auxiliary/reexport-check.rs similarity index 100% rename from tests/rustdoc/auxiliary/reexport-check.rs rename to tests/rustdoc/reexport/auxiliary/reexport-check.rs diff --git a/tests/rustdoc/auxiliary/reexport-doc-aux.rs b/tests/rustdoc/reexport/auxiliary/reexport-doc-aux.rs similarity index 100% rename from tests/rustdoc/auxiliary/reexport-doc-aux.rs rename to tests/rustdoc/reexport/auxiliary/reexport-doc-aux.rs diff --git a/tests/rustdoc/auxiliary/reexports.rs b/tests/rustdoc/reexport/auxiliary/reexports.rs similarity index 100% rename from tests/rustdoc/auxiliary/reexports.rs rename to tests/rustdoc/reexport/auxiliary/reexports.rs diff --git a/tests/rustdoc/blanket-reexport-item.rs b/tests/rustdoc/reexport/blanket-reexport-item.rs similarity index 100% rename from tests/rustdoc/blanket-reexport-item.rs rename to tests/rustdoc/reexport/blanket-reexport-item.rs diff --git a/tests/rustdoc/cfg_doc_reexport.rs b/tests/rustdoc/reexport/cfg_doc_reexport.rs similarity index 100% rename from tests/rustdoc/cfg_doc_reexport.rs rename to tests/rustdoc/reexport/cfg_doc_reexport.rs diff --git a/tests/rustdoc/doc-hidden-reexports-109449.rs b/tests/rustdoc/reexport/doc-hidden-reexports-109449.rs similarity index 100% rename from tests/rustdoc/doc-hidden-reexports-109449.rs rename to tests/rustdoc/reexport/doc-hidden-reexports-109449.rs diff --git a/tests/rustdoc/doc_auto_cfg-reexport-foreign-113982.rs b/tests/rustdoc/reexport/doc_auto_cfg-reexport-foreign-113982.rs similarity index 100% rename from tests/rustdoc/doc_auto_cfg-reexport-foreign-113982.rs rename to tests/rustdoc/reexport/doc_auto_cfg-reexport-foreign-113982.rs diff --git a/tests/rustdoc/duplicated-glob-reexport-60522.rs b/tests/rustdoc/reexport/duplicated-glob-reexport-60522.rs similarity index 100% rename from tests/rustdoc/duplicated-glob-reexport-60522.rs rename to tests/rustdoc/reexport/duplicated-glob-reexport-60522.rs diff --git a/tests/rustdoc/enum-variant-reexport-35488.rs b/tests/rustdoc/reexport/enum-variant-reexport-35488.rs similarity index 100% rename from tests/rustdoc/enum-variant-reexport-35488.rs rename to tests/rustdoc/reexport/enum-variant-reexport-35488.rs diff --git a/tests/rustdoc/foreigntype-reexport.rs b/tests/rustdoc/reexport/foreigntype-reexport.rs similarity index 100% rename from tests/rustdoc/foreigntype-reexport.rs rename to tests/rustdoc/reexport/foreigntype-reexport.rs diff --git a/tests/rustdoc/glob-reexport-attribute-merge-120487.rs b/tests/rustdoc/reexport/glob-reexport-attribute-merge-120487.rs similarity index 100% rename from tests/rustdoc/glob-reexport-attribute-merge-120487.rs rename to tests/rustdoc/reexport/glob-reexport-attribute-merge-120487.rs diff --git a/tests/rustdoc/glob-reexport-attribute-merge-doc-auto-cfg.rs b/tests/rustdoc/reexport/glob-reexport-attribute-merge-doc-auto-cfg.rs similarity index 100% rename from tests/rustdoc/glob-reexport-attribute-merge-doc-auto-cfg.rs rename to tests/rustdoc/reexport/glob-reexport-attribute-merge-doc-auto-cfg.rs diff --git a/tests/rustdoc/ice-reexport-crate-root-28927.rs b/tests/rustdoc/reexport/ice-reexport-crate-root-28927.rs similarity index 100% rename from tests/rustdoc/ice-reexport-crate-root-28927.rs rename to tests/rustdoc/reexport/ice-reexport-crate-root-28927.rs diff --git a/tests/rustdoc/local-reexport-doc.rs b/tests/rustdoc/reexport/local-reexport-doc.rs similarity index 100% rename from tests/rustdoc/local-reexport-doc.rs rename to tests/rustdoc/reexport/local-reexport-doc.rs diff --git a/tests/rustdoc/no-compiler-reexport.rs b/tests/rustdoc/reexport/no-compiler-reexport.rs similarity index 100% rename from tests/rustdoc/no-compiler-reexport.rs rename to tests/rustdoc/reexport/no-compiler-reexport.rs diff --git a/tests/rustdoc/overlapping-reexport-105735-2.rs b/tests/rustdoc/reexport/overlapping-reexport-105735-2.rs similarity index 100% rename from tests/rustdoc/overlapping-reexport-105735-2.rs rename to tests/rustdoc/reexport/overlapping-reexport-105735-2.rs diff --git a/tests/rustdoc/overlapping-reexport-105735.rs b/tests/rustdoc/reexport/overlapping-reexport-105735.rs similarity index 100% rename from tests/rustdoc/overlapping-reexport-105735.rs rename to tests/rustdoc/reexport/overlapping-reexport-105735.rs diff --git a/tests/rustdoc/primitive-reexport.rs b/tests/rustdoc/reexport/primitive-reexport.rs similarity index 100% rename from tests/rustdoc/primitive-reexport.rs rename to tests/rustdoc/reexport/primitive-reexport.rs diff --git a/tests/rustdoc/pub-reexport-of-pub-reexport-46506.rs b/tests/rustdoc/reexport/pub-reexport-of-pub-reexport-46506.rs similarity index 100% rename from tests/rustdoc/pub-reexport-of-pub-reexport-46506.rs rename to tests/rustdoc/reexport/pub-reexport-of-pub-reexport-46506.rs diff --git a/tests/rustdoc/reexport-attr-merge.rs b/tests/rustdoc/reexport/reexport-attr-merge.rs similarity index 100% rename from tests/rustdoc/reexport-attr-merge.rs rename to tests/rustdoc/reexport/reexport-attr-merge.rs diff --git a/tests/rustdoc/reexport-cfg.rs b/tests/rustdoc/reexport/reexport-cfg.rs similarity index 100% rename from tests/rustdoc/reexport-cfg.rs rename to tests/rustdoc/reexport/reexport-cfg.rs diff --git a/tests/rustdoc/reexport-check.rs b/tests/rustdoc/reexport/reexport-check.rs similarity index 100% rename from tests/rustdoc/reexport-check.rs rename to tests/rustdoc/reexport/reexport-check.rs diff --git a/tests/rustdoc/reexport-dep-foreign-fn.rs b/tests/rustdoc/reexport/reexport-dep-foreign-fn.rs similarity index 100% rename from tests/rustdoc/reexport-dep-foreign-fn.rs rename to tests/rustdoc/reexport/reexport-dep-foreign-fn.rs diff --git a/tests/rustdoc/reexport-doc-hidden-inside-private.rs b/tests/rustdoc/reexport/reexport-doc-hidden-inside-private.rs similarity index 100% rename from tests/rustdoc/reexport-doc-hidden-inside-private.rs rename to tests/rustdoc/reexport/reexport-doc-hidden-inside-private.rs diff --git a/tests/rustdoc/reexport-doc-hidden.rs b/tests/rustdoc/reexport/reexport-doc-hidden.rs similarity index 100% rename from tests/rustdoc/reexport-doc-hidden.rs rename to tests/rustdoc/reexport/reexport-doc-hidden.rs diff --git a/tests/rustdoc/reexport-doc.rs b/tests/rustdoc/reexport/reexport-doc.rs similarity index 100% rename from tests/rustdoc/reexport-doc.rs rename to tests/rustdoc/reexport/reexport-doc.rs diff --git a/tests/rustdoc/reexport-hidden-macro.rs b/tests/rustdoc/reexport/reexport-hidden-macro.rs similarity index 100% rename from tests/rustdoc/reexport-hidden-macro.rs rename to tests/rustdoc/reexport/reexport-hidden-macro.rs diff --git a/tests/rustdoc/reexport-macro.rs b/tests/rustdoc/reexport/reexport-macro.rs similarity index 100% rename from tests/rustdoc/reexport-macro.rs rename to tests/rustdoc/reexport/reexport-macro.rs diff --git a/tests/rustdoc/reexport-of-doc-hidden.rs b/tests/rustdoc/reexport/reexport-of-doc-hidden.rs similarity index 100% rename from tests/rustdoc/reexport-of-doc-hidden.rs rename to tests/rustdoc/reexport/reexport-of-doc-hidden.rs diff --git a/tests/rustdoc/reexport-of-reexport-108679.rs b/tests/rustdoc/reexport/reexport-of-reexport-108679.rs similarity index 100% rename from tests/rustdoc/reexport-of-reexport-108679.rs rename to tests/rustdoc/reexport/reexport-of-reexport-108679.rs diff --git a/tests/rustdoc/reexport-stability-tags-deprecated-and-portability.rs b/tests/rustdoc/reexport/reexport-stability-tags-deprecated-and-portability.rs similarity index 100% rename from tests/rustdoc/reexport-stability-tags-deprecated-and-portability.rs rename to tests/rustdoc/reexport/reexport-stability-tags-deprecated-and-portability.rs diff --git a/tests/rustdoc/reexport-stability-tags-unstable-and-portability.rs b/tests/rustdoc/reexport/reexport-stability-tags-unstable-and-portability.rs similarity index 100% rename from tests/rustdoc/reexport-stability-tags-unstable-and-portability.rs rename to tests/rustdoc/reexport/reexport-stability-tags-unstable-and-portability.rs diff --git a/tests/rustdoc/reexport-trait-from-hidden-111064-2.rs b/tests/rustdoc/reexport/reexport-trait-from-hidden-111064-2.rs similarity index 100% rename from tests/rustdoc/reexport-trait-from-hidden-111064-2.rs rename to tests/rustdoc/reexport/reexport-trait-from-hidden-111064-2.rs diff --git a/tests/rustdoc/reexport-trait-from-hidden-111064.rs b/tests/rustdoc/reexport/reexport-trait-from-hidden-111064.rs similarity index 100% rename from tests/rustdoc/reexport-trait-from-hidden-111064.rs rename to tests/rustdoc/reexport/reexport-trait-from-hidden-111064.rs diff --git a/tests/rustdoc/reexports-of-same-name.rs b/tests/rustdoc/reexport/reexports-of-same-name.rs similarity index 100% rename from tests/rustdoc/reexports-of-same-name.rs rename to tests/rustdoc/reexport/reexports-of-same-name.rs diff --git a/tests/rustdoc/reexports-priv.rs b/tests/rustdoc/reexport/reexports-priv.rs similarity index 100% rename from tests/rustdoc/reexports-priv.rs rename to tests/rustdoc/reexport/reexports-priv.rs diff --git a/tests/rustdoc/reexports.rs b/tests/rustdoc/reexport/reexports.rs similarity index 100% rename from tests/rustdoc/reexports.rs rename to tests/rustdoc/reexport/reexports.rs diff --git a/tests/rustdoc/assoc-type-source-link.rs b/tests/rustdoc/source-code-pages/assoc-type-source-link.rs similarity index 100% rename from tests/rustdoc/assoc-type-source-link.rs rename to tests/rustdoc/source-code-pages/assoc-type-source-link.rs diff --git a/tests/rustdoc/auxiliary/issue-26606-macro.rs b/tests/rustdoc/source-code-pages/auxiliary/issue-26606-macro.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-26606-macro.rs rename to tests/rustdoc/source-code-pages/auxiliary/issue-26606-macro.rs diff --git a/tests/rustdoc/auxiliary/issue-34274.rs b/tests/rustdoc/source-code-pages/auxiliary/issue-34274.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-34274.rs rename to tests/rustdoc/source-code-pages/auxiliary/issue-34274.rs diff --git a/tests/rustdoc/auxiliary/source-code-bar.rs b/tests/rustdoc/source-code-pages/auxiliary/source-code-bar.rs similarity index 100% rename from tests/rustdoc/auxiliary/source-code-bar.rs rename to tests/rustdoc/source-code-pages/auxiliary/source-code-bar.rs diff --git a/tests/rustdoc/auxiliary/source_code.rs b/tests/rustdoc/source-code-pages/auxiliary/source_code.rs similarity index 100% rename from tests/rustdoc/auxiliary/source_code.rs rename to tests/rustdoc/source-code-pages/auxiliary/source_code.rs diff --git a/tests/rustdoc/auxiliary/src-links-external.rs b/tests/rustdoc/source-code-pages/auxiliary/src-links-external.rs similarity index 100% rename from tests/rustdoc/auxiliary/src-links-external.rs rename to tests/rustdoc/source-code-pages/auxiliary/src-links-external.rs diff --git a/tests/rustdoc/check-source-code-urls-to-def-std.rs b/tests/rustdoc/source-code-pages/check-source-code-urls-to-def-std.rs similarity index 100% rename from tests/rustdoc/check-source-code-urls-to-def-std.rs rename to tests/rustdoc/source-code-pages/check-source-code-urls-to-def-std.rs diff --git a/tests/rustdoc/check-source-code-urls-to-def.rs b/tests/rustdoc/source-code-pages/check-source-code-urls-to-def.rs similarity index 100% rename from tests/rustdoc/check-source-code-urls-to-def.rs rename to tests/rustdoc/source-code-pages/check-source-code-urls-to-def.rs diff --git a/tests/rustdoc/doc-hidden-source.rs b/tests/rustdoc/source-code-pages/doc-hidden-source.rs similarity index 100% rename from tests/rustdoc/doc-hidden-source.rs rename to tests/rustdoc/source-code-pages/doc-hidden-source.rs diff --git a/tests/rustdoc/html-no-source.rs b/tests/rustdoc/source-code-pages/html-no-source.rs similarity index 100% rename from tests/rustdoc/html-no-source.rs rename to tests/rustdoc/source-code-pages/html-no-source.rs diff --git a/tests/rustdoc/source-code-highlight.rs b/tests/rustdoc/source-code-pages/source-code-highlight.rs similarity index 100% rename from tests/rustdoc/source-code-highlight.rs rename to tests/rustdoc/source-code-pages/source-code-highlight.rs diff --git a/tests/rustdoc/source-file.rs b/tests/rustdoc/source-code-pages/source-file.rs similarity index 100% rename from tests/rustdoc/source-file.rs rename to tests/rustdoc/source-code-pages/source-file.rs diff --git a/tests/rustdoc/source-line-numbers.rs b/tests/rustdoc/source-code-pages/source-line-numbers.rs similarity index 100% rename from tests/rustdoc/source-line-numbers.rs rename to tests/rustdoc/source-code-pages/source-line-numbers.rs diff --git a/tests/rustdoc/source-version-separator.rs b/tests/rustdoc/source-code-pages/source-version-separator.rs similarity index 100% rename from tests/rustdoc/source-version-separator.rs rename to tests/rustdoc/source-code-pages/source-version-separator.rs diff --git a/tests/rustdoc/src-link-external-macro-26606.rs b/tests/rustdoc/source-code-pages/src-link-external-macro-26606.rs similarity index 100% rename from tests/rustdoc/src-link-external-macro-26606.rs rename to tests/rustdoc/source-code-pages/src-link-external-macro-26606.rs diff --git a/tests/rustdoc/src-links-auto-impls.rs b/tests/rustdoc/source-code-pages/src-links-auto-impls.rs similarity index 100% rename from tests/rustdoc/src-links-auto-impls.rs rename to tests/rustdoc/source-code-pages/src-links-auto-impls.rs diff --git a/tests/rustdoc/src-links-external.rs b/tests/rustdoc/source-code-pages/src-links-external.rs similarity index 100% rename from tests/rustdoc/src-links-external.rs rename to tests/rustdoc/source-code-pages/src-links-external.rs diff --git a/tests/rustdoc/src-links-implementor-43893.rs b/tests/rustdoc/source-code-pages/src-links-implementor-43893.rs similarity index 100% rename from tests/rustdoc/src-links-implementor-43893.rs rename to tests/rustdoc/source-code-pages/src-links-implementor-43893.rs diff --git a/tests/rustdoc/src-links-inlined-34274.rs b/tests/rustdoc/source-code-pages/src-links-inlined-34274.rs similarity index 100% rename from tests/rustdoc/src-links-inlined-34274.rs rename to tests/rustdoc/source-code-pages/src-links-inlined-34274.rs diff --git a/tests/rustdoc/src-links.rs b/tests/rustdoc/source-code-pages/src-links.rs similarity index 100% rename from tests/rustdoc/src-links.rs rename to tests/rustdoc/source-code-pages/src-links.rs diff --git a/tests/rustdoc/src-links/compiletest-ignore-dir b/tests/rustdoc/source-code-pages/src-links/compiletest-ignore-dir similarity index 100% rename from tests/rustdoc/src-links/compiletest-ignore-dir rename to tests/rustdoc/source-code-pages/src-links/compiletest-ignore-dir diff --git a/tests/rustdoc/src-links/fizz.rs b/tests/rustdoc/source-code-pages/src-links/fizz.rs similarity index 100% rename from tests/rustdoc/src-links/fizz.rs rename to tests/rustdoc/source-code-pages/src-links/fizz.rs diff --git a/tests/rustdoc/src-links/mod.rs b/tests/rustdoc/source-code-pages/src-links/mod.rs similarity index 100% rename from tests/rustdoc/src-links/mod.rs rename to tests/rustdoc/source-code-pages/src-links/mod.rs diff --git a/tests/rustdoc/src-mod-path-absolute-26995.rs b/tests/rustdoc/source-code-pages/src-mod-path-absolute-26995.rs similarity index 100% rename from tests/rustdoc/src-mod-path-absolute-26995.rs rename to tests/rustdoc/source-code-pages/src-mod-path-absolute-26995.rs diff --git a/tests/rustdoc/version-separator-without-source.rs b/tests/rustdoc/source-code-pages/version-separator-without-source.rs similarity index 100% rename from tests/rustdoc/version-separator-without-source.rs rename to tests/rustdoc/source-code-pages/version-separator-without-source.rs diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs index 755bec8747bc..bb95bedf9733 100644 --- a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs +++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs @@ -17,13 +17,13 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use std::io::Write; use std::collections::HashSet; -use stable_mir::CrateDef; -use stable_mir::*; -use stable_mir::ty::*; +use std::io::Write; use std::ops::ControlFlow; +use stable_mir::ty::*; +use stable_mir::{CrateDef, *}; + const CRATE_NAME: &str = "crate_assoc_items"; /// This function uses the Stable MIR APIs to get information about the test crate. @@ -45,30 +45,30 @@ fn test_assoc_items() -> ControlFlow<()> { let local_impls = local_crate.trait_impls(); let local_traits = local_crate.trait_decls(); - let trait_assoc_item_defs: Vec = local_traits[0].associated_items() - .iter().map(|assoc_item| assoc_item.def_id).collect(); + let trait_assoc_item_defs: Vec = + local_traits[0].associated_items().iter().map(|assoc_item| assoc_item.def_id).collect(); check_items( &trait_assoc_item_defs, &[ - "ATrait::{anon_assoc#0}", + "ATrait::rpitit::{anon_assoc#0}", "ATrait::rpitit", "ATrait::Assoc", "ATrait::assoc_fn_no_self", "ATrait::assoc_fn_has_self", - ] + ], ); - let impl_assoc_item_defs: Vec = local_impls[0].associated_items() - .iter().map(|assoc_item| assoc_item.def_id).collect(); + let impl_assoc_item_defs: Vec = + local_impls[0].associated_items().iter().map(|assoc_item| assoc_item.def_id).collect(); check_items( &impl_assoc_item_defs, &[ - "::{anon_assoc#0}", + "::rpitit::{anon_assoc#0}", "::rpitit", "::Assoc", "::assoc_fn_no_self", "::assoc_fn_has_self", - ] + ], ); ControlFlow::Continue(()) diff --git a/tests/ui-fulldeps/stable-mir/check_attribute.rs b/tests/ui-fulldeps/stable-mir/check_attribute.rs index 81d5399d88aa..e4cc7b104b60 100644 --- a/tests/ui-fulldeps/stable-mir/check_attribute.rs +++ b/tests/ui-fulldeps/stable-mir/check_attribute.rs @@ -35,12 +35,12 @@ fn test_stable_mir() -> ControlFlow<()> { fn test_tool(items: &CrateItems) { let rustfmt_fn = *get_item(&items, "do_not_format").unwrap(); let rustfmt_attrs = rustfmt_fn.tool_attrs(&["rustfmt".to_string(), "skip".to_string()]); - assert_eq!(rustfmt_attrs[0].as_str(), "#[rustfmt::skip]"); + assert_eq!(rustfmt_attrs[0].as_str(), "#[rustfmt::skip]\n"); let clippy_fn = *get_item(&items, "complex_fn").unwrap(); let clippy_attrs = clippy_fn.tool_attrs(&["clippy".to_string(), "cyclomatic_complexity".to_string()]); - assert_eq!(clippy_attrs[0].as_str(), "#[clippy::cyclomatic_complexity = \"100\"]"); + assert_eq!(clippy_attrs[0].as_str(), "#[clippy::cyclomatic_complexity = \"100\"]\n"); } fn get_item<'a>( diff --git a/tests/ui/abi/lib-defaults.rs b/tests/ui/abi/lib-defaults.rs deleted file mode 100644 index 2c2cad4f82dc..000000000000 --- a/tests/ui/abi/lib-defaults.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ run-pass -//@ dont-check-compiler-stderr (rust-lang/rust#54222) - -//@ compile-flags: -lrust_test_helpers - -#[link(name = "rust_test_helpers", kind = "static")] -extern "C" { - pub fn rust_dbg_extern_identity_u32(x: u32) -> u32; -} - -fn main() { - unsafe { - rust_dbg_extern_identity_u32(42); - } -} diff --git a/tests/ui/annotate-snippet/missing-type.rs b/tests/ui/annotate-snippet/missing-type.rs index ea1c2521103e..bfe8ab2f5ffe 100644 --- a/tests/ui/annotate-snippet/missing-type.rs +++ b/tests/ui/annotate-snippet/missing-type.rs @@ -1,6 +1,7 @@ //@ compile-flags: --error-format human-annotate-rs -Z unstable-options -//@ error-pattern:cannot find type `Iter` in this scope pub fn main() { let x: Iter; } + +//~? RAW cannot find type `Iter` in this scope diff --git a/tests/ui/annotate-snippet/missing-type.stderr b/tests/ui/annotate-snippet/missing-type.stderr index 89ce19c182f5..c16f022a77fa 100644 --- a/tests/ui/annotate-snippet/missing-type.stderr +++ b/tests/ui/annotate-snippet/missing-type.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `Iter` in this scope - --> $DIR/missing-type.rs:5:12 + --> $DIR/missing-type.rs:4:12 | LL | let x: Iter; | ^^^^ not found in this scope diff --git a/tests/ui/annotate-snippet/multispan.rs b/tests/ui/annotate-snippet/multispan.rs index b7cf22eebcbf..c2054f62d24c 100644 --- a/tests/ui/annotate-snippet/multispan.rs +++ b/tests/ui/annotate-snippet/multispan.rs @@ -1,5 +1,4 @@ //@ proc-macro: multispan.rs -//@ error-pattern:hello to you, too! //@ compile-flags: --error-format human-annotate-rs -Z unstable-options #![feature(proc_macro_hygiene)] @@ -27,3 +26,5 @@ fn main() { hello!(whoah. hi di hi di ho); hello!(hi good hi and good bye); } + +//~? RAW hello to you, too! diff --git a/tests/ui/annotate-snippet/multispan.stderr b/tests/ui/annotate-snippet/multispan.stderr index 833b67730325..baed54c59a4e 100644 --- a/tests/ui/annotate-snippet/multispan.stderr +++ b/tests/ui/annotate-snippet/multispan.stderr @@ -1,41 +1,41 @@ error: hello to you, too! - --> $DIR/multispan.rs:16:5 + --> $DIR/multispan.rs:15:5 | LL | hello!(hi); | ^^^^^^^^^^ | error: hello to you, too! - --> $DIR/multispan.rs:19:5 + --> $DIR/multispan.rs:18:5 | LL | hello!(hi hi); | ^^^^^^^^^^^^^ | error: hello to you, too! - --> $DIR/multispan.rs:22:5 + --> $DIR/multispan.rs:21:5 | LL | hello!(hi hi hi); | ^^^^^^^^^^^^^^^^ | error: hello to you, too! - --> $DIR/multispan.rs:25:5 + --> $DIR/multispan.rs:24:5 | LL | hello!(hi hey hi yo hi beep beep hi hi); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | error: hello to you, too! - --> $DIR/multispan.rs:26:5 + --> $DIR/multispan.rs:25:5 | LL | hello!(hi there, hi how are you? hi... hi.); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | error: hello to you, too! - --> $DIR/multispan.rs:27:5 + --> $DIR/multispan.rs:26:5 | LL | hello!(whoah. hi di hi di ho); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | error: hello to you, too! - --> $DIR/multispan.rs:28:5 + --> $DIR/multispan.rs:27:5 | LL | hello!(hi good hi and good bye); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/global-asm-mono-sym-fn.rs b/tests/ui/asm/global-asm-mono-sym-fn.rs new file mode 100644 index 000000000000..e584a98badb0 --- /dev/null +++ b/tests/ui/asm/global-asm-mono-sym-fn.rs @@ -0,0 +1,27 @@ +// Test that we're properly monomorphizing sym args in global asm blocks +// that point to associated items. + +//@ edition: 2021 +//@ needs-asm-support +//@ only-x86_64-unknown-linux-gnu +//@ build-pass + +#![no_main] + +use std::arch::global_asm; + +fn foo() { + loop {} +} + +trait Foo { + fn bar(); +} + +impl Foo for i32 { + fn bar() { + loop {} + } +} + +global_asm!(".global main", "main:", "call {}", sym ::bar); diff --git a/tests/ui/asm/naked-asm-mono-sym-fn.rs b/tests/ui/asm/naked-asm-mono-sym-fn.rs new file mode 100644 index 000000000000..948c290c0b4f --- /dev/null +++ b/tests/ui/asm/naked-asm-mono-sym-fn.rs @@ -0,0 +1,35 @@ +// Regression test for . +// Test that we're properly monomorphizing sym args in naked asm blocks +// that point to associated items. + +//@ edition: 2021 +//@ needs-asm-support +//@ only-x86_64 +//@ build-pass + +trait Tr { + extern "C" fn t(); +} + +enum E {} + +impl Tr for E { + extern "C" fn t() { + println!("Const generic: {}", C); + } +} + +#[unsafe(naked)] +extern "C" fn foo() { + core::arch::naked_asm!( + "push rax", + "call {fn}", + "pop rax", + "ret", + fn = sym ::t, + ); +} + +fn main() { + foo::>(); +} diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index cb5fde9a80b8..a6f41698b411 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -231,3 +231,9 @@ pub extern "C" fn compatible_linkage() { pub extern "C" fn rustc_std_internal_symbol() { naked_asm!("", options(raw)); } + +#[rustfmt::skip] +#[unsafe(naked)] +pub extern "C" fn rustfmt_skip() { + naked_asm!("", options(raw)); +} diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr deleted file mode 100644 index 81ace4ebb6da..000000000000 --- a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0277]: the size for values of type `[u32]` cannot be known at compilation time - --> $DIR/wf-check-skipped.rs:17:25 - | -LL | fn main() -> Foo::Bar::> {} - | ^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[u32]` -note: required by an implicit `Sized` bound in `Vec` - --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs index 52df4efd13e9..2949007d770a 100644 --- a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs +++ b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs @@ -1,8 +1,8 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) -//@[current] known-bug: #100041 -//@[current] check-pass +//@ known-bug: #100041 +//@ check-pass // FIXME(inherent_associated_types): This should fail. #![feature(inherent_associated_types)] @@ -15,4 +15,3 @@ impl Foo { } fn main() -> Foo::Bar::> {} -//[next]~^ ERROR the size for values of type `[u32]` cannot be known at compilation time diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr index 13ebaf67e54a..b50e353b6988 100644 --- a/tests/ui/async-await/async-closures/def-path.stderr +++ b/tests/ui/async-await/async-closures/def-path.stderr @@ -5,11 +5,11 @@ LL | let x = async || {}; | -- the expected `async` closure body LL | LL | let () = x(); - | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?16t resume_ty=ResumeTy yield_ty=() return_ty=() witness=?6t}` + | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?16t resume_ty=ResumeTy yield_ty=() return_ty=() witness=?5t}` | | | expected `async` closure body, found `()` | - = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?16t resume_ty=ResumeTy yield_ty=() return_ty=() witness=?6t}` + = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?16t resume_ty=ResumeTy yield_ty=() return_ty=() witness=?5t}` found unit type `()` error: aborting due to 1 previous error diff --git a/tests/ui/attributes/export/crate-type-2.rs b/tests/ui/attributes/export/crate-type-2.rs new file mode 100644 index 000000000000..f0379f6d797c --- /dev/null +++ b/tests/ui/attributes/export/crate-type-2.rs @@ -0,0 +1,2 @@ +//@ compile-flags: --crate-type=sdylib +//~^ ERROR `sdylib` crate type is unstable diff --git a/tests/ui/attributes/export/crate-type-2.stderr b/tests/ui/attributes/export/crate-type-2.stderr new file mode 100644 index 000000000000..7ce6a500113f --- /dev/null +++ b/tests/ui/attributes/export/crate-type-2.stderr @@ -0,0 +1,9 @@ +error[E0658]: `sdylib` crate type is unstable + | + = note: see issue #139939 for more information + = help: add `#![feature(export_stable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/attributes/export/crate-type.rs b/tests/ui/attributes/export/crate-type.rs new file mode 100644 index 000000000000..bd092bbb1a1a --- /dev/null +++ b/tests/ui/attributes/export/crate-type.rs @@ -0,0 +1,2 @@ +#![crate_type = "sdylib"] +//~^ ERROR `sdylib` crate type is unstable diff --git a/tests/ui/attributes/export/crate-type.stderr b/tests/ui/attributes/export/crate-type.stderr new file mode 100644 index 000000000000..7ce6a500113f --- /dev/null +++ b/tests/ui/attributes/export/crate-type.stderr @@ -0,0 +1,9 @@ +error[E0658]: `sdylib` crate type is unstable + | + = note: see issue #139939 for more information + = help: add `#![feature(export_stable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/attributes/export/exportable.rs b/tests/ui/attributes/export/exportable.rs new file mode 100644 index 000000000000..f592fce88cd4 --- /dev/null +++ b/tests/ui/attributes/export/exportable.rs @@ -0,0 +1,139 @@ +//@ compile-flags: -Zunstable-options -Csymbol-mangling-version=v0 + +#![crate_type = "sdylib"] +#![allow(incomplete_features, improper_ctypes_definitions)] +#![feature(export_stable)] +#![feature(inherent_associated_types)] + +mod m { + #[export_stable] + pub struct S; + //~^ ERROR private items are not exportable + + pub fn foo() -> i32 { 0 } + //~^ ERROR only functions with "C" ABI are exportable +} + +#[export_stable] +pub use m::foo; + +#[export_stable] +pub mod m1 { + #[repr(C)] + pub struct S1; // OK, public type with stable repr + + struct S2; + + pub struct S3; + //~^ ERROR types with unstable layout are not exportable +} + +pub mod fn_sig { + #[export_stable] + pub fn foo1() {} + //~^ ERROR only functions with "C" ABI are exportable + + #[export_stable] + #[repr(C)] + pub struct S; + + #[export_stable] + pub extern "C" fn foo2(x: S) -> i32 { 0 } + + #[export_stable] + pub extern "C" fn foo3(x: Box) -> i32 { 0 } + //~^ ERROR function with `#[export_stable]` attribute uses type `Box`, which is not exportable +} + +pub mod impl_item { + pub struct S; + + impl S { + #[export_stable] + pub extern "C" fn foo1(&self) -> i32 { 0 } + //~^ ERROR method with `#[export_stable]` attribute uses type `&impl_item::S`, which is not exportable + + #[export_stable] + pub extern "C" fn foo2(self) -> i32 { 0 } + //~^ ERROR method with `#[export_stable]` attribute uses type `impl_item::S`, which is not exportable + } + + pub struct S2(T); + + impl S2 { + #[export_stable] + pub extern "C" fn foo1(&self) {} + //~^ ERROR generic functions are not exportable + } +} + +pub mod tys { + pub trait Trait { + type Type; + } + pub struct S; + + impl Trait for S { + type Type = (u32,); + } + + #[export_stable] + pub extern "C" fn foo1(x: ::Type) -> u32 { x.0 } + //~^ ERROR function with `#[export_stable]` attribute uses type `(u32,)`, which is not exportable + + #[export_stable] + pub type Type = [i32; 4]; + + #[export_stable] + pub extern "C" fn foo2(_x: Type) {} + //~^ ERROR function with `#[export_stable]` attribute uses type `[i32; 4]`, which is not exportable + + impl S { + #[export_stable] + pub type Type = extern "C" fn(); + } + + #[export_stable] + pub extern "C" fn foo3(_x: S::Type) {} + //~^ ERROR function with `#[export_stable]` attribute uses type `extern "C" fn()`, which is not exportable + + #[export_stable] + pub extern "C" fn foo4() -> impl Copy { + //~^ ERROR function with `#[export_stable]` attribute uses type `impl Copy`, which is not exportable + 0 + } +} + +pub mod privacy { + #[export_stable] + #[repr(C)] + pub struct S1 { + pub x: i32 + } + + #[export_stable] + #[repr(C)] + pub struct S2 { + //~^ ERROR ADT types with private fields are not exportable + x: i32 + } + + #[export_stable] + #[repr(i32)] + enum E { + //~^ ERROR private items are not exportable + Variant1 { x: i32 } + } +} + +pub mod use_site { + #[export_stable] + pub trait Trait {} + //~^ ERROR trait's are not exportable + + #[export_stable] + pub const C: i32 = 0; + //~^ ERROR constant's are not exportable +} + +fn main() {} diff --git a/tests/ui/attributes/export/exportable.stderr b/tests/ui/attributes/export/exportable.stderr new file mode 100644 index 000000000000..0f6469d35c3b --- /dev/null +++ b/tests/ui/attributes/export/exportable.stderr @@ -0,0 +1,130 @@ +error: private items are not exportable + --> $DIR/exportable.rs:10:5 + | +LL | pub struct S; + | ^^^^^^^^^^^^ + | +note: is only usable at visibility `pub(crate)` + --> $DIR/exportable.rs:10:5 + | +LL | pub struct S; + | ^^^^^^^^^^^^ + +error: private items are not exportable + --> $DIR/exportable.rs:123:5 + | +LL | enum E { + | ^^^^^^ + | +note: is only usable at visibility `pub(self)` + --> $DIR/exportable.rs:123:5 + | +LL | enum E { + | ^^^^^^ + +error: trait's are not exportable + --> $DIR/exportable.rs:131:5 + | +LL | pub trait Trait {} + | ^^^^^^^^^^^^^^^ + +error: constant's are not exportable + --> $DIR/exportable.rs:135:5 + | +LL | pub const C: i32 = 0; + | ^^^^^^^^^^^^^^^^ + +error: only functions with "C" ABI are exportable + --> $DIR/exportable.rs:13:5 + | +LL | pub fn foo() -> i32 { 0 } + | ^^^^^^^^^^^^^^^^^^^ + +error: types with unstable layout are not exportable + --> $DIR/exportable.rs:27:5 + | +LL | pub struct S3; + | ^^^^^^^^^^^^^ + +error: only functions with "C" ABI are exportable + --> $DIR/exportable.rs:33:5 + | +LL | pub fn foo1() {} + | ^^^^^^^^^^^^^ + +error: function with `#[export_stable]` attribute uses type `Box`, which is not exportable + --> $DIR/exportable.rs:44:5 + | +LL | pub extern "C" fn foo3(x: Box) -> i32 { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^------^^^^^^^^ + | | + | not exportable + +error: method with `#[export_stable]` attribute uses type `&impl_item::S`, which is not exportable + --> $DIR/exportable.rs:53:9 + | +LL | pub extern "C" fn foo1(&self) -> i32 { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^-----^^^^^^^^ + | | + | not exportable + +error: method with `#[export_stable]` attribute uses type `impl_item::S`, which is not exportable + --> $DIR/exportable.rs:57:9 + | +LL | pub extern "C" fn foo2(self) -> i32 { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^----^^^^^^^^ + | | + | not exportable + +error: generic functions are not exportable + --> $DIR/exportable.rs:65:9 + | +LL | pub extern "C" fn foo1(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: function with `#[export_stable]` attribute uses type `(u32,)`, which is not exportable + --> $DIR/exportable.rs:81:5 + | +LL | pub extern "C" fn foo1(x: ::Type) -> u32 { x.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^------------------^^^^^^^^ + | | + | not exportable + +error: function with `#[export_stable]` attribute uses type `[i32; 4]`, which is not exportable + --> $DIR/exportable.rs:88:5 + | +LL | pub extern "C" fn foo2(_x: Type) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^----^ + | | + | not exportable + +error: function with `#[export_stable]` attribute uses type `extern "C" fn()`, which is not exportable + --> $DIR/exportable.rs:97:5 + | +LL | pub extern "C" fn foo3(_x: S::Type) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^ + | | + | not exportable + +error: function with `#[export_stable]` attribute uses type `impl Copy`, which is not exportable + --> $DIR/exportable.rs:101:5 + | +LL | pub extern "C" fn foo4() -> impl Copy { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------- + | | + | not exportable + +error: ADT types with private fields are not exportable + --> $DIR/exportable.rs:116:5 + | +LL | pub struct S2 { + | ^^^^^^^^^^^^^ + | +note: `x` is private + --> $DIR/exportable.rs:118:9 + | +LL | x: i32 + | ^^^^^^ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/attributes/export/lang-item.rs b/tests/ui/attributes/export/lang-item.rs new file mode 100644 index 000000000000..b923b41a9575 --- /dev/null +++ b/tests/ui/attributes/export/lang-item.rs @@ -0,0 +1,8 @@ +#![feature(no_core, lang_items, export_stable)] +#![allow(incomplete_features)] +#![crate_type = "sdylib"] +#![no_core] + +#[lang = "sized"] +//~^ ERROR lang items are not allowed in stable dylibs +trait Sized {} diff --git a/tests/ui/attributes/export/lang-item.stderr b/tests/ui/attributes/export/lang-item.stderr new file mode 100644 index 000000000000..8c0741bdb6f2 --- /dev/null +++ b/tests/ui/attributes/export/lang-item.stderr @@ -0,0 +1,8 @@ +error: lang items are not allowed in stable dylibs + --> $DIR/lang-item.rs:6:1 + | +LL | #[lang = "sized"] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/auxiliary/issue-13560-1.rs b/tests/ui/attributes/no_link/auxiliary/empty-crate-1.rs similarity index 52% rename from tests/ui/auxiliary/issue-13560-1.rs rename to tests/ui/attributes/no_link/auxiliary/empty-crate-1.rs index baca1567e1b0..8bd2b3353b8f 100644 --- a/tests/ui/auxiliary/issue-13560-1.rs +++ b/tests/ui/attributes/no_link/auxiliary/empty-crate-1.rs @@ -1,3 +1 @@ -//@ no-prefer-dynamic - #![crate_type = "dylib"] diff --git a/tests/ui/auxiliary/issue-13560-2.rs b/tests/ui/attributes/no_link/auxiliary/empty-crate-2.rs similarity index 100% rename from tests/ui/auxiliary/issue-13560-2.rs rename to tests/ui/attributes/no_link/auxiliary/empty-crate-2.rs diff --git a/tests/ui/attributes/no_link/auxiliary/no_link-crate.rs b/tests/ui/attributes/no_link/auxiliary/no_link-crate.rs new file mode 100644 index 000000000000..1c3af5431cc6 --- /dev/null +++ b/tests/ui/attributes/no_link/auxiliary/no_link-crate.rs @@ -0,0 +1,6 @@ +//@ no-prefer-dynamic + +#![crate_type = "rlib"] + +#[macro_use] #[no_link] extern crate empty_crate_1 as t1; +#[macro_use] extern crate empty_crate_2 as t2; diff --git a/tests/ui/attributes/no_link/multiple-crates-and-no_link.rs b/tests/ui/attributes/no_link/multiple-crates-and-no_link.rs new file mode 100644 index 000000000000..0e6f1deb2172 --- /dev/null +++ b/tests/ui/attributes/no_link/multiple-crates-and-no_link.rs @@ -0,0 +1,17 @@ +//! Regression test for #13560. Previously, it was possible to +//! trigger an assert in crate numbering if a series of crates +//! being loaded included a "syntax-only" extern crate. +//! But it appears we don't mess with crate numbering for +//! `#[no_link]` crates anymore, so this test doesn't seem +//! to test anything now. + +//@ run-pass +//@ needs-crate-type: dylib +//@ aux-build:empty-crate-1.rs +//@ aux-build:empty-crate-2.rs +//@ aux-build:no_link-crate.rs + +extern crate empty_crate_2 as t2; +extern crate no_link_crate as t3; + +fn main() {} diff --git a/tests/ui/attributes/no_link/no-link-unknown-crate.rs b/tests/ui/attributes/no_link/no-link-unknown-crate.rs new file mode 100644 index 000000000000..3a91fa27ee3b --- /dev/null +++ b/tests/ui/attributes/no_link/no-link-unknown-crate.rs @@ -0,0 +1,19 @@ +//! Unfortunately the development of `#[phase]` and `#[no_link]` +//! predates Zulip, and thus has been lost in the sands of time. +//! Understanding the true nature of this test has been left as +//! an exercise for the reader. +//! +//! But we guess from the git history that originally this +//! test was supposed to check that we error if we can't find +//! an extern crate annotated with `#[phase(syntax)]`, +//! see `macro-crate-unknown-crate.rs` in +//! . Later, we changed +//! `#[phase]` to `#![feature(plugin)]` and added a `#[no_link]`. +//! +//! I suppose that this now tests that we still error if we can't +//! find a `#[no_link]` extern crate? + +#[no_link] +extern crate doesnt_exist; //~ ERROR can't find crate + +fn main() {} diff --git a/tests/ui/no-link-unknown-crate.stderr b/tests/ui/attributes/no_link/no-link-unknown-crate.stderr similarity index 85% rename from tests/ui/no-link-unknown-crate.stderr rename to tests/ui/attributes/no_link/no-link-unknown-crate.stderr index edc248db09ea..999b013866cd 100644 --- a/tests/ui/no-link-unknown-crate.stderr +++ b/tests/ui/attributes/no_link/no-link-unknown-crate.stderr @@ -1,5 +1,5 @@ error[E0463]: can't find crate for `doesnt_exist` - --> $DIR/no-link-unknown-crate.rs:2:1 + --> $DIR/no-link-unknown-crate.rs:17:1 | LL | extern crate doesnt_exist; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate diff --git a/tests/ui/auxiliary/inner_static.rs b/tests/ui/auxiliary/inner_static.rs deleted file mode 100644 index 42dcd379d41e..000000000000 --- a/tests/ui/auxiliary/inner_static.rs +++ /dev/null @@ -1,51 +0,0 @@ -pub struct A { pub v: T } -pub struct B { pub v: T } - -pub mod test { - pub struct A { pub v: T } - - impl A { - pub fn foo(&self) -> isize { - static a: isize = 5; - return a - } - - pub fn bar(&self) -> isize { - static a: isize = 6; - return a; - } - } -} - -impl A { - pub fn foo(&self) -> isize { - static a: isize = 1; - return a - } - - pub fn bar(&self) -> isize { - static a: isize = 2; - return a; - } -} - -impl B { - pub fn foo(&self) -> isize { - static a: isize = 3; - return a - } - - pub fn bar(&self) -> isize { - static a: isize = 4; - return a; - } -} - -pub fn foo() -> isize { - let a = A { v: () }; - let b = B { v: () }; - let c = test::A { v: () }; - return a.foo() + a.bar() + - b.foo() + b.bar() + - c.foo() + c.bar(); -} diff --git a/tests/ui/auxiliary/issue-13560-3.rs b/tests/ui/auxiliary/issue-13560-3.rs deleted file mode 100644 index 4aab2ddc73a0..000000000000 --- a/tests/ui/auxiliary/issue-13560-3.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ no-prefer-dynamic - -#![crate_type = "rlib"] - -#[macro_use] #[no_link] extern crate issue_13560_1 as t1; -#[macro_use] extern crate issue_13560_2 as t2; diff --git a/tests/ui/bootstrap/rustc_bootstrap.rs b/tests/ui/bootstrap/rustc_bootstrap.rs index daa28e0cdf29..fb72bba95a15 100644 --- a/tests/ui/bootstrap/rustc_bootstrap.rs +++ b/tests/ui/bootstrap/rustc_bootstrap.rs @@ -38,10 +38,11 @@ // also affected by `RUSTC_BOOTSTRAP`. //@[force_stable] rustc-env:RUSTC_BOOTSTRAP=-1 //@[force_stable] compile-flags: -Z unstable-options -//@[force_stable] regex-error-pattern: error: the option `Z` is only accepted on the nightly compiler #![crate_type = "lib"] // Note: `rustc_attrs` is a perma-unstable internal feature that is unlikely to change, which is // used as a proxy to check `RUSTC_BOOTSTRAP` versus stability checking logic. #![feature(rustc_attrs)] + +//[force_stable]~? RAW the option `Z` is only accepted on the nightly compiler diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs index 141ad5bd2c48..7c0378e068be 100644 --- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs @@ -17,11 +17,11 @@ pub trait Foo<'a, 't> { impl<'a, 't> Foo<'a, 't> for &'a isize { fn no_bound<'b:'a>(self, b: Inv<'b>) { - //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match + //~^ ERROR lifetime parameters do not match the trait definition } fn has_bound<'b>(self, b: Inv<'b>) { - //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match + //~^ ERROR lifetime parameters do not match the trait definition } fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { @@ -40,7 +40,7 @@ impl<'a, 't> Foo<'a, 't> for &'a isize { } fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { - //~^ ERROR lifetime parameters or bounds on method `wrong_bound2` do not match the trait + //~^ ERROR lifetime parameters do not match the trait definition } fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) { diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 5f0347bdb4d4..207ca57af38b 100644 --- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -1,20 +1,48 @@ -error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration - --> $DIR/regions-bound-missing-bound-in-impl.rs:19:16 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/regions-bound-missing-bound-in-impl.rs:19:17 | -LL | fn no_bound<'b>(self, b: Inv<'b>); - | ---- lifetimes in impl do not match this method in trait -... LL | fn no_bound<'b:'a>(self, b: Inv<'b>) { - | ^^^^^^^ lifetimes do not match method in trait - -error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration - --> $DIR/regions-bound-missing-bound-in-impl.rs:23:17 + | ^^ | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'b` differs between the trait and impl + --> $DIR/regions-bound-missing-bound-in-impl.rs:10:17 + | +LL | pub trait Foo<'a, 't> { + | --------------------- in this trait... +LL | fn no_bound<'b>(self, b: Inv<'b>); + | ^^ `'b` is late-bound +... +LL | impl<'a, 't> Foo<'a, 't> for &'a isize { + | -------------------------------------- in this impl... +LL | fn no_bound<'b:'a>(self, b: Inv<'b>) { + | ^^ -- this lifetime bound makes `'b` early-bound + | | + | `'b` is early-bound + +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/regions-bound-missing-bound-in-impl.rs:23:18 + | +LL | fn has_bound<'b>(self, b: Inv<'b>) { + | ^^ + | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'b` differs between the trait and impl + --> $DIR/regions-bound-missing-bound-in-impl.rs:11:18 + | +LL | pub trait Foo<'a, 't> { + | --------------------- in this trait... +LL | fn no_bound<'b>(self, b: Inv<'b>); LL | fn has_bound<'b:'a>(self, b: Inv<'b>); - | ------- lifetimes in impl do not match this method in trait + | ^^ -- this lifetime bound makes `'b` early-bound + | | + | `'b` is early-bound +... +LL | impl<'a, 't> Foo<'a, 't> for &'a isize { + | -------------------------------------- in this impl... ... LL | fn has_bound<'b>(self, b: Inv<'b>) { - | ^^^^ lifetimes do not match method in trait + | ^^ `'b` is late-bound error[E0308]: method not compatible with trait --> $DIR/regions-bound-missing-bound-in-impl.rs:27:5 @@ -54,14 +82,45 @@ note: ...does not necessarily outlive the lifetime `'c` as defined here LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^ -error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration - --> $DIR/regions-bound-missing-bound-in-impl.rs:42:20 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/regions-bound-missing-bound-in-impl.rs:42:30 | +LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { + | ^^^ ^^^ + | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'_` differs between the trait and impl + --> $DIR/regions-bound-missing-bound-in-impl.rs:13:21 + | +LL | pub trait Foo<'a, 't> { + | --------------------- in this trait... +... LL | fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); - | ---------------- lifetimes in impl do not match this method in trait + | ^^ -- this lifetime bound makes `'b` early-bound + | | + | `'b` is early-bound +... +LL | impl<'a, 't> Foo<'a, 't> for &'a isize { + | -------------------------------------- in this impl... ... LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { - | ^ lifetimes do not match method in trait + | ^^^ `'_` is late-bound +note: `'_` differs between the trait and impl + --> $DIR/regions-bound-missing-bound-in-impl.rs:13:27 + | +LL | pub trait Foo<'a, 't> { + | --------------------- in this trait... +... +LL | fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); + | ^^ -- this lifetime bound makes `'d` early-bound + | | + | `'d` is early-bound +... +LL | impl<'a, 't> Foo<'a, 't> for &'a isize { + | -------------------------------------- in this impl... +... +LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { + | ^^^ `'_` is late-bound error[E0276]: impl has stricter requirements than trait --> $DIR/regions-bound-missing-bound-in-impl.rs:49:26 diff --git a/tests/ui/cast/cast-alias-of-array-to-element.rs b/tests/ui/cast/cast-alias-of-array-to-element.rs new file mode 100644 index 000000000000..124d0e0346f0 --- /dev/null +++ b/tests/ui/cast/cast-alias-of-array-to-element.rs @@ -0,0 +1,22 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Regression test for . +// Test that we structually normalize in the hacky `&[T; N] -> *const T` in cast. + +trait Mirror { + type Assoc: ?Sized; +} +impl Mirror for T { + type Assoc = T; +} + +struct W<'a>(&'a <[f32; 0] as Mirror>::Assoc); + +fn foo(x: W<'_>) -> *const f32 { + x.0 as *const f32 +} + +fn main() {} diff --git a/tests/ui/cfg/cfg_false_no_std-2.rs b/tests/ui/cfg/cfg_false_no_std-2.rs index 18b2c699fd7a..666c90deaf0f 100644 --- a/tests/ui/cfg/cfg_false_no_std-2.rs +++ b/tests/ui/cfg/cfg_false_no_std-2.rs @@ -1,7 +1,11 @@ // Error, the linked empty library is `no_std` and doesn't provide a panic handler. -//@ dont-require-annotations: ERROR //@ dont-check-compiler-stderr + +// NOTE: fix a panic strategy to prevent differing errors subject to target's default panic strategy +// which changes between targets. The specific panic strategy doesn't matter for test intention. +//@ compile-flags: -Cpanic=abort + //@ aux-build: cfg_false_lib_no_std_before.rs #![no_std] @@ -11,6 +15,3 @@ extern crate cfg_false_lib_no_std_before as _; fn main() {} //~? ERROR `#[panic_handler]` function required, but not found -// FIXME: This error is target-dependent, could be served by some "optional error" annotation -// instead of `dont-require-annotations`. -//FIXME~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/check-cfg/and-more-diagnostic.rs b/tests/ui/check-cfg/and-more-diagnostic.rs index 977f55e8a6d1..5422829c5b31 100644 --- a/tests/ui/check-cfg/and-more-diagnostic.rs +++ b/tests/ui/check-cfg/and-more-diagnostic.rs @@ -5,7 +5,7 @@ //@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() //@ normalize-stderr: "and \d+ more" -> "and X more" -//@ normalize-stderr: "`[a-zA-Z0-9_-]+`" -> "`xxx`" +//@ normalize-stderr: "`[a-zA-Z0-9_\.-]+`" -> "`xxx`" fn main() { cfg!(target_feature = "zebra"); diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 712ce941c54c..eb66633f9dd7 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -27,8 +27,11 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `amx-tf32` `amx-tile` `amx-transpose` +`apxf` `atomics` `avx` +`avx10.1` +`avx10.2` `avx2` `avx512bf16` `avx512bitalg` diff --git a/tests/ui/closures/opaque-upvar.rs b/tests/ui/closures/opaque-upvar.rs new file mode 100644 index 000000000000..90e7c9ccb465 --- /dev/null +++ b/tests/ui/closures/opaque-upvar.rs @@ -0,0 +1,19 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Regression test for . +// This is only an issue in the new solver, but I'm testing it in both solvers for now. +// This has to do with the fact that the recursive `walk_dir` is a revealing use, which has not +// yet been constrained from the defining use by the time that closure signature inference is +// performed. We don't really care, though, since anywhere we structurally match on a type in +// upvar analysis, we already call `structurally_resolve_type` right before `.kind()`. + +fn walk_dir(cb: &()) -> impl Sized { + || { + let fut = walk_dir(cb); + }; +} + +fn main() {} diff --git a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr index b71cfc503339..bcf5759a194f 100644 --- a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `{mod1::f::{closure#0} closure_kind_ty=?8t closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=?7t}` + found closure `{mod1::f::{closure#0} closure_kind_ty=?7t closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=?6t}` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr index 88f4dc9b92ab..a8d2b07a00dc 100644 --- a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `{f::{closure#0} closure_kind_ty=?8t closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=?7t}` + found closure `{f::{closure#0} closure_kind_ty=?7t closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=?6t}` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs deleted file mode 100644 index e2a00ce173d1..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -fn main() { - let a: usize = { - let v = 0u8; - &v as *const _ as usize - }; - let b: usize = { - let v = 0u8; - &v as *const _ as usize - }; - - // `a` and `b` are not equal. - assert_ne!(a, b); - // But they are the same number. - assert_eq!(format!("{a}"), format!("{b}")); - // And they are equal. - assert_eq!(a, b); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs deleted file mode 100644 index 15434de50f76..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908 - -fn f() -> usize { - let v = 0; - &v as *const _ as usize -} - -fn main() { - let a = f(); - let b = f(); - - // `a` and `b` are not equal. - assert_ne!(a, b); - // But they are the same number. - assert_eq!(format!("{a}"), format!("{b}")); - // And they are equal. - assert_eq!(a, b); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs deleted file mode 100644 index f33a9e511b61..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 - -fn main() { - let a = { - let v = 0; - &v as *const _ as usize - }; - let b = { - let v = 0; - &v as *const _ as usize - }; - - assert_ne!(a, b); - println!("{a}"); // or b - assert_eq!(a, b); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs deleted file mode 100644 index b2b4934aa5f1..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -use std::ptr; - -fn main() { - let a: usize = { - let v = 0u8; - ptr::from_ref(&v).expose_provenance() - }; - let b: usize = { - let v = 0u8; - ptr::from_ref(&v).expose_provenance() - }; - - // `a` and `b` are not equal. - assert_ne!(a, b); - // But they are the same number. - assert_eq!(format!("{a}"), format!("{b}")); - // And they are equal. - assert_eq!(a, b); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs deleted file mode 100644 index bf130c9f7598..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908 - -use std::ptr; - -fn f() -> usize { - let v = 0; - ptr::from_ref(&v).expose_provenance() -} - -fn main() { - let a = f(); - let b = f(); - - // `a` and `b` are not equal. - assert_ne!(a, b); - // But they are the same number. - assert_eq!(format!("{a}"), format!("{b}")); - // And they are equal. - assert_eq!(a, b); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs deleted file mode 100644 index 0baf8886395e..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 - -use std::ptr; - -fn main() { - let a: usize = { - let v = 0; - ptr::from_ref(&v).expose_provenance() - }; - let b: usize = { - let v = 0; - ptr::from_ref(&v).expose_provenance() - }; - - assert_ne!(a, b); - println!("{a}"); // or b - assert_eq!(a, b); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs deleted file mode 100644 index 4602ec654d10..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -use std::ptr; - -fn main() { - let a: usize = { - let v = 0u8; - ptr::from_ref(&v).addr() - }; - let b: usize = { - let v = 0u8; - ptr::from_ref(&v).addr() - }; - - // `a` and `b` are not equal. - assert_ne!(a, b); - // But they are the same number. - assert_eq!(format!("{a}"), format!("{b}")); - // And they are equal. - assert_eq!(a, b); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs deleted file mode 100644 index 789a78c15b4e..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908 - -use std::ptr; - -fn f() -> usize { - let v = 0; - ptr::from_ref(&v).addr() -} - -fn main() { - let a = f(); - let b = f(); - - // `a` and `b` are not equal. - assert_ne!(a, b); - // But they are the same number. - assert_eq!(format!("{a}"), format!("{b}")); - // And they are equal. - assert_eq!(a, b); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs deleted file mode 100644 index b7165ce1e5ce..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 - -use std::ptr; - -fn main() { - let a: usize = { - let v = 0; - ptr::from_ref(&v).addr() - }; - let b: usize = { - let v = 0; - ptr::from_ref(&v).addr() - }; - - assert_ne!(a, b); - println!("{a}"); // or b - assert_eq!(a, b); -} diff --git a/tests/ui/compiletest-self-test/compile-flags-last.rs b/tests/ui/compiletest-self-test/compile-flags-last.rs index b78a64394b87..e0743d2aea58 100644 --- a/tests/ui/compiletest-self-test/compile-flags-last.rs +++ b/tests/ui/compiletest-self-test/compile-flags-last.rs @@ -4,4 +4,5 @@ // next flag as the argument of this flag. // //@ compile-flags: --cap-lints -//@ error-pattern: Argument to option 'cap-lints' missing + +//~? RAW Argument to option 'cap-lints' missing diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-7.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-7.rs index b4344f1bca5c..f05adc7bf7aa 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-7.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-7.rs @@ -1,5 +1,6 @@ // Regression test for issue #89358. //@ compile-flags: --cfg a" -//@ error-pattern: unterminated double quote string -//@ error-pattern: this error occurred on the command line + +//~? RAW unterminated double quote string +//~? RAW this error occurred on the command line diff --git a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr index 06a6a5f59d6d..16512cb69e23 100644 --- a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr +++ b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -240,41 +240,6 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error[E0747]: unresolved item provided when a constant was expected - --> $DIR/const-arg-in-const-arg.rs:36:24 - | -LL | let _: Foo<{ bar::() }>; - | ^ - | -help: if this generic argument was intended as a const parameter, surround it with braces - | -LL | let _: Foo<{ bar::<{ N }>() }>; - | + + - -error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:38:24 - | -LL | let _: Foo<{ faz::<'a>(&()) }>; - | ^^ - | -note: the late bound lifetime parameter is introduced here - --> $DIR/const-arg-in-const-arg.rs:10:14 - | -LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } - | ^^ - -error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/const-arg-in-const-arg.rs:41:24 - | -LL | let _: Foo<{ faz::<'b>(&()) }>; - | ^^ - | -note: the late bound lifetime parameter is introduced here - --> $DIR/const-arg-in-const-arg.rs:10:14 - | -LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } - | ^^ - error: constant expression depends on a generic parameter --> $DIR/const-arg-in-const-arg.rs:25:17 | @@ -326,6 +291,41 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:36:24 + | +LL | let _: Foo<{ bar::() }>; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Foo<{ bar::<{ N }>() }>; + | + + + +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:38:24 + | +LL | let _: Foo<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:10:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:41:24 + | +LL | let _: Foo<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:10:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + error[E0747]: unresolved item provided when a constant was expected --> $DIR/const-arg-in-const-arg.rs:45:27 | diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr index a05aaf2af649..1aac357d60e4 100644 --- a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr @@ -39,14 +39,6 @@ error: unconstrained generic constant LL | let _ = const_evaluatable_lib::test1::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:5:10 - | -LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] - | ----- required by a bound in this function -LL | where -LL | [u8; std::mem::size_of::() - 1]: Sized, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` help: try adding a `where` bound | LL | fn user() where [(); std::mem::size_of::() - 1]: { @@ -59,10 +51,13 @@ LL | let _ = const_evaluatable_lib::test1::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:3:27 + --> $DIR/auxiliary/const_evaluatable_lib.rs:5:10 | LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + | ----- required by a bound in this function +LL | where +LL | [u8; std::mem::size_of::() - 1]: Sized, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` help: try adding a `where` bound | LL | fn user() where [(); std::mem::size_of::() - 1]: { diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr index 7e318f8786f3..f6119c17bf47 100644 --- a/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr @@ -1,22 +1,3 @@ -error: overly complex generic constant - --> $DIR/dependence_lint.rs:21:17 - | -LL | let _: [u8; if true { size_of::() } else { 3 }]; // error on stable, error with gce - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants - | - = help: consider moving this anonymous constant into a `const` function - -error: unconstrained generic constant - --> $DIR/dependence_lint.rs:14:12 - | -LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound - | -LL | fn foo() where [(); size_of::<*mut T>()]: { - | ++++++++++++++++++++++++++++++++ - error: unconstrained generic constant --> $DIR/dependence_lint.rs:10:9 | @@ -36,5 +17,24 @@ LL | [0; if false { size_of::() } else { 3 }]; // lint on stable, error w | = help: consider moving this anonymous constant into a `const` function +error: unconstrained generic constant + --> $DIR/dependence_lint.rs:14:12 + | +LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try adding a `where` bound + | +LL | fn foo() where [(); size_of::<*mut T>()]: { + | ++++++++++++++++++++++++++++++++ + +error: overly complex generic constant + --> $DIR/dependence_lint.rs:21:17 + | +LL | let _: [u8; if true { size_of::() } else { 3 }]; // error on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/invalid-enum.stderr b/tests/ui/const-generics/invalid-enum.stderr index 7e8a632b34f7..f588ff0bc8eb 100644 --- a/tests/ui/const-generics/invalid-enum.stderr +++ b/tests/ui/const-generics/invalid-enum.stderr @@ -25,28 +25,6 @@ LL | let _: Example = Example { x: 0 }; | not a type | help: try using the variant's enum: `CompileFlag` -error[E0747]: unresolved item provided when a constant was expected - --> $DIR/invalid-enum.rs:31:18 - | -LL | let _: Example = Example { x: 0 }; - | ^^^^^^^^^^^^^^ - | -help: if this generic argument was intended as a const parameter, surround it with braces - | -LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 }; - | + + - -error[E0747]: type provided when a constant was expected - --> $DIR/invalid-enum.rs:35:18 - | -LL | let _: Example = Example { x: 0 }; - | ^^^^^^^^^^^^^^^^^^^ - | -help: if this generic argument was intended as a const parameter, surround it with braces - | -LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 }; - | + + - error[E0747]: unresolved item provided when a constant was expected --> $DIR/invalid-enum.rs:23:12 | @@ -69,6 +47,28 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | test_2::<_, { CompileFlag::A }>(0); | + + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-enum.rs:31:18 + | +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 }; + | + + + +error[E0747]: type provided when a constant was expected + --> $DIR/invalid-enum.rs:35:18 + | +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 }; + | + + + error: aborting due to 7 previous errors Some errors have detailed explanations: E0573, E0747. diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs index 6478bf9c6ee1..39e5f732a898 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs @@ -93,7 +93,6 @@ fn main() { //~| NOTE constant of non-structural type trait Trait: Sized { const ASSOC: Option; } //~ NOTE constant defined here - //~^ NOTE impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; //~^ ERROR constant of non-structural type `NoDerive` in a pattern diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr index bf54d3d76aed..fa16d0b06a7f 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -118,14 +118,14 @@ LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: constant of non-structural type `NoDerive` in a pattern - --> $DIR/reject_non_structural.rs:98:28 + --> $DIR/reject_non_structural.rs:97:28 | LL | struct NoDerive; | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns ... LL | trait Trait: Sized { const ASSOC: Option; } | ------------------ ------------------------- constant defined here -... +LL | impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; | ^^^^^^^^^^^^^^^ constant of non-structural type | @@ -136,7 +136,7 @@ LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: constant of non-structural type `NoDerive` in a pattern - --> $DIR/reject_non_structural.rs:103:28 + --> $DIR/reject_non_structural.rs:102:28 | LL | struct NoDerive; | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns @@ -153,7 +153,7 @@ LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: constant of non-structural type `NoDerive` in a pattern - --> $DIR/reject_non_structural.rs:108:29 + --> $DIR/reject_non_structural.rs:107:29 | LL | struct NoDerive; | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns diff --git a/tests/ui/consts/missing_span_in_backtrace.rs b/tests/ui/consts/missing_span_in_backtrace.rs index c8c7453daa12..490eb57c24d4 100644 --- a/tests/ui/consts/missing_span_in_backtrace.rs +++ b/tests/ui/consts/missing_span_in_backtrace.rs @@ -1,7 +1,5 @@ //@ compile-flags: -Z ui-testing=no - -#![feature(const_swap_nonoverlapping)] use std::{ mem::{self, MaybeUninit}, ptr, diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr index aad3d76dd269..88b3e37bb84f 100644 --- a/tests/ui/consts/missing_span_in_backtrace.stderr +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -1,11 +1,11 @@ error[E0080]: evaluation of constant value failed - --> $DIR/missing_span_in_backtrace.rs:16:9 + --> $DIR/missing_span_in_backtrace.rs:14:9 | -16 | / ptr::swap_nonoverlapping( -17 | | &mut ptr1 as *mut _ as *mut MaybeUninit, -18 | | &mut ptr2 as *mut _ as *mut MaybeUninit, -19 | | mem::size_of::<&i32>(), -20 | | ); +14 | / ptr::swap_nonoverlapping( +15 | | &mut ptr1 as *mut _ as *mut MaybeUninit, +16 | | &mut ptr2 as *mut _ as *mut MaybeUninit, +17 | | mem::size_of::<&i32>(), +18 | | ); | |_________^ unable to copy parts of a pointer from memory at ALLOC0 | note: inside `swap_nonoverlapping::>` diff --git a/tests/ui/auxiliary/issue-18502.rs b/tests/ui/cross-crate/auxiliary/inline-cross-crate.rs similarity index 100% rename from tests/ui/auxiliary/issue-18502.rs rename to tests/ui/cross-crate/auxiliary/inline-cross-crate.rs diff --git a/tests/ui/auxiliary/issue-76387.rs b/tests/ui/cross-crate/auxiliary/llvm-miscompile-MarkValue-MaybeLive.rs similarity index 100% rename from tests/ui/auxiliary/issue-76387.rs rename to tests/ui/cross-crate/auxiliary/llvm-miscompile-MarkValue-MaybeLive.rs diff --git a/tests/ui/cross-crate/inline-cross-crate.rs b/tests/ui/cross-crate/inline-cross-crate.rs new file mode 100644 index 000000000000..273aa8f8f0d8 --- /dev/null +++ b/tests/ui/cross-crate/inline-cross-crate.rs @@ -0,0 +1,12 @@ +//! Dpn't ice on using an inlined function from another crate +//! See and +//! + +//@ run-pass +//@ aux-build:inline-cross-crate.rs + +extern crate inline_cross_crate as fmt; + +fn main() { + ::fmt::baz(); +} diff --git a/tests/ui/cross-crate/llvm-miscompile-MarkValue-MaybeLive.rs b/tests/ui/cross-crate/llvm-miscompile-MarkValue-MaybeLive.rs new file mode 100644 index 000000000000..95d022ddd96e --- /dev/null +++ b/tests/ui/cross-crate/llvm-miscompile-MarkValue-MaybeLive.rs @@ -0,0 +1,22 @@ +//! Regression test for +//! Tests that LLVM doesn't miscompile this +//! See upstream fix: . + +//@ compile-flags: -C opt-level=3 +//@ aux-build: llvm-miscompile-MarkValue-MaybeLive.rs +//@ run-pass + +extern crate llvm_miscompile_MarkValue_MaybeLive; + +use llvm_miscompile_MarkValue_MaybeLive::FatPtr; + +fn print(data: &[u8]) { + println!("{:#?}", data); +} + +fn main() { + let ptr = FatPtr::new(20); + let data = unsafe { std::slice::from_raw_parts(ptr.as_ptr(), ptr.len()) }; + + print(data); +} diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs index b79b5ff6fdb1..35210e78dcd9 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs @@ -1,4 +1,3 @@ -//FIXME~ ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture // Make sure the compiler does not ICE when trying to generate the debuginfo name of a type that // causes a layout error. // This version of the test already ICE'd before the commit that introduce the ICE described in @@ -6,7 +5,6 @@ //@ compile-flags:-C debuginfo=2 --error-format=human //@ build-fail -//@ error-pattern: values of the type `[u8; usize::MAX]` are too big for the target architecture #![crate_type = "rlib"] @@ -18,5 +16,5 @@ pub fn foo() -> usize { std::mem::size_of::>() } -// FIXME: the error is reported on different lines on different targets -//FIXME~? ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture +// FIXME(#140620): the error is reported on different lines on different targets +//~? RAW values of the type `[u8; usize::MAX]` are too big for the target architecture diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr index cb14d9f459a2..53d05c3db8c4 100644 --- a/tests/ui/delegation/unsupported.stderr +++ b/tests/ui/delegation/unsupported.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when computing type of `opaque::::{anon_assoc#0}` +error[E0391]: cycle detected when computing type of `opaque::::opaque_ret::{anon_assoc#0}` --> $DIR/unsupported.rs:22:25 | LL | reuse to_reuse::opaque_ret; @@ -9,7 +9,7 @@ note: ...which requires comparing an impl and trait method signature, inferring | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{anon_assoc#0}`, completing the cycle + = note: ...which again requires computing type of `opaque::::opaque_ret::{anon_assoc#0}`, completing the cycle note: cycle used when checking that `opaque::` is well-formed --> $DIR/unsupported.rs:21:5 | @@ -17,7 +17,7 @@ LL | impl ToReuse for u8 { | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0391]: cycle detected when computing type of `opaque::::{anon_assoc#0}` +error[E0391]: cycle detected when computing type of `opaque::::opaque_ret::{anon_assoc#0}` --> $DIR/unsupported.rs:25:24 | LL | reuse ToReuse::opaque_ret; @@ -28,7 +28,7 @@ note: ...which requires comparing an impl and trait method signature, inferring | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{anon_assoc#0}`, completing the cycle + = note: ...which again requires computing type of `opaque::::opaque_ret::{anon_assoc#0}`, completing the cycle note: cycle used when checking that `opaque::` is well-formed --> $DIR/unsupported.rs:24:5 | diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.rs b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs index ffeb02d78b84..17aa750332c4 100644 --- a/tests/ui/derives/deriving-with-repr-packed-move-errors.rs +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs @@ -11,15 +11,15 @@ use std::cmp::Ordering; #[repr(packed)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] struct StructA(String); -//~^ ERROR: cannot move out of `self` which is behind a shared reference -//~| ERROR: cannot move out of `self` which is behind a shared reference -//~| ERROR: cannot move out of `other` which is behind a shared reference -//~| ERROR: cannot move out of `self` which is behind a shared reference -//~| ERROR: cannot move out of `other` which is behind a shared reference -//~| ERROR: cannot move out of `self` which is behind a shared reference -//~| ERROR: cannot move out of `other` which is behind a shared reference -//~| ERROR: cannot move out of `self` which is behind a shared reference -//~| ERROR: cannot move out of `self` which is behind a shared reference +//~^ ERROR: cannot move out of a shared reference [E0507] +//~| ERROR: cannot move out of a shared reference [E0507] +//~| ERROR: cannot move out of a shared reference [E0507] +//~| ERROR: cannot move out of a shared reference [E0507] +//~| ERROR: cannot move out of a shared reference [E0507] +//~| ERROR: cannot move out of a shared reference [E0507] +//~| ERROR: cannot move out of a shared reference [E0507] +//~| ERROR: cannot move out of a shared reference [E0507] +//~| ERROR: cannot move out of a shared reference [E0507] // Unrelated impl: additinal diagnostic should NOT be emitted diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr index 68c3c8ae9ead..4b085425033d 100644 --- a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr @@ -1,10 +1,10 @@ -error[E0507]: cannot move out of `self` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ----- in this derive macro expansion LL | struct StructA(String); - | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour help: consider cloning the value if the performance cost is acceptable @@ -12,13 +12,13 @@ help: consider cloning the value if the performance cost is acceptable LL | struct StructA(String.clone()); | ++++++++ -error[E0507]: cannot move out of `self` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | --------- in this derive macro expansion LL | struct StructA(String); - | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait | = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour help: consider cloning the value if the performance cost is acceptable @@ -26,27 +26,28 @@ help: consider cloning the value if the performance cost is acceptable LL | struct StructA(String.clone()); | ++++++++ -error[E0507]: cannot move out of `other` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | --------- in this derive macro expansion LL | struct StructA(String); - | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait | = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); | ++++++++ -error[E0507]: cannot move out of `self` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ---------- in this derive macro expansion LL | struct StructA(String); - | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait | = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour help: consider cloning the value if the performance cost is acceptable @@ -54,27 +55,28 @@ help: consider cloning the value if the performance cost is acceptable LL | struct StructA(String.clone()); | ++++++++ -error[E0507]: cannot move out of `other` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ---------- in this derive macro expansion LL | struct StructA(String); - | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait | = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); | ++++++++ -error[E0507]: cannot move out of `self` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | --- in this derive macro expansion LL | struct StructA(String); - | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour help: consider cloning the value if the performance cost is acceptable @@ -82,27 +84,28 @@ help: consider cloning the value if the performance cost is acceptable LL | struct StructA(String.clone()); | ++++++++ -error[E0507]: cannot move out of `other` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | --- in this derive macro expansion LL | struct StructA(String); - | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); | ++++++++ -error[E0507]: cannot move out of `self` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ---- in this derive macro expansion LL | struct StructA(String); - | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Hash)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour help: consider cloning the value if the performance cost is acceptable @@ -110,13 +113,13 @@ help: consider cloning the value if the performance cost is acceptable LL | struct StructA(String.clone()); | ++++++++ -error[E0507]: cannot move out of `self` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ----- in this derive macro expansion LL | struct StructA(String); - | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Clone)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour help: consider cloning the value if the performance cost is acceptable diff --git a/tests/ui/derives/deriving-with-repr-packed.rs b/tests/ui/derives/deriving-with-repr-packed.rs index d17b52842cef..cba0413c992e 100644 --- a/tests/ui/derives/deriving-with-repr-packed.rs +++ b/tests/ui/derives/deriving-with-repr-packed.rs @@ -20,7 +20,7 @@ struct Y(usize); #[derive(Debug, Default)] #[repr(packed)] struct X(Y); -//~^ ERROR cannot move out of `self` which is behind a shared reference +//~^ ERROR cannot move out of a shared reference [E0507] #[derive(Debug)] #[repr(packed)] diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 5117f8d1112c..9cfc4abdc0cb 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -1,11 +1,11 @@ -error[E0507]: cannot move out of `self` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed.rs:22:10 | LL | #[derive(Debug, Default)] | ----- in this derive macro expansion LL | #[repr(packed)] LL | struct X(Y); - | ^ move occurs because `self.0` has type `Y`, which does not implement the `Copy` trait + | ^ move occurs because value has type `Y`, which does not implement the `Copy` trait | note: if `Y` implemented `Clone`, you could clone the value --> $DIR/deriving-with-repr-packed.rs:16:1 @@ -23,14 +23,14 @@ error[E0161]: cannot move a value of type `[u8]` LL | data: [u8], | ^^^^^^^^^^ the size of `[u8]` cannot be statically determined -error[E0507]: cannot move out of `self.data` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed.rs:29:5 | LL | #[derive(Debug)] | ----- in this derive macro expansion ... LL | data: [u8], - | ^^^^^^^^^^ move occurs because `self.data` has type `[u8]`, which does not implement the `Copy` trait + | ^^^^^^^^^^ move occurs because value has type `[u8]`, which does not implement the `Copy` trait | = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour @@ -40,14 +40,14 @@ error[E0161]: cannot move a value of type `str` LL | data: str, | ^^^^^^^^^ the size of `str` cannot be statically determined -error[E0507]: cannot move out of `self.data` which is behind a shared reference +error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed.rs:38:5 | LL | #[derive(Debug)] | ----- in this derive macro expansion ... LL | data: str, - | ^^^^^^^^^ move occurs because `self.data` has type `str`, which does not implement the `Copy` trait + | ^^^^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait | = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour diff --git a/tests/ui/diagnostic-width/flag-json.rs b/tests/ui/diagnostic-width/flag-json.rs index 00778872727b..edc7d2e2a425 100644 --- a/tests/ui/diagnostic-width/flag-json.rs +++ b/tests/ui/diagnostic-width/flag-json.rs @@ -1,9 +1,10 @@ //@ compile-flags: --diagnostic-width=20 --error-format=json -//@ error-pattern:expected `()`, found integer // This test checks that `-Z output-width` effects the JSON error output by restricting it to an // arbitrarily low value so that the effect is visible. fn main() { - let _: () = 42; + let _: () = 42; //~ ERROR mismatched types + //~| NOTE expected `()`, found integer + //~| NOTE expected due to this } diff --git a/tests/ui/diagnostic-width/flag-json.stderr b/tests/ui/diagnostic-width/flag-json.stderr index 6a54f86dcee5..cfc0364be76d 100644 --- a/tests/ui/diagnostic-width/flag-json.stderr +++ b/tests/ui/diagnostic-width/flag-json.stderr @@ -24,10 +24,10 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":291,"byte_end":293,"line_start":8,"line_end":8,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":286,"byte_end":288,"line_start":8,"line_end":8,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types - --> $DIR/flag-json.rs:8:17 +"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":244,"byte_end":246,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42; + --> $DIR/flag-json.rs:7:17 | -LL | ..._: () = 42; +LL | ..._: () = 42; /... | -- ^^ expected `()`, found integer | | | expected due to this diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr index bb3f7899bf1c..c1e93ccb83ca 100644 --- a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr +++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr @@ -1,21 +1,3 @@ -error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15 - | -LL | let test: &mut dyn Bar = &mut thing; - | ^^^^^^^^^^^^ `Bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8 - | -LL | fn foo(&self, val: T); - | ^^^ ...because method `foo` has generic type parameters -... -LL | trait Bar: Foo { } - | --- this trait is not dyn compatible... - = help: consider moving `foo` to another trait - = help: only type `Thing` implements `Bar`; consider using it directly instead. - error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:30 | @@ -35,6 +17,24 @@ LL | trait Bar: Foo { } = help: only type `Thing` implements `Bar`; consider using it directly instead. = note: required for the cast from `&mut Thing` to `&mut dyn Bar` +error[E0038]: the trait `Bar` is not dyn compatible + --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15 + | +LL | let test: &mut dyn Bar = &mut thing; + | ^^^^^^^^^^^^ `Bar` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8 + | +LL | fn foo(&self, val: T); + | ^^^ ...because method `foo` has generic type parameters +... +LL | trait Bar: Foo { } + | --- this trait is not dyn compatible... + = help: consider moving `foo` to another trait + = help: only type `Thing` implements `Bar`; consider using it directly instead. + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/error-codes/E0195.rs b/tests/ui/error-codes/E0195.rs index a7e51dff2f3f..66968f70bd9e 100644 --- a/tests/ui/error-codes/E0195.rs +++ b/tests/ui/error-codes/E0195.rs @@ -1,13 +1,25 @@ trait Trait { +//~^ NOTE in this trait... +//~| NOTE in this trait... fn bar<'a,'b:'a>(x: &'a str, y: &'b str); - //~^ NOTE lifetimes in impl do not match this associated function in trait + //~^ NOTE `'a` is early-bound + //~| NOTE this lifetime bound makes `'a` early-bound + //~| NOTE `'b` is early-bound + //~| NOTE this lifetime bound makes `'b` early-bound } struct Foo; impl Trait for Foo { - fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195 - //~^ NOTE lifetimes do not match associated function in trait +//~^ NOTE in this impl... +//~| NOTE in this impl... + fn bar<'a,'b>(x: &'a str, y: &'b str) { + //~^ ERROR E0195 + //~| NOTE `'a` differs between the trait and impl + //~| NOTE `'a` is late-bound + //~| NOTE `'b` differs between the trait and impl + //~| NOTE `'b` is late-bound + //~| NOTE lifetime parameters differ in whether they are early- or late-bound } } diff --git a/tests/ui/error-codes/E0195.stderr b/tests/ui/error-codes/E0195.stderr index 9767dee9aecd..d0295b364347 100644 --- a/tests/ui/error-codes/E0195.stderr +++ b/tests/ui/error-codes/E0195.stderr @@ -1,11 +1,42 @@ -error[E0195]: lifetime parameters or bounds on associated function `bar` do not match the trait declaration - --> $DIR/E0195.rs:9:11 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/E0195.rs:16:12 | +LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { + | ^^ ^^ + | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'a` differs between the trait and impl + --> $DIR/E0195.rs:4:12 + | +LL | trait Trait { + | ----------- in this trait... +... LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str); - | ---------- lifetimes in impl do not match this associated function in trait + | ^^ -- this lifetime bound makes `'a` early-bound + | | + | `'a` is early-bound +... +LL | impl Trait for Foo { + | ------------------ in this impl... ... LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { - | ^^^^^^^ lifetimes do not match associated function in trait + | ^^ `'a` is late-bound +note: `'b` differs between the trait and impl + --> $DIR/E0195.rs:4:15 + | +LL | trait Trait { + | ----------- in this trait... +... +LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str); + | ^^ -- this lifetime bound makes `'b` early-bound + | | + | `'b` is early-bound +... +LL | impl Trait for Foo { + | ------------------ in this impl... +... +LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { + | ^^ `'b` is late-bound error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0253.rs b/tests/ui/error-codes/E0253.rs deleted file mode 100644 index 8284f791c648..000000000000 --- a/tests/ui/error-codes/E0253.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod foo { - pub trait MyTrait { - type SomeType; - } -} - -use foo::MyTrait::SomeType; - //~^ ERROR E0253 - -fn main() {} diff --git a/tests/ui/error-codes/E0253.stderr b/tests/ui/error-codes/E0253.stderr deleted file mode 100644 index 954dbc816939..000000000000 --- a/tests/ui/error-codes/E0253.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0253]: `SomeType` is not directly importable - --> $DIR/E0253.rs:7:5 - | -LL | use foo::MyTrait::SomeType; - | ^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0253`. diff --git a/tests/ui/error-emitter/highlighting.rs b/tests/ui/error-emitter/highlighting.rs index b3c1acbd342c..d7a0c9d22466 100644 --- a/tests/ui/error-emitter/highlighting.rs +++ b/tests/ui/error-emitter/highlighting.rs @@ -1,7 +1,6 @@ // Make sure "highlighted" code is colored purple //@ compile-flags: --error-format=human --color=always -//@ error-pattern:for<'a>  //@ edition:2018 use core::pin::Pin; @@ -21,3 +20,5 @@ fn wrapped_fn<'a>(_: Box<(dyn Any + Send)>) -> Pin  diff --git a/tests/ui/error-emitter/highlighting.svg b/tests/ui/error-emitter/highlighting.svg index 68fc118f1a6e..19818ab6146c 100644 --- a/tests/ui/error-emitter/highlighting.svg +++ b/tests/ui/error-emitter/highlighting.svg @@ -23,7 +23,7 @@ error[E0308]: mismatched types - --> $DIR/highlighting.rs:22:11 + --> $DIR/highlighting.rs:21:11 | @@ -43,7 +43,7 @@ note: function defined here - --> $DIR/highlighting.rs:11:4 + --> $DIR/highlighting.rs:10:4 | diff --git a/tests/ui/error-emitter/highlighting.windows.svg b/tests/ui/error-emitter/highlighting.windows.svg index c7dd001434ee..f891bc1d2a68 100644 --- a/tests/ui/error-emitter/highlighting.windows.svg +++ b/tests/ui/error-emitter/highlighting.windows.svg @@ -24,7 +24,7 @@ error[E0308]: mismatched types - --> $DIR/highlighting.rs:22:11 + --> $DIR/highlighting.rs:21:11 | @@ -44,7 +44,7 @@ note: function defined here - --> $DIR/highlighting.rs:11:4 + --> $DIR/highlighting.rs:10:4 | diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.rs b/tests/ui/error-emitter/multiline-multipart-suggestion.rs index a938b280ca2e..92dede1b5d83 100644 --- a/tests/ui/error-emitter/multiline-multipart-suggestion.rs +++ b/tests/ui/error-emitter/multiline-multipart-suggestion.rs @@ -1,5 +1,4 @@ //@ compile-flags: --error-format=human --color=always -//@ error-pattern: missing lifetime specifier fn short(foo_bar: &Vec<&i32>) -> &i32 { &12 @@ -17,3 +16,5 @@ fn long2( &12 } fn main() {} + +//~? RAW missing lifetime specifier diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.svg index c0fb98555ad8..dd84234236d7 100644 --- a/tests/ui/error-emitter/multiline-multipart-suggestion.svg +++ b/tests/ui/error-emitter/multiline-multipart-suggestion.svg @@ -23,7 +23,7 @@ error[E0106]: missing lifetime specifier - --> $DIR/multiline-multipart-suggestion.rs:4:34 + --> $DIR/multiline-multipart-suggestion.rs:3:34 | @@ -47,7 +47,7 @@ error[E0106]: missing lifetime specifier - --> $DIR/multiline-multipart-suggestion.rs:11:6 + --> $DIR/multiline-multipart-suggestion.rs:10:6 | @@ -83,7 +83,7 @@ error[E0106]: missing lifetime specifier - --> $DIR/multiline-multipart-suggestion.rs:16:29 + --> $DIR/multiline-multipart-suggestion.rs:15:29 | diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg index 61b544001f08..144e57165da7 100644 --- a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg +++ b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg @@ -23,7 +23,7 @@ error[E0106]: missing lifetime specifier - --> $DIR/multiline-multipart-suggestion.rs:4:34 + --> $DIR/multiline-multipart-suggestion.rs:3:34 | @@ -47,7 +47,7 @@ error[E0106]: missing lifetime specifier - --> $DIR/multiline-multipart-suggestion.rs:11:6 + --> $DIR/multiline-multipart-suggestion.rs:10:6 | @@ -83,7 +83,7 @@ error[E0106]: missing lifetime specifier - --> $DIR/multiline-multipart-suggestion.rs:16:29 + --> $DIR/multiline-multipart-suggestion.rs:15:29 | diff --git a/tests/ui/errors/auxiliary/file-debuginfo.rs b/tests/ui/errors/auxiliary/file-debuginfo.rs new file mode 100644 index 000000000000..08113ec26bfd --- /dev/null +++ b/tests/ui/errors/auxiliary/file-debuginfo.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=debuginfo + +#[macro_export] +macro_rules! my_file { + () => { file!() } +} + +pub fn file() -> &'static str { + file!() +} diff --git a/tests/ui/errors/auxiliary/file-diag.rs b/tests/ui/errors/auxiliary/file-diag.rs new file mode 100644 index 000000000000..f29c349f703b --- /dev/null +++ b/tests/ui/errors/auxiliary/file-diag.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=diagnostics + +#[macro_export] +macro_rules! my_file { + () => { file!() } +} + +pub fn file() -> &'static str { + file!() +} diff --git a/tests/ui/errors/auxiliary/file-macro.rs b/tests/ui/errors/auxiliary/file-macro.rs new file mode 100644 index 000000000000..11abc0549a7b --- /dev/null +++ b/tests/ui/errors/auxiliary/file-macro.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=macro + +#[macro_export] +macro_rules! my_file { + () => { file!() } +} + +pub fn file() -> &'static str { + file!() +} diff --git a/tests/ui/errors/auxiliary/file.rs b/tests/ui/errors/auxiliary/file.rs new file mode 100644 index 000000000000..63a7b3b58f0f --- /dev/null +++ b/tests/ui/errors/auxiliary/file.rs @@ -0,0 +1,8 @@ +#[macro_export] +macro_rules! my_file { + () => { file!() } +} + +pub fn file() -> &'static str { + file!() +} diff --git a/tests/ui/errors/auxiliary/trait-debuginfo.rs b/tests/ui/errors/auxiliary/trait-debuginfo.rs new file mode 100644 index 000000000000..d5a0825fe6d1 --- /dev/null +++ b/tests/ui/errors/auxiliary/trait-debuginfo.rs @@ -0,0 +1,4 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=debuginfo + +pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/auxiliary/trait-diag.rs b/tests/ui/errors/auxiliary/trait-diag.rs new file mode 100644 index 000000000000..e07961a276a9 --- /dev/null +++ b/tests/ui/errors/auxiliary/trait-diag.rs @@ -0,0 +1,4 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=diagnostics + +pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/auxiliary/trait-macro.rs b/tests/ui/errors/auxiliary/trait-macro.rs new file mode 100644 index 000000000000..48673d04ee16 --- /dev/null +++ b/tests/ui/errors/auxiliary/trait-macro.rs @@ -0,0 +1,4 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=macro + +pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/auxiliary/trait.rs b/tests/ui/errors/auxiliary/trait.rs new file mode 100644 index 000000000000..0e7e5400aac5 --- /dev/null +++ b/tests/ui/errors/auxiliary/trait.rs @@ -0,0 +1 @@ +pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr new file mode 100644 index 000000000000..3ddff11798de --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr new file mode 100644 index 000000000000..85c781425b16 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-debuginfo.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr new file mode 100644 index 000000000000..792ea7925ad5 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-diag.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr new file mode 100644 index 000000000000..d13333d2e482 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-macro.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.rs b/tests/ui/errors/remap-path-prefix-diagnostics.rs new file mode 100644 index 000000000000..fac7e937cb0b --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.rs @@ -0,0 +1,57 @@ +// This test exercises `-Zremap-path-scope`, diagnostics printing paths and dependency. +// +// We test different combinations with/without remap in deps, with/without remap in this +// crate but always in deps and always here but never in deps. + +//@ revisions: with-diag-in-deps with-macro-in-deps with-debuginfo-in-deps +//@ revisions: only-diag-in-deps only-macro-in-deps only-debuginfo-in-deps +//@ revisions: not-diag-in-deps + +//@[with-diag-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[with-macro-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[with-debuginfo-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[not-diag-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped + +//@[with-diag-in-deps] compile-flags: -Zremap-path-scope=diagnostics +//@[with-macro-in-deps] compile-flags: -Zremap-path-scope=macro +//@[with-debuginfo-in-deps] compile-flags: -Zremap-path-scope=debuginfo +//@[not-diag-in-deps] compile-flags: -Zremap-path-scope=diagnostics + +//@[with-diag-in-deps] aux-build:trait-diag.rs +//@[with-macro-in-deps] aux-build:trait-macro.rs +//@[with-debuginfo-in-deps] aux-build:trait-debuginfo.rs +//@[only-diag-in-deps] aux-build:trait-diag.rs +//@[only-macro-in-deps] aux-build:trait-macro.rs +//@[only-debuginfo-in-deps] aux-build:trait-debuginfo.rs +//@[not-diag-in-deps] aux-build:trait.rs + +// The $SRC_DIR*.rs:LL:COL normalisation doesn't kick in automatically +// as the remapped revision will not begin with $SRC_DIR_REAL, +// so we have to do it ourselves. +//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:COL" + +#[cfg(any(with_diag_in_deps, only_diag_in_deps))] +extern crate trait_diag as r#trait; + +#[cfg(any(with_macro_in_deps, only_macro_in_deps))] +extern crate trait_macro as r#trait; + +#[cfg(any(with_debuginfo_in_deps, only_debuginfo_in_deps))] +extern crate trait_debuginfo as r#trait; + +#[cfg(not_diag_in_deps)] +extern crate r#trait as r#trait; + +struct A; + +impl r#trait::Trait for A {} +//[with-macro-in-deps]~^ ERROR `A` doesn't implement `std::fmt::Display` +//[with-debuginfo-in-deps]~^^ ERROR `A` doesn't implement `std::fmt::Display` +//[only-diag-in-deps]~^^^ ERROR `A` doesn't implement `std::fmt::Display` +//[only-macro-in-deps]~^^^^ ERROR `A` doesn't implement `std::fmt::Display` +//[only-debuginfo-in-deps]~^^^^^ ERROR `A` doesn't implement `std::fmt::Display` + +//[with-diag-in-deps]~? ERROR `A` doesn't implement `std::fmt::Display` +//[not-diag-in-deps]~? ERROR `A` doesn't implement `std::fmt::Display` + +fn main() {} diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr new file mode 100644 index 000000000000..85c781425b16 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-debuginfo.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr new file mode 100644 index 000000000000..08f7fb2c7364 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> remapped/errors/auxiliary/trait-diag.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr new file mode 100644 index 000000000000..d13333d2e482 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-macro.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-macro.normal.run.stdout b/tests/ui/errors/remap-path-prefix-macro.normal.run.stdout deleted file mode 100644 index 3bbdcbb8655b..000000000000 --- a/tests/ui/errors/remap-path-prefix-macro.normal.run.stdout +++ /dev/null @@ -1 +0,0 @@ -remapped/errors/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.not-macro-in-deps.run.stdout b/tests/ui/errors/remap-path-prefix-macro.not-macro-in-deps.run.stdout new file mode 100644 index 000000000000..13d4611ae543 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.not-macro-in-deps.run.stdout @@ -0,0 +1,3 @@ +file::my_file!() = remapped/errors/remap-path-prefix-macro.rs +file::file() = $DIR/auxiliary/file.rs +file!() = remapped/errors/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.only-debuginfo-in-deps.run.stdout b/tests/ui/errors/remap-path-prefix-macro.only-debuginfo-in-deps.run.stdout new file mode 100644 index 000000000000..b2c62ac88c04 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.only-debuginfo-in-deps.run.stdout @@ -0,0 +1,3 @@ +file::my_file!() = $DIR/remap-path-prefix-macro.rs +file::file() = $DIR/auxiliary/file-debuginfo.rs +file!() = $DIR/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.only-diag-in-deps.run.stdout b/tests/ui/errors/remap-path-prefix-macro.only-diag-in-deps.run.stdout new file mode 100644 index 000000000000..e64cc0723619 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.only-diag-in-deps.run.stdout @@ -0,0 +1,3 @@ +file::my_file!() = $DIR/remap-path-prefix-macro.rs +file::file() = $DIR/auxiliary/file-diag.rs +file!() = $DIR/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.only-macro-in-deps.run.stdout b/tests/ui/errors/remap-path-prefix-macro.only-macro-in-deps.run.stdout new file mode 100644 index 000000000000..b1a93a5bc1ea --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.only-macro-in-deps.run.stdout @@ -0,0 +1,3 @@ +file::my_file!() = $DIR/remap-path-prefix-macro.rs +file::file() = remapped/errors/auxiliary/file-macro.rs +file!() = $DIR/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.rs b/tests/ui/errors/remap-path-prefix-macro.rs index 665156027c99..3e93843f9164 100644 --- a/tests/ui/errors/remap-path-prefix-macro.rs +++ b/tests/ui/errors/remap-path-prefix-macro.rs @@ -1,12 +1,47 @@ +// This test exercises `-Zremap-path-scope`, macros (like file!()) and dependency. +// +// We test different combinations with/without remap in deps, with/without remap in +// this crate but always in deps and always here but never in deps. + //@ run-pass //@ check-run-results -//@ revisions: normal with-macro-scope without-macro-scope -//@ compile-flags: --remap-path-prefix={{src-base}}=remapped -//@ [with-macro-scope]compile-flags: -Zremap-path-scope=macro,diagnostics -//@ [without-macro-scope]compile-flags: -Zremap-path-scope=diagnostics -// no-remap-src-base: Manually remap, so the remapped path remains in .stderr file. +//@ revisions: with-diag-in-deps with-macro-in-deps with-debuginfo-in-deps +//@ revisions: only-diag-in-deps only-macro-in-deps only-debuginfo-in-deps +//@ revisions: not-macro-in-deps + +//@[with-diag-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[with-macro-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[with-debuginfo-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[not-macro-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped + +//@[with-diag-in-deps] compile-flags: -Zremap-path-scope=diagnostics +//@[with-macro-in-deps] compile-flags: -Zremap-path-scope=macro +//@[with-debuginfo-in-deps] compile-flags: -Zremap-path-scope=debuginfo +//@[not-macro-in-deps] compile-flags: -Zremap-path-scope=macro + +//@[with-diag-in-deps] aux-build:file-diag.rs +//@[with-macro-in-deps] aux-build:file-macro.rs +//@[with-debuginfo-in-deps] aux-build:file-debuginfo.rs +//@[only-diag-in-deps] aux-build:file-diag.rs +//@[only-macro-in-deps] aux-build:file-macro.rs +//@[only-debuginfo-in-deps] aux-build:file-debuginfo.rs +//@[not-macro-in-deps] aux-build:file.rs + +#[cfg(any(with_diag_in_deps, only_diag_in_deps))] +extern crate file_diag as file; + +#[cfg(any(with_macro_in_deps, only_macro_in_deps))] +extern crate file_macro as file; + +#[cfg(any(with_debuginfo_in_deps, only_debuginfo_in_deps))] +extern crate file_debuginfo as file; + +#[cfg(not_macro_in_deps)] +extern crate file; fn main() { - println!("{}", file!()); + println!("file::my_file!() = {}", file::my_file!()); + println!("file::file() = {}", file::file()); + println!("file!() = {}", file!()); } diff --git a/tests/ui/errors/remap-path-prefix-macro.with-debuginfo-in-deps.run.stdout b/tests/ui/errors/remap-path-prefix-macro.with-debuginfo-in-deps.run.stdout new file mode 100644 index 000000000000..b2c62ac88c04 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.with-debuginfo-in-deps.run.stdout @@ -0,0 +1,3 @@ +file::my_file!() = $DIR/remap-path-prefix-macro.rs +file::file() = $DIR/auxiliary/file-debuginfo.rs +file!() = $DIR/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.with-diag-in-deps.run.stdout b/tests/ui/errors/remap-path-prefix-macro.with-diag-in-deps.run.stdout new file mode 100644 index 000000000000..e64cc0723619 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.with-diag-in-deps.run.stdout @@ -0,0 +1,3 @@ +file::my_file!() = $DIR/remap-path-prefix-macro.rs +file::file() = $DIR/auxiliary/file-diag.rs +file!() = $DIR/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.with-macro-in-deps.run.stdout b/tests/ui/errors/remap-path-prefix-macro.with-macro-in-deps.run.stdout new file mode 100644 index 000000000000..5c1781dda161 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.with-macro-in-deps.run.stdout @@ -0,0 +1,3 @@ +file::my_file!() = remapped/errors/remap-path-prefix-macro.rs +file::file() = remapped/errors/auxiliary/file-macro.rs +file!() = remapped/errors/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.with-macro-scope.run.stdout b/tests/ui/errors/remap-path-prefix-macro.with-macro-scope.run.stdout deleted file mode 100644 index 3bbdcbb8655b..000000000000 --- a/tests/ui/errors/remap-path-prefix-macro.with-macro-scope.run.stdout +++ /dev/null @@ -1 +0,0 @@ -remapped/errors/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.without-macro-scope.run.stdout b/tests/ui/errors/remap-path-prefix-macro.without-macro-scope.run.stdout deleted file mode 100644 index 642823fec86a..000000000000 --- a/tests/ui/errors/remap-path-prefix-macro.without-macro-scope.run.stdout +++ /dev/null @@ -1 +0,0 @@ -$DIR/remap-path-prefix-macro.rs diff --git a/tests/ui/explain.rs b/tests/ui/explain/basic.rs similarity index 100% rename from tests/ui/explain.rs rename to tests/ui/explain/basic.rs diff --git a/tests/ui/explain.stdout b/tests/ui/explain/basic.stdout similarity index 100% rename from tests/ui/explain.stdout rename to tests/ui/explain/basic.stdout diff --git a/tests/ui/explain/error-with-no-explanation.rs b/tests/ui/explain/error-with-no-explanation.rs new file mode 100644 index 000000000000..383820eb4580 --- /dev/null +++ b/tests/ui/explain/error-with-no-explanation.rs @@ -0,0 +1,3 @@ +// It's a valid error with no added explanation +//@ compile-flags: --explain E9999 +//~? ERROR: E9999 is not a valid error code diff --git a/tests/ui/explain/error-with-no-explanation.stderr b/tests/ui/explain/error-with-no-explanation.stderr new file mode 100644 index 000000000000..afb738cfecb9 --- /dev/null +++ b/tests/ui/explain/error-with-no-explanation.stderr @@ -0,0 +1,2 @@ +error: E9999 is not a valid error code + diff --git a/tests/ui/explain/invalid-error-code.rs b/tests/ui/explain/invalid-error-code.rs new file mode 100644 index 000000000000..114118d5196b --- /dev/null +++ b/tests/ui/explain/invalid-error-code.rs @@ -0,0 +1,2 @@ +//@ compile-flags: --explain error_code +//~? ERROR: error_code is not a valid error code diff --git a/tests/ui/explain/invalid-error-code.stderr b/tests/ui/explain/invalid-error-code.stderr new file mode 100644 index 000000000000..c33122ea88cb --- /dev/null +++ b/tests/ui/explain/invalid-error-code.stderr @@ -0,0 +1,2 @@ +error: error_code is not a valid error code + diff --git a/tests/ui/explain/no-E-prefix.rs b/tests/ui/explain/no-E-prefix.rs new file mode 100644 index 000000000000..39c9122bfe1b --- /dev/null +++ b/tests/ui/explain/no-E-prefix.rs @@ -0,0 +1,2 @@ +//@ compile-flags: --explain 425 +//@ check-pass diff --git a/tests/ui/explain/no-E-prefix.stdout b/tests/ui/explain/no-E-prefix.stdout new file mode 100644 index 000000000000..756b970aa7e6 --- /dev/null +++ b/tests/ui/explain/no-E-prefix.stdout @@ -0,0 +1,57 @@ +An unresolved name was used. + +Erroneous code examples: + +``` +something_that_doesnt_exist::foo; +// error: unresolved name `something_that_doesnt_exist::foo` + +// or: + +trait Foo { + fn bar() { + Self; // error: unresolved name `Self` + } +} + +// or: + +let x = unknown_variable; // error: unresolved name `unknown_variable` +``` + +Please verify that the name wasn't misspelled and ensure that the +identifier being referred to is valid for the given situation. Example: + +``` +enum something_that_does_exist { + Foo, +} +``` + +Or: + +``` +mod something_that_does_exist { + pub static foo : i32 = 0i32; +} + +something_that_does_exist::foo; // ok! +``` + +Or: + +``` +let unknown_variable = 12u32; +let x = unknown_variable; // ok! +``` + +If the item is not defined in the current module, it must be imported using a +`use` statement, like so: + +``` +use foo::bar; +bar(); +``` + +If the item you are importing is not defined in some super-module of the +current module, then it must also be declared as public (e.g., `pub fn`). diff --git a/tests/ui/explain/overflow-error-code.rs b/tests/ui/explain/overflow-error-code.rs new file mode 100644 index 000000000000..284d5cddb35a --- /dev/null +++ b/tests/ui/explain/overflow-error-code.rs @@ -0,0 +1,4 @@ +// Check that we don't crash on error codes exceeding our internal limit. +// issue: +//@ compile-flags: --explain E10000 +//~? ERROR: E10000 is not a valid error code diff --git a/tests/ui/explain/overflow-error-code.stderr b/tests/ui/explain/overflow-error-code.stderr new file mode 100644 index 000000000000..67e584ea32e1 --- /dev/null +++ b/tests/ui/explain/overflow-error-code.stderr @@ -0,0 +1,2 @@ +error: E10000 is not a valid error code + diff --git a/tests/ui/feature-gates/bench.rs b/tests/ui/feature-gates/bench.rs index 12e646f7a323..94c8992a8fe6 100644 --- a/tests/ui/feature-gates/bench.rs +++ b/tests/ui/feature-gates/bench.rs @@ -1,9 +1,7 @@ //@ edition:2018 #[bench] //~ ERROR use of unstable library feature `test` - //~| WARN this was previously accepted fn bench() {} use bench as _; //~ ERROR use of unstable library feature `test` - //~| WARN this was previously accepted fn main() {} diff --git a/tests/ui/feature-gates/bench.stderr b/tests/ui/feature-gates/bench.stderr index de78e863012d..f5fc579b23be 100644 --- a/tests/ui/feature-gates/bench.stderr +++ b/tests/ui/feature-gates/bench.stderr @@ -1,43 +1,23 @@ -error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable +error[E0658]: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable --> $DIR/bench.rs:3:3 | LL | #[bench] | ^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default + = note: see issue #50297 for more information + = help: add `#![feature(test)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable - --> $DIR/bench.rs:7:5 +error[E0658]: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable + --> $DIR/bench.rs:6:5 | LL | use bench as _; | ^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 + = note: see issue #50297 for more information + = help: add `#![feature(test)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors -Future incompatibility report: Future breakage diagnostic: -error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable - --> $DIR/bench.rs:3:3 - | -LL | #[bench] - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default - -Future breakage diagnostic: -error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable - --> $DIR/bench.rs:7:5 - | -LL | use bench as _; - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default - +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-apx-target-feature.rs b/tests/ui/feature-gates/feature-gate-apx-target-feature.rs new file mode 100644 index 000000000000..a2ac4ac86ac0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-apx-target-feature.rs @@ -0,0 +1,6 @@ +//@ only-x86_64 +#[target_feature(enable = "apxf")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-apx-target-feature.stderr b/tests/ui/feature-gates/feature-gate-apx-target-feature.stderr new file mode 100644 index 000000000000..1999ab535379 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-apx-target-feature.stderr @@ -0,0 +1,13 @@ +error[E0658]: the target feature `apxf` is currently unstable + --> $DIR/feature-gate-apx-target-feature.rs:2:18 + | +LL | #[target_feature(enable = "apxf")] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #139284 for more information + = help: add `#![feature(apx_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-avx10_target_feature.rs b/tests/ui/feature-gates/feature-gate-avx10_target_feature.rs new file mode 100644 index 000000000000..8557e67d1f41 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-avx10_target_feature.rs @@ -0,0 +1,6 @@ +//@ only-x86_64 +#[target_feature(enable = "avx10.1")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-avx10_target_feature.stderr b/tests/ui/feature-gates/feature-gate-avx10_target_feature.stderr new file mode 100644 index 000000000000..e45ea3524ca7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-avx10_target_feature.stderr @@ -0,0 +1,13 @@ +error[E0658]: the target feature `avx10.1` is currently unstable + --> $DIR/feature-gate-avx10_target_feature.rs:2:18 + | +LL | #[target_feature(enable = "avx10.1")] + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #138843 for more information + = help: add `#![feature(avx10_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-export_stable.rs b/tests/ui/feature-gates/feature-gate-export_stable.rs new file mode 100644 index 000000000000..5d05fee059b8 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-export_stable.rs @@ -0,0 +1,5 @@ +#![crate_type="lib"] + +#[export_stable] +//~^ ERROR the `#[export_stable]` attribute is an experimental feature +pub mod a {} diff --git a/tests/ui/feature-gates/feature-gate-export_stable.stderr b/tests/ui/feature-gates/feature-gate-export_stable.stderr new file mode 100644 index 000000000000..6beb52a77e5c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-export_stable.stderr @@ -0,0 +1,13 @@ +error[E0658]: the `#[export_stable]` attribute is an experimental feature + --> $DIR/feature-gate-export_stable.rs:3:1 + | +LL | #[export_stable] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #139939 for more information + = help: add `#![feature(export_stable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-frontmatter.rs b/tests/ui/feature-gates/feature-gate-frontmatter.rs new file mode 100644 index 000000000000..58e1f57eec02 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-frontmatter.rs @@ -0,0 +1,5 @@ +---cargo +//~^ ERROR: frontmatters are experimental +--- + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-frontmatter.stderr b/tests/ui/feature-gates/feature-gate-frontmatter.stderr new file mode 100644 index 000000000000..57d38db8e76a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-frontmatter.stderr @@ -0,0 +1,15 @@ +error[E0658]: frontmatters are experimental + --> $DIR/feature-gate-frontmatter.rs:1:1 + | +LL | / ---cargo +LL | | +LL | | --- + | |___^ + | + = note: see issue #136889 for more information + = help: add `#![feature(frontmatter)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.rs b/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.rs index aec13fb02028..c2c010eaba63 100644 --- a/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.rs +++ b/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.rs @@ -60,4 +60,7 @@ fn f() { let t: Option = DEFAULT; } +trait Glob {} +use Glob::*; //~ ERROR `use` associated items of traits is unstable + fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr b/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr index d342f5bd5512..fca3cef3e203 100644 --- a/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr +++ b/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr @@ -48,6 +48,16 @@ LL | use super::A::{self, DEFAULT, new}; = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error[E0658]: `use` associated items of traits is unstable + --> $DIR/feature-gate-import-trait-associated-functions.rs:64:5 + | +LL | use Glob::*; + | ^^^^^^^ + | + = note: see issue #134691 for more information + = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs b/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs new file mode 100644 index 000000000000..218450abd499 --- /dev/null +++ b/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs @@ -0,0 +1,12 @@ +fn f1(_: fn(a: u8)) {} +fn f2(_: impl Fn(u8, vvvv: u8)) {} //~ ERROR `Trait(...)` syntax does not support named parameters +fn f3(_: impl Fn(aaaa: u8, u8)) {} //~ ERROR `Trait(...)` syntax does not support named parameters +fn f4(_: impl Fn(aaaa: u8, vvvv: u8)) {} +//~^ ERROR `Trait(...)` syntax does not support named parameters +//~| ERROR `Trait(...)` syntax does not support named parameters +fn f5(_: impl Fn(u8, ...)) {} +//~^ ERROR `Trait(...)` syntax does not support c_variadic parameters +fn f6(_: impl Fn(u8, #[allow(unused_attributes)] u8)) {} +//~^ ERROR `Trait(...)` syntax does not support attributes in parameters + +fn main(){} diff --git a/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr b/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr new file mode 100644 index 000000000000..b72d5b7b3bc4 --- /dev/null +++ b/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr @@ -0,0 +1,38 @@ +error: `Trait(...)` syntax does not support named parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:2:22 + | +LL | fn f2(_: impl Fn(u8, vvvv: u8)) {} + | ^^^^ help: remove the parameter name + +error: `Trait(...)` syntax does not support named parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:3:18 + | +LL | fn f3(_: impl Fn(aaaa: u8, u8)) {} + | ^^^^ help: remove the parameter name + +error: `Trait(...)` syntax does not support named parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:4:18 + | +LL | fn f4(_: impl Fn(aaaa: u8, vvvv: u8)) {} + | ^^^^ help: remove the parameter name + +error: `Trait(...)` syntax does not support named parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:4:28 + | +LL | fn f4(_: impl Fn(aaaa: u8, vvvv: u8)) {} + | ^^^^ help: remove the parameter name + +error: `Trait(...)` syntax does not support c_variadic parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:7:22 + | +LL | fn f5(_: impl Fn(u8, ...)) {} + | ^^^ help: remove the `...` + +error: `Trait(...)` syntax does not support attributes in parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:9:22 + | +LL | fn f6(_: impl Fn(u8, #[allow(unused_attributes)] u8)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the attributes + +error: aborting due to 6 previous errors + diff --git a/tests/ui/fn/param-mismatch-foreign.rs b/tests/ui/fn/param-mismatch-foreign.rs index eebca29d6c93..2ab2bf95448a 100644 --- a/tests/ui/fn/param-mismatch-foreign.rs +++ b/tests/ui/fn/param-mismatch-foreign.rs @@ -1,7 +1,6 @@ extern "C" { fn foo(x: i32, y: u32, z: i32); //~^ NOTE function defined here - //~| NOTE } fn main() { diff --git a/tests/ui/fn/param-mismatch-foreign.stderr b/tests/ui/fn/param-mismatch-foreign.stderr index fff3283cbb6c..835e0a3343e9 100644 --- a/tests/ui/fn/param-mismatch-foreign.stderr +++ b/tests/ui/fn/param-mismatch-foreign.stderr @@ -1,5 +1,5 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied - --> $DIR/param-mismatch-foreign.rs:8:5 + --> $DIR/param-mismatch-foreign.rs:7:5 | LL | foo(1i32, 2i32); | ^^^ ---- argument #2 of type `u32` is missing diff --git a/tests/ui/fn/signature-error-reporting-under-verbose.rs b/tests/ui/fn/signature-error-reporting-under-verbose.rs index 4a72da789789..0047d452b7a6 100644 --- a/tests/ui/fn/signature-error-reporting-under-verbose.rs +++ b/tests/ui/fn/signature-error-reporting-under-verbose.rs @@ -4,7 +4,6 @@ fn foo(_: i32, _: i32) {} fn needs_ptr(_: fn(i32, u32)) {} //~^ NOTE function defined here -//~| NOTE fn main() { needs_ptr(foo); diff --git a/tests/ui/fn/signature-error-reporting-under-verbose.stderr b/tests/ui/fn/signature-error-reporting-under-verbose.stderr index 6c6a313c4df7..d9ccec23fcb6 100644 --- a/tests/ui/fn/signature-error-reporting-under-verbose.stderr +++ b/tests/ui/fn/signature-error-reporting-under-verbose.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/signature-error-reporting-under-verbose.rs:10:15 + --> $DIR/signature-error-reporting-under-verbose.rs:9:15 | LL | needs_ptr(foo); | --------- ^^^ expected fn pointer, found fn item diff --git a/tests/ui/frontmatter/auxiliary/lib.rs b/tests/ui/frontmatter/auxiliary/lib.rs new file mode 100644 index 000000000000..ff7094f410f5 --- /dev/null +++ b/tests/ui/frontmatter/auxiliary/lib.rs @@ -0,0 +1,6 @@ +---something +--- + +pub fn foo(x: i32) -> i32 { + -x +} diff --git a/tests/ui/frontmatter/auxiliary/makro.rs b/tests/ui/frontmatter/auxiliary/makro.rs new file mode 100644 index 000000000000..78e7417afb5f --- /dev/null +++ b/tests/ui/frontmatter/auxiliary/makro.rs @@ -0,0 +1,8 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn check(_: TokenStream) -> TokenStream { + assert!("---\n---".parse::().unwrap().is_empty()); + Default::default() +} diff --git a/tests/ui/frontmatter/dot-in-infostring-leading.rs b/tests/ui/frontmatter/dot-in-infostring-leading.rs new file mode 100644 index 000000000000..0d3d699644e9 --- /dev/null +++ b/tests/ui/frontmatter/dot-in-infostring-leading.rs @@ -0,0 +1,9 @@ +---.toml +//~^ ERROR: invalid infostring for frontmatter +--- + +// infostrings cannot have leading dots + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/dot-in-infostring-leading.stderr b/tests/ui/frontmatter/dot-in-infostring-leading.stderr new file mode 100644 index 000000000000..bc86bd80eece --- /dev/null +++ b/tests/ui/frontmatter/dot-in-infostring-leading.stderr @@ -0,0 +1,10 @@ +error: invalid infostring for frontmatter + --> $DIR/dot-in-infostring-leading.rs:1:4 + | +LL | ---.toml + | ^^^^^ + | + = note: frontmatter infostrings must be a single identifier immediately following the opening + +error: aborting due to 1 previous error + diff --git a/tests/ui/frontmatter/dot-in-infostring-non-leading.rs b/tests/ui/frontmatter/dot-in-infostring-non-leading.rs new file mode 100644 index 000000000000..a4d17bb6e813 --- /dev/null +++ b/tests/ui/frontmatter/dot-in-infostring-non-leading.rs @@ -0,0 +1,9 @@ +---Cargo.toml +--- + +// infostrings can contain dots as long as a dot isn't the first character. +//@ check-pass + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/escape.rs b/tests/ui/frontmatter/escape.rs new file mode 100644 index 000000000000..0e6f064607e8 --- /dev/null +++ b/tests/ui/frontmatter/escape.rs @@ -0,0 +1,14 @@ +---- + +--- + +---- + +//@ check-pass + +// This test checks that longer dashes for opening and closing can be used to +// escape sequences such as three dashes inside the frontmatter block. + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/extra-after-end.rs b/tests/ui/frontmatter/extra-after-end.rs new file mode 100644 index 000000000000..de2cf4cc85ef --- /dev/null +++ b/tests/ui/frontmatter/extra-after-end.rs @@ -0,0 +1,7 @@ +--- +---cargo +//~^ ERROR: extra characters after frontmatter close are not allowed + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/extra-after-end.stderr b/tests/ui/frontmatter/extra-after-end.stderr new file mode 100644 index 000000000000..c2770fdfd41f --- /dev/null +++ b/tests/ui/frontmatter/extra-after-end.stderr @@ -0,0 +1,8 @@ +error: extra characters after frontmatter close are not allowed + --> $DIR/extra-after-end.rs:2:1 + | +LL | ---cargo + | ^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/frontmatter/frontmatter-after-tokens.rs b/tests/ui/frontmatter/frontmatter-after-tokens.rs new file mode 100644 index 000000000000..6683991dc4af --- /dev/null +++ b/tests/ui/frontmatter/frontmatter-after-tokens.rs @@ -0,0 +1,10 @@ +#![feature(frontmatter)] + +--- +//~^ ERROR: expected item, found `-` +// FIXME(frontmatter): make this diagnostic better +--- + +// frontmatters must be at the start of a file. This test ensures that. + +fn main() {} diff --git a/tests/ui/frontmatter/frontmatter-after-tokens.stderr b/tests/ui/frontmatter/frontmatter-after-tokens.stderr new file mode 100644 index 000000000000..919456924d02 --- /dev/null +++ b/tests/ui/frontmatter/frontmatter-after-tokens.stderr @@ -0,0 +1,10 @@ +error: expected item, found `-` + --> $DIR/frontmatter-after-tokens.rs:3:1 + | +LL | --- + | ^ expected item + | + = note: for a full list of items that can appear in modules, see + +error: aborting due to 1 previous error + diff --git a/tests/ui/frontmatter/frontmatter-non-lexible-tokens.rs b/tests/ui/frontmatter/frontmatter-non-lexible-tokens.rs new file mode 100644 index 000000000000..ea042edef06b --- /dev/null +++ b/tests/ui/frontmatter/frontmatter-non-lexible-tokens.rs @@ -0,0 +1,12 @@ +---uwu +🏳️‍⚧️ +--- + +//@ check-pass + +#![feature(frontmatter)] + +// check that frontmatter blocks can have tokens that are otherwise not accepted by +// the lexer as Rust code. + +fn main() {} diff --git a/tests/ui/frontmatter/frontmatter-whitespace-1.rs b/tests/ui/frontmatter/frontmatter-whitespace-1.rs new file mode 100644 index 000000000000..8b6e2d1af849 --- /dev/null +++ b/tests/ui/frontmatter/frontmatter-whitespace-1.rs @@ -0,0 +1,10 @@ + --- +//~^ ERROR: invalid preceding whitespace for frontmatter opening + --- +//~^ ERROR: invalid preceding whitespace for frontmatter close + +#![feature(frontmatter)] + +// check that whitespaces should not precede the frontmatter opening or close. + +fn main() {} diff --git a/tests/ui/frontmatter/frontmatter-whitespace-1.stderr b/tests/ui/frontmatter/frontmatter-whitespace-1.stderr new file mode 100644 index 000000000000..37ece27acb22 --- /dev/null +++ b/tests/ui/frontmatter/frontmatter-whitespace-1.stderr @@ -0,0 +1,26 @@ +error: invalid preceding whitespace for frontmatter opening + --> $DIR/frontmatter-whitespace-1.rs:1:1 + | +LL | --- + | ^^^^^ + | +note: frontmatter opening should not be preceded by whitespace + --> $DIR/frontmatter-whitespace-1.rs:1:1 + | +LL | --- + | ^^ + +error: invalid preceding whitespace for frontmatter close + --> $DIR/frontmatter-whitespace-1.rs:3:1 + | +LL | --- + | ^^^^^ + | +note: frontmatter close should not be preceded by whitespace + --> $DIR/frontmatter-whitespace-1.rs:3:1 + | +LL | --- + | ^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/frontmatter/frontmatter-whitespace-2.rs b/tests/ui/frontmatter/frontmatter-whitespace-2.rs new file mode 100644 index 000000000000..e8c100849b40 --- /dev/null +++ b/tests/ui/frontmatter/frontmatter-whitespace-2.rs @@ -0,0 +1,15 @@ +---cargo + +//@ compile-flags: --crate-type lib + +#![feature(frontmatter)] + +fn foo(x: i32) -> i32 { + ---x + //~^ ERROR: invalid preceding whitespace for frontmatter close + //~| ERROR: extra characters after frontmatter close are not allowed +} +//~^ ERROR: unexpected closing delimiter: `}` + +// this test is for the weird case that valid Rust code can have three dashes +// within them and get treated as a frontmatter close. diff --git a/tests/ui/frontmatter/frontmatter-whitespace-2.stderr b/tests/ui/frontmatter/frontmatter-whitespace-2.stderr new file mode 100644 index 000000000000..ada6af0ec04c --- /dev/null +++ b/tests/ui/frontmatter/frontmatter-whitespace-2.stderr @@ -0,0 +1,26 @@ +error: invalid preceding whitespace for frontmatter close + --> $DIR/frontmatter-whitespace-2.rs:8:1 + | +LL | ---x + | ^^^^^^^^ + | +note: frontmatter close should not be preceded by whitespace + --> $DIR/frontmatter-whitespace-2.rs:8:1 + | +LL | ---x + | ^^^^ + +error: extra characters after frontmatter close are not allowed + --> $DIR/frontmatter-whitespace-2.rs:8:1 + | +LL | ---x + | ^^^^^^^^ + +error: unexpected closing delimiter: `}` + --> $DIR/frontmatter-whitespace-2.rs:11:1 + | +LL | } + | ^ unexpected closing delimiter + +error: aborting due to 3 previous errors + diff --git a/tests/ui/frontmatter/frontmatter-whitespace-3.rs b/tests/ui/frontmatter/frontmatter-whitespace-3.rs new file mode 100644 index 000000000000..95e0981e2ae8 --- /dev/null +++ b/tests/ui/frontmatter/frontmatter-whitespace-3.rs @@ -0,0 +1,16 @@ + + +---cargo +--- + +// please note the whitespace characters after the first four lines. +// This ensures that we accept whitespaces before the frontmatter, after +// the frontmatter opening and the frontmatter close. + +//@ check-pass +// ignore-tidy-end-whitespace +// ignore-tidy-leading-newlines + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/frontmatter-whitespace-4.rs b/tests/ui/frontmatter/frontmatter-whitespace-4.rs new file mode 100644 index 000000000000..3bda3227838c --- /dev/null +++ b/tests/ui/frontmatter/frontmatter-whitespace-4.rs @@ -0,0 +1,9 @@ +--- cargo +--- + +//@ check-pass +// A frontmatter infostring can have leading whitespace. + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/included-frontmatter.rs b/tests/ui/frontmatter/included-frontmatter.rs new file mode 100644 index 000000000000..57616cd1228c --- /dev/null +++ b/tests/ui/frontmatter/included-frontmatter.rs @@ -0,0 +1,12 @@ +#![feature(frontmatter)] + +//@ check-pass + +include!("auxiliary/lib.rs"); + +// auxiliary/lib.rs contains a frontmatter. Ensure that we can use them in an +// `include!` macro. + +fn main() { + foo(1); +} diff --git a/tests/ui/frontmatter/infostring-fail.rs b/tests/ui/frontmatter/infostring-fail.rs new file mode 100644 index 000000000000..91542f62f1a5 --- /dev/null +++ b/tests/ui/frontmatter/infostring-fail.rs @@ -0,0 +1,9 @@ +---cargo,clippy +//~^ ERROR: invalid infostring for frontmatter +--- + +// infostrings can only be a single identifier. + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/infostring-fail.stderr b/tests/ui/frontmatter/infostring-fail.stderr new file mode 100644 index 000000000000..6b264abc90f1 --- /dev/null +++ b/tests/ui/frontmatter/infostring-fail.stderr @@ -0,0 +1,10 @@ +error: invalid infostring for frontmatter + --> $DIR/infostring-fail.rs:1:4 + | +LL | ---cargo,clippy + | ^^^^^^^^^^^^ + | + = note: frontmatter infostrings must be a single identifier immediately following the opening + +error: aborting due to 1 previous error + diff --git a/tests/ui/frontmatter/mismatch-1.rs b/tests/ui/frontmatter/mismatch-1.rs new file mode 100644 index 000000000000..37e2b0af6b18 --- /dev/null +++ b/tests/ui/frontmatter/mismatch-1.rs @@ -0,0 +1,10 @@ +---cargo +//~^ ERROR: frontmatter close does not match the opening +---- + +// there must be the same number of dashes for both the opening and the close +// of the frontmatter. + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/mismatch-1.stderr b/tests/ui/frontmatter/mismatch-1.stderr new file mode 100644 index 000000000000..b6e29294d9e1 --- /dev/null +++ b/tests/ui/frontmatter/mismatch-1.stderr @@ -0,0 +1,16 @@ +error: frontmatter close does not match the opening + --> $DIR/mismatch-1.rs:1:1 + | +LL | ---cargo + | ^-- + | | + | _the opening here has 3 dashes... + | | +LL | | +LL | | ---- + | |_---^ + | | + | ...while the close has 4 dashes + +error: aborting due to 1 previous error + diff --git a/tests/ui/frontmatter/mismatch-2.rs b/tests/ui/frontmatter/mismatch-2.rs new file mode 100644 index 000000000000..422abe1d6bc9 --- /dev/null +++ b/tests/ui/frontmatter/mismatch-2.rs @@ -0,0 +1,8 @@ +----cargo +//~^ ERROR: frontmatter close does not match the opening +---cargo +//~^ ERROR: extra characters after frontmatter close are not allowed + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/mismatch-2.stderr b/tests/ui/frontmatter/mismatch-2.stderr new file mode 100644 index 000000000000..90bb7b80bcea --- /dev/null +++ b/tests/ui/frontmatter/mismatch-2.stderr @@ -0,0 +1,22 @@ +error: frontmatter close does not match the opening + --> $DIR/mismatch-2.rs:1:1 + | +LL | ----cargo + | ^--- + | | + | _the opening here has 4 dashes... + | | +LL | | +LL | | ---cargo + | |_---____^ + | | + | ...while the close has 3 dashes + +error: extra characters after frontmatter close are not allowed + --> $DIR/mismatch-2.rs:3:1 + | +LL | ---cargo + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/frontmatter/multifrontmatter-2.rs b/tests/ui/frontmatter/multifrontmatter-2.rs new file mode 100644 index 000000000000..33cc30cb4655 --- /dev/null +++ b/tests/ui/frontmatter/multifrontmatter-2.rs @@ -0,0 +1,12 @@ +--- + --- +//~^ ERROR: invalid preceding whitespace for frontmatter close + + --- +//~^ ERROR: expected item, found `-` +// FIXME(frontmatter): make this diagnostic better +--- + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/multifrontmatter-2.stderr b/tests/ui/frontmatter/multifrontmatter-2.stderr new file mode 100644 index 000000000000..ed9ac4029e27 --- /dev/null +++ b/tests/ui/frontmatter/multifrontmatter-2.stderr @@ -0,0 +1,22 @@ +error: invalid preceding whitespace for frontmatter close + --> $DIR/multifrontmatter-2.rs:2:1 + | +LL | --- + | ^^^^ + | +note: frontmatter close should not be preceded by whitespace + --> $DIR/multifrontmatter-2.rs:2:1 + | +LL | --- + | ^ + +error: expected item, found `-` + --> $DIR/multifrontmatter-2.rs:5:2 + | +LL | --- + | ^ expected item + | + = note: for a full list of items that can appear in modules, see + +error: aborting due to 2 previous errors + diff --git a/tests/ui/frontmatter/multifrontmatter.rs b/tests/ui/frontmatter/multifrontmatter.rs new file mode 100644 index 000000000000..f3afa47bd383 --- /dev/null +++ b/tests/ui/frontmatter/multifrontmatter.rs @@ -0,0 +1,13 @@ +--- +--- + +--- +//~^ ERROR: expected item, found `-` +// FIXME(frontmatter): make this diagnostic better +--- + +// test that we do not parse another frontmatter block after the first one. + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/multifrontmatter.stderr b/tests/ui/frontmatter/multifrontmatter.stderr new file mode 100644 index 000000000000..2e9d1cee9ddb --- /dev/null +++ b/tests/ui/frontmatter/multifrontmatter.stderr @@ -0,0 +1,10 @@ +error: expected item, found `-` + --> $DIR/multifrontmatter.rs:4:1 + | +LL | --- + | ^ expected item + | + = note: for a full list of items that can appear in modules, see + +error: aborting due to 1 previous error + diff --git a/tests/ui/frontmatter/proc-macro-observer.rs b/tests/ui/frontmatter/proc-macro-observer.rs new file mode 100644 index 000000000000..bafbe912032e --- /dev/null +++ b/tests/ui/frontmatter/proc-macro-observer.rs @@ -0,0 +1,12 @@ +//@ check-pass +//@ proc-macro: makro.rs +//@ edition: 2021 + +#![feature(frontmatter)] + +makro::check!(); + +// checks that a proc-macro cannot observe frontmatter tokens. +// see auxiliary/makro.rs for how it is tested. + +fn main() {} diff --git a/tests/ui/frontmatter/shebang.rs b/tests/ui/frontmatter/shebang.rs new file mode 100644 index 000000000000..abd983f219bd --- /dev/null +++ b/tests/ui/frontmatter/shebang.rs @@ -0,0 +1,13 @@ +#!/usr/bin/env -S cargo -Zscript +--- +[dependencies] +clap = "4" +--- + +//@ check-pass + +// Shebangs on a file can precede a frontmatter. + +#![feature(frontmatter)] + +fn main () {} diff --git a/tests/ui/frontmatter/unclosed-1.rs b/tests/ui/frontmatter/unclosed-1.rs new file mode 100644 index 000000000000..d8b52b3e69c7 --- /dev/null +++ b/tests/ui/frontmatter/unclosed-1.rs @@ -0,0 +1,10 @@ +----cargo +//~^ ERROR: unclosed frontmatter + +// This test checks that the #! characters can help us recover a frontmatter +// close. There should not be a "missing `main` function" error as the rest +// are properly parsed. + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/unclosed-1.stderr b/tests/ui/frontmatter/unclosed-1.stderr new file mode 100644 index 000000000000..04031d128398 --- /dev/null +++ b/tests/ui/frontmatter/unclosed-1.stderr @@ -0,0 +1,16 @@ +error: unclosed frontmatter + --> $DIR/unclosed-1.rs:1:1 + | +LL | / ----cargo +... | +LL | | + | |_^ + | +note: frontmatter opening here was not closed + --> $DIR/unclosed-1.rs:1:1 + | +LL | ----cargo + | ^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/frontmatter/unclosed-2.rs b/tests/ui/frontmatter/unclosed-2.rs new file mode 100644 index 000000000000..add266dce5b0 --- /dev/null +++ b/tests/ui/frontmatter/unclosed-2.rs @@ -0,0 +1,15 @@ +----cargo +//~^ ERROR: unclosed frontmatter +//~| ERROR: frontmatters are experimental + +//@ compile-flags: --crate-type lib + +// Leading whitespace on the feature line prevents recovery. However +// the dashes quoted will not be used for recovery and the entire file +// should be treated as within the frontmatter block. + + #![feature(frontmatter)] + +fn foo() -> &str { + "----" +} diff --git a/tests/ui/frontmatter/unclosed-2.stderr b/tests/ui/frontmatter/unclosed-2.stderr new file mode 100644 index 000000000000..0a4022c1557b --- /dev/null +++ b/tests/ui/frontmatter/unclosed-2.stderr @@ -0,0 +1,31 @@ +error: unclosed frontmatter + --> $DIR/unclosed-2.rs:1:1 + | +LL | / ----cargo +... | +LL | | "----" +LL | | } + | |__^ + | +note: frontmatter opening here was not closed + --> $DIR/unclosed-2.rs:1:1 + | +LL | ----cargo + | ^^^^ + +error[E0658]: frontmatters are experimental + --> $DIR/unclosed-2.rs:1:1 + | +LL | / ----cargo +... | +LL | | "----" +LL | | } + | |__^ + | + = note: see issue #136889 for more information + = help: add `#![feature(frontmatter)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/frontmatter/unclosed-3.rs b/tests/ui/frontmatter/unclosed-3.rs new file mode 100644 index 000000000000..75f3fbda675c --- /dev/null +++ b/tests/ui/frontmatter/unclosed-3.rs @@ -0,0 +1,16 @@ +----cargo +//~^ ERROR: frontmatter close does not match the opening + +//@ compile-flags: --crate-type lib + +// Unfortunate recovery situation. Not really preventable with improving the +// recovery strategy, but this type of code is rare enough already. + + #![feature(frontmatter)] + +fn foo(x: i32) -> i32 { + ---x + //~^ ERROR: invalid preceding whitespace for frontmatter close + //~| ERROR: extra characters after frontmatter close are not allowed +} +//~^ ERROR: unexpected closing delimiter: `}` diff --git a/tests/ui/frontmatter/unclosed-3.stderr b/tests/ui/frontmatter/unclosed-3.stderr new file mode 100644 index 000000000000..cd69cb000408 --- /dev/null +++ b/tests/ui/frontmatter/unclosed-3.stderr @@ -0,0 +1,41 @@ +error: invalid preceding whitespace for frontmatter close + --> $DIR/unclosed-3.rs:12:1 + | +LL | ---x + | ^^^^^^^^ + | +note: frontmatter close should not be preceded by whitespace + --> $DIR/unclosed-3.rs:12:1 + | +LL | ---x + | ^^^^ + +error: frontmatter close does not match the opening + --> $DIR/unclosed-3.rs:1:1 + | +LL | ----cargo + | ^--- + | | + | _the opening here has 4 dashes... + | | +... | +LL | | fn foo(x: i32) -> i32 { +LL | | ---x + | |_---____^ + | | + | ...while the close has 3 dashes + +error: extra characters after frontmatter close are not allowed + --> $DIR/unclosed-3.rs:12:1 + | +LL | ---x + | ^^^^^^^^ + +error: unexpected closing delimiter: `}` + --> $DIR/unclosed-3.rs:15:1 + | +LL | } + | ^ unexpected closing delimiter + +error: aborting due to 4 previous errors + diff --git a/tests/ui/frontmatter/unclosed-4.rs b/tests/ui/frontmatter/unclosed-4.rs new file mode 100644 index 000000000000..41f6461db634 --- /dev/null +++ b/tests/ui/frontmatter/unclosed-4.rs @@ -0,0 +1,9 @@ +----cargo +//~^ ERROR: unclosed frontmatter + +//! Similarly, a module-level content should allow for recovery as well (as +//! per unclosed-1.rs) + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/unclosed-4.stderr b/tests/ui/frontmatter/unclosed-4.stderr new file mode 100644 index 000000000000..b3ba56937bba --- /dev/null +++ b/tests/ui/frontmatter/unclosed-4.stderr @@ -0,0 +1,16 @@ +error: unclosed frontmatter + --> $DIR/unclosed-4.rs:1:1 + | +LL | / ----cargo +LL | | +LL | | + | |_^ + | +note: frontmatter opening here was not closed + --> $DIR/unclosed-4.rs:1:1 + | +LL | ----cargo + | ^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/frontmatter/unclosed-5.rs b/tests/ui/frontmatter/unclosed-5.rs new file mode 100644 index 000000000000..9abbcfff94c7 --- /dev/null +++ b/tests/ui/frontmatter/unclosed-5.rs @@ -0,0 +1,10 @@ +----cargo +//~^ ERROR: unclosed frontmatter +//~| ERROR: frontmatters are experimental + +// Similarly, a use statement should allow for recovery as well (as +// per unclosed-1.rs) + +use std::env; + +fn main() {} diff --git a/tests/ui/frontmatter/unclosed-5.stderr b/tests/ui/frontmatter/unclosed-5.stderr new file mode 100644 index 000000000000..e904014a175a --- /dev/null +++ b/tests/ui/frontmatter/unclosed-5.stderr @@ -0,0 +1,29 @@ +error: unclosed frontmatter + --> $DIR/unclosed-5.rs:1:1 + | +LL | / ----cargo +... | +LL | | + | |_^ + | +note: frontmatter opening here was not closed + --> $DIR/unclosed-5.rs:1:1 + | +LL | ----cargo + | ^^^^ + +error[E0658]: frontmatters are experimental + --> $DIR/unclosed-5.rs:1:1 + | +LL | / ----cargo +... | +LL | | + | |_^ + | + = note: see issue #136889 for more information + = help: add `#![feature(frontmatter)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/generic-const-items/user_type_annotations_pattern.rs b/tests/ui/generic-const-items/user_type_annotations_pattern.rs new file mode 100644 index 000000000000..aa3846df2bca --- /dev/null +++ b/tests/ui/generic-const-items/user_type_annotations_pattern.rs @@ -0,0 +1,14 @@ +#![feature(generic_const_items)] +#![expect(incomplete_features)] + +const FOO<'a: 'static>: usize = 10; + +fn bar<'a>() { + match 10_usize { + FOO::<'a> => todo!(), + //~^ ERROR: lifetime may not live long enough + _ => todo!(), + } +} + +fn main() {} diff --git a/tests/ui/generic-const-items/user_type_annotations_pattern.stderr b/tests/ui/generic-const-items/user_type_annotations_pattern.stderr new file mode 100644 index 000000000000..e15be275d297 --- /dev/null +++ b/tests/ui/generic-const-items/user_type_annotations_pattern.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/user_type_annotations_pattern.rs:8:9 + | +LL | fn bar<'a>() { + | -- lifetime `'a` defined here +LL | match 10_usize { +LL | FOO::<'a> => todo!(), + | ^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-privacy-xc-1.rs b/tests/ui/impl-privacy-xc-1.rs deleted file mode 100644 index 6a10986739cd..000000000000 --- a/tests/ui/impl-privacy-xc-1.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass -//@ aux-build:impl_privacy_xc_1.rs - - -extern crate impl_privacy_xc_1; - -pub fn main() { - let fish = impl_privacy_xc_1::Fish { x: 1 }; - fish.swim(); -} diff --git a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.rs b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.rs index f1c196a154d5..ffb7a1008e0f 100644 --- a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.rs +++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.rs @@ -1,6 +1,5 @@ //@ only-linux //@ compile-flags: --error-format=human --color=always -//@ error-pattern: the trait bound trait Foo: Bar {} @@ -18,3 +17,5 @@ fn foo() -> impl Foo { } fn main() {} + +//~? RAW the trait bound diff --git a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg index 1a79a9d7efa2..9832e28e008b 100644 --- a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg +++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg @@ -1,4 +1,4 @@ - + ::Type; - | -LL - let _: S::Type; -LL + let _: ::Type; - | - error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-blanket-impl.rs:30:8 | @@ -63,6 +48,21 @@ LL - S::CONST; LL + ::CONST; | +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-blanket-impl.rs:36:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use fully-qualified syntax + | +LL - let _: S::Type; +LL + let _: ::Type; + | +LL - let _: S::Type; +LL + let _: ::Type; + | + error: aborting due to 3 previous errors Some errors have detailed explanations: E0034, E0223. diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr index 2563c2327b7a..319d5886f8ed 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -1,18 +1,3 @@ -error[E0223]: ambiguous associated type - --> $DIR/disambiguate-multiple-impl.rs:32:12 - | -LL | let _: S::Type = (); - | ^^^^^^^ - | -help: use fully-qualified syntax - | -LL - let _: S::Type = (); -LL + let _: ::Type = (); - | -LL - let _: S::Type = (); -LL + let _: ::Type = (); - | - error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-impl.rs:29:8 | @@ -38,6 +23,21 @@ LL - S::foo(&s); LL + B::foo(&s); | +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-impl.rs:32:12 + | +LL | let _: S::Type = (); + | ^^^^^^^ + | +help: use fully-qualified syntax + | +LL - let _: S::Type = (); +LL + let _: ::Type = (); + | +LL - let _: S::Type = (); +LL + let _: ::Type = (); + | + error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-impl.rs:34:16 | diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr index 08e264c20c89..f9119e607501 100644 --- a/tests/ui/methods/disambiguate-multiple-trait-2.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr @@ -1,26 +1,3 @@ -error[E0221]: ambiguous associated type `Type` in bounds of `T` - --> $DIR/disambiguate-multiple-trait-2.rs:23:12 - | -LL | type Type; - | --------- ambiguous `Type` from `A` -... -LL | type Type; - | --------- ambiguous `Type` from `B` -... -LL | let _: T::Type; - | ^^^^^^^ ambiguous associated type `Type` - | -help: use fully-qualified syntax to disambiguate - | -LL - let _: T::Type; -LL + let _: ::Type; - | -help: use fully-qualified syntax to disambiguate - | -LL - let _: T::Type; -LL + let _: ::Type; - | - error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait-2.rs:16:7 | @@ -73,19 +50,27 @@ LL - let _ = T::CONST; LL + let _ = ::CONST; | -error[E0223]: ambiguous associated type - --> $DIR/disambiguate-multiple-trait-2.rs:52:12 +error[E0221]: ambiguous associated type `Type` in bounds of `T` + --> $DIR/disambiguate-multiple-trait-2.rs:23:12 | -LL | let _: S::Type; - | ^^^^^^^ +LL | type Type; + | --------- ambiguous `Type` from `A` +... +LL | type Type; + | --------- ambiguous `Type` from `B` +... +LL | let _: T::Type; + | ^^^^^^^ ambiguous associated type `Type` | -help: use fully-qualified syntax +help: use fully-qualified syntax to disambiguate | -LL - let _: S::Type; -LL + let _: ::Type; +LL - let _: T::Type; +LL + let _: ::Type; | -LL - let _: S::Type; -LL + let _: ::Type; +help: use fully-qualified syntax to disambiguate + | +LL - let _: T::Type; +LL + let _: ::Type; | error[E0034]: multiple applicable items in scope @@ -138,6 +123,21 @@ LL - let _ = S::CONST; LL + let _ = ::CONST; | +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-trait-2.rs:52:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use fully-qualified syntax + | +LL - let _: S::Type; +LL + let _: ::Type; + | +LL - let _: S::Type; +LL + let _: ::Type; + | + error: aborting due to 6 previous errors Some errors have detailed explanations: E0034, E0221, E0223. diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr index a977fe2cd033..f35eec3b048c 100644 --- a/tests/ui/methods/disambiguate-multiple-trait.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait.stderr @@ -1,18 +1,3 @@ -error[E0223]: ambiguous associated type - --> $DIR/disambiguate-multiple-trait.rs:30:12 - | -LL | let _: S::Type; - | ^^^^^^^ - | -help: use fully-qualified syntax - | -LL - let _: S::Type; -LL + let _: ::Type; - | -LL - let _: S::Type; -LL + let _: ::Type; - | - error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait.rs:24:8 | @@ -63,6 +48,21 @@ LL - let _ = S::CONST; LL + let _ = ::CONST; | +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-trait.rs:30:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use fully-qualified syntax + | +LL - let _: S::Type; +LL + let _: ::Type; + | +LL - let _: S::Type; +LL + let _: ::Type; + | + error: aborting due to 3 previous errors Some errors have detailed explanations: E0034, E0223. diff --git a/tests/ui/mir/lint/assignment-overlap.rs b/tests/ui/mir/lint/assignment-overlap.rs index 950279b1555f..bbc140904671 100644 --- a/tests/ui/mir/lint/assignment-overlap.rs +++ b/tests/ui/mir/lint/assignment-overlap.rs @@ -2,7 +2,7 @@ //@ build-fail //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: encountered `Assign` statement with overlapping memory + #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; @@ -13,6 +13,7 @@ pub fn main() { let a: [u8; 1024]; { a = a; //~ ERROR broken MIR + //~^ ERROR encountered `Assign` statement with overlapping memory Return() } } diff --git a/tests/ui/mir/lint/call-overlap.rs b/tests/ui/mir/lint/call-overlap.rs index 3c42e04e3ec8..f43edfb87382 100644 --- a/tests/ui/mir/lint/call-overlap.rs +++ b/tests/ui/mir/lint/call-overlap.rs @@ -2,7 +2,7 @@ //@ build-fail //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: encountered overlapping memory in `Move` arguments to `Call` + #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; @@ -13,6 +13,7 @@ pub fn main() { let a: [u8; 1024]; { Call(a = f(Move(a)), ReturnTo(bb1), UnwindUnreachable()) //~ ERROR broken MIR + //~^ ERROR encountered overlapping memory in `Move` arguments to `Call` } bb1 = { Return() diff --git a/tests/ui/mir/lint/storage-live.rs b/tests/ui/mir/lint/storage-live.rs index 19d046b619c4..252e3b8456c2 100644 --- a/tests/ui/mir/lint/storage-live.rs +++ b/tests/ui/mir/lint/storage-live.rs @@ -1,7 +1,5 @@ //@ compile-flags: -Zlint-mir -Ztreat-err-as-bug //@ failure-status: 101 -//@ error-pattern: broken MIR in -//@ error-pattern: StorageLive(_1) which already has storage here //@ normalize-stderr: "note: .*\n\n" -> "" //@ normalize-stderr: "thread 'rustc' panicked.*\n" -> "" //@ normalize-stderr: "storage_live\[....\]" -> "storage_live[HASH]" @@ -21,6 +19,7 @@ fn multiple_storage() { { StorageLive(a); StorageLive(a); //~ ERROR broken MIR + //~| ERROR StorageLive(_1) which already has storage here Return() } } diff --git a/tests/ui/mir/lint/storage-live.stderr b/tests/ui/mir/lint/storage-live.stderr index 651b8e2327ee..50df9ae061fc 100644 --- a/tests/ui/mir/lint/storage-live.stderr +++ b/tests/ui/mir/lint/storage-live.stderr @@ -1,12 +1,12 @@ error: internal compiler error: broken MIR in Item(DefId(0:8 ~ storage_live[HASH]::multiple_storage)) (after pass CheckForceInline) at bb0[1]: StorageLive(_1) which already has storage here - --> $DIR/storage-live.rs:23:13 + --> $DIR/storage-live.rs:21:13 | LL | StorageLive(a); | ^^^^^^^^^^^^^^ | note: delayed at compiler/rustc_mir_transform/src/lint.rs:LL:CC - disabled backtrace - --> $DIR/storage-live.rs:23:13 + --> $DIR/storage-live.rs:21:13 | LL | StorageLive(a); | ^^^^^^^^^^^^^^ diff --git a/tests/ui/mir/lint/storage-return.rs b/tests/ui/mir/lint/storage-return.rs index 3bbd0045d9db..c3e1f00bd720 100644 --- a/tests/ui/mir/lint/storage-return.rs +++ b/tests/ui/mir/lint/storage-return.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Zlint-mir -Ztreat-err-as-bug -Zeagerly-emit-delayed-bugs //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: has storage when returning + #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; @@ -14,6 +14,7 @@ fn main() { StorageLive(a); RET = a; Return() //~ ERROR broken MIR + //~^ ERROR has storage when returning } } } diff --git a/tests/ui/mir/validate/critical-edge.rs b/tests/ui/mir/validate/critical-edge.rs index 9048d08a22a7..2a3bf6a6181b 100644 --- a/tests/ui/mir/validate/critical-edge.rs +++ b/tests/ui/mir/validate/critical-edge.rs @@ -5,7 +5,7 @@ //@ compile-flags: --crate-type=lib //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: encountered critical edge in `Call` terminator + #![feature(custom_mir, core_intrinsics)] use core::intrinsics::mir::*; @@ -29,3 +29,5 @@ pub fn f(a: u32) -> u32 { } } } + +//~? RAW encountered critical edge in `Call` terminator diff --git a/tests/ui/mismatched_types/dont-point-return-on-E0308.rs b/tests/ui/mismatched_types/dont-point-return-on-E0308.rs index dca917e3ba1e..750329d29c00 100644 --- a/tests/ui/mismatched_types/dont-point-return-on-E0308.rs +++ b/tests/ui/mismatched_types/dont-point-return-on-E0308.rs @@ -2,7 +2,6 @@ async fn f(_: &()) {} //~^ NOTE function defined here -//~| NOTE // Second note is the span of the underlined argument, I think... fn main() { diff --git a/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr b/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr index 9d4852cff8c6..105dc5c2e798 100644 --- a/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr +++ b/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/dont-point-return-on-E0308.rs:11:11 + --> $DIR/dont-point-return-on-E0308.rs:10:11 | LL | f(()); | - ^^ expected `&()`, found `()` diff --git a/tests/ui/mismatched_types/similar_paths_primitive.rs b/tests/ui/mismatched_types/similar_paths_primitive.rs index b20ca80ac071..a58fe68b8638 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.rs +++ b/tests/ui/mismatched_types/similar_paths_primitive.rs @@ -4,9 +4,8 @@ struct bool; //~ NOTE the other `bool` is defined in the current crate struct str; //~ NOTE the other `str` is defined in the current crate fn foo(_: bool) {} //~ NOTE function defined here - //~^ NOTE fn bar(_: &str) {} //~ NOTE function defined here - //~^ NOTE + fn main() { foo(true); //~^ ERROR mismatched types [E0308] diff --git a/tests/ui/mismatched_types/similar_paths_primitive.stderr b/tests/ui/mismatched_types/similar_paths_primitive.stderr index 9c1aa0d7105b..cf26234dba85 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.stderr +++ b/tests/ui/mismatched_types/similar_paths_primitive.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/similar_paths_primitive.rs:11:9 + --> $DIR/similar_paths_primitive.rs:10:9 | LL | foo(true); | --- ^^^^ expected `bool`, found a different `bool` @@ -20,7 +20,7 @@ LL | fn foo(_: bool) {} | ^^^ ------- error[E0308]: mismatched types - --> $DIR/similar_paths_primitive.rs:17:9 + --> $DIR/similar_paths_primitive.rs:16:9 | LL | bar("hello"); | --- ^^^^^^^ expected `str`, found a different `str` @@ -35,7 +35,7 @@ note: the other `str` is defined in the current crate LL | struct str; | ^^^^^^^^^^ note: function defined here - --> $DIR/similar_paths_primitive.rs:8:4 + --> $DIR/similar_paths_primitive.rs:7:4 | LL | fn bar(_: &str) {} | ^^^ ------- diff --git a/tests/ui/nll/nested-bodies-in-dead-code.rs b/tests/ui/nll/nested-bodies-in-dead-code.rs new file mode 100644 index 000000000000..6ac68f5adbce --- /dev/null +++ b/tests/ui/nll/nested-bodies-in-dead-code.rs @@ -0,0 +1,28 @@ +//@ edition: 2024 + +// Regression test for #140583. We want to borrowck nested +// bodies even if they are in dead code. While not necessary for +// soundness, it is desirable to error in such cases. + +fn main() { + return; + |x: &str| -> &'static str { x }; + //~^ ERROR lifetime may not live long enough + || { + || { + let temp = 1; + let p: &'static u32 = &temp; + //~^ ERROR `temp` does not live long enough + }; + }; + const { + let temp = 1; + let p: &'static u32 = &temp; + //~^ ERROR `temp` does not live long enough + }; + async { + let temp = 1; + let p: &'static u32 = &temp; + //~^ ERROR `temp` does not live long enough + }; +} diff --git a/tests/ui/nll/nested-bodies-in-dead-code.stderr b/tests/ui/nll/nested-bodies-in-dead-code.stderr new file mode 100644 index 000000000000..da6ccff5777c --- /dev/null +++ b/tests/ui/nll/nested-bodies-in-dead-code.stderr @@ -0,0 +1,50 @@ +error: lifetime may not live long enough + --> $DIR/nested-bodies-in-dead-code.rs:9:33 + | +LL | |x: &str| -> &'static str { x }; + | - ^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + +error[E0597]: `temp` does not live long enough + --> $DIR/nested-bodies-in-dead-code.rs:14:35 + | +LL | let temp = 1; + | ---- binding `temp` declared here +LL | let p: &'static u32 = &temp; + | ------------ ^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `temp` is borrowed for `'static` +LL | +LL | }; + | - `temp` dropped here while still borrowed + +error[E0597]: `temp` does not live long enough + --> $DIR/nested-bodies-in-dead-code.rs:20:31 + | +LL | let temp = 1; + | ---- binding `temp` declared here +LL | let p: &'static u32 = &temp; + | ------------ ^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `temp` is borrowed for `'static` +LL | +LL | }; + | - `temp` dropped here while still borrowed + +error[E0597]: `temp` does not live long enough + --> $DIR/nested-bodies-in-dead-code.rs:25:31 + | +LL | let temp = 1; + | ---- binding `temp` declared here +LL | let p: &'static u32 = &temp; + | ------------ ^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `temp` is borrowed for `'static` +LL | +LL | }; + | - `temp` dropped here while still borrowed + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/no-link-unknown-crate.rs b/tests/ui/no-link-unknown-crate.rs deleted file mode 100644 index c7da2e41832f..000000000000 --- a/tests/ui/no-link-unknown-crate.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[no_link] -extern crate doesnt_exist; //~ ERROR can't find crate - -fn main() {} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed index e3b613cc3f64..9f891afc313a 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_i32); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.rs index 3b384e763107..a735fade86ed 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.rs +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.rs @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_usize); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr index 6c6b8b51c226..b3450b41d38c 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:28:16 + --> $DIR/numeric-suffix-i32.rs:17:16 | LL | foo::(42_usize); | ---------- ^^^^^^^^ expected `i32`, found `usize` @@ -18,7 +18,7 @@ LL + foo::(42_i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:32:16 + --> $DIR/numeric-suffix-i32.rs:21:16 | LL | foo::(42_u64); | ---------- ^^^^^^ expected `i32`, found `u64` @@ -37,7 +37,7 @@ LL + foo::(42_i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:36:16 + --> $DIR/numeric-suffix-i32.rs:25:16 | LL | foo::(42_u32); | ---------- ^^^^^^ expected `i32`, found `u32` @@ -56,7 +56,7 @@ LL + foo::(42_i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:40:16 + --> $DIR/numeric-suffix-i32.rs:29:16 | LL | foo::(42_u16); | ---------- ^^^^^^ expected `i32`, found `u16` @@ -75,7 +75,7 @@ LL + foo::(42_i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:44:16 + --> $DIR/numeric-suffix-i32.rs:33:16 | LL | foo::(42_u8); | ---------- ^^^^^ expected `i32`, found `u8` @@ -94,7 +94,7 @@ LL + foo::(42_i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:48:16 + --> $DIR/numeric-suffix-i32.rs:37:16 | LL | foo::(42_isize); | ---------- ^^^^^^^^ expected `i32`, found `isize` @@ -113,7 +113,7 @@ LL + foo::(42_i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:52:16 + --> $DIR/numeric-suffix-i32.rs:41:16 | LL | foo::(42_i64); | ---------- ^^^^^^ expected `i32`, found `i64` @@ -132,7 +132,7 @@ LL + foo::(42_i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:57:16 + --> $DIR/numeric-suffix-i32.rs:46:16 | LL | foo::(42_i16); | ---------- ^^^^^^ expected `i32`, found `i16` @@ -151,7 +151,7 @@ LL + foo::(42_i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:61:16 + --> $DIR/numeric-suffix-i32.rs:50:16 | LL | foo::(42_i8); | ---------- ^^^^^ expected `i32`, found `i8` @@ -170,7 +170,7 @@ LL + foo::(42_i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:65:16 + --> $DIR/numeric-suffix-i32.rs:54:16 | LL | foo::(42.0_f64); | ---------- ^^^^^^^^ expected `i32`, found `f64` @@ -189,7 +189,7 @@ LL + foo::(42i32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i32.rs:69:16 + --> $DIR/numeric-suffix-i32.rs:58:16 | LL | foo::(42.0_f32); | ---------- ^^^^^^^^ expected `i32`, found `f32` diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed index 0fcda6c1f806..6d1c585a5639 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_i64); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.rs index 9c912bc38dad..fd4862be3873 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.rs +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.rs @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_usize); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr index 7c26dd7be1c6..63326f49a8f0 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:28:16 + --> $DIR/numeric-suffix-i64.rs:17:16 | LL | foo::(42_usize); | ---------- ^^^^^^^^ expected `i64`, found `usize` @@ -18,7 +18,7 @@ LL + foo::(42_i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:32:16 + --> $DIR/numeric-suffix-i64.rs:21:16 | LL | foo::(42_u64); | ---------- ^^^^^^ expected `i64`, found `u64` @@ -37,7 +37,7 @@ LL + foo::(42_i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:36:16 + --> $DIR/numeric-suffix-i64.rs:25:16 | LL | foo::(42_u32); | ---------- ^^^^^^ expected `i64`, found `u32` @@ -56,7 +56,7 @@ LL + foo::(42_i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:40:16 + --> $DIR/numeric-suffix-i64.rs:29:16 | LL | foo::(42_u16); | ---------- ^^^^^^ expected `i64`, found `u16` @@ -75,7 +75,7 @@ LL + foo::(42_i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:44:16 + --> $DIR/numeric-suffix-i64.rs:33:16 | LL | foo::(42_u8); | ---------- ^^^^^ expected `i64`, found `u8` @@ -94,7 +94,7 @@ LL + foo::(42_i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:48:16 + --> $DIR/numeric-suffix-i64.rs:37:16 | LL | foo::(42_isize); | ---------- ^^^^^^^^ expected `i64`, found `isize` @@ -113,7 +113,7 @@ LL + foo::(42_i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:53:16 + --> $DIR/numeric-suffix-i64.rs:42:16 | LL | foo::(42_i32); | ---------- ^^^^^^ expected `i64`, found `i32` @@ -132,7 +132,7 @@ LL + foo::(42_i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:57:16 + --> $DIR/numeric-suffix-i64.rs:46:16 | LL | foo::(42_i16); | ---------- ^^^^^^ expected `i64`, found `i16` @@ -151,7 +151,7 @@ LL + foo::(42_i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:61:16 + --> $DIR/numeric-suffix-i64.rs:50:16 | LL | foo::(42_i8); | ---------- ^^^^^ expected `i64`, found `i8` @@ -170,7 +170,7 @@ LL + foo::(42_i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:65:16 + --> $DIR/numeric-suffix-i64.rs:54:16 | LL | foo::(42.0_f64); | ---------- ^^^^^^^^ expected `i64`, found `f64` @@ -189,7 +189,7 @@ LL + foo::(42i64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-i64.rs:69:16 + --> $DIR/numeric-suffix-i64.rs:58:16 | LL | foo::(42.0_f32); | ---------- ^^^^^^^^ expected `i64`, found `f32` diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed index 23e7cf780e9a..f24fce3f1d67 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_isize); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.rs index 5d6fd4d932ac..fdf86895ff23 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.rs +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.rs @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_usize); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr index 8365350f2bfe..99561b19021a 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:28:18 + --> $DIR/numeric-suffix-isize.rs:17:18 | LL | foo::(42_usize); | ------------ ^^^^^^^^ expected `isize`, found `usize` @@ -18,7 +18,7 @@ LL + foo::(42_isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:32:18 + --> $DIR/numeric-suffix-isize.rs:21:18 | LL | foo::(42_u64); | ------------ ^^^^^^ expected `isize`, found `u64` @@ -37,7 +37,7 @@ LL + foo::(42_isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:36:18 + --> $DIR/numeric-suffix-isize.rs:25:18 | LL | foo::(42_u32); | ------------ ^^^^^^ expected `isize`, found `u32` @@ -56,7 +56,7 @@ LL + foo::(42_isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:40:18 + --> $DIR/numeric-suffix-isize.rs:29:18 | LL | foo::(42_u16); | ------------ ^^^^^^ expected `isize`, found `u16` @@ -75,7 +75,7 @@ LL + foo::(42_isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:44:18 + --> $DIR/numeric-suffix-isize.rs:33:18 | LL | foo::(42_u8); | ------------ ^^^^^ expected `isize`, found `u8` @@ -94,7 +94,7 @@ LL + foo::(42_isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:49:18 + --> $DIR/numeric-suffix-isize.rs:38:18 | LL | foo::(42_i64); | ------------ ^^^^^^ expected `isize`, found `i64` @@ -113,7 +113,7 @@ LL + foo::(42_isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:53:18 + --> $DIR/numeric-suffix-isize.rs:42:18 | LL | foo::(42_i32); | ------------ ^^^^^^ expected `isize`, found `i32` @@ -132,7 +132,7 @@ LL + foo::(42_isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:57:18 + --> $DIR/numeric-suffix-isize.rs:46:18 | LL | foo::(42_i16); | ------------ ^^^^^^ expected `isize`, found `i16` @@ -151,7 +151,7 @@ LL + foo::(42_isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:61:18 + --> $DIR/numeric-suffix-isize.rs:50:18 | LL | foo::(42_i8); | ------------ ^^^^^ expected `isize`, found `i8` @@ -170,7 +170,7 @@ LL + foo::(42_isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:65:18 + --> $DIR/numeric-suffix-isize.rs:54:18 | LL | foo::(42.0_f64); | ------------ ^^^^^^^^ expected `isize`, found `f64` @@ -189,7 +189,7 @@ LL + foo::(42isize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-isize.rs:69:18 + --> $DIR/numeric-suffix-isize.rs:58:18 | LL | foo::(42.0_f32); | ------------ ^^^^^^^^ expected `isize`, found `f32` diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed index 2dd7d9aabdb5..eba5d7c1c266 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_u32); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.rs index 46bbb0331854..d127353e9754 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.rs +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.rs @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_usize); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr index 610e6ece2769..95e913595e5e 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:28:16 + --> $DIR/numeric-suffix-u32.rs:17:16 | LL | foo::(42_usize); | ---------- ^^^^^^^^ expected `u32`, found `usize` @@ -18,7 +18,7 @@ LL + foo::(42_u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:32:16 + --> $DIR/numeric-suffix-u32.rs:21:16 | LL | foo::(42_u64); | ---------- ^^^^^^ expected `u32`, found `u64` @@ -37,7 +37,7 @@ LL + foo::(42_u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:37:16 + --> $DIR/numeric-suffix-u32.rs:26:16 | LL | foo::(42_u16); | ---------- ^^^^^^ expected `u32`, found `u16` @@ -56,7 +56,7 @@ LL + foo::(42_u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:41:16 + --> $DIR/numeric-suffix-u32.rs:30:16 | LL | foo::(42_u8); | ---------- ^^^^^ expected `u32`, found `u8` @@ -75,7 +75,7 @@ LL + foo::(42_u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:45:16 + --> $DIR/numeric-suffix-u32.rs:34:16 | LL | foo::(42_isize); | ---------- ^^^^^^^^ expected `u32`, found `isize` @@ -94,7 +94,7 @@ LL + foo::(42_u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:49:16 + --> $DIR/numeric-suffix-u32.rs:38:16 | LL | foo::(42_i64); | ---------- ^^^^^^ expected `u32`, found `i64` @@ -113,7 +113,7 @@ LL + foo::(42_u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:53:16 + --> $DIR/numeric-suffix-u32.rs:42:16 | LL | foo::(42_i32); | ---------- ^^^^^^ expected `u32`, found `i32` @@ -132,7 +132,7 @@ LL + foo::(42_u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:57:16 + --> $DIR/numeric-suffix-u32.rs:46:16 | LL | foo::(42_i16); | ---------- ^^^^^^ expected `u32`, found `i16` @@ -151,7 +151,7 @@ LL + foo::(42_u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:61:16 + --> $DIR/numeric-suffix-u32.rs:50:16 | LL | foo::(42_i8); | ---------- ^^^^^ expected `u32`, found `i8` @@ -170,7 +170,7 @@ LL + foo::(42_u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:65:16 + --> $DIR/numeric-suffix-u32.rs:54:16 | LL | foo::(42.0_f64); | ---------- ^^^^^^^^ expected `u32`, found `f64` @@ -189,7 +189,7 @@ LL + foo::(42u32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u32.rs:69:16 + --> $DIR/numeric-suffix-u32.rs:58:16 | LL | foo::(42.0_f32); | ---------- ^^^^^^^^ expected `u32`, found `f32` diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed index 2dea195f0981..c8344211d3d0 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_u64); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.rs index 6fca089b07d4..f9b35efbc4be 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.rs +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.rs @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_usize); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr index 112dddccd6f4..0c92b4137614 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:28:16 + --> $DIR/numeric-suffix-u64.rs:17:16 | LL | foo::(42_usize); | ---------- ^^^^^^^^ expected `u64`, found `usize` @@ -18,7 +18,7 @@ LL + foo::(42_u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:33:16 + --> $DIR/numeric-suffix-u64.rs:22:16 | LL | foo::(42_u32); | ---------- ^^^^^^ expected `u64`, found `u32` @@ -37,7 +37,7 @@ LL + foo::(42_u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:37:16 + --> $DIR/numeric-suffix-u64.rs:26:16 | LL | foo::(42_u16); | ---------- ^^^^^^ expected `u64`, found `u16` @@ -56,7 +56,7 @@ LL + foo::(42_u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:41:16 + --> $DIR/numeric-suffix-u64.rs:30:16 | LL | foo::(42_u8); | ---------- ^^^^^ expected `u64`, found `u8` @@ -75,7 +75,7 @@ LL + foo::(42_u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:45:16 + --> $DIR/numeric-suffix-u64.rs:34:16 | LL | foo::(42_isize); | ---------- ^^^^^^^^ expected `u64`, found `isize` @@ -94,7 +94,7 @@ LL + foo::(42_u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:49:16 + --> $DIR/numeric-suffix-u64.rs:38:16 | LL | foo::(42_i64); | ---------- ^^^^^^ expected `u64`, found `i64` @@ -113,7 +113,7 @@ LL + foo::(42_u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:53:16 + --> $DIR/numeric-suffix-u64.rs:42:16 | LL | foo::(42_i32); | ---------- ^^^^^^ expected `u64`, found `i32` @@ -132,7 +132,7 @@ LL + foo::(42_u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:57:16 + --> $DIR/numeric-suffix-u64.rs:46:16 | LL | foo::(42_i16); | ---------- ^^^^^^ expected `u64`, found `i16` @@ -151,7 +151,7 @@ LL + foo::(42_u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:61:16 + --> $DIR/numeric-suffix-u64.rs:50:16 | LL | foo::(42_i8); | ---------- ^^^^^ expected `u64`, found `i8` @@ -170,7 +170,7 @@ LL + foo::(42_u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:65:16 + --> $DIR/numeric-suffix-u64.rs:54:16 | LL | foo::(42.0_f64); | ---------- ^^^^^^^^ expected `u64`, found `f64` @@ -189,7 +189,7 @@ LL + foo::(42u64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-u64.rs:69:16 + --> $DIR/numeric-suffix-u64.rs:58:16 | LL | foo::(42.0_f32); | ---------- ^^^^^^^^ expected `u64`, found `f32` diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed index 63422c305d35..4d5176fe7245 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_usize); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.rs index 4d20e4fc8431..118d8ca219ec 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.rs +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.rs @@ -12,17 +12,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE fn main() { foo::(42_usize); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr index e7d6a04f18ef..86181d6714f5 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:29:18 + --> $DIR/numeric-suffix-usize.rs:18:18 | LL | foo::(42_u64); | ------------ ^^^^^^ expected `usize`, found `u64` @@ -18,7 +18,7 @@ LL + foo::(42_usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:33:18 + --> $DIR/numeric-suffix-usize.rs:22:18 | LL | foo::(42_u32); | ------------ ^^^^^^ expected `usize`, found `u32` @@ -37,7 +37,7 @@ LL + foo::(42_usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:37:18 + --> $DIR/numeric-suffix-usize.rs:26:18 | LL | foo::(42_u16); | ------------ ^^^^^^ expected `usize`, found `u16` @@ -56,7 +56,7 @@ LL + foo::(42_usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:41:18 + --> $DIR/numeric-suffix-usize.rs:30:18 | LL | foo::(42_u8); | ------------ ^^^^^ expected `usize`, found `u8` @@ -75,7 +75,7 @@ LL + foo::(42_usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:45:18 + --> $DIR/numeric-suffix-usize.rs:34:18 | LL | foo::(42_isize); | ------------ ^^^^^^^^ expected `usize`, found `isize` @@ -94,7 +94,7 @@ LL + foo::(42_usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:49:18 + --> $DIR/numeric-suffix-usize.rs:38:18 | LL | foo::(42_i64); | ------------ ^^^^^^ expected `usize`, found `i64` @@ -113,7 +113,7 @@ LL + foo::(42_usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:53:18 + --> $DIR/numeric-suffix-usize.rs:42:18 | LL | foo::(42_i32); | ------------ ^^^^^^ expected `usize`, found `i32` @@ -132,7 +132,7 @@ LL + foo::(42_usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:57:18 + --> $DIR/numeric-suffix-usize.rs:46:18 | LL | foo::(42_i16); | ------------ ^^^^^^ expected `usize`, found `i16` @@ -151,7 +151,7 @@ LL + foo::(42_usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:61:18 + --> $DIR/numeric-suffix-usize.rs:50:18 | LL | foo::(42_i8); | ------------ ^^^^^ expected `usize`, found `i8` @@ -170,7 +170,7 @@ LL + foo::(42_usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:65:18 + --> $DIR/numeric-suffix-usize.rs:54:18 | LL | foo::(42.0_f64); | ------------ ^^^^^^^^ expected `usize`, found `f64` @@ -189,7 +189,7 @@ LL + foo::(42usize); | error[E0308]: mismatched types - --> $DIR/numeric-suffix-usize.rs:69:18 + --> $DIR/numeric-suffix-usize.rs:58:18 | LL | foo::(42.0_f32); | ------------ ^^^^^^^^ expected `usize`, found `f32` diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix.fixed index 270afb639575..b20b594dc2c3 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix.fixed +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix.fixed @@ -69,75 +69,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE - fn main() { foo::(42_u16); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix.rs index 05be58e335bc..9272902f5190 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix.rs +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix.rs @@ -69,75 +69,6 @@ fn foo(_x: N) {} //~| NOTE function defined here //~| NOTE function defined here //~| NOTE function defined here -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE -//~| NOTE - fn main() { foo::(42_usize); diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix.stderr index d26639a76f0f..cae1268beec0 100644 --- a/tests/ui/numeric/numeric-suffix/numeric-suffix.stderr +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:143:16 + --> $DIR/numeric-suffix.rs:74:16 | LL | foo::(42_usize); | ---------- ^^^^^^^^ expected `u16`, found `usize` @@ -18,7 +18,7 @@ LL + foo::(42_u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:147:16 + --> $DIR/numeric-suffix.rs:78:16 | LL | foo::(42_u64); | ---------- ^^^^^^ expected `u16`, found `u64` @@ -37,7 +37,7 @@ LL + foo::(42_u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:151:16 + --> $DIR/numeric-suffix.rs:82:16 | LL | foo::(42_u32); | ---------- ^^^^^^ expected `u16`, found `u32` @@ -56,7 +56,7 @@ LL + foo::(42_u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:156:16 + --> $DIR/numeric-suffix.rs:87:16 | LL | foo::(42_u8); | ---------- ^^^^^ expected `u16`, found `u8` @@ -75,7 +75,7 @@ LL + foo::(42_u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:160:16 + --> $DIR/numeric-suffix.rs:91:16 | LL | foo::(42_isize); | ---------- ^^^^^^^^ expected `u16`, found `isize` @@ -94,7 +94,7 @@ LL + foo::(42_u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:164:16 + --> $DIR/numeric-suffix.rs:95:16 | LL | foo::(42_i64); | ---------- ^^^^^^ expected `u16`, found `i64` @@ -113,7 +113,7 @@ LL + foo::(42_u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:168:16 + --> $DIR/numeric-suffix.rs:99:16 | LL | foo::(42_i32); | ---------- ^^^^^^ expected `u16`, found `i32` @@ -132,7 +132,7 @@ LL + foo::(42_u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:172:16 + --> $DIR/numeric-suffix.rs:103:16 | LL | foo::(42_i16); | ---------- ^^^^^^ expected `u16`, found `i16` @@ -151,7 +151,7 @@ LL + foo::(42_u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:176:16 + --> $DIR/numeric-suffix.rs:107:16 | LL | foo::(42_i8); | ---------- ^^^^^ expected `u16`, found `i8` @@ -170,7 +170,7 @@ LL + foo::(42_u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:180:16 + --> $DIR/numeric-suffix.rs:111:16 | LL | foo::(42.0_f64); | ---------- ^^^^^^^^ expected `u16`, found `f64` @@ -189,7 +189,7 @@ LL + foo::(42u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:184:16 + --> $DIR/numeric-suffix.rs:115:16 | LL | foo::(42.0_f32); | ---------- ^^^^^^^^ expected `u16`, found `f32` @@ -208,7 +208,7 @@ LL + foo::(42u16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:189:16 + --> $DIR/numeric-suffix.rs:120:16 | LL | foo::(42_usize); | ---------- ^^^^^^^^ expected `i16`, found `usize` @@ -227,7 +227,7 @@ LL + foo::(42_i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:193:16 + --> $DIR/numeric-suffix.rs:124:16 | LL | foo::(42_u64); | ---------- ^^^^^^ expected `i16`, found `u64` @@ -246,7 +246,7 @@ LL + foo::(42_i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:197:16 + --> $DIR/numeric-suffix.rs:128:16 | LL | foo::(42_u32); | ---------- ^^^^^^ expected `i16`, found `u32` @@ -265,7 +265,7 @@ LL + foo::(42_i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:201:16 + --> $DIR/numeric-suffix.rs:132:16 | LL | foo::(42_u16); | ---------- ^^^^^^ expected `i16`, found `u16` @@ -284,7 +284,7 @@ LL + foo::(42_i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:205:16 + --> $DIR/numeric-suffix.rs:136:16 | LL | foo::(42_u8); | ---------- ^^^^^ expected `i16`, found `u8` @@ -303,7 +303,7 @@ LL + foo::(42_i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:209:16 + --> $DIR/numeric-suffix.rs:140:16 | LL | foo::(42_isize); | ---------- ^^^^^^^^ expected `i16`, found `isize` @@ -322,7 +322,7 @@ LL + foo::(42_i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:213:16 + --> $DIR/numeric-suffix.rs:144:16 | LL | foo::(42_i64); | ---------- ^^^^^^ expected `i16`, found `i64` @@ -341,7 +341,7 @@ LL + foo::(42_i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:217:16 + --> $DIR/numeric-suffix.rs:148:16 | LL | foo::(42_i32); | ---------- ^^^^^^ expected `i16`, found `i32` @@ -360,7 +360,7 @@ LL + foo::(42_i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:222:16 + --> $DIR/numeric-suffix.rs:153:16 | LL | foo::(42_i8); | ---------- ^^^^^ expected `i16`, found `i8` @@ -379,7 +379,7 @@ LL + foo::(42_i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:226:16 + --> $DIR/numeric-suffix.rs:157:16 | LL | foo::(42.0_f64); | ---------- ^^^^^^^^ expected `i16`, found `f64` @@ -398,7 +398,7 @@ LL + foo::(42i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:230:16 + --> $DIR/numeric-suffix.rs:161:16 | LL | foo::(42.0_f32); | ---------- ^^^^^^^^ expected `i16`, found `f32` @@ -417,7 +417,7 @@ LL + foo::(42i16); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:235:15 + --> $DIR/numeric-suffix.rs:166:15 | LL | foo::(42_usize); | --------- ^^^^^^^^ expected `u8`, found `usize` @@ -436,7 +436,7 @@ LL + foo::(42_u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:239:15 + --> $DIR/numeric-suffix.rs:170:15 | LL | foo::(42_u64); | --------- ^^^^^^ expected `u8`, found `u64` @@ -455,7 +455,7 @@ LL + foo::(42_u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:243:15 + --> $DIR/numeric-suffix.rs:174:15 | LL | foo::(42_u32); | --------- ^^^^^^ expected `u8`, found `u32` @@ -474,7 +474,7 @@ LL + foo::(42_u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:247:15 + --> $DIR/numeric-suffix.rs:178:15 | LL | foo::(42_u16); | --------- ^^^^^^ expected `u8`, found `u16` @@ -493,7 +493,7 @@ LL + foo::(42_u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:252:15 + --> $DIR/numeric-suffix.rs:183:15 | LL | foo::(42_isize); | --------- ^^^^^^^^ expected `u8`, found `isize` @@ -512,7 +512,7 @@ LL + foo::(42_u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:256:15 + --> $DIR/numeric-suffix.rs:187:15 | LL | foo::(42_i64); | --------- ^^^^^^ expected `u8`, found `i64` @@ -531,7 +531,7 @@ LL + foo::(42_u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:260:15 + --> $DIR/numeric-suffix.rs:191:15 | LL | foo::(42_i32); | --------- ^^^^^^ expected `u8`, found `i32` @@ -550,7 +550,7 @@ LL + foo::(42_u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:264:15 + --> $DIR/numeric-suffix.rs:195:15 | LL | foo::(42_i16); | --------- ^^^^^^ expected `u8`, found `i16` @@ -569,7 +569,7 @@ LL + foo::(42_u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:268:15 + --> $DIR/numeric-suffix.rs:199:15 | LL | foo::(42_i8); | --------- ^^^^^ expected `u8`, found `i8` @@ -588,7 +588,7 @@ LL + foo::(42_u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:272:15 + --> $DIR/numeric-suffix.rs:203:15 | LL | foo::(42.0_f64); | --------- ^^^^^^^^ expected `u8`, found `f64` @@ -607,7 +607,7 @@ LL + foo::(42u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:276:15 + --> $DIR/numeric-suffix.rs:207:15 | LL | foo::(42.0_f32); | --------- ^^^^^^^^ expected `u8`, found `f32` @@ -626,7 +626,7 @@ LL + foo::(42u8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:281:15 + --> $DIR/numeric-suffix.rs:212:15 | LL | foo::(42_usize); | --------- ^^^^^^^^ expected `i8`, found `usize` @@ -645,7 +645,7 @@ LL + foo::(42_i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:285:15 + --> $DIR/numeric-suffix.rs:216:15 | LL | foo::(42_u64); | --------- ^^^^^^ expected `i8`, found `u64` @@ -664,7 +664,7 @@ LL + foo::(42_i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:289:15 + --> $DIR/numeric-suffix.rs:220:15 | LL | foo::(42_u32); | --------- ^^^^^^ expected `i8`, found `u32` @@ -683,7 +683,7 @@ LL + foo::(42_i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:293:15 + --> $DIR/numeric-suffix.rs:224:15 | LL | foo::(42_u16); | --------- ^^^^^^ expected `i8`, found `u16` @@ -702,7 +702,7 @@ LL + foo::(42_i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:297:15 + --> $DIR/numeric-suffix.rs:228:15 | LL | foo::(42_u8); | --------- ^^^^^ expected `i8`, found `u8` @@ -721,7 +721,7 @@ LL + foo::(42_i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:301:15 + --> $DIR/numeric-suffix.rs:232:15 | LL | foo::(42_isize); | --------- ^^^^^^^^ expected `i8`, found `isize` @@ -740,7 +740,7 @@ LL + foo::(42_i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:305:15 + --> $DIR/numeric-suffix.rs:236:15 | LL | foo::(42_i64); | --------- ^^^^^^ expected `i8`, found `i64` @@ -759,7 +759,7 @@ LL + foo::(42_i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:309:15 + --> $DIR/numeric-suffix.rs:240:15 | LL | foo::(42_i32); | --------- ^^^^^^ expected `i8`, found `i32` @@ -778,7 +778,7 @@ LL + foo::(42_i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:313:15 + --> $DIR/numeric-suffix.rs:244:15 | LL | foo::(42_i16); | --------- ^^^^^^ expected `i8`, found `i16` @@ -797,7 +797,7 @@ LL + foo::(42_i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:318:15 + --> $DIR/numeric-suffix.rs:249:15 | LL | foo::(42.0_f64); | --------- ^^^^^^^^ expected `i8`, found `f64` @@ -816,7 +816,7 @@ LL + foo::(42i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:322:15 + --> $DIR/numeric-suffix.rs:253:15 | LL | foo::(42.0_f32); | --------- ^^^^^^^^ expected `i8`, found `f32` @@ -835,7 +835,7 @@ LL + foo::(42i8); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:327:16 + --> $DIR/numeric-suffix.rs:258:16 | LL | foo::(42_usize); | ---------- ^^^^^^^^ expected `f64`, found `usize` @@ -854,7 +854,7 @@ LL + foo::(42_f64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:331:16 + --> $DIR/numeric-suffix.rs:262:16 | LL | foo::(42_u64); | ---------- ^^^^^^ expected `f64`, found `u64` @@ -873,7 +873,7 @@ LL + foo::(42_f64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:335:16 + --> $DIR/numeric-suffix.rs:266:16 | LL | foo::(42_u32); | ---------- ^^^^^^ expected `f64`, found `u32` @@ -891,7 +891,7 @@ LL | foo::(42_u32.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:339:16 + --> $DIR/numeric-suffix.rs:270:16 | LL | foo::(42_u16); | ---------- ^^^^^^ expected `f64`, found `u16` @@ -909,7 +909,7 @@ LL | foo::(42_u16.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:343:16 + --> $DIR/numeric-suffix.rs:274:16 | LL | foo::(42_u8); | ---------- ^^^^^ expected `f64`, found `u8` @@ -927,7 +927,7 @@ LL | foo::(42_u8.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:347:16 + --> $DIR/numeric-suffix.rs:278:16 | LL | foo::(42_isize); | ---------- ^^^^^^^^ expected `f64`, found `isize` @@ -946,7 +946,7 @@ LL + foo::(42_f64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:351:16 + --> $DIR/numeric-suffix.rs:282:16 | LL | foo::(42_i64); | ---------- ^^^^^^ expected `f64`, found `i64` @@ -965,7 +965,7 @@ LL + foo::(42_f64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:355:16 + --> $DIR/numeric-suffix.rs:286:16 | LL | foo::(42_i32); | ---------- ^^^^^^ expected `f64`, found `i32` @@ -983,7 +983,7 @@ LL | foo::(42_i32.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:359:16 + --> $DIR/numeric-suffix.rs:290:16 | LL | foo::(42_i16); | ---------- ^^^^^^ expected `f64`, found `i16` @@ -1001,7 +1001,7 @@ LL | foo::(42_i16.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:363:16 + --> $DIR/numeric-suffix.rs:294:16 | LL | foo::(42_i8); | ---------- ^^^^^ expected `f64`, found `i8` @@ -1019,7 +1019,7 @@ LL | foo::(42_i8.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:368:16 + --> $DIR/numeric-suffix.rs:299:16 | LL | foo::(42.0_f32); | ---------- ^^^^^^^^ expected `f64`, found `f32` @@ -1038,7 +1038,7 @@ LL + foo::(42.0_f64); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:373:16 + --> $DIR/numeric-suffix.rs:304:16 | LL | foo::(42_usize); | ---------- ^^^^^^^^ expected `f32`, found `usize` @@ -1057,7 +1057,7 @@ LL + foo::(42_f32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:377:16 + --> $DIR/numeric-suffix.rs:308:16 | LL | foo::(42_u64); | ---------- ^^^^^^ expected `f32`, found `u64` @@ -1076,7 +1076,7 @@ LL + foo::(42_f32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:381:16 + --> $DIR/numeric-suffix.rs:312:16 | LL | foo::(42_u32); | ---------- ^^^^^^ expected `f32`, found `u32` @@ -1095,7 +1095,7 @@ LL + foo::(42_f32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:385:16 + --> $DIR/numeric-suffix.rs:316:16 | LL | foo::(42_u16); | ---------- ^^^^^^ expected `f32`, found `u16` @@ -1113,7 +1113,7 @@ LL | foo::(42_u16.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:389:16 + --> $DIR/numeric-suffix.rs:320:16 | LL | foo::(42_u8); | ---------- ^^^^^ expected `f32`, found `u8` @@ -1131,7 +1131,7 @@ LL | foo::(42_u8.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:393:16 + --> $DIR/numeric-suffix.rs:324:16 | LL | foo::(42_isize); | ---------- ^^^^^^^^ expected `f32`, found `isize` @@ -1150,7 +1150,7 @@ LL + foo::(42_f32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:397:16 + --> $DIR/numeric-suffix.rs:328:16 | LL | foo::(42_i64); | ---------- ^^^^^^ expected `f32`, found `i64` @@ -1169,7 +1169,7 @@ LL + foo::(42_f32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:401:16 + --> $DIR/numeric-suffix.rs:332:16 | LL | foo::(42_i32); | ---------- ^^^^^^ expected `f32`, found `i32` @@ -1188,7 +1188,7 @@ LL + foo::(42_f32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:405:16 + --> $DIR/numeric-suffix.rs:336:16 | LL | foo::(42_i16); | ---------- ^^^^^^ expected `f32`, found `i16` @@ -1206,7 +1206,7 @@ LL | foo::(42_i16.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:409:16 + --> $DIR/numeric-suffix.rs:340:16 | LL | foo::(42_i8); | ---------- ^^^^^ expected `f32`, found `i8` @@ -1224,7 +1224,7 @@ LL | foo::(42_i8.into()); | +++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:413:16 + --> $DIR/numeric-suffix.rs:344:16 | LL | foo::(42.0_f64); | ---------- ^^^^^^^^ expected `f32`, found `f64` @@ -1243,7 +1243,7 @@ LL + foo::(42.0_f32); | error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:419:16 + --> $DIR/numeric-suffix.rs:350:16 | LL | foo::(42_u8 as u16); | ---------- ^^^^^^^^^^^^ expected `u32`, found `u16` @@ -1261,7 +1261,7 @@ LL | foo::((42_u8 as u16).into()); | + ++++++++ error[E0308]: mismatched types - --> $DIR/numeric-suffix.rs:423:16 + --> $DIR/numeric-suffix.rs:354:16 | LL | foo::(-42_i8); | ---------- ^^^^^^ expected `i32`, found `i8` diff --git a/tests/ui/on-unimplemented/bad-annotation.rs b/tests/ui/on-unimplemented/bad-annotation.rs index f2b978657597..25de59781102 100644 --- a/tests/ui/on-unimplemented/bad-annotation.rs +++ b/tests/ui/on-unimplemented/bad-annotation.rs @@ -1,64 +1,109 @@ -// ignore-tidy-linelength - +#![crate_type = "lib"] #![feature(rustc_attrs)] - #![allow(unused)] #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"] -trait Foo -{} +trait Foo {} -#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"] +#[rustc_on_unimplemented = "a collection of type `{Self}` cannot \ + be built from an iterator over elements of type `{A}`"] trait MyFromIterator { /// Builds a container with elements from an external iterator. - fn my_from_iter>(iterator: T) -> Self; + fn my_from_iter>(iterator: T) -> Self; } #[rustc_on_unimplemented] //~^ ERROR malformed `rustc_on_unimplemented` attribute -trait BadAnnotation1 -{} +trait NoContent {} #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"] //~^ ERROR cannot find parameter C on this trait -trait BadAnnotation2 -{} +trait ParameterNotPresent {} #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"] //~^ ERROR positional format arguments are not allowed here -trait BadAnnotation3 -{} +trait NoPositionalArgs {} -#[rustc_on_unimplemented(lorem="")] -//~^ ERROR this attribute must have a valid -trait BadAnnotation4 {} +#[rustc_on_unimplemented(lorem = "")] +//~^ ERROR this attribute must have a value +//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]` +//~^^^ NOTE expected value here +trait EmptyMessage {} #[rustc_on_unimplemented(lorem(ipsum(dolor)))] -//~^ ERROR this attribute must have a valid -trait BadAnnotation5 {} +//~^ ERROR this attribute must have a value +//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]` +//~^^^ NOTE expected value here +trait Invalid {} -#[rustc_on_unimplemented(message="x", message="y")] -//~^ ERROR this attribute must have a valid -trait BadAnnotation6 {} +#[rustc_on_unimplemented(message = "x", message = "y")] +//~^ ERROR this attribute must have a value +//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]` +//~^^^ NOTE expected value here +trait DuplicateMessage {} -#[rustc_on_unimplemented(message="x", on(desugared, message="y"))] -//~^ ERROR this attribute must have a valid -trait BadAnnotation7 {} +#[rustc_on_unimplemented(message = "x", on(desugared, message = "y"))] +//~^ ERROR this attribute must have a value +//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]` +//~^^^ NOTE expected value here +trait OnInWrongPosition {} -#[rustc_on_unimplemented(on(), message="y")] +#[rustc_on_unimplemented(on(), message = "y")] //~^ ERROR empty `on`-clause -trait BadAnnotation8 {} +//~^^ NOTE empty `on`-clause here +trait EmptyOn {} -#[rustc_on_unimplemented(on="x", message="y")] -//~^ ERROR this attribute must have a valid -trait BadAnnotation9 {} +#[rustc_on_unimplemented(on = "x", message = "y")] +//~^ ERROR this attribute must have a value +//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]` +//~^^^ NOTE expected value here +trait ExpectedPredicateInOn {} -#[rustc_on_unimplemented(on(x="y"), message="y")] -trait BadAnnotation10 {} +#[rustc_on_unimplemented(on(x = "y"), message = "y")] +trait OnWithoutDirectives {} -#[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")] -//~^ ERROR this attribute must have a valid -trait BadAnnotation11 {} +#[rustc_on_unimplemented(on(from_desugaring, on(from_desugaring, message = "x")), message = "y")] +//~^ ERROR this attribute must have a value +//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]` +//~^^^ NOTE expected value here +trait NestedOn {} -pub fn main() { -} +#[rustc_on_unimplemented(on("y", message = "y"))] +//~^ ERROR literals inside `on`-clauses are not supported +//~^^ NOTE unexpected literal here +trait UnsupportedLiteral {} + +#[rustc_on_unimplemented(on(42, message = "y"))] +//~^ ERROR literals inside `on`-clauses are not supported +//~^^ NOTE unexpected literal here +trait UnsupportedLiteral2 {} + +#[rustc_on_unimplemented(on(not(a, b), message = "y"))] +//~^ ERROR expected a single predicate in `not(..)` [E0232] +//~^^ NOTE unexpected quantity of predicates here +trait ExpectedOnePattern {} + +#[rustc_on_unimplemented(on(not(), message = "y"))] +//~^ ERROR expected a single predicate in `not(..)` [E0232] +//~^^ NOTE unexpected quantity of predicates here +trait ExpectedOnePattern2 {} + +#[rustc_on_unimplemented(on(thing::What, message = "y"))] +//~^ ERROR expected an identifier inside this `on`-clause +//~^^ NOTE expected an identifier here, not `thing::What` +trait KeyMustBeIdentifier {} + +#[rustc_on_unimplemented(on(thing::What = "value", message = "y"))] +//~^ ERROR expected an identifier inside this `on`-clause +//~^^ NOTE expected an identifier here, not `thing::What` +trait KeyMustBeIdentifier2 {} + +#[rustc_on_unimplemented(on(aaaaaaaaaaaaaa(a, b), message = "y"))] +//~^ ERROR this predicate is invalid +//~^^ NOTE expected one of `any`, `all` or `not` here, not `aaaaaaaaaaaaaa` +trait InvalidPredicate {} + +#[rustc_on_unimplemented(on(something, message = "y"))] +//~^ ERROR invalid flag in `on`-clause +//~^^ NOTE expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `something` +trait InvalidFlag {} diff --git a/tests/ui/on-unimplemented/bad-annotation.stderr b/tests/ui/on-unimplemented/bad-annotation.stderr index afd737dc85e6..35b919c7b785 100644 --- a/tests/ui/on-unimplemented/bad-annotation.stderr +++ b/tests/ui/on-unimplemented/bad-annotation.stderr @@ -1,5 +1,5 @@ error: malformed `rustc_on_unimplemented` attribute input - --> $DIR/bad-annotation.rs:17:1 + --> $DIR/bad-annotation.rs:15:1 | LL | #[rustc_on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,72 +12,120 @@ LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /* | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0230]: cannot find parameter C on this trait - --> $DIR/bad-annotation.rs:22:90 + --> $DIR/bad-annotation.rs:19:90 | LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"] | ^ error[E0231]: positional format arguments are not allowed here - --> $DIR/bad-annotation.rs:27:90 + --> $DIR/bad-annotation.rs:23:90 | LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"] | ^ -error[E0232]: this attribute must have a valid value - --> $DIR/bad-annotation.rs:32:26 +error[E0232]: this attribute must have a value + --> $DIR/bad-annotation.rs:27:26 | -LL | #[rustc_on_unimplemented(lorem="")] - | ^^^^^^^^ expected value here +LL | #[rustc_on_unimplemented(lorem = "")] + | ^^^^^^^^^^ expected value here | - = note: eg `#[rustc_on_unimplemented(message="foo")]` + = note: e.g. `#[rustc_on_unimplemented(message="foo")]` -error[E0232]: this attribute must have a valid value - --> $DIR/bad-annotation.rs:36:26 +error[E0232]: this attribute must have a value + --> $DIR/bad-annotation.rs:33:26 | LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))] | ^^^^^^^^^^^^^^^^^^^ expected value here | - = note: eg `#[rustc_on_unimplemented(message="foo")]` + = note: e.g. `#[rustc_on_unimplemented(message="foo")]` -error[E0232]: this attribute must have a valid value - --> $DIR/bad-annotation.rs:40:39 +error[E0232]: this attribute must have a value + --> $DIR/bad-annotation.rs:39:41 | -LL | #[rustc_on_unimplemented(message="x", message="y")] - | ^^^^^^^^^^^ expected value here +LL | #[rustc_on_unimplemented(message = "x", message = "y")] + | ^^^^^^^^^^^^^ expected value here | - = note: eg `#[rustc_on_unimplemented(message="foo")]` + = note: e.g. `#[rustc_on_unimplemented(message="foo")]` -error[E0232]: this attribute must have a valid value - --> $DIR/bad-annotation.rs:44:39 +error[E0232]: this attribute must have a value + --> $DIR/bad-annotation.rs:45:41 | -LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here +LL | #[rustc_on_unimplemented(message = "x", on(desugared, message = "y"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here | - = note: eg `#[rustc_on_unimplemented(message="foo")]` + = note: e.g. `#[rustc_on_unimplemented(message="foo")]` error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]` - --> $DIR/bad-annotation.rs:48:26 + --> $DIR/bad-annotation.rs:51:26 | -LL | #[rustc_on_unimplemented(on(), message="y")] - | ^^^^ empty on-clause here +LL | #[rustc_on_unimplemented(on(), message = "y")] + | ^^^^ empty `on`-clause here -error[E0232]: this attribute must have a valid value - --> $DIR/bad-annotation.rs:52:26 +error[E0232]: this attribute must have a value + --> $DIR/bad-annotation.rs:56:26 | -LL | #[rustc_on_unimplemented(on="x", message="y")] - | ^^^^^^ expected value here +LL | #[rustc_on_unimplemented(on = "x", message = "y")] + | ^^^^^^^^ expected value here | - = note: eg `#[rustc_on_unimplemented(message="foo")]` + = note: e.g. `#[rustc_on_unimplemented(message="foo")]` -error[E0232]: this attribute must have a valid value - --> $DIR/bad-annotation.rs:59:40 +error[E0232]: this attribute must have a value + --> $DIR/bad-annotation.rs:65:46 | -LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here +LL | #[rustc_on_unimplemented(on(from_desugaring, on(from_desugaring, message = "x")), message = "y")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here | - = note: eg `#[rustc_on_unimplemented(message="foo")]` + = note: e.g. `#[rustc_on_unimplemented(message="foo")]` -error: aborting due to 10 previous errors +error[E0232]: literals inside `on`-clauses are not supported + --> $DIR/bad-annotation.rs:71:29 + | +LL | #[rustc_on_unimplemented(on("y", message = "y"))] + | ^^^ unexpected literal here + +error[E0232]: literals inside `on`-clauses are not supported + --> $DIR/bad-annotation.rs:76:29 + | +LL | #[rustc_on_unimplemented(on(42, message = "y"))] + | ^^ unexpected literal here + +error[E0232]: expected a single predicate in `not(..)` + --> $DIR/bad-annotation.rs:81:33 + | +LL | #[rustc_on_unimplemented(on(not(a, b), message = "y"))] + | ^^^^ unexpected quantity of predicates here + +error[E0232]: expected a single predicate in `not(..)` + --> $DIR/bad-annotation.rs:86:29 + | +LL | #[rustc_on_unimplemented(on(not(), message = "y"))] + | ^^^^^ unexpected quantity of predicates here + +error[E0232]: expected an identifier inside this `on`-clause + --> $DIR/bad-annotation.rs:91:29 + | +LL | #[rustc_on_unimplemented(on(thing::What, message = "y"))] + | ^^^^^^^^^^^ expected an identifier here, not `thing::What` + +error[E0232]: expected an identifier inside this `on`-clause + --> $DIR/bad-annotation.rs:96:29 + | +LL | #[rustc_on_unimplemented(on(thing::What = "value", message = "y"))] + | ^^^^^^^^^^^ expected an identifier here, not `thing::What` + +error[E0232]: this predicate is invalid + --> $DIR/bad-annotation.rs:101:29 + | +LL | #[rustc_on_unimplemented(on(aaaaaaaaaaaaaa(a, b), message = "y"))] + | ^^^^^^^^^^^^^^ expected one of `any`, `all` or `not` here, not `aaaaaaaaaaaaaa` + +error[E0232]: invalid flag in `on`-clause + --> $DIR/bad-annotation.rs:106:29 + | +LL | #[rustc_on_unimplemented(on(something, message = "y"))] + | ^^^^^^^^^ expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `something` + +error: aborting due to 18 previous errors Some errors have detailed explanations: E0230, E0231, E0232. For more information about an error, try `rustc --explain E0230`. diff --git a/tests/ui/panic-runtime/two-panic-runtimes.rs b/tests/ui/panic-runtime/two-panic-runtimes.rs index 80591edd1077..de76578a267f 100644 --- a/tests/ui/panic-runtime/two-panic-runtimes.rs +++ b/tests/ui/panic-runtime/two-panic-runtimes.rs @@ -1,11 +1,19 @@ // ignore-tidy-linelength //@ build-fail -//@ dont-require-annotations: ERROR //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ aux-build:panic-runtime-unwind2.rs //@ aux-build:panic-runtime-lang-items.rs +// NOTE: there can be additional errors regarding trying to mix this crate if the precompiled target +// (such as `wasm32-unknown-unknown` currently unconditionally defaulting to panic=abort) panic +// strategy differs to abort, then involving a potentially-unwinding `panic_runtime_unwind` that +// uses a different panic strategy. These errors are important but not to the test intention, which +// is to check that trying to bring two panic runtimes (`panic_runtime_unwind`) and +// (`panic_runtime_unwind2`) is prohibited. As such, the additional errors are not checked in this +// test. +//@ dont-require-annotations: ERROR + #![no_std] #![no_main] @@ -16,7 +24,3 @@ extern crate panic_runtime_lang_items; fn main() {} //~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 -// FIXME: These errors are target-dependent, could be served by some "optional error" annotation -// instead of `dont-require-annotations`. -//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind2` is not compiled with this crate's panic strategy `abort` -//FIXME~? ERROR the crate `panic_runtime_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/want-abort-got-unwind.rs b/tests/ui/panic-runtime/want-abort-got-unwind.rs index 42cdf8bc6626..7a6bd011d9e4 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind.rs @@ -1,16 +1,18 @@ // ignore-tidy-linelength //@ build-fail -//@ dont-require-annotations: ERROR //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ compile-flags:-C panic=abort +// NOTE: depending on the target's default panic strategy, there can be additional errors that +// complain about linking two panic runtimes (e.g. precompiled `panic_unwind` if target default +// panic strategy is unwind, in addition to `panic_runtime_unwind`). These additional errors will +// not be observed on targets whose default panic strategy is abort, where `panic_abort` is linked +// in instead. +//@ dont-require-annotations: ERROR + extern crate panic_runtime_unwind; fn main() {} //~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` -// FIXME: These errors are target-dependent, could be served by some "optional error" annotation -// instead of `dont-require-annotations`. -//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind -//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/want-abort-got-unwind2.rs b/tests/ui/panic-runtime/want-abort-got-unwind2.rs index ddf12cd2a9a5..da239a675e5b 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind2.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind2.rs @@ -1,17 +1,23 @@ // ignore-tidy-linelength //@ build-fail -//@ dont-require-annotations: ERROR //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ aux-build:wants-panic-runtime-unwind.rs //@ compile-flags:-C panic=abort +// Like `want-abort-got-unwind.rs`, this version checks that if the root binary wants abort panic +// runtime, that the compiler rejects a setup where a dependency crate in the dependency DAG +// transitively provides an unwind panic runtime (which also is built with `-Cpanic=unwind`, making +// that potentially-unwinding). + +// NOTE: similar to `want-abort-got-unwind.rs`, there can be additional errors if the target default +// panic strategy is unwind, because then the precompiled `panic_unwind` would also be linked in, +// duplicating `panic_runtime_unwind` (transitively). But those additional errors are not important +// to test intention. +//@ dont-require-annotations: ERROR + extern crate wants_panic_runtime_unwind; fn main() {} //~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` -// FIXME: These errors are target-dependent, could be served by some "optional error" annotation -// instead of `dont-require-annotations`. -//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind -//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panics/default-backtrace-ice.rs b/tests/ui/panics/default-backtrace-ice.rs index cf8b0cea8496..e919e1a4ea62 100644 --- a/tests/ui/panics/default-backtrace-ice.rs +++ b/tests/ui/panics/default-backtrace-ice.rs @@ -1,8 +1,5 @@ //@ unset-rustc-env:RUST_BACKTRACE //@ compile-flags:-Z treat-err-as-bug=1 -//@ error-pattern:stack backtrace: -// Verify this is a full backtrace, not a short backtrace. -//@ error-pattern:__rust_begin_short_backtrace //@ failure-status:101 //@ ignore-msvc //@ normalize-stderr: "note: .*" -> "" @@ -21,3 +18,7 @@ // aren't reliable. fn main() { missing_ident; } //~ ERROR cannot find value `missing_ident` in this scope + +//~? RAW stack backtrace: +// Verify this is a full backtrace, not a short backtrace. +//~? RAW __rust_begin_short_backtrace diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr index 2147b0971b5f..a7d99e325d9b 100644 --- a/tests/ui/panics/default-backtrace-ice.stderr +++ b/tests/ui/panics/default-backtrace-ice.stderr @@ -1,5 +1,5 @@ error: internal compiler error[E0425]: cannot find value `missing_ident` in this scope - --> $DIR/default-backtrace-ice.rs:23:13 + --> $DIR/default-backtrace-ice.rs:20:13 | LL | fn main() { missing_ident; } | ^^^^^^^^^^^^^ not found in this scope diff --git a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs index 6bfe16ae37d2..db25ce440893 100644 --- a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs +++ b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs @@ -2,8 +2,10 @@ fn main() { unsafe { - dealloc(ptr2, Layout::(x: !)(1, 1)); //~ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` - //~^ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` - //~| NOTE while parsing this parenthesized list of type arguments starting here + dealloc(ptr2, Layout::(x: !)(1, 1)); //~ ERROR `Trait(...)` syntax does not support named parameters + //~^ ERROR cannot find function `dealloc` in this scope [E0425] + //~| ERROR cannot find value `ptr2` in this scope [E0425] + //~| ERROR the `!` type is experimental [E0658] + //~| ERROR cannot find function, tuple struct or tuple variant `Layout` in this scope [E0425] } } diff --git a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr index c12bf7f9e3f0..a083883af219 100644 --- a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr +++ b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr @@ -1,16 +1,43 @@ -error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` - --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:33 +error: `Trait(...)` syntax does not support named parameters + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:32 | LL | dealloc(ptr2, Layout::(x: !)(1, 1)); - | --- ^ expected one of 7 possible tokens - | | - | while parsing this parenthesized list of type arguments starting here + | ^ help: remove the parameter name -error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` - --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:43 +error[E0425]: cannot find function `dealloc` in this scope + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:9 | LL | dealloc(ptr2, Layout::(x: !)(1, 1)); - | ^ expected one of `.`, `;`, `?`, `}`, or an operator + | ^^^^^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::alloc::dealloc; + | -error: aborting due to 2 previous errors +error[E0425]: cannot find value `ptr2` in this scope + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:17 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | ^^^^ not found in this scope +error[E0658]: the `!` type is experimental + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:35 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0425]: cannot find function, tuple struct or tuple variant `Layout` in this scope + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:23 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | ^^^^^^ not found in this scope + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0425, E0658. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/fn-arg-doc-comment.rs b/tests/ui/parser/fn-arg-doc-comment.rs index 21d753ad0372..57a4d15fa256 100644 --- a/tests/ui/parser/fn-arg-doc-comment.rs +++ b/tests/ui/parser/fn-arg-doc-comment.rs @@ -2,12 +2,10 @@ pub fn f( //~ NOTE function defined here /// Comment //~^ ERROR documentation comments cannot be applied to function parameters //~| NOTE doc comments are not allowed here - //~| NOTE id: u8, /// Other //~^ ERROR documentation comments cannot be applied to function parameters //~| NOTE doc comments are not allowed here - //~| NOTE a: u8, ) {} @@ -15,7 +13,6 @@ fn bar(id: #[allow(dead_code)] i32) {} //~^ ERROR attributes cannot be applied to a function parameter's type //~| NOTE attributes are not allowed here //~| NOTE function defined here -//~| NOTE fn main() { // verify that the parser recovered and properly typechecked the args diff --git a/tests/ui/parser/fn-arg-doc-comment.stderr b/tests/ui/parser/fn-arg-doc-comment.stderr index 1891c7089034..84c8bb3c2d09 100644 --- a/tests/ui/parser/fn-arg-doc-comment.stderr +++ b/tests/ui/parser/fn-arg-doc-comment.stderr @@ -1,5 +1,5 @@ error: attributes cannot be applied to a function parameter's type - --> $DIR/fn-arg-doc-comment.rs:14:12 + --> $DIR/fn-arg-doc-comment.rs:12:12 | LL | fn bar(id: #[allow(dead_code)] i32) {} | ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here @@ -11,13 +11,13 @@ LL | /// Comment | ^^^^^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/fn-arg-doc-comment.rs:7:5 + --> $DIR/fn-arg-doc-comment.rs:6:5 | LL | /// Other | ^^^^^^^^^ doc comments are not allowed here error[E0308]: arguments to this function are incorrect - --> $DIR/fn-arg-doc-comment.rs:22:5 + --> $DIR/fn-arg-doc-comment.rs:19:5 | LL | f("", ""); | ^ -- -- expected `u8`, found `&str` @@ -39,7 +39,7 @@ LL | | a: u8, | |_________- error[E0308]: mismatched types - --> $DIR/fn-arg-doc-comment.rs:26:9 + --> $DIR/fn-arg-doc-comment.rs:23:9 | LL | bar(""); | --- ^^ expected `i32`, found `&str` @@ -47,7 +47,7 @@ LL | bar(""); | arguments to this function are incorrect | note: function defined here - --> $DIR/fn-arg-doc-comment.rs:14:4 + --> $DIR/fn-arg-doc-comment.rs:12:4 | LL | fn bar(id: #[allow(dead_code)] i32) {} | ^^^ --------------------------- diff --git a/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs b/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs new file mode 100644 index 000000000000..7644df8be49a --- /dev/null +++ b/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs @@ -0,0 +1,13 @@ +fn main() { + println!("{foo:_1.4}", foo = 3.14); //~ ERROR invalid format string: expected `}`, found `.` + println!("{0:_1.4}", 1.11); //~ ERROR invalid format string: expected `}`, found `.` + println!("{:_1.4}", 3.14); //~ ERROR invalid format string: expected `}`, found `.` + + println!("{foo:_1.4", foo = 3.14); //~ ERROR invalid format string: expected `}`, found `.` + println!("{0:_1.4", 1.11); //~ ERROR invalid format string: expected `}`, found `.` + println!("{:_1.4", 3.14); //~ ERROR invalid format string: expected `}`, found `.` + + println!("{ 0", 1.11); //~ ERROR invalid format string: expected `}`, found `0` + println!("{foo:1.4_1.4}", foo = 3.14); //~ ERROR invalid format string: expected `}`, found `.` + println!("{0:1.4_1.4}", 3.14); //~ ERROR invalid format string: expected `}`, found `.` +} diff --git a/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr b/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr new file mode 100644 index 000000000000..202aa450cab7 --- /dev/null +++ b/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr @@ -0,0 +1,92 @@ +error: invalid format string: expected `}`, found `.` + --> $DIR/invalid-parse-format-issue-139104.rs:2:22 + | +LL | println!("{foo:_1.4}", foo = 3.14); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `}`, found `.` + --> $DIR/invalid-parse-format-issue-139104.rs:3:20 + | +LL | println!("{0:_1.4}", 1.11); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `}`, found `.` + --> $DIR/invalid-parse-format-issue-139104.rs:4:19 + | +LL | println!("{:_1.4}", 3.14); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `}`, found `.` + --> $DIR/invalid-parse-format-issue-139104.rs:6:22 + | +LL | println!("{foo:_1.4", foo = 3.14); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `}`, found `.` + --> $DIR/invalid-parse-format-issue-139104.rs:7:20 + | +LL | println!("{0:_1.4", 1.11); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `}`, found `.` + --> $DIR/invalid-parse-format-issue-139104.rs:8:19 + | +LL | println!("{:_1.4", 3.14); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `}`, found `0` + --> $DIR/invalid-parse-format-issue-139104.rs:10:18 + | +LL | println!("{ 0", 1.11); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `}`, found `.` + --> $DIR/invalid-parse-format-issue-139104.rs:11:25 + | +LL | println!("{foo:1.4_1.4}", foo = 3.14); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `}`, found `.` + --> $DIR/invalid-parse-format-issue-139104.rs:12:23 + | +LL | println!("{0:1.4_1.4}", 3.14); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs index 1c28c0632fa8..60dd88e65400 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs @@ -2,7 +2,4 @@ struct Apple((Apple, Option(Banana ? Citron))); //~^ ERROR invalid `?` in type -//~| ERROR expected one of `)` or `,`, found `Citron` -//~| ERROR cannot find type `Citron` in this scope [E0412] -//~| ERROR parenthesized type parameters may only be used with a `Fn` trait [E0214] -//~| ERROR `Apple` has infinite size +//~| ERROR unexpected token: `Citron` diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr index 97a73b4fd5ed..c92535c3906b 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr @@ -10,44 +10,11 @@ LL - struct Apple((Apple, Option(Banana ? Citron))); LL + struct Apple((Apple, Option(Option Citron))); | -error: expected one of `)` or `,`, found `Citron` +error: unexpected token: `Citron` --> $DIR/issue-103748-ICE-wrong-braces.rs:3:38 | LL | struct Apple((Apple, Option(Banana ? Citron))); - | -^^^^^^ expected one of `)` or `,` - | | - | help: missing `,` + | ^^^^^^ unexpected token after this -error[E0412]: cannot find type `Citron` in this scope - --> $DIR/issue-103748-ICE-wrong-braces.rs:3:38 - | -LL | struct Apple((Apple, Option(Banana ? Citron))); - | ^^^^^^ not found in this scope +error: aborting due to 2 previous errors -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-103748-ICE-wrong-braces.rs:3:22 - | -LL | struct Apple((Apple, Option(Banana ? Citron))); - | ^^^^^^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses - | -help: use angle brackets instead - | -LL - struct Apple((Apple, Option(Banana ? Citron))); -LL + struct Apple((Apple, Option)); - | - -error[E0072]: recursive type `Apple` has infinite size - --> $DIR/issue-103748-ICE-wrong-braces.rs:3:1 - | -LL | struct Apple((Apple, Option(Banana ? Citron))); - | ^^^^^^^^^^^^ ----- recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | struct Apple((Box, Option(Banana ? Citron))); - | ++++ + - -error: aborting due to 5 previous errors - -Some errors have detailed explanations: E0072, E0214, E0412. -For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs index c137e1363359..e6235b1e8923 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs @@ -10,6 +10,5 @@ const async const fn test() {} //~| ERROR functions cannot be both `const` and `async` //~| NOTE `const` because of this //~| NOTE `async` because of this -//~| NOTE fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs index 49a49d337c47..40f993eafbb1 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs @@ -15,6 +15,5 @@ async unsafe const fn test() {} //~| ERROR functions cannot be both `const` and `async` //~| NOTE `const` because of this //~| NOTE `async` because of this -//~| NOTE fn main() {} diff --git a/tests/ui/auxiliary/issue-24106.rs b/tests/ui/pattern/auxiliary/cross-crate-enum-pattern.rs similarity index 100% rename from tests/ui/auxiliary/issue-24106.rs rename to tests/ui/pattern/auxiliary/cross-crate-enum-pattern.rs diff --git a/tests/ui/pattern/cross-crate-enum-pattern.rs b/tests/ui/pattern/cross-crate-enum-pattern.rs new file mode 100644 index 000000000000..254caf99277c --- /dev/null +++ b/tests/ui/pattern/cross-crate-enum-pattern.rs @@ -0,0 +1,13 @@ +//! Test that we can match on enum constants across crates. +//! +//! Regression test for . + + +//@ run-pass +//@ aux-build:cross-crate-enum-pattern.rs + +extern crate cross_crate_enum_pattern; + +fn main() { + cross_crate_enum_pattern::go::<()>(); +} diff --git a/tests/ui/pattern/deref-patterns/bindings.rs b/tests/ui/pattern/deref-patterns/bindings.rs index ac48e3ffefcc..92c01d737bac 100644 --- a/tests/ui/pattern/deref-patterns/bindings.rs +++ b/tests/ui/pattern/deref-patterns/bindings.rs @@ -13,7 +13,6 @@ fn simple_vec(vec: Vec) -> u32 { deref!([x]) => x, deref!([1, x]) => x + 200, deref!(ref slice) => slice.iter().sum(), - _ => 2000, } } @@ -25,7 +24,6 @@ fn simple_vec(vec: Vec) -> u32 { [x] => x, [1, x] => x + 200, deref!(ref slice) => slice.iter().sum(), - _ => 2000, } } diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs index 64acc4748afd..fdcc6cb46111 100644 --- a/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs +++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs @@ -33,4 +33,23 @@ fn main() { if let b"test" = *b"this array is too long" {} //~^ ERROR mismatched types //~| NOTE expected an array with a size of 22, found one with a size of 4 + + // Test matching on `&mut T`: we peel the `&mut` before applying the usual special cases. + // No special cases apply to `()`, so the "found" type is the type of the literal. + if let b"test" = &mut () {} + //~^ ERROR mismatched types + //~| NOTE expected `()`, found `&[u8; 4]` + + // If the pointee is an array or slice, the usual special cases will apply to the "found" type: + if let b"test" = &mut [] as &mut [i8] {} + //~^ ERROR mismatched type + //~| NOTE expected `[i8]`, found `[u8]` + + if let b"test" = &mut [()] {} + //~^ ERROR mismatched types + //~| NOTE expected `[(); 1]`, found `[u8; 4]` + + if let b"test" = &mut *b"this array is too long" {} + //~^ ERROR mismatched type + //~| NOTE expected an array with a size of 22, found one with a size of 4 } diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr index 0317b7209e16..046682004be7 100644 --- a/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr +++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr @@ -47,6 +47,44 @@ LL | if let b"test" = *b"this array is too long" {} | | | expected an array with a size of 22, found one with a size of 4 -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/byte-string-type-errors.rs:39:12 + | +LL | if let b"test" = &mut () {} + | ^^^^^^^ ------- this expression has type `&mut ()` + | | + | expected `()`, found `&[u8; 4]` + +error[E0308]: mismatched types + --> $DIR/byte-string-type-errors.rs:44:12 + | +LL | if let b"test" = &mut [] as &mut [i8] {} + | ^^^^^^^ -------------------- this expression has type `&mut [i8]` + | | + | expected `[i8]`, found `[u8]` + | + = note: expected slice `[i8]` + found slice `[u8]` + +error[E0308]: mismatched types + --> $DIR/byte-string-type-errors.rs:48:12 + | +LL | if let b"test" = &mut [()] {} + | ^^^^^^^ --------- this expression has type `&mut [(); 1]` + | | + | expected `[(); 1]`, found `[u8; 4]` + | + = note: expected array `[(); 1]` + found array `[u8; 4]` + +error[E0308]: mismatched types + --> $DIR/byte-string-type-errors.rs:52:12 + | +LL | if let b"test" = &mut *b"this array is too long" {} + | ^^^^^^^ ------------------------------- this expression has type `&mut [u8; 22]` + | | + | expected an array with a size of 22, found one with a size of 4 + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/deref-patterns/closure_capture.rs b/tests/ui/pattern/deref-patterns/closure_capture.rs index cf78eeda1d5a..497ec622b0cf 100644 --- a/tests/ui/pattern/deref-patterns/closure_capture.rs +++ b/tests/ui/pattern/deref-patterns/closure_capture.rs @@ -9,7 +9,7 @@ struct NoCopy; fn main() { let b = Rc::new("aaa".to_string()); let f = || { - let deref!(ref s) = b else { unreachable!() }; + let deref!(ref s) = b; assert_eq!(s.len(), 3); }; assert_eq!(b.len(), 3); @@ -26,7 +26,7 @@ fn main() { let mut b = "aaa".to_string(); let mut f = || { - let deref!(ref mut s) = b else { unreachable!() }; + let deref!(ref mut s) = b; s.make_ascii_uppercase(); }; f(); @@ -53,7 +53,7 @@ fn main() { let b = Box::new(NoCopy); let f = || { // this should move out of the box rather than borrow. - let deref!(x) = b else { unreachable!() }; + let deref!(x) = b; drop::(x); }; f(); @@ -61,7 +61,7 @@ fn main() { let b = Box::new((NoCopy,)); let f = || { // this should move out of the box rather than borrow. - let (x,) = b else { unreachable!() }; + let (x,) = b; drop::(x); }; f(); diff --git a/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.rs b/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.rs new file mode 100644 index 000000000000..3a2531f4b95e --- /dev/null +++ b/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.rs @@ -0,0 +1,54 @@ +//@ revisions: stable deref_patterns +//@[deref_patterns] check-pass +//! `deref_patterns` allows string and byte string literal patterns to implicitly peel references +//! and smart pointers from the scrutinee before matching. Since strings and byte strings themselves +//! have reference types, we need to make sure we don't peel too much. By leaving the type of the +//! match scrutinee partially uninferred, these tests make sure we only peel as much as needed in +//! order to match. In particular, when peeling isn't needed, the results should be the same was +//! we'd get without `deref_patterns` enabled. + +#![cfg_attr(deref_patterns, feature(deref_patterns))] +#![cfg_attr(deref_patterns, expect(incomplete_features))] + +fn uninferred() -> T { unimplemented!() } + +// Assert type equality without allowing coercions. +trait Is {} +impl Is for T {} +fn has_type(_: impl Is) {} + +fn main() { + // We don't need to peel anything to unify the type of `x` with `&str`, so `x: &str`. + let x = uninferred(); + if let "..." = x {} + has_type::<&str>(x); + + // We don't need to peel anything to unify the type of `&x` with `&[u8; 3]`, so `x: [u8; 3]`. + let x = uninferred(); + if let b"..." = &x {} + has_type::<[u8; 3]>(x); + + // Peeling a single `&` lets us unify the type of `&x` with `&[u8; 3]`, giving `x: [u8; 3]`. + let x = uninferred(); + if let b"..." = &&x {} + //[stable]~^ ERROR: mismatched types + has_type::<[u8; 3]>(x); + + // We have to peel both the `&` and the box before unifying the type of `x` with `&str`. + let x = uninferred(); + if let "..." = &Box::new(x) {} + //[stable]~^ ERROR mismatched types + has_type::<&str>(x); + + // After peeling the box, we can unify the type of `&x` with `&[u8; 3]`, giving `x: [u8; 3]`. + let x = uninferred(); + if let b"..." = Box::new(&x) {} + //[stable]~^ ERROR mismatched types + has_type::<[u8; 3]>(x); + + // `&` and `&mut` aren't interchangeable: `&mut`s need to be peeled before unifying, like boxes: + let mut x = uninferred(); + if let "..." = &mut x {} + //[stable]~^ ERROR mismatched types + has_type::<&str>(x); +} diff --git a/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.stable.stderr b/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.stable.stderr new file mode 100644 index 000000000000..61079718c5d5 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.stable.stderr @@ -0,0 +1,55 @@ +error[E0308]: mismatched types + --> $DIR/const-pats-do-not-mislead-inference.rs:33:12 + | +LL | if let b"..." = &&x {} + | ^^^^^^ --- this expression has type `&&_` + | | + | expected `&&_`, found `&[u8; 3]` + | + = note: expected reference `&&_` + found reference `&'static [u8; 3]` + +error[E0308]: mismatched types + --> $DIR/const-pats-do-not-mislead-inference.rs:39:12 + | +LL | if let "..." = &Box::new(x) {} + | ^^^^^ ------------ this expression has type `&Box<_>` + | | + | expected `&Box<_>`, found `&str` + | + = note: expected reference `&Box<_>` + found reference `&'static str` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | if let "..." = &*Box::new(x) {} + | + + +error[E0308]: mismatched types + --> $DIR/const-pats-do-not-mislead-inference.rs:45:12 + | +LL | if let b"..." = Box::new(&x) {} + | ^^^^^^ ------------ this expression has type `Box<&_>` + | | + | expected `Box<&_>`, found `&[u8; 3]` + | + = note: expected struct `Box<&_>` + found reference `&'static [u8; 3]` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | if let b"..." = *Box::new(&x) {} + | + + +error[E0308]: mismatched types + --> $DIR/const-pats-do-not-mislead-inference.rs:51:12 + | +LL | if let "..." = &mut x {} + | ^^^^^ ------ this expression has type `&mut _` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut _` + found reference `&'static str` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/deref-patterns/deref-box.rs b/tests/ui/pattern/deref-patterns/deref-box.rs index 2d0a8d01972e..39b23dcab51e 100644 --- a/tests/ui/pattern/deref-patterns/deref-box.rs +++ b/tests/ui/pattern/deref-patterns/deref-box.rs @@ -6,18 +6,18 @@ #![expect(incomplete_features)] fn unbox_1(b: Box) -> T { - let deref!(x) = b else { unreachable!() }; + let deref!(x) = b; x } fn unbox_2(b: Box<(T,)>) -> T { - let (x,) = b else { unreachable!() }; + let (x,) = b; x } fn unbox_separately(b: Box<(T, T)>) -> (T, T) { - let (x, _) = b else { unreachable!() }; - let (_, y) = b else { unreachable!() }; + let (x, _) = b; + let (_, y) = b; (x, y) } @@ -31,7 +31,7 @@ fn main() { // test that borrowing from a box also works let mut b = "hi".to_owned().into_boxed_str(); - let deref!(ref mut s) = b else { unreachable!() }; + let deref!(ref mut s) = b; s.make_ascii_uppercase(); assert_eq!(&*b, "HI"); } diff --git a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs index 04c83d4c33fd..24770261edc5 100644 --- a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs +++ b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs @@ -11,7 +11,6 @@ fn main() { match cow { [..] => {} - _ => unreachable!(), } match cow { @@ -22,14 +21,12 @@ fn main() { match Rc::new(&cow) { Cow::Borrowed { 0: _ } => {} Cow::Owned { 0: _ } => unreachable!(), - _ => unreachable!(), } let cow_of_cow: Cow<'_, Cow<'static, [u8]>> = Cow::Owned(cow); match cow_of_cow { [..] => {} - _ => unreachable!(), } // This matches on the outer `Cow` (the owned one). @@ -41,6 +38,5 @@ fn main() { match Rc::new(&cow_of_cow) { Cow::Borrowed { 0: _ } => unreachable!(), Cow::Owned { 0: _ } => {} - _ => unreachable!(), } } diff --git a/tests/ui/pattern/deref-patterns/needs-gate.rs b/tests/ui/pattern/deref-patterns/needs-gate.rs index 7944744ee839..953051f7b04b 100644 --- a/tests/ui/pattern/deref-patterns/needs-gate.rs +++ b/tests/ui/pattern/deref-patterns/needs-gate.rs @@ -29,4 +29,30 @@ fn main() { //~^ ERROR: mismatched types _ => {} } + + // `deref_patterns` allows string and byte string patterns to implicitly peel references. + match &"str" { + "str" => {} + //~^ ERROR: mismatched types + _ => {} + } + match &b"str" { + b"str" => {} + //~^ ERROR: mismatched types + _ => {} + } + match "str".to_owned() { + "str" => {} + //~^ ERROR: mismatched types + _ => {} + } + + // `deref_patterns` allows string and byte string patterns to match on mutable references. + // See also `tests/ui/pattern/byte-string-mutability-mismatch.rs`. + if let "str" = &mut *"str".to_string() {} + //~^ ERROR mismatched types + if let b"str" = &mut b"str".clone() {} + //~^ ERROR mismatched types + if let b"str" = &mut b"str".clone()[..] {} + //~^ ERROR mismatched types } diff --git a/tests/ui/pattern/deref-patterns/needs-gate.stderr b/tests/ui/pattern/deref-patterns/needs-gate.stderr index e886ca980558..3d938a7e23fc 100644 --- a/tests/ui/pattern/deref-patterns/needs-gate.stderr +++ b/tests/ui/pattern/deref-patterns/needs-gate.stderr @@ -47,7 +47,70 @@ LL | match *(b"test" as &[u8]) { LL | b"test" => {} | ^^^^^^^ expected `[u8]`, found `&[u8; 4]` -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/needs-gate.rs:35:9 + | +LL | match &"str" { + | ------ this expression has type `&&str` +LL | "str" => {} + | ^^^^^ expected `&&str`, found `&str` + | + = note: expected reference `&&_` + found reference `&'static _` + +error[E0308]: mismatched types + --> $DIR/needs-gate.rs:40:9 + | +LL | match &b"str" { + | ------- this expression has type `&&[u8; 3]` +LL | b"str" => {} + | ^^^^^^ expected `&&[u8; 3]`, found `&[u8; 3]` + | + = note: expected reference `&&_` + found reference `&'static _` + +error[E0308]: mismatched types + --> $DIR/needs-gate.rs:45:9 + | +LL | match "str".to_owned() { + | ---------------- this expression has type `String` +LL | "str" => {} + | ^^^^^ expected `String`, found `&str` + +error[E0308]: mismatched types + --> $DIR/needs-gate.rs:52:12 + | +LL | if let "str" = &mut *"str".to_string() {} + | ^^^^^ ----------------------- this expression has type `&mut str` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut _` + found reference `&'static _` + +error[E0308]: mismatched types + --> $DIR/needs-gate.rs:54:12 + | +LL | if let b"str" = &mut b"str".clone() {} + | ^^^^^^ ------------------- this expression has type `&mut [u8; 3]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut _` + found reference `&'static _` + +error[E0308]: mismatched types + --> $DIR/needs-gate.rs:56:12 + | +LL | if let b"str" = &mut b"str".clone()[..] {} + | ^^^^^^ ----------------------- this expression has type `&mut [u8]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut _` + found reference `&'static _` + +error: aborting due to 11 previous errors Some errors have detailed explanations: E0308, E0658. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/deref-patterns/strings.rs b/tests/ui/pattern/deref-patterns/strings.rs index 536e943b3f67..fac15a9aee3d 100644 --- a/tests/ui/pattern/deref-patterns/strings.rs +++ b/tests/ui/pattern/deref-patterns/strings.rs @@ -14,10 +14,26 @@ fn main() { }; assert_eq!(test_actual, test_expect); - // Test string literals in explicit `deref!(_)` patterns. + // Test matching on `&mut str`. + let test_actual = match &mut *test_in.to_string() { + "zero" => 0, + "one" => 1, + _ => 2, + }; + assert_eq!(test_actual, test_expect); + + // Test string literals in deref patterns. let test_actual = match test_in.to_string() { deref!("zero") => 0, - deref!("one") => 1, + "one" => 1, + _ => 2, + }; + assert_eq!(test_actual, test_expect); + + // Test peeling references in addition to smart pointers. + let test_actual = match &test_in.to_string() { + deref!("zero") => 0, + "one" => 1, _ => 2, }; assert_eq!(test_actual, test_expect); @@ -47,18 +63,34 @@ fn main() { }; assert_eq!(test_actual, test_expect); - // Test byte string literals used as arrays in explicit `deref!(_)` patterns. - let test_actual = match Box::new(*test_in) { - deref!(b"0") => 0, - deref!(b"1") => 1, + // Test matching on `&mut [u8; N]`. + let test_actual = match &mut test_in.clone() { + b"0" => 0, + b"1" => 1, _ => 2, }; assert_eq!(test_actual, test_expect); - // Test byte string literals used as slices in explicit `deref!(_)` patterns. + // Test matching on `&mut [u8]`. + let test_actual = match &mut test_in.clone()[..] { + b"0" => 0, + b"1" => 1, + _ => 2, + }; + assert_eq!(test_actual, test_expect); + + // Test byte string literals used as arrays in deref patterns. + let test_actual = match Box::new(*test_in) { + deref!(b"0") => 0, + b"1" => 1, + _ => 2, + }; + assert_eq!(test_actual, test_expect); + + // Test byte string literals used as slices in deref patterns. let test_actual = match test_in.to_vec() { deref!(b"0") => 0, - deref!(b"1") => 1, + b"1" => 1, _ => 2, }; assert_eq!(test_actual, test_expect); diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.rs b/tests/ui/pattern/deref-patterns/typeck_fail.rs index 52d84f7a34de..6ae87bb7bc36 100644 --- a/tests/ui/pattern/deref-patterns/typeck_fail.rs +++ b/tests/ui/pattern/deref-patterns/typeck_fail.rs @@ -2,19 +2,6 @@ #![allow(incomplete_features)] fn main() { - // FIXME(deref_patterns): fails to typecheck because string literal patterns don't peel - // references from the scrutinee. - match "foo".to_string() { - "foo" => {} - //~^ ERROR: mismatched types - _ => {} - } - match &"foo".to_string() { - "foo" => {} - //~^ ERROR: mismatched types - _ => {} - } - // Make sure we don't try implicitly dereferncing any ADT. match Some(0) { Ok(0) => {} diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.stderr b/tests/ui/pattern/deref-patterns/typeck_fail.stderr index e87528c1c51a..fc29caac5630 100644 --- a/tests/ui/pattern/deref-patterns/typeck_fail.stderr +++ b/tests/ui/pattern/deref-patterns/typeck_fail.stderr @@ -1,24 +1,5 @@ error[E0308]: mismatched types - --> $DIR/typeck_fail.rs:8:9 - | -LL | match "foo".to_string() { - | ----------------- this expression has type `String` -LL | "foo" => {} - | ^^^^^ expected `String`, found `&str` - -error[E0308]: mismatched types - --> $DIR/typeck_fail.rs:13:9 - | -LL | match &"foo".to_string() { - | ------------------ this expression has type `&String` -LL | "foo" => {} - | ^^^^^ expected `&String`, found `&str` - | - = note: expected reference `&String` - found reference `&'static str` - -error[E0308]: mismatched types - --> $DIR/typeck_fail.rs:20:9 + --> $DIR/typeck_fail.rs:7:9 | LL | match Some(0) { | ------- this expression has type `Option<{integer}>` @@ -28,6 +9,6 @@ LL | Ok(0) => {} = note: expected enum `Option<{integer}>` found enum `Result<_, _>` -error: aborting due to 3 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs b/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs new file mode 100644 index 000000000000..03419030e72f --- /dev/null +++ b/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs @@ -0,0 +1,47 @@ +//! Test that the place behind a deref pattern is treated as maybe-invalid, and thus empty arms +//! cannot be omitted. This is handled the same as for refs and union fields, so this leaves the +//! bulk of the testing to `tests/ui/pattern/usefulness/empty-types.rs`. +// FIXME(deref_patterns): On stabilization, cases for deref patterns could be worked into that file +// to keep the tests for empty types in one place and test more thoroughly. +#![feature(deref_patterns)] +#![expect(incomplete_features)] +#![deny(unreachable_patterns)] + +enum Void {} + +fn main() { + // Sanity check: matching on an empty type without pointer indirection lets us omit arms. + let opt_void: Option = None; + match opt_void { + None => {} + } + + // But if we hide it behind a smart pointer, we need an arm. + let box_opt_void: Box> = Box::new(None); + match box_opt_void { + //~^ ERROR non-exhaustive patterns: `deref!(Some(_))` not covered + None => {} + } + match box_opt_void { + None => {} + Some(_) => {} + } + match box_opt_void { + None => {} + _ => {} + } + + // For consistency, this behaves the same as if we manually dereferenced the scrutinee. + match *box_opt_void { + //~^ ERROR non-exhaustive patterns: `Some(_)` not covered + None => {} + } + match *box_opt_void { + None => {} + Some(_) => {} + } + match *box_opt_void { + None => {} + _ => {} + } +} diff --git a/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr b/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr new file mode 100644 index 000000000000..e32477085661 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr @@ -0,0 +1,38 @@ +error[E0004]: non-exhaustive patterns: `deref!(Some(_))` not covered + --> $DIR/empty-types.rs:21:11 + | +LL | match box_opt_void { + | ^^^^^^^^^^^^ pattern `deref!(Some(_))` not covered + | +note: `Box>` defined here + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: the matched value is of type `Box>` + = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + deref!(Some(_)) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/empty-types.rs:35:11 + | +LL | match *box_opt_void { + | ^^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` + = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.rs b/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.rs new file mode 100644 index 000000000000..f567dc07bb59 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.rs @@ -0,0 +1,48 @@ +//! Test matches with a mix of ADT constructors and deref patterns. Currently, usefulness analysis +//! doesn't support this, so make sure we catch it beforehand. As a consequence, it takes priority +//! over non-exhaustive match and unreachable pattern errors. +#![feature(deref_patterns)] +#![expect(incomplete_features)] +#![deny(unreachable_patterns)] + +use std::borrow::Cow; + +fn main() { + let cow: Cow<'static, bool> = Cow::Borrowed(&false); + + match cow { + true => {} + //~v ERROR mix of deref patterns and normal constructors + false => {} + Cow::Borrowed(_) => {} + } + + match cow { + Cow::Owned(_) => {} + Cow::Borrowed(_) => {} + true => {} + //~^ ERROR mix of deref patterns and normal constructors + } + + match cow { + _ => {} + Cow::Owned(_) => {} + false => {} + //~^ ERROR mix of deref patterns and normal constructors + } + + match (cow, 0) { + (Cow::Owned(_), 0) => {} + (Cow::Borrowed(_), 0) => {} + (true, 0) => {} + //~^ ERROR mix of deref patterns and normal constructors + } + + match (0, cow) { + (0, Cow::Owned(_)) => {} + (0, Cow::Borrowed(_)) => {} + _ => {} + (1, true) => {} + //~^ ERROR mix of deref patterns and normal constructors + } +} diff --git a/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.stderr b/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.stderr new file mode 100644 index 000000000000..5ad24164b985 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.stderr @@ -0,0 +1,43 @@ +error: mix of deref patterns and normal constructors + --> $DIR/mixed-constructors.rs:16:9 + | +LL | false => {} + | ^^^^^ matches on the result of dereferencing `Cow<'_, bool>` +LL | Cow::Borrowed(_) => {} + | ^^^^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` + +error: mix of deref patterns and normal constructors + --> $DIR/mixed-constructors.rs:22:9 + | +LL | Cow::Borrowed(_) => {} + | ^^^^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` +LL | true => {} + | ^^^^ matches on the result of dereferencing `Cow<'_, bool>` + +error: mix of deref patterns and normal constructors + --> $DIR/mixed-constructors.rs:29:9 + | +LL | Cow::Owned(_) => {} + | ^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` +LL | false => {} + | ^^^^^ matches on the result of dereferencing `Cow<'_, bool>` + +error: mix of deref patterns and normal constructors + --> $DIR/mixed-constructors.rs:36:10 + | +LL | (Cow::Borrowed(_), 0) => {} + | ^^^^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` +LL | (true, 0) => {} + | ^^^^ matches on the result of dereferencing `Cow<'_, bool>` + +error: mix of deref patterns and normal constructors + --> $DIR/mixed-constructors.rs:43:13 + | +LL | (0, Cow::Borrowed(_)) => {} + | ^^^^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` +LL | _ => {} +LL | (1, true) => {} + | ^^^^ matches on the result of dereferencing `Cow<'_, bool>` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs new file mode 100644 index 000000000000..704cae8bdbc4 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs @@ -0,0 +1,28 @@ +//! Test non-exhaustive matches involving deref patterns. +#![feature(deref_patterns)] +#![expect(incomplete_features)] +#![deny(unreachable_patterns)] + +fn main() { + match Box::new(false) { + //~^ ERROR non-exhaustive patterns: `deref!(true)` not covered + false => {} + } + + match Box::new(Box::new(false)) { + //~^ ERROR non-exhaustive patterns: `deref!(deref!(false))` not covered + true => {} + } + + match Box::new((true, Box::new(false))) { + //~^ ERROR non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered + (true, false) => {} + (false, true) => {} + } + + enum T { A, B, C } + match Box::new((Box::new(T::A), Box::new(T::A))) { + //~^ ERROR non-exhaustive patterns: `deref!((deref!(T::C), _))` not covered + (T::A | T::B, T::C) => {} + } +} diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr new file mode 100644 index 000000000000..55fa84bafde2 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr @@ -0,0 +1,63 @@ +error[E0004]: non-exhaustive patterns: `deref!(true)` not covered + --> $DIR/non-exhaustive.rs:7:11 + | +LL | match Box::new(false) { + | ^^^^^^^^^^^^^^^ pattern `deref!(true)` not covered + | +note: `Box` defined here + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: the matched value is of type `Box` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ false => {}, +LL + deref!(true) => todo!() + | + +error[E0004]: non-exhaustive patterns: `deref!(deref!(false))` not covered + --> $DIR/non-exhaustive.rs:12:11 + | +LL | match Box::new(Box::new(false)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `deref!(deref!(false))` not covered + | +note: `Box>` defined here + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: the matched value is of type `Box>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ true => {}, +LL + deref!(deref!(false)) => todo!() + | + +error[E0004]: non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered + --> $DIR/non-exhaustive.rs:17:11 + | +LL | match Box::new((true, Box::new(false))) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered + | +note: `Box<(bool, Box)>` defined here + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: the matched value is of type `Box<(bool, Box)>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (false, true) => {}, +LL + deref!((false, deref!(false))) | deref!((true, deref!(true))) => todo!() + | + +error[E0004]: non-exhaustive patterns: `deref!((deref!(T::C), _))` not covered + --> $DIR/non-exhaustive.rs:24:11 + | +LL | match Box::new((Box::new(T::A), Box::new(T::A))) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `deref!((deref!(T::C), _))` not covered + | +note: `Box<(Box, Box)>` defined here + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: the matched value is of type `Box<(Box, Box)>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (T::A | T::B, T::C) => {}, +LL + deref!((deref!(T::C), _)) => todo!() + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs new file mode 100644 index 000000000000..2677fc54dedc --- /dev/null +++ b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs @@ -0,0 +1,33 @@ +//! Test unreachable patterns involving deref patterns. +#![feature(deref_patterns)] +#![expect(incomplete_features)] +#![deny(unreachable_patterns)] + +fn main() { + match Box::new(false) { + true => {} + false => {} + false => {} //~ ERROR unreachable pattern + } + + match Box::new(Box::new(false)) { + true => {} + false => {} + true => {} //~ ERROR unreachable pattern + } + + match Box::new((true, Box::new(false))) { + (true, _) => {} + (_, true) => {} + (false, false) => {} + _ => {} //~ ERROR unreachable pattern + } + + enum T { A, B, C } + match Box::new((Box::new(T::A), Box::new(T::A))) { + (T::A | T::B, T::A | T::C) => {} + (T::A, T::C) => {} //~ ERROR unreachable pattern + (T::B, T::A) => {} //~ ERROR unreachable pattern + _ => {} + } +} diff --git a/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr new file mode 100644 index 000000000000..045e11be3196 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr @@ -0,0 +1,60 @@ +error: unreachable pattern + --> $DIR/unreachable-patterns.rs:10:9 + | +LL | false => {} + | ----- matches all the relevant values +LL | false => {} + | ^^^^^ no value can reach this + | +note: the lint level is defined here + --> $DIR/unreachable-patterns.rs:4:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/unreachable-patterns.rs:16:9 + | +LL | true => {} + | ---- matches all the relevant values +LL | false => {} +LL | true => {} + | ^^^^ no value can reach this + +error: unreachable pattern + --> $DIR/unreachable-patterns.rs:23:9 + | +LL | _ => {} + | ^ no value can reach this + | +note: multiple earlier patterns match some of the same values + --> $DIR/unreachable-patterns.rs:23:9 + | +LL | (true, _) => {} + | --------- matches some of the same values +LL | (_, true) => {} + | --------- matches some of the same values +LL | (false, false) => {} + | -------------- matches some of the same values +LL | _ => {} + | ^ collectively making this unreachable + +error: unreachable pattern + --> $DIR/unreachable-patterns.rs:29:9 + | +LL | (T::A | T::B, T::A | T::C) => {} + | -------------------------- matches all the relevant values +LL | (T::A, T::C) => {} + | ^^^^^^^^^^^^ no value can reach this + +error: unreachable pattern + --> $DIR/unreachable-patterns.rs:30:9 + | +LL | (T::A | T::B, T::A | T::C) => {} + | -------------------------- matches all the relevant values +LL | (T::A, T::C) => {} +LL | (T::B, T::A) => {} + | ^^^^^^^^^^^^ no value can reach this + +error: aborting due to 5 previous errors + diff --git a/tests/ui/pattern/normalize-ty-in-range.rs b/tests/ui/pattern/normalize-ty-in-range.rs new file mode 100644 index 000000000000..f0d22362608e --- /dev/null +++ b/tests/ui/pattern/normalize-ty-in-range.rs @@ -0,0 +1,24 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Regression test for . +// Make sure we structurally normalize in range pattern checking in HIR typeck. + +trait Foo { + type Bar; +} + +impl Foo for () { + type Bar = i32; +} + +fn main() { + const X: <() as Foo>::Bar = 0; + + match 0 { + X..=X => {} + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs index cbfcf0eafd49..6c5a331b4b56 100644 --- a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs +++ b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs @@ -1,6 +1,5 @@ enum A {} //~^ NOTE `A` defined here - //~| NOTE fn f(a: &A) { match a {} diff --git a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr index c37a9a515790..67ee38eed60c 100644 --- a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr +++ b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `&A` is non-empty - --> $DIR/issue-78123-non-exhaustive-reference.rs:6:11 + --> $DIR/issue-78123-non-exhaustive-reference.rs:5:11 | LL | match a {} | ^ diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs index e505fe435207..2771b4717fbf 100644 --- a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs +++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs @@ -9,14 +9,14 @@ use core::{ fn function_call_stops_borrow_extension() { let phantom_pinned = identity(pin!(PhantomPinned)); - //~^ ERROR does not live long enough + //~^ ERROR temporary value dropped while borrowed [E0716] stuff(phantom_pinned) } fn promotion_only_works_for_the_innermost_block() { let phantom_pinned = { let phantom_pinned = pin!(PhantomPinned); - //~^ ERROR does not live long enough + //~^ ERROR temporary value dropped while borrowed [E0716] phantom_pinned }; stuff(phantom_pinned) diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr index 43fb82be7c2f..4ecc6370d3ca 100644 --- a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr +++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr @@ -1,29 +1,31 @@ -error[E0597]: value does not live long enough +error[E0716]: temporary value dropped while borrowed --> $DIR/lifetime_errors_on_promotion_misusage.rs:11:35 | LL | let phantom_pinned = identity(pin!(PhantomPinned)); - | ^^^^^^^^^^^^^^^^^^^ - value dropped here while still borrowed + | ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | borrowed value does not live long enough + | creates a temporary value which is freed while still in use LL | LL | stuff(phantom_pinned) | -------------- borrow later used here | + = note: consider using a `let` binding to create a longer lived value = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0597]: value does not live long enough +error[E0716]: temporary value dropped while borrowed --> $DIR/lifetime_errors_on_promotion_misusage.rs:18:30 | LL | let phantom_pinned = { | -------------- borrow later stored here LL | let phantom_pinned = pin!(PhantomPinned); - | ^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use ... LL | }; - | - value dropped here while still borrowed + | - temporary value is freed at the end of this statement | + = note: consider using a `let` binding to create a longer lived value = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/auxiliary/impl_privacy_xc_1.rs b/tests/ui/privacy/auxiliary/impl-privacy-cross-crate-1.rs similarity index 100% rename from tests/ui/auxiliary/impl_privacy_xc_1.rs rename to tests/ui/privacy/auxiliary/impl-privacy-cross-crate-1.rs diff --git a/tests/ui/privacy/auxiliary/impl_privacy_xc_2.rs b/tests/ui/privacy/auxiliary/impl-privacy-cross-crate-2.rs similarity index 100% rename from tests/ui/privacy/auxiliary/impl_privacy_xc_2.rs rename to tests/ui/privacy/auxiliary/impl-privacy-cross-crate-2.rs diff --git a/tests/ui/privacy/impl-privacy-cross-crate-1.rs b/tests/ui/privacy/impl-privacy-cross-crate-1.rs new file mode 100644 index 000000000000..6b2ef3ccc781 --- /dev/null +++ b/tests/ui/privacy/impl-privacy-cross-crate-1.rs @@ -0,0 +1,10 @@ +//@ run-pass +//@ aux-build:impl-privacy-cross-crate-1.rs + + +extern crate impl_privacy_cross_crate_1; + +pub fn main() { + let fish = impl_privacy_cross_crate_1::Fish { x: 1 }; + fish.swim(); +} diff --git a/tests/ui/privacy/impl-privacy-cross-crate-2.rs b/tests/ui/privacy/impl-privacy-cross-crate-2.rs new file mode 100644 index 000000000000..fa07e6e8ccea --- /dev/null +++ b/tests/ui/privacy/impl-privacy-cross-crate-2.rs @@ -0,0 +1,10 @@ +//@ run-pass +//@ aux-build:impl-privacy-cross-crate-2.rs + +extern crate impl_privacy_cross_crate_2; + +pub fn main() { + let fish1 = impl_privacy_cross_crate_2::Fish { x: 1 }; + let fish2 = impl_privacy_cross_crate_2::Fish { x: 2 }; + if fish1.eq(&fish2) { println!("yes") } else { println!("no") }; +} diff --git a/tests/ui/privacy/impl-privacy-xc-2.rs b/tests/ui/privacy/impl-privacy-xc-2.rs deleted file mode 100644 index da345ba20720..000000000000 --- a/tests/ui/privacy/impl-privacy-xc-2.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass -//@ aux-build:impl_privacy_xc_2.rs - -extern crate impl_privacy_xc_2; - -pub fn main() { - let fish1 = impl_privacy_xc_2::Fish { x: 1 }; - let fish2 = impl_privacy_xc_2::Fish { x: 2 }; - if fish1.eq(&fish2) { println!("yes") } else { println!("no") }; -} diff --git a/tests/ui/pub/pub-restricted-warning.rs b/tests/ui/pub/pub-restricted-warning.rs new file mode 100644 index 000000000000..80384afbb008 --- /dev/null +++ b/tests/ui/pub/pub-restricted-warning.rs @@ -0,0 +1,25 @@ +//@ check-pass + +#![allow(dead_code)] + +mod outer { + pub mod inner { + pub(in crate::outer) struct Foo; + pub fn bar() -> Foo { + //~^ WARNING type `Foo` is more private than the item `outer::inner::bar` [private_interfaces] + Foo + } + } + + pub mod nested { + pub mod inner { + pub(in crate::outer::nested) struct NestedFoo; + pub fn bar() -> NestedFoo { + //~^ WARNING type `NestedFoo` is more private than the item `nested::inner::bar` [private_interfaces] + NestedFoo + } + } + } +} + +fn main() {} diff --git a/tests/ui/pub/pub-restricted-warning.stderr b/tests/ui/pub/pub-restricted-warning.stderr new file mode 100644 index 000000000000..74f32d3de3c2 --- /dev/null +++ b/tests/ui/pub/pub-restricted-warning.stderr @@ -0,0 +1,27 @@ +warning: type `Foo` is more private than the item `outer::inner::bar` + --> $DIR/pub-restricted-warning.rs:8:9 + | +LL | pub fn bar() -> Foo { + | ^^^^^^^^^^^^^^^^^^^ function `outer::inner::bar` is reachable at visibility `pub(crate)` + | +note: but type `Foo` is only usable at visibility `pub(in crate::outer)` + --> $DIR/pub-restricted-warning.rs:7:9 + | +LL | pub(in crate::outer) struct Foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +warning: type `NestedFoo` is more private than the item `nested::inner::bar` + --> $DIR/pub-restricted-warning.rs:17:13 + | +LL | pub fn bar() -> NestedFoo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ function `nested::inner::bar` is reachable at visibility `pub(crate)` + | +note: but type `NestedFoo` is only usable at visibility `pub(in crate::outer::nested)` + --> $DIR/pub-restricted-warning.rs:16:13 + | +LL | pub(in crate::outer::nested) struct NestedFoo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr index 400969c279e6..99fd83e7b6ff 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `Something: Termination` is not satisfied LL | fn main() -> Something { | ^^^^^^^^^ the trait `Termination` is not implemented for `Something` | -note: required by a bound in `Main::{anon_assoc#0}` +note: required by a bound in `Main::main::{anon_assoc#0}` --> $DIR/issue-103052-2.rs:3:27 | LL | fn main() -> impl std::process::Termination; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{anon_assoc#0}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{anon_assoc#0}` error: aborting due to 1 previous error diff --git a/tests/ui/runtime/backtrace-debuginfo.rs b/tests/ui/runtime/backtrace-debuginfo.rs index afc96d6bb5f5..37fce2788b7f 100644 --- a/tests/ui/runtime/backtrace-debuginfo.rs +++ b/tests/ui/runtime/backtrace-debuginfo.rs @@ -42,9 +42,13 @@ macro_rules! dump_and_die { // there, even on i686-pc-windows-msvc. We do the best we can in // rust-lang/rust to test it as well, but sometimes we just gotta keep // landing PRs. + // + // aarch64-msvc is broken as its backtraces are truncated. + // See https://github.com/rust-lang/rust/issues/140489 if cfg!(any(target_os = "android", all(target_os = "linux", target_arch = "arm"), all(target_env = "msvc", target_arch = "x86"), + all(target_env = "msvc", target_arch = "aarch64"), target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")) { diff --git a/tests/ui/rust-2024/unsafe-attributes/auxiliary/safe_attr.rs b/tests/ui/rust-2024/unsafe-attributes/auxiliary/safe_attr.rs new file mode 100644 index 000000000000..161b71b9737b --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/auxiliary/safe_attr.rs @@ -0,0 +1,7 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn safe(_attr: TokenStream, item: TokenStream) -> TokenStream { + item +} diff --git a/tests/ui/rust-2024/unsafe-attributes/safe-proc-macro-attribute.rs b/tests/ui/rust-2024/unsafe-attributes/safe-proc-macro-attribute.rs new file mode 100644 index 000000000000..56b7001bdbf0 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/safe-proc-macro-attribute.rs @@ -0,0 +1,22 @@ +//! Anti-regression test for `#[safe]` proc-macro attribute. + +//@ revisions: unknown_attr proc_macro_attr +//@[proc_macro_attr] proc-macro: safe_attr.rs +//@[proc_macro_attr] check-pass + +#![warn(unsafe_attr_outside_unsafe)] + +#[cfg(proc_macro_attr)] +extern crate safe_attr; +#[cfg(proc_macro_attr)] +use safe_attr::safe; + +#[safe] +//[unknown_attr]~^ ERROR cannot find attribute `safe` in this scope +fn foo() {} + +#[safe(no_mangle)] +//[unknown_attr]~^ ERROR cannot find attribute `safe` in this scope +fn bar() {} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-attributes/safe-proc-macro-attribute.unknown_attr.stderr b/tests/ui/rust-2024/unsafe-attributes/safe-proc-macro-attribute.unknown_attr.stderr new file mode 100644 index 000000000000..93c6d75e52ff --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/safe-proc-macro-attribute.unknown_attr.stderr @@ -0,0 +1,14 @@ +error: cannot find attribute `safe` in this scope + --> $DIR/safe-proc-macro-attribute.rs:18:3 + | +LL | #[safe(no_mangle)] + | ^^^^ + +error: cannot find attribute `safe` in this scope + --> $DIR/safe-proc-macro-attribute.rs:14:3 + | +LL | #[safe] + | ^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-allow.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-allow.rs new file mode 100644 index 000000000000..76fdce7e5cff --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-allow.rs @@ -0,0 +1,16 @@ +//@ check-pass +//@ edition: 2021 +// +// Anti-regression test for https://github.com/rust-lang/rust/issues/140602 +// where the generated warning couldn't be allowed due too being attached to +// the wrong AST node. + +#![deny(unsafe_attr_outside_unsafe)] + +#[allow(unsafe_attr_outside_unsafe)] +mod generated { + #[no_mangle] + fn _generated_foo() {} +} + +fn main() {} diff --git a/tests/ui/stability-attribute/generics-default-stability.stderr b/tests/ui/stability-attribute/generics-default-stability.stderr index f4f51a14248e..53ef3e170cc1 100644 --- a/tests/ui/stability-attribute/generics-default-stability.stderr +++ b/tests/ui/stability-attribute/generics-default-stability.stderr @@ -270,6 +270,18 @@ LL | let _: Struct3 = Struct3 { field1: 0, field2: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +warning: use of deprecated field `unstable_generic_param::Struct4::field`: test + --> $DIR/generics-default-stability.rs:71:39 + | +LL | let _: Struct4 = Struct4 { field: 1 }; + | ^^^^^^^^ + +warning: use of deprecated field `unstable_generic_param::Struct4::field`: test + --> $DIR/generics-default-stability.rs:78:39 + | +LL | let _: Struct4 = Struct4 { field: 0 }; + | ^^^^^^^^ + error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:84:20 | @@ -279,6 +291,12 @@ LL | let _: Struct5 = Struct5 { field: 1 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +warning: use of deprecated field `unstable_generic_param::Struct5::field`: test + --> $DIR/generics-default-stability.rs:84:39 + | +LL | let _: Struct5 = Struct5 { field: 1 }; + | ^^^^^^^^ + error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:90:20 | @@ -297,6 +315,12 @@ LL | let _: Struct5 = Struct5 { field: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +warning: use of deprecated field `unstable_generic_param::Struct5::field`: test + --> $DIR/generics-default-stability.rs:92:39 + | +LL | let _: Struct5 = Struct5 { field: 0 }; + | ^^^^^^^^ + error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:100:19 | @@ -468,30 +492,6 @@ LL | let _: Box1 = Box1::new(1); = help: add `#![feature(box_alloc_param)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -warning: use of deprecated field `unstable_generic_param::Struct4::field`: test - --> $DIR/generics-default-stability.rs:71:39 - | -LL | let _: Struct4 = Struct4 { field: 1 }; - | ^^^^^^^^ - -warning: use of deprecated field `unstable_generic_param::Struct4::field`: test - --> $DIR/generics-default-stability.rs:78:39 - | -LL | let _: Struct4 = Struct4 { field: 0 }; - | ^^^^^^^^ - -warning: use of deprecated field `unstable_generic_param::Struct5::field`: test - --> $DIR/generics-default-stability.rs:84:39 - | -LL | let _: Struct5 = Struct5 { field: 1 }; - | ^^^^^^^^ - -warning: use of deprecated field `unstable_generic_param::Struct5::field`: test - --> $DIR/generics-default-stability.rs:92:39 - | -LL | let _: Struct5 = Struct5 { field: 0 }; - | ^^^^^^^^ - error: aborting due to 28 previous errors; 40 warnings emitted For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr b/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr index 6662ceda90b9..78b7d07b60cc 100644 --- a/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr +++ b/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr @@ -26,16 +26,6 @@ LL + String, LL ~ _)> = vec![]; | -error[E0658]: use of unstable library feature `allocator_api` - --> $DIR/suggest-vec-allocator-api.rs:8:26 - | -LL | let _boxed: Box = Box::new(10); - | ^ - | - = note: see issue #32838 for more information - = help: add `#![feature(allocator_api)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: use of unstable library feature `allocator_api` --> $DIR/suggest-vec-allocator-api.rs:7:24 | @@ -48,6 +38,16 @@ LL | let _ = Vec::::new(); = help: add `#![feature(allocator_api)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: use of unstable library feature `allocator_api` + --> $DIR/suggest-vec-allocator-api.rs:8:26 + | +LL | let _boxed: Box = Box::new(10); + | ^ + | + = note: see issue #32838 for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/statics/auxiliary/inner_static.rs b/tests/ui/statics/auxiliary/inner_static.rs new file mode 100644 index 000000000000..1c62046438fc --- /dev/null +++ b/tests/ui/statics/auxiliary/inner_static.rs @@ -0,0 +1,67 @@ +//! Test for inner statics with the same name. +//! +//! Before, the path name for all items defined in methods of traits and impls never +//! took into account the name of the method. This meant that if you had two statics +//! of the same name in two different methods the statics would end up having the +//! same symbol named (even after mangling) because the path components leading to +//! the symbol were exactly the same (just __extensions__ and the static name). +//! +//! It turns out that if you add the symbol "A" twice to LLVM, it automatically +//! makes the second one "A1" instead of "A". What this meant is that in local crate +//! compilations we never found this bug. Even across crates, this was never a +//! problem. The problem arises when you have generic methods that don't get +//! generated at compile-time of a library. If the statics were re-added to LLVM by +//! a client crate of a library in a different order, you would reference different +//! constants (the integer suffixes wouldn't be guaranteed to be the same). + +pub struct A { pub v: T } +pub struct B { pub v: T } + +pub mod test { + pub struct A { pub v: T } + + impl A { + pub fn foo(&self) -> isize { + static a: isize = 5; + return a + } + + pub fn bar(&self) -> isize { + static a: isize = 6; + return a; + } + } +} + +impl A { + pub fn foo(&self) -> isize { + static a: isize = 1; + return a + } + + pub fn bar(&self) -> isize { + static a: isize = 2; + return a; + } +} + +impl B { + pub fn foo(&self) -> isize { + static a: isize = 3; + return a + } + + pub fn bar(&self) -> isize { + static a: isize = 4; + return a; + } +} + +pub fn foo() -> isize { + let a = A { v: () }; + let b = B { v: () }; + let c = test::A { v: () }; + return a.foo() + a.bar() + + b.foo() + b.bar() + + c.foo() + c.bar(); +} diff --git a/tests/ui/statics/inner-static.rs b/tests/ui/statics/inner-static.rs new file mode 100644 index 000000000000..1916435c46a1 --- /dev/null +++ b/tests/ui/statics/inner-static.rs @@ -0,0 +1,30 @@ +//! Test for inner statics with the same name. +//! +//! Before, the path name for all items defined in methods of traits and impls never +//! took into account the name of the method. This meant that if you had two statics +//! of the same name in two different methods the statics would end up having the +//! same symbol named (even after mangling) because the path components leading to +//! the symbol were exactly the same (just __extensions__ and the static name). +//! +//! It turns out that if you add the symbol "A" twice to LLVM, it automatically +//! makes the second one "A1" instead of "A". What this meant is that in local crate +//! compilations we never found this bug. Even across crates, this was never a +//! problem. The problem arises when you have generic methods that don't get +//! generated at compile-time of a library. If the statics were re-added to LLVM by +//! a client crate of a library in a different order, you would reference different +//! constants (the integer suffixes wouldn't be guaranteed to be the same). + +//@ run-pass +//@ aux-build:inner_static.rs + + +extern crate inner_static; + +pub fn main() { + let a = inner_static::A::<()> { v: () }; + let b = inner_static::B::<()> { v: () }; + let c = inner_static::test::A::<()> { v: () }; + assert_eq!(a.bar(), 2); + assert_eq!(b.bar(), 4); + assert_eq!(c.bar(), 6); +} diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-attribute.riscv.stderr b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.riscv.stderr new file mode 100644 index 000000000000..49c5479275f3 --- /dev/null +++ b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.riscv.stderr @@ -0,0 +1,8 @@ +error: target feature `d` cannot be enabled with `#[target_feature]`: this feature is incompatible with the target ABI + --> $DIR/abi-incompatible-target-feature-attribute.rs:15:90 + | +LL | #[cfg_attr(x86, target_feature(enable = "soft-float"))] #[cfg_attr(riscv, target_feature(enable = "d"))] + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-attribute.rs b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.rs new file mode 100644 index 000000000000..a87334407592 --- /dev/null +++ b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.rs @@ -0,0 +1,17 @@ +//! Ensure ABI-incompatible features cannot be enabled via `#[target_feature]`. +// ignore-tidy-linelength +//@ compile-flags: --crate-type=lib +//@ revisions: x86 riscv +//@[x86] compile-flags: --target=x86_64-unknown-linux-gnu +//@[x86] needs-llvm-components: x86 +//@[riscv] compile-flags: --target=riscv32e-unknown-none-elf +//@[riscv] needs-llvm-components: riscv +#![feature(no_core, lang_items, riscv_target_feature, x87_target_feature)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} + +#[cfg_attr(x86, target_feature(enable = "soft-float"))] #[cfg_attr(riscv, target_feature(enable = "d"))] +//~^ERROR: cannot be enabled with +pub unsafe fn my_fun() {} diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-attribute.x86.stderr b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.x86.stderr new file mode 100644 index 000000000000..81471fd7e303 --- /dev/null +++ b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.x86.stderr @@ -0,0 +1,8 @@ +error: target feature `soft-float` cannot be enabled with `#[target_feature]`: this feature is incompatible with the target ABI + --> $DIR/abi-incompatible-target-feature-attribute.rs:15:32 + | +LL | #[cfg_attr(x86, target_feature(enable = "soft-float"))] #[cfg_attr(riscv, target_feature(enable = "d"))] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr new file mode 100644 index 000000000000..2dca0c220332 --- /dev/null +++ b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr @@ -0,0 +1,19 @@ +warning: target feature `d` must be disabled to ensure that the ABI of the current target can be implemented correctly + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 + +warning: unstable feature specified for `-Ctarget-feature`: `d` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: unstable feature specified for `-Ctarget-feature`: `f` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: unstable feature specified for `-Ctarget-feature`: `zicsr` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: 4 warnings emitted + diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs new file mode 100644 index 000000000000..68e1d3b9ddc6 --- /dev/null +++ b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs @@ -0,0 +1,22 @@ +//! Ensure ABI-incompatible features cannot be enabled via `-Ctarget-feature`. +// These are just warnings for now. +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ revisions: x86 riscv +//@[x86] compile-flags: --target=x86_64-unknown-linux-gnu -Ctarget-feature=+soft-float +//@[x86] needs-llvm-components: x86 +//@[riscv] compile-flags: --target=riscv32e-unknown-none-elf -Ctarget-feature=+d +//@[riscv] needs-llvm-components: riscv + +#![feature(no_core, lang_items, riscv_target_feature)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} +#[lang = "freeze"] +pub trait Freeze {} + +//~? WARN must be disabled to ensure that the ABI of the current target can be implemented correctly +//~? WARN unstable feature specified for `-Ctarget-feature` +//[riscv]~? WARN unstable feature specified for `-Ctarget-feature` +//[riscv]~? WARN unstable feature specified for `-Ctarget-feature` diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.stderr b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.x86.stderr similarity index 100% rename from tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.stderr rename to tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.x86.stderr diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs similarity index 59% rename from tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs rename to tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs index 7368ef120fa6..0013d033b9c5 100644 --- a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs @@ -1,3 +1,6 @@ +//! `x87` is a required target feature on some x86 targets, but not on this one as this one +//! uses soft-floats. So ensure disabling the target feature here (which is a NOP) does +//! not trigger a warning. //@ compile-flags: --target=x86_64-unknown-none --crate-type=lib //@ needs-llvm-components: x86 //@ compile-flags: -Ctarget-feature=-x87 diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.stderr b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr similarity index 100% rename from tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.stderr rename to tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs b/tests/ui/target-feature/abi-required-target-feature-attribute.rs similarity index 69% rename from tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs rename to tests/ui/target-feature/abi-required-target-feature-attribute.rs index 8b60820cc9b6..95723c57f94d 100644 --- a/tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs +++ b/tests/ui/target-feature/abi-required-target-feature-attribute.rs @@ -1,3 +1,5 @@ +//! Enabling a target feature that is anyway required changes nothing, so this is allowed +//! for `#[target_feature]`. //@ compile-flags: --target=x86_64-unknown-none --crate-type=lib //@ needs-llvm-components: x86 //@ build-pass diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.stderr b/tests/ui/target-feature/abi-required-target-feature-flag-disable.aarch64.stderr similarity index 100% rename from tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.stderr rename to tests/ui/target-feature/abi-required-target-feature-flag-disable.aarch64.stderr diff --git a/tests/ui/target-feature/abi-required-target-feature-flag-disable.loongarch.stderr b/tests/ui/target-feature/abi-required-target-feature-flag-disable.loongarch.stderr new file mode 100644 index 000000000000..35102e0571f4 --- /dev/null +++ b/tests/ui/target-feature/abi-required-target-feature-flag-disable.loongarch.stderr @@ -0,0 +1,11 @@ +warning: target feature `d` must be enabled to ensure that the ABI of the current target can be implemented correctly + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 + +warning: unstable feature specified for `-Ctarget-feature`: `d` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: 2 warnings emitted + diff --git a/tests/ui/target-feature/abi-required-target-feature-flag-disable.riscv.stderr b/tests/ui/target-feature/abi-required-target-feature-flag-disable.riscv.stderr new file mode 100644 index 000000000000..35102e0571f4 --- /dev/null +++ b/tests/ui/target-feature/abi-required-target-feature-flag-disable.riscv.stderr @@ -0,0 +1,11 @@ +warning: target feature `d` must be enabled to ensure that the ABI of the current target can be implemented correctly + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 + +warning: unstable feature specified for `-Ctarget-feature`: `d` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: 2 warnings emitted + diff --git a/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs b/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs new file mode 100644 index 000000000000..c3ce05baa64b --- /dev/null +++ b/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs @@ -0,0 +1,27 @@ +//! Ensure ABI-required features cannot be disabled via `-Ctarget-feature`. +//! Also covers the case of a feature indirectly disabling another via feature implications. +//@ compile-flags: --crate-type=lib +//@ revisions: x86 x86-implied aarch64 riscv loongarch +//@[x86] compile-flags: --target=x86_64-unknown-linux-gnu -Ctarget-feature=-x87 +//@[x86] needs-llvm-components: x86 +//@[x86-implied] compile-flags: --target=x86_64-unknown-linux-gnu -Ctarget-feature=-sse +//@[x86-implied] needs-llvm-components: x86 +//@[aarch64] compile-flags: --target=aarch64-unknown-linux-gnu -Ctarget-feature=-neon +//@[aarch64] needs-llvm-components: aarch64 +//@[riscv] compile-flags: --target=riscv64gc-unknown-none-elf -Ctarget-feature=-d +//@[riscv] needs-llvm-components: riscv +//@[loongarch] compile-flags: --target=loongarch64-unknown-none -Ctarget-feature=-d +//@[loongarch] needs-llvm-components: loongarch +// For now this is just a warning. +//@ build-pass +// Remove some LLVM warnings that only show up sometimes. +//@ normalize-stderr: "\n[^\n]*(target-abi|lp64f)[^\n]*" -> "" + +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} + +//~? WARN must be enabled to ensure that the ABI of the current target can be implemented correctly +//[x86,riscv,loongarch]~? WARN unstable feature specified for `-Ctarget-feature` diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr b/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86-implied.stderr similarity index 100% rename from tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr rename to tests/ui/target-feature/abi-required-target-feature-flag-disable.x86-implied.stderr diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr b/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr similarity index 100% rename from tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr rename to tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs deleted file mode 100644 index 12e7e3bc45b3..000000000000 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Ensure that if disabling a target feature implies disabling an ABI-required target feature, -//! we complain. -//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib -//@ needs-llvm-components: x86 -//@ compile-flags: -Ctarget-feature=-sse -// For now this is just a warning. -//@ build-pass - -#![feature(no_core, lang_items)] -#![no_core] - -#[lang = "sized"] -pub trait Sized {} - -//~? WARN target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs deleted file mode 100644 index 33e4f12694f3..000000000000 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=lib -//@ needs-llvm-components: aarch64 -//@ compile-flags: -Ctarget-feature=-neon -// For now this is just a warning. -//@ build-pass - -#![feature(no_core, lang_items)] -#![no_core] - -#[lang = "sized"] -pub trait Sized {} - -//~? WARN target feature `neon` must be enabled to ensure that the ABI of the current target can be implemented correctly diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs deleted file mode 100644 index e1bd25ffad1e..000000000000 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Ensure ABI-required features cannot be disabled via `-Ctarget-feature`. -//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib -//@ needs-llvm-components: x86 -//@ compile-flags: -Ctarget-feature=-x87 -// For now this is just a warning. -//@ build-pass - -#![feature(no_core, lang_items)] -#![no_core] - -#[lang = "sized"] -pub trait Sized {} - -//~? WARN target feature `x87` must be enabled to ensure that the ABI of the current target can be implemented correctly -//~? WARN unstable feature specified for `-Ctarget-feature`: `x87` diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs deleted file mode 100644 index 4ccc6e0e941f..000000000000 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Ensure ABI-incompatible features cannot be enabled via `-Ctarget-feature`. -//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib -//@ needs-llvm-components: x86 -//@ compile-flags: -Ctarget-feature=+soft-float -// For now this is just a warning. -//@ build-pass - -#![feature(no_core, lang_items, riscv_target_feature)] -#![no_core] - -#[lang = "sized"] -pub trait Sized {} - -//~? WARN target feature `soft-float` must be disabled to ensure that the ABI of the current target can be implemented correctl -//~? WARN unstable feature specified for `-Ctarget-feature`: `soft-float` diff --git a/tests/ui/target_modifiers/auxiliary/fixed_x18.rs b/tests/ui/target_modifiers/auxiliary/fixed_x18.rs new file mode 100644 index 000000000000..32eff76ec54c --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/fixed_x18.rs @@ -0,0 +1,7 @@ +//@ no-prefer-dynamic +//@ compile-flags: --target aarch64-unknown-none -Zfixed-x18 +//@ needs-llvm-components: aarch64 + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/incompatible_fixedx18.error_generated.stderr b/tests/ui/target_modifiers/incompatible_fixedx18.error_generated.stderr new file mode 100644 index 000000000000..096d7cb5f258 --- /dev/null +++ b/tests/ui/target_modifiers/incompatible_fixedx18.error_generated.stderr @@ -0,0 +1,13 @@ +error: mixing `-Zfixed-x18` will cause an ABI mismatch in crate `incompatible_fixedx18` + --> $DIR/incompatible_fixedx18.rs:12:1 + | +LL | #![feature(no_core)] + | ^ + | + = help: the `-Zfixed-x18` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: unset `-Zfixed-x18` in this crate is incompatible with `-Zfixed-x18=` in dependency `fixed_x18` + = help: set `-Zfixed-x18=` in this crate or unset `-Zfixed-x18` in `fixed_x18` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=fixed-x18` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/incompatible_fixedx18.rs b/tests/ui/target_modifiers/incompatible_fixedx18.rs new file mode 100644 index 000000000000..6c13984f608e --- /dev/null +++ b/tests/ui/target_modifiers/incompatible_fixedx18.rs @@ -0,0 +1,17 @@ +//@ aux-build:fixed_x18.rs +//@ compile-flags: --target aarch64-unknown-none +//@ needs-llvm-components: aarch64 + +//@ revisions:allow_match allow_mismatch error_generated +//@[allow_match] compile-flags: -Zfixed-x18 +//@[allow_mismatch] compile-flags: -Cunsafe-allow-abi-mismatch=fixed-x18 +//@[error_generated] compile-flags: +//@[allow_mismatch] check-pass +//@[allow_match] check-pass + +#![feature(no_core)] +//[error_generated]~^ ERROR mixing `-Zfixed-x18` will cause an ABI mismatch in crate `incompatible_fixedx18` +#![crate_type = "rlib"] +#![no_core] + +extern crate fixed_x18; diff --git a/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr index e26cb22163f1..f8a6252f991e 100644 --- a/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr +++ b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr @@ -10,26 +10,53 @@ LL | fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a; LL | fn foo<'a, K>(self, _: (), _: K) where { | ^^^^^^^ lifetimes do not match method in trait -error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration - --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:12 | -LL | fn foo<'a>(&self, state: &'a State) -> &'a T - | ---- lifetimes in impl do not match this method in trait -LL | where -LL | T: 'a; - | -- this bound might be missing in the impl -... LL | fn foo<'a>(&self, state: &'a State) -> &'a T { - | ^^^^ lifetimes do not match method in trait - -error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration - --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11 + | ^^ | -LL | fn foo<'a>(&'a self) {} - | ---- lifetimes in impl do not match this method in trait + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'a` differs between the trait and impl + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:14:12 + | +LL | trait Foo { + | ------------ in this trait... +LL | fn foo<'a>(&self, state: &'a State) -> &'a T + | ^^ `'a` is early-bound +LL | where +LL | T: 'a; + | -- this lifetime bound makes `'a` early-bound ... +LL | / impl Foo for F +LL | | where +LL | | F: Fn(&State) -> &T, + | |________________________- in this impl... +LL | { +LL | fn foo<'a>(&self, state: &'a State) -> &'a T { + | ^^ `'a` is late-bound + +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:12 + | LL | fn foo<'a: 'a>(&'a self) {} - | ^^^^^^^^ lifetimes do not match method in trait + | ^^ + | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'a` differs between the trait and impl + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:29:12 + | +LL | trait Bar { + | --------- in this trait... +LL | fn foo<'a>(&'a self) {} + | ^^ `'a` is late-bound +... +LL | impl Bar for () { + | --------------- in this impl... +LL | fn foo<'a: 'a>(&'a self) {} + | ^^ -- this lifetime bound makes `'a` early-bound + | | + | `'a` is early-bound error: aborting due to 3 previous errors diff --git a/tests/ui/traits/bound/on-structs-and-enums-locals.stderr b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr index 01cf76c62d54..88077f4e4d7d 100644 --- a/tests/ui/traits/bound/on-structs-and-enums-locals.stderr +++ b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr @@ -1,20 +1,3 @@ -error[E0277]: the trait bound `usize: Trait` is not satisfied - --> $DIR/on-structs-and-enums-locals.rs:15:14 - | -LL | let baz: Foo = loop { }; - | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` - | -help: this trait has no implementations, consider adding one - --> $DIR/on-structs-and-enums-locals.rs:1:1 - | -LL | trait Trait { - | ^^^^^^^^^^^ -note: required by a bound in `Foo` - --> $DIR/on-structs-and-enums-locals.rs:5:14 - | -LL | struct Foo { - | ^^^^^ required by this bound in `Foo` - error[E0277]: the trait bound `{integer}: Trait` is not satisfied --> $DIR/on-structs-and-enums-locals.rs:11:12 | @@ -32,6 +15,23 @@ note: required by a bound in `Foo` LL | struct Foo { | ^^^^^ required by this bound in `Foo` +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums-locals.rs:15:14 + | +LL | let baz: Foo = loop { }; + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +help: this trait has no implementations, consider adding one + --> $DIR/on-structs-and-enums-locals.rs:1:1 + | +LL | trait Trait { + | ^^^^^^^^^^^ +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-locals.rs:5:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr b/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr index 3fb5decb723e..1f46415e2436 100644 --- a/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr +++ b/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr @@ -1,15 +1,3 @@ -error[E0277]: the trait bound `f64: Trait` is not satisfied - --> $DIR/on-structs-and-enums-xc1.rs:12:14 - | -LL | let bar: Bar = return; - | ^^^^^^^^ the trait `Trait` is not implemented for `f64` - | -note: required by a bound in `Bar` - --> $DIR/auxiliary/on_structs_and_enums_xc.rs:9:16 - | -LL | pub enum Bar { - | ^^^^^ required by this bound in `Bar` - error[E0277]: the trait bound `{integer}: Trait` is not satisfied --> $DIR/on-structs-and-enums-xc1.rs:9:12 | @@ -22,6 +10,18 @@ note: required by a bound in `Foo` LL | pub struct Foo { | ^^^^^ required by this bound in `Foo` +error[E0277]: the trait bound `f64: Trait` is not satisfied + --> $DIR/on-structs-and-enums-xc1.rs:12:14 + | +LL | let bar: Bar = return; + | ^^^^^^^^ the trait `Trait` is not implemented for `f64` + | +note: required by a bound in `Bar` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:9:16 + | +LL | pub enum Bar { + | ^^^^^ required by this bound in `Bar` + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr index 2d42fedae438..e1ae981b2492 100644 --- a/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr +++ b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied - --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:11 + --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:22 | LL | fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()` | help: this trait has no implementations, consider adding one --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1 diff --git a/tests/ui/traits/next-solver/global-param-env-after-norm.rs b/tests/ui/traits/next-solver/global-param-env-after-norm.rs new file mode 100644 index 000000000000..0d098db67d36 --- /dev/null +++ b/tests/ui/traits/next-solver/global-param-env-after-norm.rs @@ -0,0 +1,15 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +struct NewSolver; +struct OldSolver; + +fn foo() +where + T: Iterator, + OldSolver: Into, +{ + let x: OldSolver = OldSolver.into(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs index 8fe53d6773b9..fe336766891d 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.rs +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -19,5 +19,6 @@ impl Overlap for T {} impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} //~^ ERROR cannot find type `Missing` in this scope //~| ERROR the trait bound `T: Overlap fn(Assoc<'a, T>)>` is not satisfied +//~| ERROR the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied fn main() {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index d2a58e95629a..45fa33dff52f 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -26,6 +26,18 @@ LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } +error[E0277]: the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied + --> $DIR/issue-118950-root-region.rs:19:9 + | +LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `*const T` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-118950-root-region.rs:8:1 + | +LL | trait ToUnit<'a> { + | ^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `T: Overlap fn(Assoc<'a, T>)>` is not satisfied --> $DIR/issue-118950-root-region.rs:19:47 | @@ -37,7 +49,7 @@ help: consider further restricting type parameter `T` with trait `Overlap` LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap, T: Overlap fn(Assoc<'a, T>)> {} | ++++++++++++++++++++++++++++++++++++++ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0277, E0412. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr index 32a7766a638d..72be10367dac 100644 --- a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr +++ b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `(): Wf` is not satisfied - --> $DIR/non-wf-in-coerce-pointers.rs:8:17 + --> $DIR/non-wf-in-coerce-pointers.rs:8:8 | LL | f: &'static <() as Wf>::Assoc, - | ^^^^^^^^^^^^^^^^^ the trait `Wf` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Wf` is not implemented for `()` | help: this trait has no implementations, consider adding one --> $DIR/non-wf-in-coerce-pointers.rs:3:1 diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index e91a48f62aec..f5fd9ce9864c 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -4,24 +4,6 @@ error[E0275]: overflow evaluating the requirement `::Assoc: Trait` LL | ::Assoc: Trait, | ^^^^^ -error[E0275]: overflow evaluating the requirement `::Assoc well-formed` - --> $DIR/normalize-param-env-4.rs:19:26 - | -LL | ::Assoc: Trait, - | ^^^^^ - -error[E0275]: overflow evaluating the requirement `T: Trait` - --> $DIR/normalize-param-env-4.rs:32:19 - | -LL | impls_trait::(); - | ^ - | -note: required by a bound in `impls_trait` - --> $DIR/normalize-param-env-4.rs:15:19 - | -LL | fn impls_trait() {} - | ^^^^^ required by this bound in `impls_trait` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/opaques/duplicate-opaque-type-entries.rs b/tests/ui/traits/next-solver/opaques/duplicate-opaque-type-entries.rs new file mode 100644 index 000000000000..e0668ac3d39f --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/duplicate-opaque-type-entries.rs @@ -0,0 +1,25 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass +#![crate_type = "lib"] +trait Eq {} +impl Eq for T {} +trait ConstrainAndEq {} +impl ConstrainAndEq for U +where + T: FnOnce() -> u32, + U: FnOnce() -> u32, + T: Eq, +{} + +fn constrain_and_eq, U>(_: T, _: U) {} +fn foo<'a>() -> impl Sized + use<'a> { + // This proves `foo<'a>: FnOnce() -> u32` and `foo<'1>: FnOnce() -> u32`, + // We constrain both `opaque<'a>` and `opaque<'1>` to `u32`, resulting in + // two distinct opaque type uses. Proving `foo<'a>: Eq>` then + // equates the two regions at which point the two opaque type keys are now + // equal. This previously caused an ICE. + constrain_and_eq(foo::<'a>, foo::<'_>); + 1u32 +} diff --git a/tests/ui/traits/next-solver/overflow-plus-ambiguity-normalizes-to-response.rs b/tests/ui/traits/next-solver/overflow-plus-ambiguity-normalizes-to-response.rs new file mode 100644 index 000000000000..4b20cd11b0d4 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow-plus-ambiguity-normalizes-to-response.rs @@ -0,0 +1,56 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// Regression test for . +// See comment below on `fn main`. + +trait Intersect { + type Output; +} + +impl Intersect> for T +where + T: Intersect, +{ + type Output = T; +} + +impl Intersect for Cuboid { + type Output = Cuboid; +} + +fn intersect(_: &T, _: &U) -> T::Output +where + T: Intersect, +{ + todo!() +} + +struct Cuboid; +impl Cuboid { + fn method(&self) {} +} + +fn main() { + let x = vec![]; + // Here we end up trying to normalize `>>::Output` + // for the return type of the function, to constrain `y`. The impl then requires + // `Cuboid: Intersect`, which has two candidates. One that constrains + // `?0 = Vec`, which itself has the same two candidates and ends up leading + // to a recursion depth overflow. In the second impl, we constrain `?0 = Cuboid`. + // + // Floundering leads to us combining the overflow candidate and yes candidate to + // overflow. Because the response was overflow, we used to bubble it up to the + // parent normalizes-to goal, which caused us to drop its constraint that would + // guide us to normalize the associated type mentioned before. + // + // After this PR, we implement a new floundering "algebra" such that `Overflow OR Maybe` + // returns anew `Overflow { keep_constraints: true }`, which means that we don't + // need to drop constraints in the parent normalizes-to goal. This allows us to + // normalize `y` to `Cuboid`, and allows us to call the method successfully. We + // then constrain the `?0` in `let x: Vec = x` below, so that we don't have + // a left over ambiguous goal. + let y = intersect(&Cuboid, &x); + y.method(); + let x: Vec = x; +} diff --git a/tests/ui/traits/object/constrain-via-unnecessary-bound.rs b/tests/ui/traits/object/constrain-via-unnecessary-bound.rs new file mode 100644 index 000000000000..4640d6b3ed59 --- /dev/null +++ b/tests/ui/traits/object/constrain-via-unnecessary-bound.rs @@ -0,0 +1,24 @@ +//@ check-pass + +// Regression test for . +// Test that we lower impossible-to-satisfy associated type bounds, which +// may for example constrain impl parameters. + +pub trait Other {} + +pub trait Trait { + type Assoc + where + Self: Sized; +} + +impl Other for dyn Trait {} +// `dyn Trait` is a different "nominal type" than `dyn Trait`. +impl Other for dyn Trait {} +//~^ WARN unnecessary associated type bound for dyn-incompatible associated type + +// I hope it's clear that `dyn Trait` (w/o `Assoc`) wouldn't match this impl. +impl dyn Trait {} +//~^ WARN unnecessary associated type bound for dyn-incompatible associated type + +fn main() {} diff --git a/tests/ui/traits/object/constrain-via-unnecessary-bound.stderr b/tests/ui/traits/object/constrain-via-unnecessary-bound.stderr new file mode 100644 index 000000000000..4383ca869eac --- /dev/null +++ b/tests/ui/traits/object/constrain-via-unnecessary-bound.stderr @@ -0,0 +1,19 @@ +warning: unnecessary associated type bound for dyn-incompatible associated type + --> $DIR/constrain-via-unnecessary-bound.rs:17:26 + | +LL | impl Other for dyn Trait {} + | ^^^^^^^^^^ help: remove this bound + | + = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` + = note: `#[warn(unused_associated_type_bounds)]` on by default + +warning: unnecessary associated type bound for dyn-incompatible associated type + --> $DIR/constrain-via-unnecessary-bound.rs:21:19 + | +LL | impl dyn Trait {} + | ^^^^^^^^^ help: remove this bound + | + = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` + +warning: 2 warnings emitted + diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr index 37fe142951d8..2f9fdf151f08 100644 --- a/tests/ui/traits/object/pretty.stderr +++ b/tests/ui/traits/object/pretty.stderr @@ -154,12 +154,12 @@ error[E0308]: mismatched types --> $DIR/pretty.rs:41:56 | LL | fn dyn_has_gat(x: &dyn HasGat = ()>) { x } - | - ^ expected `()`, found `&dyn HasGat` + | - ^ expected `()`, found `&dyn HasGat = ()>` | | - | help: try adding a return type: `-> &dyn HasGat` + | help: try adding a return type: `-> &dyn HasGat = ()>` | = note: expected unit type `()` - found reference `&dyn HasGat` + found reference `&dyn HasGat = ()>` error: aborting due to 14 previous errors; 1 warning emitted diff --git a/tests/ui/traits/suggest-remove-deref-issue-140166.rs b/tests/ui/traits/suggest-remove-deref-issue-140166.rs new file mode 100644 index 000000000000..1b832c7eba5c --- /dev/null +++ b/tests/ui/traits/suggest-remove-deref-issue-140166.rs @@ -0,0 +1,18 @@ +trait Trait {} + +struct Chars; +impl Trait for Chars {} + +struct FlatMap(T); +impl std::fmt::Debug for FlatMap { + fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + unimplemented!() + } +} + +fn lol() { + format_args!("{:?}", FlatMap(&Chars)); + //~^ ERROR the trait bound `&Chars: Trait` is not satisfied [E0277] +} + +fn main() {} diff --git a/tests/ui/traits/suggest-remove-deref-issue-140166.stderr b/tests/ui/traits/suggest-remove-deref-issue-140166.stderr new file mode 100644 index 000000000000..90f24d86d53e --- /dev/null +++ b/tests/ui/traits/suggest-remove-deref-issue-140166.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `&Chars: Trait` is not satisfied + --> $DIR/suggest-remove-deref-issue-140166.rs:14:26 + | +LL | format_args!("{:?}", FlatMap(&Chars)); + | ---- ^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `&Chars` + | | + | required by a bound introduced by this call + | + = help: the trait `Trait` is implemented for `Chars` +note: required for `FlatMap<&Chars>` to implement `Debug` + --> $DIR/suggest-remove-deref-issue-140166.rs:7:16 + | +LL | impl std::fmt::Debug for FlatMap { + | ----- ^^^^^^^^^^^^^^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `core::fmt::rt::Argument::<'_>::new_debug` + --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmute/unnecessary-transmutation.fixed b/tests/ui/transmute/unnecessary-transmutation.fixed index 1a0df143cc5f..bf7d769348aa 100644 --- a/tests/ui/transmute/unnecessary-transmutation.fixed +++ b/tests/ui/transmute/unnecessary-transmutation.fixed @@ -49,6 +49,10 @@ fn main() { //~^ ERROR let y: char = char::from_u32_unchecked(y); //~^ ERROR + let y: i32 = u32::from('🐱').cast_signed(); + //~^ ERROR + let y: char = char::from_u32_unchecked(i32::cast_unsigned(y)); + //~^ ERROR let x: u16 = i16::cast_unsigned(8i16); //~^ ERROR @@ -72,6 +76,11 @@ fn main() { let y: u64 = f64::to_bits(2.0); //~^ ERROR + let y: f64 = f64::from_bits(i64::cast_unsigned(1i64)); + //~^ ERROR + let y: i64 = f64::to_bits(1f64).cast_signed(); + //~^ ERROR + let z: bool = (1u8 == 1); //~^ ERROR let z: u8 = (z) as u8; diff --git a/tests/ui/transmute/unnecessary-transmutation.rs b/tests/ui/transmute/unnecessary-transmutation.rs index 6b979263c56c..b9de529f1ccc 100644 --- a/tests/ui/transmute/unnecessary-transmutation.rs +++ b/tests/ui/transmute/unnecessary-transmutation.rs @@ -49,6 +49,10 @@ fn main() { //~^ ERROR let y: char = transmute(y); //~^ ERROR + let y: i32 = transmute('🐱'); + //~^ ERROR + let y: char = transmute(y); + //~^ ERROR let x: u16 = transmute(8i16); //~^ ERROR @@ -72,6 +76,11 @@ fn main() { let y: u64 = transmute(2.0); //~^ ERROR + let y: f64 = transmute(1i64); + //~^ ERROR + let y: i64 = transmute(1f64); + //~^ ERROR + let z: bool = transmute(1u8); //~^ ERROR let z: u8 = transmute(z); diff --git a/tests/ui/transmute/unnecessary-transmutation.stderr b/tests/ui/transmute/unnecessary-transmutation.stderr index b661aa13c985..a19f1bebf16f 100644 --- a/tests/ui/transmute/unnecessary-transmutation.stderr +++ b/tests/ui/transmute/unnecessary-transmutation.stderr @@ -154,82 +154,108 @@ LL | let y: char = transmute(y); = help: consider `char::from_u32(…).unwrap()` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:53:22 + --> $DIR/unnecessary-transmutation.rs:52:22 + | +LL | let y: i32 = transmute('🐱'); + | ^^^^^^^^^^^^^^^ help: replace this with: `u32::from('🐱').cast_signed()` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:54:23 + | +LL | let y: char = transmute(y); + | ^^^^^^^^^^^^ help: replace this with: `char::from_u32_unchecked(i32::cast_unsigned(y))` + | + = help: consider `char::from_u32(i32::cast_unsigned(…)).unwrap()` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:57:22 | LL | let x: u16 = transmute(8i16); | ^^^^^^^^^^^^^^^ help: replace this with: `i16::cast_unsigned(8i16)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:55:22 + --> $DIR/unnecessary-transmutation.rs:59:22 | LL | let x: i16 = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u16::cast_signed(x)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:57:22 + --> $DIR/unnecessary-transmutation.rs:61:22 | LL | let x: u32 = transmute(4i32); | ^^^^^^^^^^^^^^^ help: replace this with: `i32::cast_unsigned(4i32)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:59:22 + --> $DIR/unnecessary-transmutation.rs:63:22 | LL | let x: i32 = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u32::cast_signed(x)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:61:22 + --> $DIR/unnecessary-transmutation.rs:65:22 | LL | let x: u64 = transmute(7i64); | ^^^^^^^^^^^^^^^ help: replace this with: `i64::cast_unsigned(7i64)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:63:22 + --> $DIR/unnecessary-transmutation.rs:67:22 | LL | let x: i64 = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u64::cast_signed(x)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:66:22 + --> $DIR/unnecessary-transmutation.rs:70:22 | LL | let y: f32 = transmute(1u32); | ^^^^^^^^^^^^^^^ help: replace this with: `f32::from_bits(1u32)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:68:22 + --> $DIR/unnecessary-transmutation.rs:72:22 | LL | let y: u32 = transmute(y); | ^^^^^^^^^^^^ help: replace this with: `f32::to_bits(y)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:70:22 + --> $DIR/unnecessary-transmutation.rs:74:22 | LL | let y: f64 = transmute(3u64); | ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(3u64)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:72:22 + --> $DIR/unnecessary-transmutation.rs:76:22 | LL | let y: u64 = transmute(2.0); | ^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(2.0)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:75:23 + --> $DIR/unnecessary-transmutation.rs:79:22 + | +LL | let y: f64 = transmute(1i64); + | ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(i64::cast_unsigned(1i64))` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:81:22 + | +LL | let y: i64 = transmute(1f64); + | ^^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(1f64).cast_signed()` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:84:23 | LL | let z: bool = transmute(1u8); | ^^^^^^^^^^^^^^ help: replace this with: `(1u8 == 1)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:77:21 + --> $DIR/unnecessary-transmutation.rs:86:21 | LL | let z: u8 = transmute(z); | ^^^^^^^^^^^^ help: replace this with: `(z) as u8` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:82:21 + --> $DIR/unnecessary-transmutation.rs:91:21 | LL | let z: i8 = transmute(z); | ^^^^^^^^^^^^ help: replace this with: `(z) as i8` -error: aborting due to 32 previous errors +error: aborting due to 36 previous errors diff --git a/tests/ui/treat-err-as-bug/err.rs b/tests/ui/treat-err-as-bug/err.rs index 9f0e293b4cb1..7868c06fee1c 100644 --- a/tests/ui/treat-err-as-bug/err.rs +++ b/tests/ui/treat-err-as-bug/err.rs @@ -1,7 +1,5 @@ //@ compile-flags: -Ztreat-err-as-bug //@ failure-status: 101 -//@ error-pattern: aborting due to `-Z treat-err-as-bug=1` -//@ error-pattern: [eval_static_initializer] evaluating initializer of static `C` //@ normalize-stderr: "note: .*\n\n" -> "" //@ normalize-stderr: "thread 'rustc' panicked.*:\n.*\n" -> "" //@ rustc-env:RUST_BACKTRACE=0 @@ -10,3 +8,6 @@ pub static C: u32 = 0 - 1; //~^ ERROR could not evaluate static initializer + +//~? RAW aborting due to `-Z treat-err-as-bug=1` +//~? RAW [eval_static_initializer] evaluating initializer of static `C` diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr index df5fed3fb8e9..2049df22000a 100644 --- a/tests/ui/treat-err-as-bug/err.stderr +++ b/tests/ui/treat-err-as-bug/err.stderr @@ -1,5 +1,5 @@ error: internal compiler error[E0080]: could not evaluate static initializer - --> $DIR/err.rs:11:21 + --> $DIR/err.rs:9:21 | LL | pub static C: u32 = 0 - 1; | ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow diff --git a/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs b/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs index cfb2d7c52180..3f963888c300 100644 --- a/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs +++ b/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Ztreat-err-as-bug //@ dont-check-failure-status -//@ error-pattern: aborting due to `-Z treat-err-as-bug=1` //@ dont-check-compiler-stderr //@ rustc-env:RUST_BACKTRACE=0 @@ -8,3 +7,5 @@ fn main() { #[deny(while_true)] while true {} //~ ERROR denote infinite loops with `loop { ... }` } + +//~? RAW aborting due to `-Z treat-err-as-bug=1` diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.rs b/tests/ui/treat-err-as-bug/span_delayed_bug.rs index a242d11129f7..4681a8fc1ee0 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.rs +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.rs @@ -1,7 +1,5 @@ //@ compile-flags: -Ztreat-err-as-bug -Zeagerly-emit-delayed-bugs //@ failure-status: 101 -//@ error-pattern: aborting due to `-Z treat-err-as-bug=1` -//@ error-pattern: [trigger_delayed_bug] triggering a delayed bug for testing incremental //@ normalize-stderr: "note: .*\n\n" -> "" //@ normalize-stderr: "thread 'rustc' panicked.*:\n.*\n" -> "" //@ rustc-env:RUST_BACKTRACE=0 @@ -10,3 +8,6 @@ #[rustc_delayed_bug_from_inside_query] fn main() {} //~ ERROR delayed bug triggered by #[rustc_delayed_bug_from_inside_query] + +//~? RAW aborting due to `-Z treat-err-as-bug=1` +//~? RAW [trigger_delayed_bug] triggering a delayed bug for testing incremental diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr index 1c8d279c14c4..88983e95cee7 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr @@ -1,5 +1,5 @@ error: internal compiler error: delayed bug triggered by #[rustc_delayed_bug_from_inside_query] - --> $DIR/span_delayed_bug.rs:12:1 + --> $DIR/span_delayed_bug.rs:10:1 | LL | fn main() {} | ^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.rs b/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.rs new file mode 100644 index 000000000000..bfaa48585ef1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/140731 +// This tests that there's no def path conflict between the +// remapped lifetime and the lifetime present in the source. + +#![feature(impl_trait_in_assoc_type)] + +trait Trait<'a> {} + +impl<'a> Trait<'a> for u32 { + type Opq2 = impl for<'a> Trait<'a>; + //~^ ERROR: unconstrained opaque type + //~| ERROR: type `Opq2` is not a member of trait `Trait` + //~| ERROR: lifetime name `'a` shadows a lifetime name that is already in scope +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.stderr b/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.stderr new file mode 100644 index 000000000000..e1544c5911b9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.stderr @@ -0,0 +1,26 @@ +error[E0437]: type `Opq2` is not a member of trait `Trait` + --> $DIR/lifetime-def-path-conflict-40731.rs:10:5 + | +LL | type Opq2 = impl for<'a> Trait<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `Trait` + +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/lifetime-def-path-conflict-40731.rs:10:26 + | +LL | impl<'a> Trait<'a> for u32 { + | -- first declared here +LL | type Opq2 = impl for<'a> Trait<'a>; + | ^^ lifetime `'a` already in scope + +error: unconstrained opaque type + --> $DIR/lifetime-def-path-conflict-40731.rs:10:17 + | +LL | type Opq2 = impl for<'a> Trait<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Opq2` must be used in combination with a concrete type within the same impl + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0437, E0496. +For more information about an error, try `rustc --explain E0437`. diff --git a/tests/ui/type-inference/regression-issue-81317.rs b/tests/ui/type-inference/regression-issue-81317.rs new file mode 100644 index 000000000000..0b1266e6a0fd --- /dev/null +++ b/tests/ui/type-inference/regression-issue-81317.rs @@ -0,0 +1,71 @@ +// Regression test for #81317: type can no longer be infered as of 1.49 +// +// The problem is that the xor operator and the index.into() call +// each have two candidate impls that could apply +// { S as BitXor, S as BitXor<&'a S> } for xor and +// { T::I as Into, T::I as Into } for index.into() +// previously inference was able to infer that the only valid combination was +// S as BitXor and T::I as Into +// +// after rust-lang/rust#73905 this is no longer infered +// +// the error message could be better e.g. +// when iv is unused or has an an explicitly specified type S +// there is currently the following help message +// +// error[E0284]: type annotations needed +// --> src/main.rs:13:24 +// | +// 44 | let iv = S ^ index.into(); +// | - ^^^^ +// | | +// | type must be known at this point +// | +// = note: cannot satisfy `>::Output == _` +// help: try using a fully qualified path to specify the expected types +// | +// 44 - let iv = S ^ index.into(); +// 44 + let iv = S ^ <::I as Into>::into(index); +// +// this is better as it's actually sufficent to fix the problem, +// while just specifying the type of iv as currently suggested is insufficent +// +//@ check-fail + +use std::ops::BitXor; + +pub struct S; + +pub trait P { + type I: Into + Into; +} + +pub fn decrypt_portion(index: T::I) { + let iv = S ^ index.into(); + //~^ ERROR type annotations needed + &iv.to_bytes_be(); +} + +impl S { + fn to_bytes_be(&self) -> &[u8] { + &[] + } +} + +impl BitXor for S { + type Output = S; + + fn bitxor(self, _rhs: Self) -> Self::Output { + S + } +} + +impl<'a> BitXor<&'a S> for S { + type Output = S; + + fn bitxor(self, _rhs: &'a S) -> Self::Output { + S + } +} + +fn main() {} diff --git a/tests/ui/type-inference/regression-issue-81317.stderr b/tests/ui/type-inference/regression-issue-81317.stderr new file mode 100644 index 000000000000..fcd3fca06e18 --- /dev/null +++ b/tests/ui/type-inference/regression-issue-81317.stderr @@ -0,0 +1,17 @@ +error[E0282]: type annotations needed + --> $DIR/regression-issue-81317.rs:44:9 + | +LL | let iv = S ^ index.into(); + | ^^ +LL | +LL | &iv.to_bytes_be(); + | -- type must be known at this point + | +help: consider giving `iv` an explicit type + | +LL | let iv: /* Type */ = S ^ index.into(); + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-check/point-at-inference-4.rs b/tests/ui/type/type-check/point-at-inference-4.rs index 258374f299e2..504e6aa6db08 100644 --- a/tests/ui/type/type-check/point-at-inference-4.rs +++ b/tests/ui/type/type-check/point-at-inference-4.rs @@ -3,7 +3,6 @@ struct S(Option<(A, B)>); impl S { fn infer(&self, a: A, b: B) {} //~^ NOTE method defined here - //~| NOTE } fn main() { diff --git a/tests/ui/type/type-check/point-at-inference-4.stderr b/tests/ui/type/type-check/point-at-inference-4.stderr index adfb0cebf26e..8630f75d1190 100644 --- a/tests/ui/type/type-check/point-at-inference-4.stderr +++ b/tests/ui/type/type-check/point-at-inference-4.stderr @@ -1,5 +1,5 @@ error[E0061]: this method takes 2 arguments but 1 argument was supplied - --> $DIR/point-at-inference-4.rs:11:7 + --> $DIR/point-at-inference-4.rs:10:7 | LL | s.infer(0i32); | ^^^^^------ argument #2 is missing @@ -15,7 +15,7 @@ LL | s.infer(0i32, /* b */); | +++++++++ error[E0308]: mismatched types - --> $DIR/point-at-inference-4.rs:18:24 + --> $DIR/point-at-inference-4.rs:17:24 | LL | s.infer(0i32); | - ---- this argument has type `i32`... diff --git a/tests/ui/unboxed-closures/arg-constrained-after-closure-inference.rs b/tests/ui/unboxed-closures/arg-constrained-after-closure-inference.rs new file mode 100644 index 000000000000..343a27616d1d --- /dev/null +++ b/tests/ui/unboxed-closures/arg-constrained-after-closure-inference.rs @@ -0,0 +1,16 @@ +#![feature(unboxed_closures)] + +//@ check-pass + +// Regression test for #131758. We only know the type of `x` after closure upvar +// inference is done, even if we don't need to structurally resolve the type of `x`. + +trait Foo {} + +impl> Foo for T {} + +fn baz(_: T) {} + +fn main() { + baz(|x| ()); +} diff --git a/tests/ui/unpretty/exhaustive-asm.hir.stdout b/tests/ui/unpretty/exhaustive-asm.hir.stdout index 5a642dff6f2e..810db69bff16 100644 --- a/tests/ui/unpretty/exhaustive-asm.hir.stdout +++ b/tests/ui/unpretty/exhaustive-asm.hir.stdout @@ -27,5 +27,6 @@ mod expressions { mod items { /// ItemKind::GlobalAsm mod item_global_asm {/// ItemKind::GlobalAsm - global_asm! (".globl my_asm_func") } + global_asm! (".globl my_asm_func"); } +} diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index d2c379d43662..c20f123b16e8 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -8,7 +8,28 @@ // Note: the HIR revision includes a `.stderr` file because there are some // errors that only occur once we get past the AST. -#![feature(auto_traits)]#![feature(box_patterns)]#![feature(builtin_syntax)]#![feature(concat_idents)]#![feature(const_trait_impl)]#![feature(decl_macro)]#![feature(deref_patterns)]#![feature(dyn_star)]#![feature(explicit_tail_calls)]#![feature(gen_blocks)]#![feature(more_qualified_paths)]#![feature(never_patterns)]#![feature(never_type)]#![feature(pattern_types)]#![feature(pattern_type_macro)]#![feature(prelude_import)]#![feature(specialization)]#![feature(trace_macros)]#![feature(trait_alias)]#![feature(try_blocks)]#![feature(yeet_expr)]#![allow(incomplete_features)] +#![feature(auto_traits)] +#![feature(box_patterns)] +#![feature(builtin_syntax)] +#![feature(concat_idents)] +#![feature(const_trait_impl)] +#![feature(decl_macro)] +#![feature(deref_patterns)] +#![feature(dyn_star)] +#![feature(explicit_tail_calls)] +#![feature(gen_blocks)] +#![feature(more_qualified_paths)] +#![feature(never_patterns)] +#![feature(never_type)] +#![feature(pattern_types)] +#![feature(pattern_type_macro)] +#![feature(prelude_import)] +#![feature(specialization)] +#![feature(trace_macros)] +#![feature(trait_alias)] +#![feature(try_blocks)] +#![feature(yeet_expr)] +#![allow(incomplete_features)] #[prelude_import] use std::prelude::rust_2024::*; #[macro_use] @@ -33,20 +54,25 @@ mod prelude { /*! * inner multi-line doc comment */ -#[doc = "inner doc attribute"]#[allow(dead_code, unused_variables)]#[no_std] +#[doc = "inner doc attribute"] +#[allow(dead_code, unused_variables)] +#[no_std] mod attributes {//! inner single-line doc comment /*! * inner multi-line doc comment */ - #![doc = - "inner doc attribute"]#![allow(dead_code, unused_variables)]#![no_std] + #![doc = "inner doc attribute"] + #![allow(dead_code, unused_variables)] + #![no_std] /// outer single-line doc comment /** * outer multi-line doc comment */ - #[doc = - "outer doc attribute"]#[doc = "macro"]#[allow()]#[attr = Repr([ReprC])] + #[doc = "outer doc attribute"] + #[doc = "macro"] + #[allow()] + #[attr = Repr([ReprC])] struct Struct; } @@ -147,32 +173,31 @@ mod expressions { fn expr_for_loop() { let x; { - let _t = - match #[lang = "into_iter"](x) { - mut iter => - loop { - match #[lang = "next"](&mut iter) { - #[lang = "None"] {} => break, - #[lang = "Some"] { 0: _ } => { } - } - }, - }; - _t - }; + let _t = + match #[lang = "into_iter"](x) { + mut iter => + loop { + match #[lang = "next"](&mut iter) { + #[lang = "None"] {} => break, + #[lang = "Some"] { 0: _ } => { } + } + }, + }; + _t + }; { - let _t = - match #[lang = "into_iter"](x) { - mut iter => - 'a: - loop { - match #[lang = "next"](&mut iter) { - #[lang = "None"] {} => break, - #[lang = "Some"] { 0: _ } => { } - } - }, - }; - _t - } + let _t = + match #[lang = "into_iter"](x) { + mut iter => + 'a: loop { + match #[lang = "next"](&mut iter) { + #[lang = "None"] {} => break, + #[lang = "Some"] { 0: _ } => { } + } + }, + }; + _t + } } /// ExprKind::Loop @@ -357,12 +382,11 @@ mod expressions { fn expr_try() { let expr; match #[lang = "branch"](expr) { - #[lang = "Break"] { 0: residual } => - #[allow(unreachable_code)] - return #[lang = "from_residual"](residual), - #[lang = "Continue"] { 0: val } => #[allow(unreachable_code)] - val, - }; + #[lang = "Break"] { 0: residual } => #[allow(unreachable_code)] + return #[lang = "from_residual"](residual), + #[lang = "Continue"] { 0: val } => #[allow(unreachable_code)] + val, + }; } /// ExprKind::Yield fn expr_yield() { yield (); yield true; } diff --git a/tests/ui/unpretty/hir-tree.rs b/tests/ui/unpretty/hir-tree.rs index 3388c60c4253..41ac51641c5e 100644 --- a/tests/ui/unpretty/hir-tree.rs +++ b/tests/ui/unpretty/hir-tree.rs @@ -3,8 +3,9 @@ //@ check-stdout //@ dont-check-compiler-stdout //@ dont-check-compiler-stderr -//@ regex-error-pattern: Hello, Rustaceans! fn main() { println!("Hello, Rustaceans!"); } + +//~? RAW Hello, Rustaceans! diff --git a/tests/ui/use/import_trait_associated_item_bad.rs b/tests/ui/use/import_trait_associated_item_bad.rs new file mode 100644 index 000000000000..d3d2a8e83cdd --- /dev/null +++ b/tests/ui/use/import_trait_associated_item_bad.rs @@ -0,0 +1,18 @@ +#![feature(import_trait_associated_functions)] +#![feature(min_generic_const_args)] +#![allow(incomplete_features)] + +trait Trait { + type AssocTy; + const CONST: usize; +} + +use Trait::AssocTy; +type Alias1 = AssocTy; //~ ERROR ambiguous associated type +type Alias2 = self::AssocTy; //~ ERROR ambiguous associated type + +use Trait::CONST; +type Alias3 = [u8; CONST]; //~ ERROR ambiguous associated constant +type Alias4 = [u8; self::CONST]; //~ ERROR ambiguous associated constant + +fn main() {} diff --git a/tests/ui/use/import_trait_associated_item_bad.stderr b/tests/ui/use/import_trait_associated_item_bad.stderr new file mode 100644 index 000000000000..d5cd5d37bd71 --- /dev/null +++ b/tests/ui/use/import_trait_associated_item_bad.stderr @@ -0,0 +1,49 @@ +error[E0223]: ambiguous associated type + --> $DIR/import_trait_associated_item_bad.rs:11:15 + | +LL | type Alias1 = AssocTy; + | ^^^^^^^ + | +help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path + | +LL | type Alias1 = ::AssocTy; + | ++++++++++++++++++++ + +error[E0223]: ambiguous associated type + --> $DIR/import_trait_associated_item_bad.rs:12:15 + | +LL | type Alias2 = self::AssocTy; + | ^^^^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path + | +LL - type Alias2 = self::AssocTy; +LL + type Alias2 = ::AssocTy; + | + +error[E0223]: ambiguous associated constant + --> $DIR/import_trait_associated_item_bad.rs:15:20 + | +LL | type Alias3 = [u8; CONST]; + | ^^^^^ + | +help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path + | +LL | type Alias3 = [u8; ::CONST]; + | ++++++++++++++++++++ + +error[E0223]: ambiguous associated constant + --> $DIR/import_trait_associated_item_bad.rs:16:20 + | +LL | type Alias4 = [u8; self::CONST]; + | ^^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path + | +LL - type Alias4 = [u8; self::CONST]; +LL + type Alias4 = [u8; ::CONST]; + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/use/import_trait_associated_item_glob.rs b/tests/ui/use/import_trait_associated_item_glob.rs new file mode 100644 index 000000000000..8a712514ed59 --- /dev/null +++ b/tests/ui/use/import_trait_associated_item_glob.rs @@ -0,0 +1,17 @@ +//@ check-pass + +#![feature(import_trait_associated_functions)] + +trait Trait: Default { + fn f() -> Self { Default::default() } + fn g() -> Self { Default::default() } +} + +impl Trait for u8 {} + +use Trait::*; + +fn main() { + let _: u8 = f(); + let _: u8 = g(); +} diff --git a/tests/ui/use/use-from-trait-xc.rs b/tests/ui/use/use-from-trait-xc.rs index b030892aa269..220bf8cad46f 100644 --- a/tests/ui/use/use-from-trait-xc.rs +++ b/tests/ui/use/use-from-trait-xc.rs @@ -6,7 +6,7 @@ use use_from_trait_xc::Trait::foo; //~^ ERROR `use` associated items of traits is unstable [E0658] use use_from_trait_xc::Trait::Assoc; -//~^ ERROR `Assoc` is not directly importable +//~^ ERROR `use` associated items of traits is unstable [E0658] use use_from_trait_xc::Trait::CONST; //~^ ERROR `use` associated items of traits is unstable [E0658] diff --git a/tests/ui/use/use-from-trait-xc.stderr b/tests/ui/use/use-from-trait-xc.stderr index 0f8440aa5307..c8ee29b18d0c 100644 --- a/tests/ui/use/use-from-trait-xc.stderr +++ b/tests/ui/use/use-from-trait-xc.stderr @@ -8,11 +8,15 @@ LL | use use_from_trait_xc::Trait::foo; = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0253]: `Assoc` is not directly importable +error[E0658]: `use` associated items of traits is unstable --> $DIR/use-from-trait-xc.rs:8:5 | LL | use use_from_trait_xc::Trait::Assoc; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #134691 for more information + = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `use` associated items of traits is unstable --> $DIR/use-from-trait-xc.rs:11:5 @@ -74,5 +78,5 @@ LL | struct Foo; error: aborting due to 9 previous errors -Some errors have detailed explanations: E0253, E0432, E0603, E0658. -For more information about an error, try `rustc --explain E0253`. +Some errors have detailed explanations: E0432, E0603, E0658. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/use/use-from-trait.rs b/tests/ui/use/use-from-trait.rs index 89b7aaa4ba38..cab661a29e8e 100644 --- a/tests/ui/use/use-from-trait.rs +++ b/tests/ui/use/use-from-trait.rs @@ -1,5 +1,5 @@ use Trait::foo; //~ ERROR `use` associated items of traits is unstable [E0658] -use Trait::Assoc; //~ ERROR `Assoc` is not directly importable +use Trait::Assoc; //~ ERROR `use` associated items of traits is unstable [E0658] use Trait::C; //~ ERROR `use` associated items of traits is unstable [E0658] use Foo::new; //~ ERROR unresolved import `Foo` [E0432] diff --git a/tests/ui/use/use-from-trait.stderr b/tests/ui/use/use-from-trait.stderr index 2dd78a354529..63cfcc207504 100644 --- a/tests/ui/use/use-from-trait.stderr +++ b/tests/ui/use/use-from-trait.stderr @@ -8,11 +8,15 @@ LL | use Trait::foo; = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0253]: `Assoc` is not directly importable +error[E0658]: `use` associated items of traits is unstable --> $DIR/use-from-trait.rs:2:5 | LL | use Trait::Assoc; - | ^^^^^^^^^^^^ cannot be imported directly + | ^^^^^^^^^^^^ + | + = note: see issue #134691 for more information + = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `use` associated items of traits is unstable --> $DIR/use-from-trait.rs:3:5 @@ -38,5 +42,5 @@ LL | use Foo::C2; error: aborting due to 5 previous errors -Some errors have detailed explanations: E0253, E0432, E0658. -For more information about an error, try `rustc --explain E0253`. +Some errors have detailed explanations: E0432, E0658. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/wf/check-wf-of-normalized-signature.rs b/tests/ui/wf/check-wf-of-normalized-signature.rs new file mode 100644 index 000000000000..5fda69601d99 --- /dev/null +++ b/tests/ui/wf/check-wf-of-normalized-signature.rs @@ -0,0 +1,24 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// Regression test for . +// Ensure that we check the well-formedness of `::Output` after normalizing +// the type to `()`, since we only imply outlives bounds from the normalized signature, so we +// don't know (e.g.) that `&mut T` is WF. + + +trait Mode { + type Output; + fn from_mut(_r: &mut Self::Output) -> Self::Output<&mut T>; +} + +struct Check; + +impl Mode for Check { + type Output = (); + fn from_mut(_r: &mut Self::Output) -> Self::Output<&mut T> {} +} + +fn main() {} diff --git a/tests/ui/wf/wf-normalization-sized.next.stderr b/tests/ui/wf/wf-normalization-sized.next.stderr index 66c4f214415d..804dd0a252d1 100644 --- a/tests/ui/wf/wf-normalization-sized.next.stderr +++ b/tests/ui/wf/wf-normalization-sized.next.stderr @@ -8,7 +8,7 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); = note: slice and array elements must have `Sized` type error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/wf-normalization-sized.rs:22:11 + --> $DIR/wf-normalization-sized.rs:21:11 | LL | const _: as WellUnformed>::RequestNormalize = (); | ^^^^^^^^ doesn't have a size known at compile-time @@ -17,27 +17,6 @@ LL | const _: as WellUnformed>::RequestNormalize = (); note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time - --> $DIR/wf-normalization-sized.rs:19:11 - | -LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); - | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` - = note: slice and array elements must have `Sized` type - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/wf-normalization-sized.rs:22:11 - | -LL | const _: as WellUnformed>::RequestNormalize = (); - | ^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `str` -note: required by an implicit `Sized` bound in `Vec` - --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-normalization-sized.rs b/tests/ui/wf/wf-normalization-sized.rs index 5396cc8b32a8..e695fd93fb0e 100644 --- a/tests/ui/wf/wf-normalization-sized.rs +++ b/tests/ui/wf/wf-normalization-sized.rs @@ -18,9 +18,7 @@ impl WellUnformed for T { const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); //[next]~^ ERROR the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time -//[next]~| ERROR the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time const _: as WellUnformed>::RequestNormalize = (); //[next]~^ ERROR the size for values of type `str` cannot be known at compilation time -//[next]~| ERROR the size for values of type `str` cannot be known at compilation time fn main() {} diff --git a/triagebot.toml b/triagebot.toml index 422996cb200d..1f0afdc44425 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1001,7 +1001,15 @@ message = "This PR changes how GCC is built. Consider updating src/bootstrap/dow message = "This PR changes a file inside `tests/crashes`. If a crash was fixed, please move into the corresponding `ui` subdir and add 'Fixes #' to the PR description to autoclose the issue upon merge." [mentions."tests/rustdoc-json"] -cc = ["@aDotInTheVoid"] +message = """ +These commits modify `tests/rustdoc-json`. +rustdoc-json is a **public** (but unstable) interface. + +Please ensure that if you've changed the output: +- It's intentional. +- The `FORMAT_VERSION` in `src/librustdoc-json-types` is bumped if necessary. +""" +cc = ["@aDotInTheVoid", "@obi1kenobi"] [mentions."tests/ui/deriving/deriving-all-codegen.stdout"] message = "Changes to the code generated for builtin derived traits." @@ -1161,7 +1169,6 @@ compiler = [ "@BoxyUwU", "@compiler-errors", "@davidtwco", - "@estebank", "@fee1-dead", "@fmease", "@jieyouxu", @@ -1221,14 +1228,12 @@ incremental = [ diagnostics = [ "@compiler-errors", "@davidtwco", - "@estebank", "@oli-obk", "@chenyukang", ] parser = [ "@compiler-errors", "@davidtwco", - "@estebank", "@nnethercote", "@petrochenkov", "@spastorino", @@ -1236,7 +1241,6 @@ parser = [ lexer = [ "@nnethercote", "@petrochenkov", - "@estebank", "@chenyukang", ] arena = [ @@ -1268,7 +1272,6 @@ borrowck = [ ] ast_lowering = [ "@compiler-errors", - "@estebank", "@spastorino", ] debuginfo = [ @@ -1394,3 +1397,7 @@ compiletest = [ # Enable issue transfers within the org # Documentation at: https://forge.rust-lang.org/triagebot/transfer.html [transfer] + +# Enable `@rustbot note` functionality +# Documentation at: https://forge.rust-lang.org/triagebot/note.html +[note]