diff options
1328 files changed, 21967 insertions, 12442 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 307e22b0df1..b40066d05d3 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -4,3 +4,5 @@ a06baa56b95674fc626b3c3fd680d6a65357fe60 95e00bfed801e264e9c4ac817004153ca0f19eb6 # reformat with new rustfmt 971c549ca334b7b7406e61e958efcca9c4152822 +# refactor infcx building +283abbf0e7d20176f76006825b5c52e9a4234e4c diff --git a/.mailmap b/.mailmap index 564a68955d3..f887d29096e 100644 --- a/.mailmap +++ b/.mailmap @@ -217,7 +217,7 @@ Hsiang-Cheng Yang <rick68@users.noreply.github.com> Ian Jackson <ijackson@chiark.greenend.org.uk> <ian.jackson@citrix.com> Ian Jackson <ijackson@chiark.greenend.org.uk> <ijackson+github@slimy.greenend.org.uk> Ian Jackson <ijackson@chiark.greenend.org.uk> <iwj@xenproject.org> -Ibraheem Ahmed <ibrah1440@gmail.com> +Ibraheem Ahmed <ibraheem@ibraheem.ca> <ibrah1440@gmail.com> Ilyong Cho <ilyoan@gmail.com> inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> Irina Popa <irinagpopa@gmail.com> diff --git a/Cargo.lock b/Cargo.lock index 33b1299976f..c105d04c1f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,42 +4,27 @@ version = 3 [[package]] name = "addr2line" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "compiler_builtins", - "gimli 0.25.0", + "gimli", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] [[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli 0.26.1", -] - -[[package]] name = "adler" -version = "0.2.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", ] [[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] name = "ahash" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -185,12 +170,12 @@ version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ - "addr2line 0.17.0", + "addr2line", "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide 0.5.3", - "object 0.29.0", + "miniz_oxide", + "object", "rustc-demangle", ] @@ -288,7 +273,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.67.0" +version = "0.68.0" dependencies = [ "anyhow", "atty", @@ -427,7 +412,6 @@ dependencies = [ "glob", "itertools", "lazy_static", - "remove_dir_all", "serde_json", "snapbox", "tar", @@ -449,7 +433,7 @@ dependencies = [ "jobserver", "libc", "log", - "miow", + "miow 0.4.0", "same-file", "shell-escape", "tempfile", @@ -815,7 +799,7 @@ dependencies = [ "lazy_static", "lazycell", "libc", - "miow", + "miow 0.3.7", "miropt-test-tools", "regex", "rustfix", @@ -840,7 +824,7 @@ dependencies = [ "lazy_static", "libc", "log", - "miow", + "miow 0.3.7", "regex", "rustfix", "serde", @@ -853,9 +837,9 @@ dependencies = [ [[package]] name = "concolor" -version = "0.0.8" +version = "0.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "015267563b1df20adccdd00cb05257b1dfbea70a04928e9cf88ffb850c1a40af" +checksum = "b90f9dcd9490a97db91a85ccd79e38a87e14323f0bb824659ee3274e9143ba37" dependencies = [ "atty", "bitflags", @@ -864,9 +848,9 @@ dependencies = [ [[package]] name = "concolor-query" -version = "0.0.5" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6417fe6fc03a8b533fd2177742eeb39a90c7233eedec7bac96d4d6b69a09449" +checksum = "82a90734b3d5dcf656e7624cca6bce9c3a90ee11f900e80141a7427ccfb3d317" [[package]] name = "content_inspector" @@ -1036,9 +1020,9 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d855aeef205b43f65a5001e0997d81f8efca7badad4fad7d897aa7f0d0651f" +checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" dependencies = [ "curl-sys", "libc", @@ -1051,9 +1035,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.55+curl-7.83.1" +version = "0.4.59+curl-7.86.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23734ec77368ec583c2e61dd3f0b0e5c98b93abe6d2a004ca06b91dd7e3e2762" +checksum = "6cfce34829f448b08f55b7db6d0009e23e2e86a34e8c2b366269bf5799b4a407" dependencies = [ "cc", "libc", @@ -1296,15 +1280,15 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" -version = "1.0.16" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e" +checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "crc32fast", "libc", "libz-sys", - "miniz_oxide 0.4.0", + "miniz_oxide", ] [[package]] @@ -1526,11 +1510,11 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -1548,23 +1532,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "gimli" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" dependencies = [ + "compiler_builtins", "fallible-iterator", "indexmap", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", "stable_deref_trait", ] @@ -2229,32 +2205,32 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.4.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ - "adler 0.2.3", + "adler", "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] [[package]] -name = "miniz_oxide" -version = "0.5.3" +name = "miow" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "adler 1.0.2", + "winapi", ] [[package]] name = "miow" -version = "0.3.7" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +checksum = "a7377f7792b3afb6a3cba68daa54ca23c032137010460d667fda53a8d66be00e" dependencies = [ - "winapi", + "windows-sys 0.28.0", ] [[package]] @@ -2340,27 +2316,18 @@ dependencies = [ [[package]] name = "object" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" -dependencies = [ - "compiler_builtins", - "memchr", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "object" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ + "compiler_builtins", "crc32fast", "flate2", "hashbrown", "indexmap", "memchr", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", ] [[package]] @@ -2478,7 +2445,7 @@ name = "panic_abort" version = "0.0.0" dependencies = [ "alloc", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "compiler_builtins", "core", "libc", @@ -2489,7 +2456,7 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "compiler_builtins", "core", "libc", @@ -2514,7 +2481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.3", + "parking_lot_core 0.9.4", ] [[package]] @@ -2533,15 +2500,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2766,9 +2733,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.16" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" dependencies = [ "cc", ] @@ -2817,7 +2784,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom 0.1.14", + "getrandom 0.1.16", "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", @@ -2861,7 +2828,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.14", + "getrandom 0.1.16", ] [[package]] @@ -3297,7 +3264,7 @@ dependencies = [ "cstr", "libc", "measureme", - "object 0.29.0", + "object", "rustc-demangle", "rustc_ast", "rustc_attr", @@ -3331,7 +3298,7 @@ dependencies = [ "itertools", "jobserver", "libc", - "object 0.29.0", + "object", "pathdiff", "regex", "rustc_arena", @@ -3664,7 +3631,6 @@ dependencies = [ name = "rustc_interface" version = "0.0.0" dependencies = [ - "libc", "libloading", "rustc-rayon", "rustc-rayon-core", @@ -3707,7 +3673,6 @@ dependencies = [ "rustc_ty_utils", "smallvec", "tracing", - "winapi", ] [[package]] @@ -4127,6 +4092,7 @@ name = "rustc_session" version = "0.0.0" dependencies = [ "getopts", + "libc", "rustc_ast", "rustc_data_structures", "rustc_errors", @@ -4138,7 +4104,9 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", + "smallvec", "tracing", + "winapi", ] [[package]] @@ -4628,9 +4596,9 @@ checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e" [[package]] name = "snapbox" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d199ccf8f606592df2d145db26f2aa45344e23c64b074cc5a4047f1d99b0f7" +checksum = "827c00e91b15e2674d8a5270bae91f898693cbf9561cbb58d8eaa31974597293" dependencies = [ "concolor", "content_inspector", @@ -4668,9 +4636,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stacker" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90939d5171a4420b3ff5fbc8954d641e7377335454c259dcb80786f3f21dc9b4" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" dependencies = [ "cc", "cfg-if 1.0.0", @@ -4689,7 +4657,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" name = "std" version = "0.0.0" dependencies = [ - "addr2line 0.16.0", + "addr2line", "alloc", "cfg-if 1.0.0", "compiler_builtins", @@ -4699,8 +4667,8 @@ dependencies = [ "hashbrown", "hermit-abi 0.2.6", "libc", - "miniz_oxide 0.4.0", - "object 0.26.2", + "miniz_oxide", + "object", "panic_abort", "panic_unwind", "profiler_builtins", @@ -4887,9 +4855,9 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thin-vec" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "104c2cb3180b6fb6d5b2278768e9b88b578d32ba751ea6e8d026688a40d7ed87" +checksum = "ceb05e71730d396f960f8f3901cdb41be2d339b303e9d7d3a07c5ff0536e671b" [[package]] name = "thiserror" @@ -4917,9 +4885,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6cb0c7868d7f90407531108ab03263d9452a8811b7cdd87675343a40d4aa254" dependencies = [ - "gimli 0.26.1", + "gimli", "hashbrown", - "object 0.29.0", + "object", "tracing", ] @@ -4937,6 +4905,7 @@ name = "tidy" version = "0.1.0" dependencies = [ "cargo_metadata 0.14.0", + "ignore", "lazy_static", "miropt-test-tools", "regex", @@ -5357,7 +5326,7 @@ name = "unwind" version = "0.0.0" dependencies = [ "cc", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "compiler_builtins", "core", "libc", @@ -5476,46 +5445,103 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82ca39602d5cbfa692c4b67e3bcbb2751477355141c1ed434c94da4186836ff6" +dependencies = [ + "windows_aarch64_msvc 0.28.0", + "windows_i686_gnu 0.28.0", + "windows_i686_msvc 0.28.0", + "windows_x86_64_gnu 0.28.0", + "windows_x86_64_msvc 0.28.0", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", ] [[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "xattr" diff --git a/RELEASES.md b/RELEASES.md index a3df56f1d2a..5c1990bb6c9 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -6,7 +6,7 @@ Language - [Error on `as` casts of enums with `#[non_exhaustive]` variants](https://github.com/rust-lang/rust/pull/92744/) - [Stabilize `let else`](https://github.com/rust-lang/rust/pull/93628/) - [Stabilize generic associated types (GATs)](https://github.com/rust-lang/rust/pull/96709/) -- [Add lints `let_underscore_drop`, `let_underscore_lock`, and `let_underscore_must_use` from Clippy](https://github.com/rust-lang/rust/pull/97739/) +- [Add lints `let_underscore_drop` and `let_underscore_lock` from Clippy](https://github.com/rust-lang/rust/pull/97739/) - [Stabilize `break`ing from arbitrary labeled blocks ("label-break-value")](https://github.com/rust-lang/rust/pull/99332/) - [Uninitialized integers, floats, and raw pointers are now considered immediate UB](https://github.com/rust-lang/rust/pull/98919/). Usage of `MaybeUninit` is the correct way to work with uninitialized memory. @@ -87,6 +87,9 @@ Compatibility Notes This strengthens the forward compatibility lint deprecated_cfg_attr_crate_type_name to deny. - [`llvm-has-rust-patches` allows setting the build system to treat the LLVM as having Rust-specific patches](https://github.com/rust-lang/rust/pull/101072) This option may need to be set for distributions that are building Rust with a patched LLVM via `llvm-config`, not the built-in LLVM. +- Combining three or more languages (e.g. Objective C, C++ and Rust) into one binary may hit linker limitations when using `lld`. For more information, see [issue 102754][102754]. + +[102754]: https://github.com/rust-lang/rust/issues/102754 Internal Changes ---------------- diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index fcbf9681825..9253b7e6891 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -14,5 +14,5 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.8" +thin-vec = "0.2.9" tracing = "0.1" diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4ef43735a62..c999b06b0ab 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1208,7 +1208,7 @@ impl Expr { ExprKind::Tup(_) => ExprPrecedence::Tup, ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node), ExprKind::Unary(..) => ExprPrecedence::Unary, - ExprKind::Lit(_) => ExprPrecedence::Lit, + ExprKind::Lit(_) | ExprKind::IncludedBytes(..) => ExprPrecedence::Lit, ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Let(..) => ExprPrecedence::Let, ExprKind::If(..) => ExprPrecedence::If, @@ -1446,6 +1446,12 @@ pub enum ExprKind { /// with an optional value to be returned. Yeet(Option<P<Expr>>), + /// Bytes included via `include_bytes!` + /// Added for optimization purposes to avoid the need to escape + /// large binary blobs - should always behave like [`ExprKind::Lit`] + /// with a `ByteStr` literal. + IncludedBytes(Lrc<[u8]>), + /// Placeholder for an expression that wasn't syntactically well formed in some way. Err, } diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index eeb7e56e2b1..9c1dfeb1a61 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -29,6 +29,7 @@ extern crate rustc_macros; extern crate tracing; pub mod util { + pub mod case; pub mod classify; pub mod comments; pub mod literal; diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index b970e57e017..3ab8267263d 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1428,7 +1428,7 @@ pub fn noop_visit_expr<T: MutVisitor>( } ExprKind::Try(expr) => vis.visit_expr(expr), ExprKind::TryBlock(body) => vis.visit_block(body), - ExprKind::Lit(_) | ExprKind::Err => {} + ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err => {} } vis.visit_id(id); vis.visit_span(span); diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 83b10d906e2..f6aac0b55f1 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -5,6 +5,7 @@ pub use TokenKind::*; use crate::ast; use crate::ptr::P; +use crate::util::case::Case; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; @@ -615,6 +616,15 @@ impl Token { self.is_non_raw_ident_where(|id| id.name == kw) } + /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this token is an identifier equal to `kw` ignoring the case. + pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool { + self.is_keyword(kw) + || (case == Case::Insensitive + && self.is_non_raw_ident_where(|id| { + id.name.as_str().to_lowercase() == kw.as_str().to_lowercase() + })) + } + pub fn is_path_segment_keyword(&self) -> bool { self.is_non_raw_ident_where(Ident::is_path_segment_keyword) } diff --git a/compiler/rustc_ast/src/util/case.rs b/compiler/rustc_ast/src/util/case.rs new file mode 100644 index 00000000000..1afd7dea740 --- /dev/null +++ b/compiler/rustc_ast/src/util/case.rs @@ -0,0 +1,6 @@ +/// Whatever to ignore case (`fn` vs `Fn` vs `FN`) or not. Used for recovering. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum Case { + Sensitive, + Insensitive, +} diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 536b385606c..e267f8cd100 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -2,12 +2,10 @@ use crate::ast::{self, Lit, LitKind}; use crate::token::{self, Token}; - -use rustc_lexer::unescape::{unescape_byte, unescape_char}; -use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode}; +use rustc_data_structures::sync::Lrc; +use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; - use std::ascii; pub enum LitError { @@ -109,13 +107,11 @@ impl LitKind { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_byte_literal(&s, Mode::ByteStr, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } + unescape_literal(&s, Mode::ByteStr, &mut |_, c| match c { + Ok(c) => buf.push(byte_from_char(c)), + Err(err) => { + if err.is_fatal() { + error = Err(LitError::LexerError); } } }); @@ -127,13 +123,11 @@ impl LitKind { let bytes = if s.contains('\r') { let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_byte_literal(&s, Mode::RawByteStr, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } + unescape_literal(&s, Mode::RawByteStr, &mut |_, c| match c { + Ok(c) => buf.push(byte_from_char(c)), + Err(err) => { + if err.is_fatal() { + error = Err(LitError::LexerError); } } }); @@ -238,6 +232,13 @@ impl Lit { Lit { token_lit: kind.to_token_lit(), kind, span } } + /// Recovers an AST literal from a string of bytes produced by `include_bytes!`. + /// This requires ASCII-escaping the string, which can result in poor performance + /// for very large strings of bytes. + pub fn from_included_bytes(bytes: &Lrc<[u8]>, span: Span) -> Lit { + Self::from_lit_kind(LitKind::ByteStr(bytes.clone()), span) + } + /// Losslessly convert an AST literal into a token. pub fn to_token(&self) -> Token { let kind = match self.token_lit.kind { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 6f56c1ef0e8..9053a5a1d64 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -901,7 +901,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { } ExprKind::Try(ref subexpression) => visitor.visit_expr(subexpression), ExprKind::TryBlock(ref body) => visitor.visit_block(body), - ExprKind::Lit(_) | ExprKind::Err => {} + ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err => {} } visitor.visit_expr_post(expression) diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index ce1c8d4997d..6a59b9e6151 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -21,5 +21,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.8" +thin-vec = "0.2.9" tracing = "0.1" diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index ec9c3935020..a4ae493af86 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -87,6 +87,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Lit(ref l) => { hir::ExprKind::Lit(respan(self.lower_span(l.span), l.kind.clone())) } + ExprKind::IncludedBytes(ref bytes) => hir::ExprKind::Lit(respan( + self.lower_span(e.span), + LitKind::ByteStr(bytes.clone()), + )), ExprKind::Cast(ref expr, ref ty) => { let expr = self.lower_expr(expr); let ty = diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 1af1633b524..7fdfc79164b 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -323,7 +323,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // ``` fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::Expr<'hir> { match expr.kind { - ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Err => {} + ExprKind::Lit(..) + | ExprKind::ConstBlock(..) + | ExprKind::IncludedBytes(..) + | ExprKind::Err => {} ExprKind::Path(..) if allow_paths => {} ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} _ => { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index bcefa8ce0b9..930276242c3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -322,6 +322,10 @@ impl<'a> State<'a> { ast::ExprKind::Lit(ref lit) => { self.print_literal(lit); } + ast::ExprKind::IncludedBytes(ref bytes) => { + let lit = ast::Lit::from_included_bytes(bytes, expr.span); + self.print_literal(&lit) + } ast::ExprKind::Cast(ref expr, ref ty) => { let prec = AssocOp::As.precedence() as i8; self.print_expr_maybe_paren(expr, prec); diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 41279588e63..563ff056ae4 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use crate::nll::ToRegionVid; use crate::path_utils::allow_two_phase_borrow; use crate::place_ext::PlaceExt; diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 08ea00d71ef..01be379120d 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -8,9 +8,18 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { pub(crate) fn cannot_move_when_borrowed( &self, span: Span, - desc: &str, + borrow_span: Span, + place: &str, + borrow_place: &str, + value_place: &str, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { - struct_span_err!(self, span, E0505, "cannot move out of {} because it is borrowed", desc,) + self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow { + place, + span, + borrow_place, + value_place, + borrow_span, + }) } pub(crate) fn cannot_use_when_mutably_borrowed( diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs index f185e402fc6..11b31c3f140 100644 --- a/compiler/rustc_borrowck/src/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/constraint_generation.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_infer::infer::InferCtxt; use rustc_middle::mir::visit::TyContext; use rustc_middle::mir::visit::Visitor; diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs index 609fbc2bc15..385f153174c 100644 --- a/compiler/rustc_borrowck/src/constraints/graph.rs +++ b/compiler/rustc_borrowck/src/constraints/graph.rs @@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> { span: DUMMY_SP, category: ConstraintCategory::Internal, variance_info: VarianceDiagInfo::default(), + from_closure: false, }) } else { None diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index df04128135b..84a93e5f72e 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use rustc_data_structures::graph::scc::Sccs; use rustc_index::vec::IndexVec; use rustc_middle::mir::ConstraintCategory; @@ -96,6 +99,9 @@ pub struct OutlivesConstraint<'tcx> { /// Variance diagnostic information pub variance_info: VarianceDiagInfo<'tcx>, + + /// If this constraint is promoted from closure requirements. + pub from_closure: bool, } impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> { diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index b162095f8a6..86da767f322 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] //! This file provides API for compiler consumers. use rustc_hir::def_id::LocalDefId; diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 9f7a4d49989..8070c0e6710 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::BitSet; use rustc_middle::mir::{self, BasicBlock, Body, Location, Place}; diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index a5c0d77429d..8e62a0198be 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_middle::mir::visit::{ MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext, }; diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index dac6abe37f5..b99bfda1a51 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; @@ -158,6 +161,7 @@ trait TypeOpInfo<'tcx> { error_region: Option<ty::Region<'tcx>>, ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>; + #[instrument(level = "debug", skip(self, mbcx))] fn report_error( &self, mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, @@ -167,6 +171,7 @@ trait TypeOpInfo<'tcx> { ) { let tcx = mbcx.infcx.tcx; let base_universe = self.base_universe(); + debug!(?base_universe); let Some(adjusted_universe) = placeholder.universe.as_u32().checked_sub(base_universe.as_u32()) @@ -389,6 +394,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( ) } +#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))] fn try_extract_error_from_region_constraints<'tcx>( infcx: &InferCtxt<'tcx>, placeholder_region: ty::Region<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 583bc2e281d..9e0aa57b255 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -23,7 +23,6 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::sym; use rustc_span::{BytePos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; -use rustc_trait_selection::traits::TraitEngineExt as _; use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; @@ -225,10 +224,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - use_spans.var_span_label_path_only( - &mut err, - format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), - ); + use_spans.var_path_only_subdiag(&mut err, desired_action); if !is_loop_move { err.span_label( @@ -405,10 +401,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let used = desired_action.as_general_verb_in_past_tense(); let mut err = struct_span_err!(self, span, E0381, "{used} binding {desc}{isnt_initialized}"); - use_spans.var_span_label_path_only( - &mut err, - format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), - ); + use_spans.var_path_only_subdiag(&mut err, desired_action); if let InitializationRequiringAction::PartialAssignment | InitializationRequiringAction::Assignment = desired_action @@ -613,24 +606,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { else { return; }; // Try to find predicates on *generic params* that would allow copying `ty` let infcx = tcx.infer_ctxt().build(); - let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx); - let copy_did = infcx.tcx.lang_items().copy_trait().unwrap(); let cause = ObligationCause::new( span, self.mir_hir_id(), rustc_infer::traits::ObligationCauseCode::MiscObligation, ); - fulfill_cx.register_bound( + let errors = rustc_trait_selection::traits::fully_solve_bound( &infcx, + cause, self.param_env, // Erase any region vids from the type, which may not be resolved infcx.tcx.erase_regions(ty), copy_did, - cause, ); - // Select all, including ambiguous predicates - let errors = fulfill_cx.select_all_or_error(&infcx); // Only emit suggestion if all required predicates are on generic let predicates: Result<Vec<_>, _> = errors @@ -678,16 +667,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let move_spans = self.move_spans(place.as_ref(), location); let span = move_spans.args_or_use(); - let mut err = - self.cannot_move_when_borrowed(span, &self.describe_any_place(place.as_ref())); - err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); - err.span_label(span, format!("move out of {} occurs here", value_msg)); - - borrow_spans.var_span_label_path_only( - &mut err, - format!("borrow occurs due to use{}", borrow_spans.describe()), + let mut err = self.cannot_move_when_borrowed( + span, + borrow_span, + &self.describe_any_place(place.as_ref()), + &borrow_msg, + &value_msg, ); + borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow); + move_spans.var_span_label( &mut err, format!("move occurs due to use{}", move_spans.describe()), @@ -729,16 +718,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - - borrow_spans.var_span_label( - &mut err, - { - let place = &borrow.borrowed_place; - let desc_place = self.describe_any_place(place.as_ref()); - format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe()) - }, - "mutable", - ); + borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + let place = &borrow.borrowed_place; + let desc_place = self.describe_any_place(place.as_ref()); + match kind { + Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span }, + None => BorrowUsePlaceClosure { place: desc_place, var_span }, + } + }); self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( @@ -1556,7 +1544,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let mut err = self.temporary_value_borrowed_for_too_long(proper_span); - err.span_label(proper_span, "creates a temporary which is freed while still in use"); + err.span_label(proper_span, "creates a temporary value which is freed while still in use"); err.span_label(drop_span, "temporary value is freed at the end of this statement"); match explanation { diff --git a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs index b3edc35dc36..498e9834354 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use std::collections::BTreeSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index b5a3081e56a..15f42e26cbf 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use std::collections::VecDeque; use std::rc::Rc; diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 534d9ecae6e..7f26af67c71 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -595,11 +595,34 @@ impl UseSpans<'_> { } } - // Add a span label to the use of the captured variable, if it exists. - // only adds label to the `path_span` - pub(super) fn var_span_label_path_only(self, err: &mut Diagnostic, message: impl Into<String>) { - if let UseSpans::ClosureUse { path_span, .. } = self { - err.span_label(path_span, message); + /// Add a span label to the use of the captured variable, if it exists. + /// only adds label to the `path_span` + pub(super) fn var_path_only_subdiag( + self, + err: &mut Diagnostic, + action: crate::InitializationRequiringAction, + ) { + use crate::session_diagnostics::CaptureVarPathUseCause::*; + use crate::InitializationRequiringAction::*; + if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self { + match generator_kind { + Some(_) => { + err.subdiagnostic(match action { + Borrow => BorrowInGenerator { path_span }, + MatchOn | Use => UseInGenerator { path_span }, + Assignment => AssignInGenerator { path_span }, + PartialAssignment => AssignPartInGenerator { path_span }, + }); + } + None => { + err.subdiagnostic(match action { + Borrow => BorrowInClosure { path_span }, + MatchOn | Use => UseInClosure { path_span }, + Assignment => AssignInClosure { path_span }, + PartialAssignment => AssignPartInClosure { path_span }, + }); + } + } } } @@ -623,6 +646,35 @@ impl UseSpans<'_> { } } + /// Add a subdiagnostic to the use of the captured variable, if it exists. + pub(super) fn var_subdiag( + self, + err: &mut Diagnostic, + kind: Option<rustc_middle::mir::BorrowKind>, + f: impl Fn(Option<GeneratorKind>, Span) -> crate::session_diagnostics::CaptureVarCause, + ) { + use crate::session_diagnostics::CaptureVarKind::*; + if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self { + if capture_kind_span != path_span { + err.subdiagnostic(match kind { + Some(kd) => match kd { + rustc_middle::mir::BorrowKind::Shared + | rustc_middle::mir::BorrowKind::Shallow + | rustc_middle::mir::BorrowKind::Unique => { + Immute { kind_span: capture_kind_span } + } + + rustc_middle::mir::BorrowKind::Mut { .. } => { + Mut { kind_span: capture_kind_span } + } + }, + None => Move { kind_span: capture_kind_span }, + }); + }; + err.subdiagnostic(f(generator_kind, path_span)); + } + } + /// Returns `false` if this place is not used in a closure. pub(super) fn for_closure(&self) -> bool { match *self { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 8ad40c0aa0a..7457369aa58 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1,6 +1,4 @@ -use rustc_errors::{ - Applicability, Diagnostic, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, -}; +use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; @@ -629,25 +627,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.buffer_error(err); } - fn suggest_map_index_mut_alternatives( - &self, - ty: Ty<'_>, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, - span: Span, - ) { + fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diagnostic, span: Span) { let Some(adt) = ty.ty_adt_def() else { return }; let did = adt.did(); if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did) || self.infcx.tcx.is_diagnostic_item(sym::BTreeMap, did) { - struct V<'a, 'b, 'tcx, G: EmissionGuarantee> { + struct V<'a, 'tcx> { assign_span: Span, - err: &'a mut DiagnosticBuilder<'b, G>, + err: &'a mut Diagnostic, ty: Ty<'tcx>, suggested: bool, } - impl<'a, 'b: 'a, 'hir, 'tcx, G: EmissionGuarantee> Visitor<'hir> for V<'a, 'b, 'tcx, G> { - fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'hir>) { + impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> { + fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { hir::intravisit::walk_stmt(self, stmt); let expr = match stmt.kind { hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr) => expr, @@ -705,7 +698,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ), (rv.span.shrink_to_hi(), ")".to_string()), ], - ].into_iter(), + ], Applicability::MachineApplicable, ); self.suggested = true; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 15230718dc0..76f249dac51 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -2,7 +2,7 @@ #![deny(rustc::diagnostic_outside_of_impl)] //! Error reporting machinery for lifetime errors. -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -181,7 +181,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Try to convert the lower-bound region into something named we can print for the user. let lower_bound_region = self.to_error_region(type_test.lower_bound); - let type_test_span = type_test.locations.span(&self.body); + let type_test_span = type_test.span; if let Some(lower_bound_region) = lower_bound_region { let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx); @@ -276,7 +276,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn get_impl_ident_and_self_ty_from_trait( &self, def_id: DefId, - trait_objects: &FxHashSet<DefId>, + trait_objects: &FxIndexSet<DefId>, ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { let tcx = self.infcx.tcx; match tcx.hir().get_if_local(def_id) { @@ -830,7 +830,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; debug!(?param); - let mut visitor = TraitObjectVisitor(FxHashSet::default()); + let mut visitor = TraitObjectVisitor(FxIndexSet::default()); visitor.visit_ty(param.param_ty); let Some((ident, self_ty)) = @@ -843,7 +843,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn suggest_constrain_dyn_trait_in_impl( &self, err: &mut Diagnostic, - found_dids: &FxHashSet<DefId>, + found_dids: &FxIndexSet<DefId>, ident: Ident, self_ty: &hir::Ty<'_>, ) -> bool { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index c044dbaba47..f9741bacd17 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -355,7 +355,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { }) } - ty::BoundRegionKind::BrAnon(_) => None, + ty::BoundRegionKind::BrAnon(..) => None, }, ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None, diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 9ba29f04b1a..b385f95b67c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use crate::Upvar; use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext}; use rustc_index::vec::{Idx, IndexVec}; diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index 22134d5a71c..51ed27c167d 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use crate::location::{LocationIndex, LocationTable}; use crate::BorrowIndex; use polonius_engine::AllFacts as PoloniusFacts; diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 3157f861d93..f5317a143ae 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue}; diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index abfe253d43d..4a4887f1970 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -18,6 +18,7 @@ extern crate tracing; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::vec_map::VecMap; use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -129,6 +130,19 @@ fn mir_borrowck<'tcx>( ) -> &'tcx BorrowCheckResult<'tcx> { let (input_body, promoted) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id())); + + if input_body.borrow().should_skip() { + debug!("Skipping borrowck because of injected body"); + // Let's make up a borrowck result! Fun times! + let result = BorrowCheckResult { + concrete_opaque_types: VecMap::new(), + closure_requirements: None, + used_mut_upvars: SmallVec::new(), + tainted_by_errors: None, + }; + return tcx.arena.alloc(result); + } + let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner; let infcx = diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs index 877944d3d70..9fa7e218b1b 100644 --- a/compiler/rustc_borrowck/src/location.rs +++ b/compiler/rustc_borrowck/src/location.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::{BasicBlock, Body, Location}; diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs index 43253a2aab0..b48f9f97daa 100644 --- a/compiler/rustc_borrowck/src/member_constraints.rs +++ b/compiler/rustc_borrowck/src/member_constraints.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::IndexVec; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 08fdd28eb01..f8856b56d14 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] //! The entry point of the NLL borrow checker. use rustc_data_structures::vec_map::VecMap; @@ -242,7 +244,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>( mut liveness_constraints, outlives_constraints, member_constraints, - closure_bounds_mapping, universe_causes, type_tests, } = constraints; @@ -264,7 +265,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>( universal_region_relations, outlives_constraints, member_constraints, - closure_bounds_mapping, universe_causes, type_tests, liveness_constraints, diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index b2c8dfc82c2..f8a99a2699e 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; use crate::places_conflict; use crate::AccessDepth; diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs index 93d202e49a1..9f6b1fdfcb5 100644 --- a/compiler/rustc_borrowck/src/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use crate::borrow_set::LocalsStateAtExit; use rustc_hir as hir; use rustc_middle::mir::ProjectionElem; diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 0e71efd6f8d..8a87d1972eb 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use crate::ArtificialField; use crate::Overlap; use crate::{AccessDepth, Deep, Shallow}; diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index 2b50cbac9a0..6f281349863 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] //! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an //! place are formed by stripping away fields and derefs, except that //! we stop when we reach the deref of a shared reference. [...] " diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index fe5193102f9..6524b594e44 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] //! As part of generating the regions, if you enable `-Zdump-mir=nll`, //! we will generate an annotated copy of the MIR that includes the //! state of region inference. This code handles emitting the region @@ -74,8 +76,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut constraints: Vec<_> = self.constraints.outlives().iter().collect(); constraints.sort_by_key(|c| (c.sup, c.sub)); for constraint in &constraints { - let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } = - constraint; + let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint; let (name, arg) = match locations { Locations::All(span) => { ("All", tcx.sess.source_map().span_to_embeddable_string(*span)) diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index f31ccd74ca6..2e15586e03b 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] //! This module provides linkage between RegionInferenceContext and //! `rustc_graphviz` traits, specialized to attaching borrowck analysis //! data to rendered labels. diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 8b63294fbab..94e9e05e5d6 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::scc::Sccs; use rustc_errors::Diagnostic; -use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; +use rustc_hir::def_id::CRATE_DEF_ID; use rustc_hir::CRATE_HIR_ID; use rustc_index::vec::IndexVec; -use rustc_infer::infer::canonical::QueryOutlivesConstraint; use rustc_infer::infer::outlives::test_type_match; use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; @@ -19,9 +18,7 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCauseCode; -use rustc_middle::ty::{ - self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable, -}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_span::Span; use crate::{ @@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> { /// `member_region_scc`. member_constraints_applied: Vec<AppliedMemberConstraint>, - /// Map closure bounds to a `Span` that should be used for error reporting. - closure_bounds_mapping: - FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>, - /// Map universe indexes to information on why we created it. universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>, @@ -221,8 +214,8 @@ pub struct TypeTest<'tcx> { /// The region `'x` that the type must outlive. pub lower_bound: RegionVid, - /// Where did this constraint arise and why? - pub locations: Locations, + /// The span to blame. + pub span: Span, /// A test which, if met by the region `'x`, proves that this type /// constraint is satisfied. @@ -265,10 +258,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>, outlives_constraints: OutlivesConstraintSet<'tcx>, member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, - closure_bounds_mapping: FxHashMap< - Location, - FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>, - >, universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>, type_tests: Vec<TypeTest<'tcx>>, liveness_constraints: LivenessValues<RegionVid>, @@ -310,7 +299,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { rev_scc_graph: None, member_constraints, member_constraints_applied: Vec::new(), - closure_bounds_mapping, universe_causes, scc_universes, scc_representatives, @@ -882,13 +870,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { if deduplicate_errors.insert(( erased_generic_kind, type_test.lower_bound, - type_test.locations, + type_test.span, )) { debug!( "check_type_test: reporting error for erased_generic_kind={:?}, \ lower_bound_region={:?}, \ - type_test.locations={:?}", - erased_generic_kind, type_test.lower_bound, type_test.locations, + type_test.span={:?}", + erased_generic_kind, type_test.lower_bound, type_test.span, ); errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() }); @@ -931,7 +919,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> bool { let tcx = infcx.tcx; - let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test; + let TypeTest { generic_kind, lower_bound, span: _, verify_bound: _ } = type_test; let generic_ty = generic_kind.to_ty(tcx); let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else { @@ -959,7 +947,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { propagated_outlives_requirements.push(ClosureOutlivesRequirement { subject, outlived_free_region: static_r, - blame_span: locations.span(body), + blame_span: type_test.span, category: ConstraintCategory::Boring, }); @@ -1011,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let requirement = ClosureOutlivesRequirement { subject, outlived_free_region: upper_bound, - blame_span: locations.span(body), + blame_span: type_test.span, category: ConstraintCategory::Boring, }; debug!("try_promote_type_test: pushing {:#?}", requirement); @@ -1804,18 +1792,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - pub(crate) fn retrieve_closure_constraint_info( - &self, - constraint: OutlivesConstraint<'tcx>, - ) -> Option<(ConstraintCategory<'tcx>, Span)> { - match constraint.locations { - Locations::All(_) => None, - Locations::Single(loc) => { - self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied() - } - } - } - /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`. pub(crate) fn find_outlives_blame_span( &self, @@ -1921,6 +1897,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { span: p_c.definition_span, category: ConstraintCategory::OpaqueType, variance_info: ty::VarianceDiagInfo::default(), + from_closure: false, }; handle_constraint(constraint); } @@ -2066,31 +2043,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Classify each of the constraints along the path. let mut categorized_path: Vec<BlameConstraint<'tcx>> = path .iter() - .map(|constraint| { - let (category, span, from_closure, cause_code) = - if constraint.category == ConstraintCategory::ClosureBounds { - if let Some((category, span)) = - self.retrieve_closure_constraint_info(*constraint) - { - (category, span, true, ObligationCauseCode::MiscObligation) - } else { - ( - constraint.category, - constraint.span, - false, - ObligationCauseCode::MiscObligation, - ) - } - } else { - (constraint.category, constraint.span, false, cause_code.clone()) - }; - BlameConstraint { - category, - from_closure, - cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code), - variance_info: constraint.variance_info, - outlives_constraint: *constraint, - } + .map(|constraint| BlameConstraint { + category: constraint.category, + from_closure: constraint.from_closure, + cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()), + variance_info: constraint.variance_info, + outlives_constraint: *constraint, }) .collect(); debug!("categorized_path={:#?}", categorized_path); @@ -2274,92 +2232,6 @@ impl<'tcx> RegionDefinition<'tcx> { } } -pub trait ClosureRegionRequirementsExt<'tcx> { - fn apply_requirements( - &self, - tcx: TyCtxt<'tcx>, - closure_def_id: DefId, - closure_substs: SubstsRef<'tcx>, - ) -> Vec<QueryOutlivesConstraint<'tcx>>; -} - -impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> { - /// Given an instance T of the closure type, this method - /// instantiates the "extra" requirements that we computed for the - /// closure into the inference context. This has the effect of - /// adding new outlives obligations to existing variables. - /// - /// As described on `ClosureRegionRequirements`, the extra - /// requirements are expressed in terms of regionvids that index - /// into the free regions that appear on the closure type. So, to - /// do this, we first copy those regions out from the type T into - /// a vector. Then we can just index into that vector to extract - /// out the corresponding region from T and apply the - /// requirements. - fn apply_requirements( - &self, - tcx: TyCtxt<'tcx>, - closure_def_id: DefId, - closure_substs: SubstsRef<'tcx>, - ) -> Vec<QueryOutlivesConstraint<'tcx>> { - debug!( - "apply_requirements(closure_def_id={:?}, closure_substs={:?})", - closure_def_id, closure_substs - ); - - // Extract the values of the free regions in `closure_substs` - // into a vector. These are the regions that we will be - // relating to one another. - let closure_mapping = &UniversalRegions::closure_mapping( - tcx, - closure_substs, - self.num_external_vids, - tcx.typeck_root_def_id(closure_def_id), - ); - debug!("apply_requirements: closure_mapping={:?}", closure_mapping); - - // Create the predicates. - self.outlives_requirements - .iter() - .map(|outlives_requirement| { - let outlived_region = closure_mapping[outlives_requirement.outlived_free_region]; - - match outlives_requirement.subject { - ClosureOutlivesSubject::Region(region) => { - let region = closure_mapping[region]; - debug!( - "apply_requirements: region={:?} \ - outlived_region={:?} \ - outlives_requirement={:?}", - region, outlived_region, outlives_requirement, - ); - ( - ty::Binder::dummy(ty::OutlivesPredicate( - region.into(), - outlived_region, - )), - ConstraintCategory::BoringNoLocation, - ) - } - - ClosureOutlivesSubject::Ty(ty) => { - debug!( - "apply_requirements: ty={:?} \ - outlived_region={:?} \ - outlives_requirement={:?}", - ty, outlived_region, outlives_requirement, - ); - ( - ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)), - ConstraintCategory::BoringNoLocation, - ) - } - } - }) - .collect() - } -} - #[derive(Clone, Debug)] pub struct BlameConstraint<'tcx> { pub category: ConstraintCategory<'tcx>, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 465f353aaa3..dd222485daf 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -4,7 +4,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::OpaqueTyOrigin; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::infer::{DefiningAnchor, InferCtxt}; -use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; +use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ @@ -12,7 +12,7 @@ use rustc_middle::ty::{ }; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::TraitEngineExt as _; +use rustc_trait_selection::traits::ObligationCtxt; use super::RegionInferenceContext; @@ -252,48 +252,45 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { // type-alias-impl-trait/issue-67844-nested-opaque.rs let infcx = self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build(); + let ocx = ObligationCtxt::new(&infcx); // Require the hidden type to be well-formed with only the generics of the opaque type. // Defining use functions may have more bounds than the opaque type, which is ok, as long as the // hidden type is well formed even without those bounds. let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) .to_predicate(infcx.tcx); - let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx); let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id()); // Require that the hidden type actually fulfills all the bounds of the opaque type, even without // the bounds that the function supplies. let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs); - match infcx - .at(&ObligationCause::misc(instantiated_ty.span, body_id), param_env) - .eq(opaque_ty, definition_ty) - { - Ok(infer_ok) => { - for obligation in infer_ok.obligations { - fulfillment_cx.register_predicate_obligation(&infcx, obligation); - } - } - Err(err) => { - infcx - .err_ctxt() - .report_mismatched_types( - &ObligationCause::misc(instantiated_ty.span, body_id), - opaque_ty, - definition_ty, - err, - ) - .emit(); - } + if let Err(err) = ocx.eq( + &ObligationCause::misc(instantiated_ty.span, body_id), + param_env, + opaque_ty, + definition_ty, + ) { + infcx + .err_ctxt() + .report_mismatched_types( + &ObligationCause::misc(instantiated_ty.span, body_id), + opaque_ty, + definition_ty, + err, + ) + .emit(); } - fulfillment_cx.register_predicate_obligation( - &infcx, - Obligation::misc(instantiated_ty.span, body_id, param_env, predicate), - ); + ocx.register_obligation(Obligation::misc( + instantiated_ty.span, + body_id, + param_env, + predicate, + )); // Check that all obligations are satisfied by the implementation's // version. - let errors = fulfillment_cx.select_all_or_error(&infcx); + let errors = ocx.select_all_or_error(); // This is still required for many(half of the tests in ui/type-alias-impl-trait) // tests to pass @@ -302,8 +299,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { if errors.is_empty() { definition_ty } else { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); - self.tcx.ty_error() + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); + self.tcx.ty_error_with_guaranteed(reported) } } } diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs index 1e6798eee3d..167f6646096 100644 --- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs +++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use crate::constraints::ConstraintSccIndex; use crate::RegionInferenceContext; use itertools::Itertools; diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index de20a4bb465..7498ddccf19 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::SparseBitMatrix; use rustc_index::interval::IntervalSet; diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index f3023769081..084754830bd 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_index::vec::IndexVec; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_middle::mir::visit::{MutVisitor, TyContext}; diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index fe24f85fae1..577332c0744 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -148,3 +148,95 @@ pub(crate) enum RequireStaticErr { multi_span: MultiSpan, }, } + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureVarPathUseCause { + #[label(borrowck_borrow_due_to_use_generator)] + BorrowInGenerator { + #[primary_span] + path_span: Span, + }, + #[label(borrowck_use_due_to_use_generator)] + UseInGenerator { + #[primary_span] + path_span: Span, + }, + #[label(borrowck_assign_due_to_use_generator)] + AssignInGenerator { + #[primary_span] + path_span: Span, + }, + #[label(borrowck_assign_part_due_to_use_generator)] + AssignPartInGenerator { + #[primary_span] + path_span: Span, + }, + #[label(borrowck_borrow_due_to_use_closure)] + BorrowInClosure { + #[primary_span] + path_span: Span, + }, + #[label(borrowck_use_due_to_use_closure)] + UseInClosure { + #[primary_span] + path_span: Span, + }, + #[label(borrowck_assign_due_to_use_closure)] + AssignInClosure { + #[primary_span] + path_span: Span, + }, + #[label(borrowck_assign_part_due_to_use_closure)] + AssignPartInClosure { + #[primary_span] + path_span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureVarKind { + #[label(borrowck_capture_immute)] + Immute { + #[primary_span] + kind_span: Span, + }, + #[label(borrowck_capture_mut)] + Mut { + #[primary_span] + kind_span: Span, + }, + #[label(borrowck_capture_move)] + Move { + #[primary_span] + kind_span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureVarCause { + #[label(borrowck_var_borrow_by_use_place_in_generator)] + BorrowUsePlaceGenerator { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_borrow_by_use_place_in_closure)] + BorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, +} + +#[derive(Diagnostic)] +#[diag(borrowck_cannot_move_when_borrowed, code = "E0505")] +pub(crate) struct MoveBorrow<'a> { + pub place: &'a str, + pub borrow_place: &'a str, + pub value_place: &'a str, + #[primary_span] + #[label(move_label)] + pub span: Span, + #[label] + pub borrow_span: Span, +} diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index d5bfc2f5208..ce7f857e273 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -1,10 +1,10 @@ -use rustc_infer::infer::canonical::QueryOutlivesConstraint; +use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; -use rustc_middle::mir::ConstraintCategory; +use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, TyCtxt}; @@ -38,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { locations: Locations, span: Span, category: ConstraintCategory<'tcx>, + from_closure: bool, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } @@ -64,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { span, category, constraints, + from_closure: false, } } @@ -81,12 +83,62 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } self.constraints.member_constraints = tmp; - for query_constraint in outlives { - self.convert(query_constraint); + for (predicate, constraint_category) in outlives { + // At the moment, we never generate any "higher-ranked" + // region constraints like `for<'a> 'a: 'b`. At some point + // when we move to universes, we will, and this assertion + // will start to fail. + let predicate = predicate.no_bound_vars().unwrap_or_else(|| { + bug!("query_constraint {:?} contained bound vars", predicate,); + }); + + self.convert(predicate, *constraint_category); } } - fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) { + /// Given an instance of the closure type, this method instantiates the "extra" requirements + /// that we computed for the closure. This has the effect of adding new outlives obligations + /// to existing region variables in `closure_substs`. + #[instrument(skip(self), level = "debug")] + pub fn apply_closure_requirements( + &mut self, + closure_requirements: &ClosureRegionRequirements<'tcx>, + closure_def_id: DefId, + closure_substs: ty::SubstsRef<'tcx>, + ) { + // Extract the values of the free regions in `closure_substs` + // into a vector. These are the regions that we will be + // relating to one another. + let closure_mapping = &UniversalRegions::closure_mapping( + self.tcx, + closure_substs, + closure_requirements.num_external_vids, + closure_def_id.expect_local(), + ); + debug!(?closure_mapping); + + // Create the predicates. + let backup = (self.category, self.span, self.from_closure); + self.from_closure = true; + for outlives_requirement in &closure_requirements.outlives_requirements { + let outlived_region = closure_mapping[outlives_requirement.outlived_free_region]; + let subject = match outlives_requirement.subject { + ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(), + ClosureOutlivesSubject::Ty(ty) => ty.into(), + }; + + self.category = outlives_requirement.category; + self.span = outlives_requirement.blame_span; + self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category); + } + (self.category, self.span, self.from_closure) = backup; + } + + fn convert( + &mut self, + predicate: ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>, + constraint_category: ConstraintCategory<'tcx>, + ) { debug!("generate: constraints at: {:#?}", self.locations); // Extract out various useful fields we'll need below. @@ -94,17 +146,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { tcx, region_bound_pairs, implicit_region_bound, param_env, .. } = *self; - // At the moment, we never generate any "higher-ranked" - // region constraints like `for<'a> 'a: 'b`. At some point - // when we move to universes, we will, and this assertion - // will start to fail. - let ty::OutlivesPredicate(k1, r2) = - query_constraint.0.no_bound_vars().unwrap_or_else(|| { - bug!("query_constraint {:?} contained bound vars", query_constraint,); - }); - - let constraint_category = query_constraint.1; - + let ty::OutlivesPredicate(k1, r2) = predicate; match k1.unpack() { GenericArgKind::Lifetime(r1) => { let r1_vid = self.to_region_vid(r1); @@ -127,10 +169,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { .type_must_outlive(origin, t1, r2, constraint_category); } - GenericArgKind::Const(_) => { - // Consts cannot outlive one another, so we - // don't need to handle any relations here. - } + GenericArgKind::Const(_) => unreachable!(), } } @@ -160,7 +199,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { verify_bound: VerifyBound<'tcx>, ) -> TypeTest<'tcx> { let lower_bound = self.to_region_vid(region); - TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound } + TypeTest { generic_kind, lower_bound, span: self.span, verify_bound } } fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid { @@ -188,6 +227,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { sub, sup, variance_info: ty::VarianceDiagInfo::default(), + from_closure: self.from_closure, }); } 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 02909592637..14cfc3613bf 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -247,12 +247,13 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { .and(type_op::normalize::Normalize::new(ty)) .fully_perform(self.infcx) .unwrap_or_else(|_| { - self.infcx + let reported = self + .infcx .tcx .sess .delay_span_bug(span, &format!("failed to normalize {:?}", ty)); TypeOpOutput { - output: self.infcx.tcx.ty_error(), + output: self.infcx.tcx.ty_error_with_guaranteed(reported), constraints: None, error_info: None, } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3c1c3ab45ce..6ccc29b09c0 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] //! This pass type-checks the MIR to ensure it is not broken. use std::rc::Rc; @@ -27,7 +29,7 @@ use rustc_middle::mir::AssertKind; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::cast::CastTy; -use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; +use rustc_middle::ty::subst::{SubstsRef, UserSubsts}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic, @@ -61,7 +63,7 @@ use crate::{ region_infer::values::{ LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements, }, - region_infer::{ClosureRegionRequirementsExt, TypeTest}, + region_infer::TypeTest, type_check::free_region_relations::{CreateResult, UniversalRegionRelations}, universal_regions::{DefiningTy, UniversalRegions}, Upvar, @@ -144,7 +146,6 @@ pub(crate) fn type_check<'mir, 'tcx>( liveness_constraints: LivenessValues::new(elements.clone()), outlives_constraints: OutlivesConstraintSet::default(), member_constraints: MemberConstraintSet::default(), - closure_bounds_mapping: Default::default(), type_tests: Vec::default(), universe_causes: FxHashMap::default(), }; @@ -234,11 +235,11 @@ pub(crate) fn type_check<'mir, 'tcx>( let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind()); if hidden_type.has_non_region_infer() { - infcx.tcx.sess.delay_span_bug( + let reported = infcx.tcx.sess.delay_span_bug( decl.hidden_type.span, &format!("could not resolve {:#?}", hidden_type.ty.kind()), ); - hidden_type.ty = infcx.tcx.ty_error(); + hidden_type.ty = infcx.tcx.ty_error_with_guaranteed(reported); } (opaque_type_key, (hidden_type, decl.origin)) @@ -584,8 +585,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // modify their locations. let all_facts = &mut None; let mut constraints = Default::default(); - let mut type_tests = Default::default(); - let mut closure_bounds = Default::default(); let mut liveness_constraints = LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body))); // Don't try to add borrow_region facts for the promoted MIR @@ -596,11 +595,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { &mut this.cx.borrowck_context.constraints.outlives_constraints, &mut constraints, ); - mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests); - mem::swap( - &mut this.cx.borrowck_context.constraints.closure_bounds_mapping, - &mut closure_bounds, - ); mem::swap( &mut this.cx.borrowck_context.constraints.liveness_constraints, &mut liveness_constraints, @@ -621,13 +615,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { swap_constraints(self); let locations = location.to_locations(); - - // Use location of promoted const in collected constraints - for type_test in type_tests.iter() { - let mut type_test = type_test.clone(); - type_test.locations = locations; - self.cx.borrowck_context.constraints.type_tests.push(type_test) - } for constraint in constraints.outlives().iter() { let mut constraint = constraint.clone(); constraint.locations = locations; @@ -653,18 +640,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { .add_element(region, location); } } - - if !closure_bounds.is_empty() { - let combined_bounds_mapping = - closure_bounds.into_iter().flat_map(|(_, value)| value).collect(); - let existing = self - .cx - .borrowck_context - .constraints - .closure_bounds_mapping - .insert(location, combined_bounds_mapping); - assert!(existing.is_none(), "Multiple promoteds/closures at the same location."); - } } fn sanitize_projection( @@ -941,9 +916,6 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> { pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>, - pub(crate) closure_bounds_mapping: - FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>, - pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>, pub(crate) type_tests: Vec<TypeTest<'tcx>>, @@ -2562,6 +2534,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span: location.to_locations().span(body), category, variance_info: ty::VarianceDiagInfo::default(), + from_closure: false, }); match mutbl { @@ -2679,62 +2652,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { substs: SubstsRef<'tcx>, location: Location, ) -> ty::InstantiatedPredicates<'tcx> { - if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements - { - let closure_constraints = QueryRegionConstraints { - outlives: closure_region_requirements.apply_requirements( - tcx, - def_id.to_def_id(), - substs, - ), - - // Presently, closures never propagate member - // constraints to their parents -- they are enforced - // locally. This is largely a non-issue as member - // constraints only come from `-> impl Trait` and - // friends which don't appear (thus far...) in - // closures. - member_constraints: vec![], - }; - - let bounds_mapping = closure_constraints - .outlives - .iter() - .enumerate() - .filter_map(|(idx, constraint)| { - let ty::OutlivesPredicate(k1, r2) = - constraint.0.no_bound_vars().unwrap_or_else(|| { - bug!("query_constraint {:?} contained bound vars", constraint,); - }); - - match k1.unpack() { - GenericArgKind::Lifetime(r1) => { - // constraint is r1: r2 - let r1_vid = self.borrowck_context.universal_regions.to_region_vid(r1); - let r2_vid = self.borrowck_context.universal_regions.to_region_vid(r2); - let outlives_requirements = - &closure_region_requirements.outlives_requirements[idx]; - Some(( - (r1_vid, r2_vid), - (outlives_requirements.category, outlives_requirements.blame_span), - )) - } - GenericArgKind::Type(_) | GenericArgKind::Const(_) => None, - } - }) - .collect(); - - let existing = self - .borrowck_context - .constraints - .closure_bounds_mapping - .insert(location, bounds_mapping); - assert!(existing.is_none(), "Multiple closures at the same location."); - - self.push_region_constraints( + if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements { + constraint_conversion::ConstraintConversion::new( + self.infcx, + self.borrowck_context.universal_regions, + self.region_bound_pairs, + self.implicit_region_bound, + self.param_env, location.to_locations(), - ConstraintCategory::ClosureBounds, - &closure_constraints, + DUMMY_SP, // irrelevant; will be overrided. + ConstraintCategory::Boring, // same as above. + &mut self.borrowck_context.constraints, + ) + .apply_closure_requirements( + &closure_requirements, + def_id.to_def_id(), + substs, ); } diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 4f2dc263bf5..94d51032866 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -136,6 +136,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> span: self.locations.span(self.type_checker.body), category: self.category, variance_info: info, + from_closure: false, }, ); } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 2beb5e0ab5d..618da9e3253 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -22,7 +22,9 @@ use rustc_hir::{BodyOwnerKind, HirId}; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{ + self, DefIdTree, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt, +}; use rustc_middle::ty::{InternalSubsts, SubstsRef}; use std::iter; @@ -241,7 +243,7 @@ impl<'tcx> UniversalRegions<'tcx> { tcx: TyCtxt<'tcx>, closure_substs: SubstsRef<'tcx>, expected_num_vars: usize, - typeck_root_def_id: DefId, + closure_def_id: LocalDefId, ) -> IndexVec<RegionVid, ty::Region<'tcx>> { let mut region_mapping = IndexVec::with_capacity(expected_num_vars); region_mapping.push(tcx.lifetimes.re_static); @@ -249,7 +251,7 @@ impl<'tcx> UniversalRegions<'tcx> { region_mapping.push(fr); }); - for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| { + for_each_late_bound_region_in_recursive_scope(tcx, tcx.local_parent(closure_def_id), |r| { region_mapping.push(r); }); @@ -339,9 +341,8 @@ impl<'tcx> UniversalRegions<'tcx> { // tests, and the resulting print-outs include def-ids // and other things that are not stable across tests! // So we just include the region-vid. Annoying. - let typeck_root_def_id = tcx.typeck_root_def_id(def_id); - for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| { - err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),)); + for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| { + err.note(&format!("late-bound region is {:?}", self.to_region_vid(r))); }); } DefiningTy::Generator(def_id, substs, _) => { @@ -354,9 +355,8 @@ impl<'tcx> UniversalRegions<'tcx> { // FIXME: As above, we'd like to print out the region // `r` but doing so is not stable across architectures // and so forth. - let typeck_root_def_id = tcx.typeck_root_def_id(def_id); - for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| { - err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),)); + for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| { + err.note(&format!("late-bound region is {:?}", self.to_region_vid(r))); }); } DefiningTy::FnDef(def_id, substs) => { @@ -421,13 +421,24 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { first_extern_index } else { // If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing - // function are actually external regions to us. For example, here, 'a is not local + // function/closures are actually external regions to us. For example, here, 'a is not local // to the closure c (although it is local to the fn foo): // fn foo<'a>() { // let c = || { let x: &'a u32 = ...; } // } - self.infcx - .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices); + for_each_late_bound_region_in_recursive_scope( + self.infcx.tcx, + self.infcx.tcx.local_parent(self.mir_def.did), + |r| { + debug!(?r); + if !indices.indices.contains_key(&r) { + let region_vid = self.infcx.next_nll_region_var(FR); + debug!(?region_vid); + indices.insert_late_bound_region(r, region_vid.to_region_vid()); + } + }, + ); + // Any regions created during the execution of `defining_ty` or during the above // late-bound region replacement are all considered 'extern' regions self.infcx.num_region_vars() @@ -444,12 +455,16 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { bound_inputs_and_output, &mut indices, ); - // Converse of above, if this is a function then the late-bound regions declared on its - // signature are local to the fn. - if self.mir_def.did.to_def_id() == typeck_root_def_id { - self.infcx - .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices); - } + // Converse of above, if this is a function/closure then the late-bound regions declared on its + // signature are local. + for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def.did, |r| { + debug!(?r); + if !indices.indices.contains_key(&r) { + let region_vid = self.infcx.next_nll_region_var(FR); + debug!(?region_vid); + indices.insert_late_bound_region(r, region_vid.to_region_vid()); + } + }); let (unnormalized_output_ty, mut unnormalized_input_tys) = inputs_and_output.split_last().unwrap(); @@ -692,7 +707,13 @@ trait InferCtxtExt<'tcx> { where T: TypeFoldable<'tcx>; - fn replace_late_bound_regions_with_nll_infer_vars( + fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope( + &self, + mir_def_id: LocalDefId, + indices: &mut UniversalRegionIndices<'tcx>, + ); + + fn replace_late_bound_regions_with_nll_infer_vars_in_item( &self, mir_def_id: LocalDefId, indices: &mut UniversalRegionIndices<'tcx>, @@ -746,13 +767,28 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// set of late-bound regions and checks for any that we have not yet seen, adding them to the /// inputs vector. #[instrument(skip(self, indices))] - fn replace_late_bound_regions_with_nll_infer_vars( + fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope( + &self, + mir_def_id: LocalDefId, + indices: &mut UniversalRegionIndices<'tcx>, + ) { + for_each_late_bound_region_in_recursive_scope(self.tcx, mir_def_id, |r| { + debug!(?r); + if !indices.indices.contains_key(&r) { + let region_vid = self.next_nll_region_var(FR); + debug!(?region_vid); + indices.insert_late_bound_region(r, region_vid.to_region_vid()); + } + }); + } + + #[instrument(skip(self, indices))] + fn replace_late_bound_regions_with_nll_infer_vars_in_item( &self, mir_def_id: LocalDefId, indices: &mut UniversalRegionIndices<'tcx>, ) { - let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id()); - for_each_late_bound_region_defined_on(self.tcx, typeck_root_def_id, |r| { + for_each_late_bound_region_in_item(self.tcx, mir_def_id, |r| { debug!(?r); if !indices.indices.contains_key(&r) { let region_vid = self.next_nll_region_var(FR); @@ -803,21 +839,44 @@ impl<'tcx> UniversalRegionIndices<'tcx> { } } -/// Iterates over the late-bound regions defined on fn_def_id and -/// invokes `f` with the liberated form of each one. -fn for_each_late_bound_region_defined_on<'tcx>( +/// Iterates over the late-bound regions defined on `mir_def_id` and all of its +/// parents, up to the typeck root, and invokes `f` with the liberated form +/// of each one. +fn for_each_late_bound_region_in_recursive_scope<'tcx>( tcx: TyCtxt<'tcx>, - fn_def_id: DefId, + mut mir_def_id: LocalDefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) { - for ®ion_def_id in late_bounds.iter() { - let name = tcx.item_name(region_def_id.to_def_id()); - let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { - scope: fn_def_id, - bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name), - })); - f(liberated_region); + let typeck_root_def_id = tcx.typeck_root_def_id(mir_def_id.to_def_id()); + + // Walk up the tree, collecting late-bound regions until we hit the typeck root + loop { + for_each_late_bound_region_in_item(tcx, mir_def_id, &mut f); + + if mir_def_id.to_def_id() == typeck_root_def_id { + break; + } else { + mir_def_id = tcx.local_parent(mir_def_id); } } } + +/// Iterates over the late-bound regions defined on `mir_def_id` and all of its +/// parents, up to the typeck root, and invokes `f` with the liberated form +/// of each one. +fn for_each_late_bound_region_in_item<'tcx>( + tcx: TyCtxt<'tcx>, + mir_def_id: LocalDefId, + mut f: impl FnMut(ty::Region<'tcx>), +) { + if !tcx.def_kind(mir_def_id).is_fn_like() { + return; + } + + for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) { + let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; + let liberated_region = tcx + .mk_region(ty::ReFree(ty::FreeRegion { scope: mir_def_id.to_def_id(), bound_region })); + f(liberated_region); + } +} diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index 8833753b12c..e297b1230ea 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 6469d0d7b88..467fa932a15 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -23,5 +23,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.8" +thin-vec = "0.2.9" tracing = "0.1" diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index bb683936026..f72cd14bea0 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -303,6 +303,7 @@ impl<'cx, 'a> Context<'cx, 'a> { | ExprKind::Field(_, _) | ExprKind::ForLoop(_, _, _, _) | ExprKind::If(_, _, _) + | ExprKind::IncludedBytes(..) | ExprKind::InlineAsm(_) | ExprKind::Let(_, _, _) | ExprKind::Lit(_) diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index cb5359dd1e2..86df3c44eb3 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -34,6 +34,7 @@ impl MultiItemModifier for Expander { span: Span, meta_item: &ast::MetaItem, item: Annotatable, + _is_derive_const: bool, ) -> ExpandResult<Vec<Annotatable>, Annotatable> { let template = AttributeTemplate { list: Some("path"), ..Default::default() }; let attr = &ecx.attribute(meta_item.clone()); diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index 41f4e8c234d..01454d0e98e 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -43,6 +43,9 @@ pub fn expand_concat( has_errors = true; } }, + ast::ExprKind::IncludedBytes(..) => { + cx.span_err(e.span, "cannot concatenate a byte string literal") + } ast::ExprKind::Err => { has_errors = true; } diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 66e86bf2182..4886ca786a5 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -108,6 +108,16 @@ fn handle_array_element( None } }, + ast::ExprKind::IncludedBytes(..) => { + if !*has_errors { + cx.struct_span_err(expr.span, "cannot concatenate doubly nested array") + .note("byte strings are treated as arrays of bytes") + .help("try flattening the array") + .emit(); + } + *has_errors = true; + None + } _ => { missing_literals.push(expr.span); None @@ -167,6 +177,9 @@ pub fn expand_concat_bytes( has_errors = true; } }, + ast::ExprKind::IncludedBytes(ref bytes) => { + accumulator.extend_from_slice(bytes); + } ast::ExprKind::Err => { has_errors = true; } diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index e0fb7affb34..01f237e6ab5 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -10,7 +10,7 @@ use rustc_session::Session; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; -pub(crate) struct Expander; +pub(crate) struct Expander(pub bool); impl MultiItemModifier for Expander { fn expand( @@ -19,6 +19,7 @@ impl MultiItemModifier for Expander { span: Span, meta_item: &ast::MetaItem, item: Annotatable, + _: bool, ) -> ExpandResult<Vec<Annotatable>, Annotatable> { let sess = ecx.sess; if report_bad_target(sess, &item, span) { @@ -58,20 +59,20 @@ impl MultiItemModifier for Expander { report_path_args(sess, &meta); meta.path }) - .map(|path| (path, dummy_annotatable(), None)) + .map(|path| (path, dummy_annotatable(), None, self.0)) .collect(); // Do not configure or clone items unless necessary. match &mut resolutions[..] { [] => {} - [(_, first_item, _), others @ ..] => { + [(_, first_item, ..), others @ ..] => { *first_item = cfg_eval( sess, features, item.clone(), ecx.current_expansion.lint_node_id, ); - for (_, item, _) in others { + for (_, item, _, _) in others { *item = first_item.clone(); } } diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 7bd344467d0..345db700298 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -12,6 +12,7 @@ pub fn expand_deriving_copy( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let trait_def = TraitDef { span, @@ -22,6 +23,7 @@ pub fn expand_deriving_copy( supports_unions: true, methods: Vec::new(), associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push); diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index fa8685f5f4e..55cbb654723 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -14,6 +14,7 @@ pub fn expand_deriving_clone( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { // The simple form is `fn clone(&self) -> Self { *self }`, possibly with // some additional `AssertParamIsClone` assertions. @@ -87,6 +88,7 @@ pub fn expand_deriving_clone( combine_substructure: substructure, }], associated_types: Vec::new(), + is_const, }; trait_def.expand_ext(cx, mitem, item, push, is_simple) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index eab67b0d354..6190b7a8c77 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -15,6 +15,7 @@ pub fn expand_deriving_eq( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let span = cx.with_def_site_ctxt(span); let inline = cx.meta_word(span, sym::inline); @@ -42,6 +43,7 @@ pub fn expand_deriving_eq( })), }], associated_types: Vec::new(), + is_const, }; super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push); diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 7f117981a9a..d2412b20a09 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -13,6 +13,7 @@ pub fn expand_deriving_ord( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let inline = cx.meta_word(span, sym::inline); let attrs = thin_vec![cx.attribute(inline)]; @@ -34,6 +35,7 @@ pub fn expand_deriving_ord( combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 236cbccaf9f..353f28fc45f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -14,6 +14,7 @@ pub fn expand_deriving_partial_eq( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { let base = true; @@ -89,6 +90,7 @@ pub fn expand_deriving_partial_eq( supports_unions: false, methods, associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 4173403a1b8..e7458b23ef3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -13,6 +13,7 @@ pub fn expand_deriving_partial_ord( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let ordering_ty = Path(path_std!(cmp::Ordering)); let ret_ty = @@ -43,6 +44,7 @@ pub fn expand_deriving_partial_ord( supports_unions: false, methods: vec![partial_cmp_def], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 2cf614ed947..e6d5759bb52 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -13,6 +13,7 @@ pub fn expand_deriving_debug( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { // &mut ::std::fmt::Formatter let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut); @@ -37,6 +38,7 @@ pub fn expand_deriving_debug( })), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index d669f616802..37aa665e5c6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -16,6 +16,7 @@ pub fn expand_deriving_rustc_decodable( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let krate = sym::rustc_serialize; let typaram = sym::__D; @@ -55,6 +56,7 @@ pub fn expand_deriving_rustc_decodable( })), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 17df9fb279a..234957ab8a1 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -16,6 +16,7 @@ pub fn expand_deriving_default( mitem: &ast::MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { item.visit_with(&mut DetectNonVariantDefaultAttr { cx }); @@ -47,6 +48,7 @@ pub fn expand_deriving_default( })), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index f83f58b97d3..baacaa8b979 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -100,6 +100,7 @@ pub fn expand_deriving_rustc_encodable( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let krate = sym::rustc_serialize; let typaram = sym::__S; @@ -139,6 +140,7 @@ pub fn expand_deriving_rustc_encodable( })), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 16ee3aa89bb..3972c3b4934 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -171,7 +171,7 @@ use rustc_ast::{GenericArg, GenericParamKind, VariantData}; use rustc_attr as attr; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::cell::RefCell; use std::iter; use std::ops::Not; @@ -204,6 +204,8 @@ pub struct TraitDef<'a> { pub methods: Vec<MethodDef<'a>>, pub associated_types: Vec<(Ident, Ty)>, + + pub is_const: bool, } pub struct MethodDef<'a> { @@ -730,7 +732,7 @@ impl<'a> TraitDef<'a> { unsafety: ast::Unsafe::No, polarity: ast::ImplPolarity::Positive, defaultness: ast::Defaultness::Final, - constness: ast::Const::No, + constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No }, generics: trait_generics, of_trait: opt_trait_ref, self_ty: self_type, diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 6e9d5f08b94..8fb1a4ba262 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -13,6 +13,7 @@ pub fn expand_deriving_hash( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std); @@ -39,6 +40,7 @@ pub fn expand_deriving_hash( })), }], associated_types: Vec::new(), + is_const, }; hash_trait_def.expand(cx, mitem, item, push); diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index ee346047a0b..73a1df5d426 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -38,9 +38,10 @@ pub mod partial_ord; pub mod generic; -pub(crate) struct BuiltinDerive( - pub(crate) fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)), -); +pub(crate) type BuiltinDeriveFn = + fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool); + +pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn); impl MultiItemModifier for BuiltinDerive { fn expand( @@ -49,6 +50,7 @@ impl MultiItemModifier for BuiltinDerive { span: Span, meta_item: &MetaItem, item: Annotatable, + is_derive_const: bool, ) -> ExpandResult<Vec<Annotatable>, Annotatable> { // FIXME: Built-in derives often forget to give spans contexts, // so we are doing it here in a centralized way. @@ -57,21 +59,28 @@ impl MultiItemModifier for BuiltinDerive { match item { Annotatable::Stmt(stmt) => { if let ast::StmtKind::Item(item) = stmt.into_inner().kind { - (self.0)(ecx, span, meta_item, &Annotatable::Item(item), &mut |a| { - // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx' - // to the function - items.push(Annotatable::Stmt(P(ast::Stmt { - id: ast::DUMMY_NODE_ID, - kind: ast::StmtKind::Item(a.expect_item()), - span, - }))); - }); + (self.0)( + ecx, + span, + meta_item, + &Annotatable::Item(item), + &mut |a| { + // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx' + // to the function + items.push(Annotatable::Stmt(P(ast::Stmt { + id: ast::DUMMY_NODE_ID, + kind: ast::StmtKind::Item(a.expect_item()), + span, + }))); + }, + is_derive_const, + ); } else { unreachable!("should have already errored on non-item statement") } } _ => { - (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a)); + (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const); } } ExpandResult::Ready(items) diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index bde0102186a..1cbbfb43264 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -99,7 +99,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, - derive: derive::Expander, + derive: derive::Expander(false), + derive_const: derive::Expander(true), global_allocator: global_allocator::expand, test: test::expand_test, test_case: test::expand_test_case, diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index d78bbc3c932..3411bd40c9d 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -216,7 +216,10 @@ pub fn expand_include_bytes( } }; match cx.source_map().load_binary_file(&file) { - Ok(bytes) => base::MacEager::expr(cx.expr_byte_str(sp, bytes)), + Ok(bytes) => { + let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes.into())); + base::MacEager::expr(expr) + } Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); DummyResult::any(sp) diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index fee5d04cdae..b62840d4bc8 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -112,7 +112,7 @@ pub fn expand_test_or_bench( }; // Note: non-associated fn items are already handled by `expand_test_or_bench` - if !matches!(item.kind, ast::ItemKind::Fn(_)) { + let ast::ItemKind::Fn(fn_) = &item.kind else { let diag = &cx.sess.parse_sess.span_diagnostic; let msg = "the `#[test]` attribute may only be used on a non-associated function"; let mut err = match item.kind { @@ -130,7 +130,7 @@ pub fn expand_test_or_bench( .emit(); return vec![Annotatable::Item(item)]; - } + }; // has_*_signature will report any errors in the type so compilation // will fail. We shouldn't try to expand in this case because the errors @@ -141,12 +141,14 @@ pub fn expand_test_or_bench( return vec![Annotatable::Item(item)]; } - let (sp, attr_sp) = (cx.with_def_site_ctxt(item.span), cx.with_def_site_ctxt(attr_sp)); + let sp = cx.with_def_site_ctxt(item.span); + let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span()); + let attr_sp = cx.with_def_site_ctxt(attr_sp); let test_id = Ident::new(sym::test, attr_sp); // creates test::$name - let test_path = |name| cx.path(sp, vec![test_id, Ident::from_str_and_span(name, sp)]); + let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]); // creates test::ShouldPanic::$name let should_panic_path = |name| { @@ -192,7 +194,7 @@ pub fn expand_test_or_bench( vec![ // super::$test_fn(b) cx.expr_call( - sp, + ret_ty_sp, cx.expr_path(cx.path(sp, vec![item.ident])), vec![cx.expr_ident(sp, b)], ), @@ -216,7 +218,11 @@ pub fn expand_test_or_bench( cx.expr_path(test_path("assert_test_result")), vec![ // $test_fn() - cx.expr_call(sp, cx.expr_path(cx.path(sp, vec![item.ident])), vec![]), // ) + cx.expr_call( + ret_ty_sp, + cx.expr_path(cx.path(sp, vec![item.ident])), + vec![], + ), // ) ], ), // } ), // ) diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index c55db2017ee..2ba012a77b0 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -59,7 +59,7 @@ impl DebugContext { let producer = format!( "cg_clif (rustc {}, cranelift {})", - rustc_interface::util::version_str().unwrap_or("unknown version"), + rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), cranelift_codegen::VERSION, ); let comp_dir = tcx diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 68bdb8d4e55..862ed62c68b 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -201,6 +201,27 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> { value.get_type() } + + fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> { + if let Some(struct_type) = ty.is_struct() { + if struct_type.get_field_count() == 0 { + // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a + // size of usize::MAX in test_binary_search, we workaround this by setting the size to + // zero for ZSTs. + // FIXME(antoyo): fix gccjit API. + len = 0; + } + } + + // NOTE: see note above. Some other test uses usize::MAX. + if len == u64::MAX { + len = 0; + } + + let len: i32 = len.try_into().expect("array len"); + + self.context.new_array_type(None, ty, len) + } } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -227,27 +248,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.context.new_opaque_struct_type(None, name) } - pub fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> { - if let Some(struct_type) = ty.is_struct() { - if struct_type.get_field_count() == 0 { - // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a - // size of usize::MAX in test_binary_search, we workaround this by setting the size to - // zero for ZSTs. - // FIXME(antoyo): fix gccjit API. - len = 0; - } - } - - // NOTE: see note above. Some other test uses usize::MAX. - if len == u64::MAX { - len = 0; - } - - let len: i32 = len.try_into().expect("array len"); - - self.context.new_array_type(None, ty, len) - } - pub fn type_bool(&self) -> Type<'gcc> { self.context.new_type::<bool>() } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 017513721b7..219a4f8fa89 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -130,7 +130,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { op_idx.insert(idx, constraints.len()); constraints.push(reg_to_llvm(reg, Some(&value.layout))); } - InlineAsmOperandRef::InOut { reg, late: _, in_value, out_place: _ } => { + InlineAsmOperandRef::InOut { reg, late, in_value, out_place: _ } => { let value = llvm_fixup_input( self, in_value.immediate(), @@ -138,7 +138,16 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { &in_value.layout, ); inputs.push(value); - constraints.push(format!("{}", op_idx[&idx])); + + // In the case of fixed registers, we have the choice of + // either using a tied operand or duplicating the constraint. + // We prefer the latter because it matches the behavior of + // Clang. + if late && matches!(reg, InlineAsmRegOrRegClass::Reg(_)) { + constraints.push(format!("{}", reg_to_llvm(reg, Some(&in_value.layout)))); + } else { + constraints.push(format!("{}", op_idx[&idx])); + } } InlineAsmOperandRef::SymFn { instance } => { inputs.push(self.cx.get_fn(instance)); @@ -276,13 +285,13 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let mut attrs = SmallVec::<[_; 2]>::new(); if options.contains(InlineAsmOptions::PURE) { if options.contains(InlineAsmOptions::NOMEM) { - attrs.push(llvm::AttributeKind::ReadNone.create_attr(self.cx.llcx)); + attrs.push(llvm::MemoryEffects::None.create_attr(self.cx.llcx)); } else if options.contains(InlineAsmOptions::READONLY) { - attrs.push(llvm::AttributeKind::ReadOnly.create_attr(self.cx.llcx)); + attrs.push(llvm::MemoryEffects::ReadOnly.create_attr(self.cx.llcx)); } attrs.push(llvm::AttributeKind::WillReturn.create_attr(self.cx.llcx)); } else if options.contains(InlineAsmOptions::NOMEM) { - attrs.push(llvm::AttributeKind::InaccessibleMemOnly.create_attr(self.cx.llcx)); + attrs.push(llvm::MemoryEffects::InaccessibleMemOnly.create_attr(self.cx.llcx)); } else { // LLVM doesn't have an attribute to represent ReadOnly + SideEffect } @@ -496,6 +505,44 @@ fn xmm_reg_index(reg: InlineAsmReg) -> Option<u32> { } } +/// If the register is an AArch64 integer register then return its index. +fn a64_reg_index(reg: InlineAsmReg) -> Option<u32> { + match reg { + InlineAsmReg::AArch64(AArch64InlineAsmReg::x0) => Some(0), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x1) => Some(1), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x2) => Some(2), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x3) => Some(3), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x4) => Some(4), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x5) => Some(5), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x6) => Some(6), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x7) => Some(7), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x8) => Some(8), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x9) => Some(9), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x10) => Some(10), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x11) => Some(11), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x12) => Some(12), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x13) => Some(13), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x14) => Some(14), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x15) => Some(15), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x16) => Some(16), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x17) => Some(17), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x18) => Some(18), + // x19 is reserved + InlineAsmReg::AArch64(AArch64InlineAsmReg::x20) => Some(20), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x21) => Some(21), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x22) => Some(22), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x23) => Some(23), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x24) => Some(24), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x25) => Some(25), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x26) => Some(26), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x27) => Some(27), + InlineAsmReg::AArch64(AArch64InlineAsmReg::x28) => Some(28), + // x29 is reserved + InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) => Some(30), + _ => None, + } +} + /// If the register is an AArch64 vector register then return its index. fn a64_vreg_index(reg: InlineAsmReg) -> Option<u32> { match reg { @@ -526,6 +573,22 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> 'x' }; format!("{{{}mm{}}}", class, idx) + } else if let Some(idx) = a64_reg_index(reg) { + let class = if let Some(layout) = layout { + match layout.size.bytes() { + 8 => 'x', + _ => 'w', + } + } else { + // We use i32 as the type for discarded outputs + 'w' + }; + if class == 'x' && reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) { + // LLVM doesn't recognize x30. use lr instead. + "{lr}".to_string() + } else { + format!("{{{}{}}}", class, idx) + } } else if let Some(idx) = a64_vreg_index(reg) { let class = if let Some(layout) = layout { match layout.size.bytes() { @@ -541,9 +604,6 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> 'q' }; format!("{{{}{}}}", class, idx) - } else if reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) { - // LLVM doesn't recognize x30 - "{lr}".to_string() } else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) { // LLVM doesn't recognize r14 "{lr}".to_string() diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index eff2436d41c..a8b47633519 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -12,8 +12,9 @@ use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtec use smallvec::SmallVec; use crate::attributes; +use crate::errors::{MissingFeatures, SanitizerMemtagRequiresMte, TargetFeatureDisableOrEnable}; use crate::llvm::AttributePlace::Function; -use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace}; +use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects}; use crate::llvm_util; pub use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; @@ -82,7 +83,7 @@ pub fn sanitize_attrs<'ll>( let mte_feature = features.iter().map(|s| &s[..]).rfind(|n| ["+mte", "-mte"].contains(&&n[..])); if let None | Some("-mte") = mte_feature { - cx.tcx.sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`"); + cx.tcx.sess.emit_err(SanitizerMemtagRequiresMte); } attrs.push(llvm::AttributeKind::SanitizeMemTag.create_attr(cx.llcx)); @@ -303,10 +304,10 @@ pub fn from_fn_attrs<'ll, 'tcx>( to_add.push(AttributeKind::ReturnsTwice.create_attr(cx.llcx)); } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { - to_add.push(AttributeKind::ReadOnly.create_attr(cx.llcx)); + to_add.push(MemoryEffects::ReadOnly.create_attr(cx.llcx)); } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_CONST) { - to_add.push(AttributeKind::ReadNone.create_attr(cx.llcx)); + to_add.push(MemoryEffects::None.create_attr(cx.llcx)); } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) { to_add.push(AttributeKind::Naked.create_attr(cx.llcx)); @@ -393,13 +394,14 @@ pub fn from_fn_attrs<'ll, 'tcx>( .get_attrs(instance.def_id(), sym::target_feature) .next() .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); - let msg = format!( - "the target features {} must all be either enabled or disabled together", - f.join(", ") - ); - let mut err = cx.tcx.sess.struct_span_err(span, &msg); - err.help("add the missing features in a `target_feature` attribute"); - err.emit(); + cx.tcx + .sess + .create_err(TargetFeatureDisableOrEnable { + features: f, + span: Some(span), + missing_features: Some(MissingFeatures), + }) + .emit(); return; } diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 082665bba38..5c68abeb08b 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -12,6 +12,10 @@ use std::str; use object::read::macho::FatArch; use crate::common; +use crate::errors::{ + ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, + ErrorWritingDEFFile, UnknownArchiveKind, +}; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; @@ -147,7 +151,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { fn build(mut self: Box<Self>, output: &Path) -> bool { match self.build_with_llvm(output) { Ok(any_members) => any_members, - Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)), + Err(e) => self.sess.emit_fatal(ArchiveBuildFailure { error: e }), } } } @@ -217,7 +221,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { match std::fs::write(&def_file_path, def_file_content) { Ok(_) => {} Err(e) => { - sess.fatal(&format!("Error writing .DEF file: {}", e)); + sess.emit_fatal(ErrorWritingDEFFile { error: e }); } }; @@ -239,13 +243,14 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { match result { Err(e) => { - sess.fatal(&format!("Error calling dlltool: {}", e)); + sess.emit_fatal(ErrorCallingDllTool { error: e }); + } + Ok(output) if !output.status.success() => { + sess.emit_fatal(DlltoolFailImportLibrary { + stdout: String::from_utf8_lossy(&output.stdout), + stderr: String::from_utf8_lossy(&output.stderr), + }) } - Ok(output) if !output.status.success() => sess.fatal(&format!( - "Dlltool could not create import library: {}\n{}", - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr) - )), _ => {} } } else { @@ -293,11 +298,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { }; if result == crate::llvm::LLVMRustResult::Failure { - sess.fatal(&format!( - "Error creating import library for {}: {}", + sess.emit_fatal(ErrorCreatingImportLibrary { lib_name, - llvm::last_error().unwrap_or("unknown LLVM error".to_string()) - )); + error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()), + }); } }; @@ -308,9 +312,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { impl<'a> LlvmArchiveBuilder<'a> { fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> { let kind = &*self.sess.target.archive_format; - let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| { - self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind)) - }); + let kind = kind + .parse::<ArchiveKind>() + .map_err(|_| kind) + .unwrap_or_else(|kind| self.sess.emit_fatal(UnknownArchiveKind { kind })); let mut additions = mem::take(&mut self.additions); let mut strings = Vec::new(); diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index a49cc7f8d66..3fa21355b7f 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -1,4 +1,5 @@ use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers}; +use crate::errors::DynamicLinkingWithLTO; use crate::llvm::{self, build_string}; use crate::{LlvmCodegenBackend, ModuleLlvm}; use object::read::archive::ArchiveFile; @@ -90,13 +91,7 @@ fn prepare_lto( } if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto { - diag_handler - .struct_err("cannot prefer dynamic linking when performing LTO") - .note( - "only 'staticlib', 'bin', and 'cdylib' outputs are \ - supported with LTO", - ) - .emit(); + diag_handler.emit_err(DynamicLinkingWithLTO); return Err(FatalError); } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index dd3c43ba5ca..3b504d3a7df 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -1,6 +1,7 @@ use crate::base; use crate::common::{self, CodegenCx}; use crate::debuginfo; +use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined}; use crate::llvm::{self, True}; use crate::llvm_util; use crate::type_::Type; @@ -19,6 +20,7 @@ use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, span_bug}; +use rustc_session::config::Lto; use rustc_target::abi::{ AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange, }; @@ -145,7 +147,7 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: match Align::from_bits(min) { Ok(min) => align = align.max(min), Err(err) => { - cx.sess().err(&format!("invalid minimum global alignment: {}", err)); + cx.sess().emit_err(InvalidMinimumAlignment { err }); } } } @@ -173,10 +175,7 @@ fn check_and_apply_linkage<'ll, 'tcx>( let llty2 = if let ty::RawPtr(ref mt) = ty.kind() { cx.layout_of(mt.ty).llvm_type(cx) } else { - cx.sess().span_fatal( - cx.tcx.def_span(def_id), - "must have type `*const T` or `*mut T` due to `#[linkage]` attribute", - ) + cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) }) }; unsafe { // Declare a symbol `foo` with the desired linkage. @@ -192,10 +191,10 @@ fn check_and_apply_linkage<'ll, 'tcx>( let mut real_name = "_rust_extern_with_linkage_".to_string(); real_name.push_str(sym); let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| { - cx.sess().span_fatal( - cx.tcx.def_span(def_id), - &format!("symbol `{}` is already defined", &sym), - ) + cx.sess().emit_fatal(SymbolAlreadyDefined { + span: cx.tcx.def_span(def_id), + symbol_name: sym, + }) }); llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage); llvm::LLVMSetInitializer(g2, g1); @@ -303,7 +302,8 @@ impl<'ll> CodegenCx<'ll, '_> { // ThinLTO can't handle this workaround in all cases, so we don't // emit the attrs. Instead we make them unnecessary by disallowing // dynamic linking when linker plugin based LTO is enabled. - !self.tcx.sess.opts.cg.linker_plugin_lto.enabled(); + !self.tcx.sess.opts.cg.linker_plugin_lto.enabled() && + self.tcx.sess.lto() != Lto::Thin; // If this assertion triggers, there's something wrong with commandline // argument validation. diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 79ddfd884df..eaa2ccfc835 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -3,6 +3,7 @@ use crate::back::write::to_llvm_code_model; use crate::callee::get_fn; use crate::coverageinfo; use crate::debuginfo; +use crate::errors::BranchProtectionRequiresAArch64; use crate::llvm; use crate::llvm_util; use crate::type_::Type; @@ -26,6 +27,7 @@ use rustc_session::config::{BranchProtection, CFGuard, CFProtection}; use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet}; use rustc_session::Session; use rustc_span::source_map::Span; +use rustc_span::source_map::Spanned; use rustc_target::abi::{ call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx, }; @@ -158,6 +160,10 @@ pub unsafe fn create_module<'ll>( if sess.target.arch == "s390x" { target_data_layout = target_data_layout.replace("-v128:64", ""); } + + if sess.target.arch == "riscv64" { + target_data_layout = target_data_layout.replace("-n32:64-", "-n64-"); + } } // Ensure the data-layout values hardcoded remain the defaults. @@ -271,7 +277,7 @@ pub unsafe fn create_module<'ll>( if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection { if sess.target.arch != "aarch64" { - sess.err("-Zbranch-protection is only supported on aarch64"); + sess.emit_err(BranchProtectionRequiresAArch64); } else { llvm::LLVMRustAddModuleFlag( llmod, @@ -947,7 +953,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { if let LayoutError::SizeOverflow(_) = err { - self.sess().span_fatal(span, &err.to_string()) + self.sess().emit_fatal(Spanned { span, node: err }) } else { span_bug!(span, "failed to get layout for `{}`: {}", ty, err) } @@ -965,7 +971,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - self.sess().span_fatal(span, &err.to_string()) + self.sess().emit_fatal(Spanned { span, node: err }) } else { match fn_abi_request { FnAbiRequest::OfFnPtr { sig, extra_args } => { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 433f043209e..8a8d889a298 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,5 +1,6 @@ use crate::common::CodegenCx; use crate::coverageinfo; +use crate::errors::InstrumentCoverageRequiresLLVM12; use crate::llvm; use llvm::coverageinfo::CounterMappingRegion; @@ -37,7 +38,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { // LLVM 12. let version = coverageinfo::mapping_version(); if version < 4 { - tcx.sess.fatal("rustc option `-C instrument-coverage` requires LLVM 12 or higher."); + tcx.sess.emit_fatal(InstrumentCoverageRequiresLLVM12); } debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name()); diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs new file mode 100644 index 00000000000..0fafc214f2f --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -0,0 +1,139 @@ +use std::borrow::Cow; + +use rustc_errors::fluent; +use rustc_errors::DiagnosticBuilder; +use rustc_errors::ErrorGuaranteed; +use rustc_errors::Handler; +use rustc_errors::IntoDiagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_span::Span; + +#[derive(Diagnostic)] +#[diag(codegen_llvm_unknown_ctarget_feature_prefix)] +#[note] +pub(crate) struct UnknownCTargetFeaturePrefix<'a> { + pub feature: &'a str, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_unknown_ctarget_feature)] +#[note] +pub(crate) struct UnknownCTargetFeature<'a> { + pub feature: &'a str, + #[subdiagnostic] + pub rust_feature: PossibleFeature<'a>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum PossibleFeature<'a> { + #[help(possible_feature)] + Some { rust_feature: &'a str }, + #[help(consider_filing_feature_request)] + None, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_error_creating_import_library)] +pub(crate) struct ErrorCreatingImportLibrary<'a> { + pub lib_name: &'a str, + pub error: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_instrument_coverage_requires_llvm_12)] +pub(crate) struct InstrumentCoverageRequiresLLVM12; + +#[derive(Diagnostic)] +#[diag(codegen_llvm_symbol_already_defined)] +pub(crate) struct SymbolAlreadyDefined<'a> { + #[primary_span] + pub span: Span, + pub symbol_name: &'a str, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_branch_protection_requires_aarch64)] +pub(crate) struct BranchProtectionRequiresAArch64; + +#[derive(Diagnostic)] +#[diag(codegen_llvm_invalid_minimum_alignment)] +pub(crate) struct InvalidMinimumAlignment { + pub err: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_linkage_const_or_mut_type)] +pub(crate) struct LinkageConstOrMutType { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_sanitizer_memtag_requires_mte)] +pub(crate) struct SanitizerMemtagRequiresMte; + +#[derive(Diagnostic)] +#[diag(codegen_llvm_archive_build_failure)] +pub(crate) struct ArchiveBuildFailure { + pub error: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_error_writing_def_file)] +pub(crate) struct ErrorWritingDEFFile { + pub error: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_error_calling_dlltool)] +pub(crate) struct ErrorCallingDllTool { + pub error: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_dlltool_fail_import_library)] +pub(crate) struct DlltoolFailImportLibrary<'a> { + pub stdout: Cow<'a, str>, + pub stderr: Cow<'a, str>, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_unknown_archive_kind)] +pub(crate) struct UnknownArchiveKind<'a> { + pub kind: &'a str, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_dynamic_linking_with_lto)] +#[note] +pub(crate) struct DynamicLinkingWithLTO; + +#[derive(Diagnostic)] +#[diag(codegen_llvm_fail_parsing_target_machine_config_to_target_machine)] +pub(crate) struct FailParsingTargetMachineConfigToTargetMachine { + pub error: String, +} + +pub(crate) struct TargetFeatureDisableOrEnable<'a> { + pub features: &'a [&'a str], + pub span: Option<Span>, + pub missing_features: Option<MissingFeatures>, +} + +#[derive(Subdiagnostic)] +#[help(codegen_llvm_missing_features)] +pub(crate) struct MissingFeatures; + +impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable); + if let Some(span) = self.span { + diag.set_span(span); + }; + if let Some(missing_features) = self.missing_features { + diag.subdiagnostic(missing_features); + } + diag.set_arg("features", self.features.join(", ")); + diag + } +} diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 825011941a2..cf590a43826 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -340,17 +340,26 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { sym::black_box => { args[0].val.store(self, result); - + let result_val_span = [result.llval]; // We need to "use" the argument in some way LLVM can't introspect, and on // targets that support it we can typically leverage inline assembly to do // this. LLVM's interpretation of inline assembly is that it's, well, a black // box. This isn't the greatest implementation since it probably deoptimizes // more than we want, but it's so far good enough. + // + // For zero-sized types, the location pointed to by the result may be + // uninitialized. Do not "use" the result in this case; instead just clobber + // the memory. + let (constraint, inputs): (&str, &[_]) = if result.layout.is_zst() { + ("~{memory}", &[]) + } else { + ("r,~{memory}", &result_val_span) + }; crate::asm::inline_asm_call( self, "", - "r,~{memory}", - &[result.llval], + constraint, + inputs, self.type_void(), true, false, diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index d51aced85df..246e82545c8 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -12,6 +12,8 @@ #![feature(iter_intersperse)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; @@ -20,6 +22,7 @@ extern crate tracing; use back::write::{create_informational_target_machine, create_target_machine}; +use errors::FailParsingTargetMachineConfigToTargetMachine; pub use llvm_util::target_features; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; @@ -62,6 +65,7 @@ mod context; mod coverageinfo; mod debuginfo; mod declare; +mod errors; mod intrinsic; // The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912. @@ -412,7 +416,7 @@ impl ModuleLlvm { let tm = match (cgcx.tm_factory)(tm_factory_config) { Ok(m) => m, Err(e) => { - handler.struct_err(&e).emit(); + handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e }); return Err(FatalError); } }; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 42cb694c0e7..e2d0390821d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -183,7 +183,6 @@ pub enum AttributeKind { OptimizeNone = 24, ReturnsTwice = 25, ReadNone = 26, - InaccessibleMemOnly = 27, SanitizeHWAddress = 28, WillReturn = 29, StackProtectReq = 30, @@ -590,6 +589,15 @@ pub enum ChecksumKind { SHA256, } +/// LLVMRustMemoryEffects +#[derive(Copy, Clone)] +#[repr(C)] +pub enum MemoryEffects { + None, + ReadOnly, + InaccessibleMemOnly, +} + extern "C" { type Opaque; } @@ -1175,6 +1183,7 @@ extern "C" { pub fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute; pub fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute; pub fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute; + pub fn LLVMRustCreateMemoryEffectsAttr(C: &Context, effects: MemoryEffects) -> &Attribute; // Operations on functions pub fn LLVMRustGetOrInsertFunction<'a>( diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 6602a4ab863..f820e752371 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -185,6 +185,13 @@ impl AttributeKind { } } +impl MemoryEffects { + /// Create an LLVM Attribute with these memory effects. + pub fn create_attr(self, llcx: &Context) -> &Attribute { + unsafe { LLVMRustCreateMemoryEffectsAttr(llcx, self) } + } +} + pub fn set_section(llglobal: &Value, section_name: &str) { let section_name_cstr = CString::new(section_name).expect("unexpected CString error"); unsafe { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 2fd58567c48..e1f54356228 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,4 +1,8 @@ use crate::back::write::create_informational_target_machine; +use crate::errors::{ + PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, + UnknownCTargetFeaturePrefix, +}; use crate::llvm; use libc::c_int; use rustc_codegen_ssa::target_features::{ @@ -434,12 +438,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str Some(c @ '+' | c @ '-') => c, Some(_) => { if diagnostics { - let mut diag = sess.struct_warn(&format!( - "unknown feature specified for `-Ctarget-feature`: `{}`", - s - )); - diag.note("features must begin with a `+` to enable or `-` to disable it"); - diag.emit(); + sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s }); } return None; } @@ -456,17 +455,15 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str None } }); - let mut diag = sess.struct_warn(&format!( - "unknown feature specified for `-Ctarget-feature`: `{}`", - feature - )); - diag.note("it is still passed through to the codegen backend"); - if let Some(rust_feature) = rust_feature { - diag.help(&format!("you might have meant: `{}`", rust_feature)); + let unknown_feature = if let Some(rust_feature) = rust_feature { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::Some { rust_feature }, + } } else { - diag.note("consider filing a feature request"); - } - diag.emit(); + UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } + }; + sess.emit_warning(unknown_feature); } if diagnostics { @@ -492,10 +489,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str features.extend(feats); if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) { - sess.err(&format!( - "target features {} must all be enabled or disabled together", - f.join(", ") - )); + sess.emit_err(TargetFeatureDisableOrEnable { + features: f, + span: None, + missing_features: None, + }); } features diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 1eceb7f5c87..76f692b2016 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -1,6 +1,7 @@ use crate::attributes; use crate::base; use crate::context::CodegenCx; +use crate::errors::SymbolAlreadyDefined; use crate::llvm; use crate::type_of::LayoutLlvmExt; use rustc_codegen_ssa::traits::*; @@ -25,10 +26,8 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { let llty = self.layout_of(ty).llvm_type(self); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { - self.sess().span_fatal( - self.tcx.def_span(def_id), - &format!("symbol `{}` is already defined", symbol_name), - ) + self.sess() + .emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name }) }); unsafe { diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index eeb38d4ecf5..5eec7dc6130 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -127,10 +127,6 @@ impl<'ll> CodegenCx<'ll, '_> { pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) } } - - pub(crate) fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type { - unsafe { llvm::LLVMRustArrayType(ty, len) } - } } impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -231,6 +227,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn val_ty(&self, v: &'ll Value) -> &'ll Type { common::val_ty(v) } + + fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type { + unsafe { llvm::LLVMRustArrayType(ty, len) } + } } impl Type { diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index bb76ca5d2b9..18789d00fd3 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -6,11 +6,12 @@ use rustc_span::symbol::Symbol; use object::read::archive::ArchiveFile; -use std::fmt::Display; use std::fs::File; use std::io; use std::path::{Path, PathBuf}; +use crate::errors::ExtractBundledLibsError; + pub trait ArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>; @@ -28,32 +29,35 @@ pub trait ArchiveBuilderBuilder { is_direct_dependency: bool, ) -> PathBuf; - fn extract_bundled_libs( - &self, - rlib: &Path, + fn extract_bundled_libs<'a>( + &'a self, + rlib: &'a Path, outdir: &Path, bundled_lib_file_names: &FxHashSet<Symbol>, - ) -> Result<(), String> { - let message = |msg: &str, e: &dyn Display| format!("{} '{}': {}", msg, &rlib.display(), e); + ) -> Result<(), ExtractBundledLibsError<'_>> { let archive_map = unsafe { - Mmap::map(File::open(rlib).map_err(|e| message("failed to open file", &e))?) - .map_err(|e| message("failed to mmap file", &e))? + Mmap::map( + File::open(rlib) + .map_err(|e| ExtractBundledLibsError::OpenFile { rlib, error: Box::new(e) })?, + ) + .map_err(|e| ExtractBundledLibsError::MmapFile { rlib, error: Box::new(e) })? }; let archive = ArchiveFile::parse(&*archive_map) - .map_err(|e| message("failed to parse archive", &e))?; + .map_err(|e| ExtractBundledLibsError::ParseArchive { rlib, error: Box::new(e) })?; for entry in archive.members() { - let entry = entry.map_err(|e| message("failed to read entry", &e))?; + let entry = entry + .map_err(|e| ExtractBundledLibsError::ReadEntry { rlib, error: Box::new(e) })?; let data = entry .data(&*archive_map) - .map_err(|e| message("failed to get data from archive member", &e))?; + .map_err(|e| ExtractBundledLibsError::ArchiveMember { rlib, error: Box::new(e) })?; let name = std::str::from_utf8(entry.name()) - .map_err(|e| message("failed to convert name", &e))?; + .map_err(|e| ExtractBundledLibsError::ConvertName { rlib, error: Box::new(e) })?; if !bundled_lib_file_names.contains(&Symbol::intern(name)) { continue; // We need to extract only native libraries. } std::fs::write(&outdir.join(&name), data) - .map_err(|e| message("failed to write file", &e))?; + .map_err(|e| ExtractBundledLibsError::WriteFile { rlib, error: Box::new(e) })?; } Ok(()) } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 0dc0dee862c..5a1ad792924 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -919,29 +919,17 @@ fn link_natively<'a>( ) .is_some(); - sess.note_without_error("`link.exe` returned an unexpected error"); + sess.emit_note(errors::LinkExeUnexpectedError); if is_vs_installed && has_linker { // the linker is broken - sess.note_without_error( - "the Visual Studio build tools may need to be repaired \ - using the Visual Studio installer", - ); - sess.note_without_error( - "or a necessary component may be missing from the \ - \"C++ build tools\" workload", - ); + sess.emit_note(errors::RepairVSBuildTools); + sess.emit_note(errors::MissingCppBuildToolComponent); } else if is_vs_installed { // the linker is not installed - sess.note_without_error( - "in the Visual Studio installer, ensure the \ - \"C++ build tools\" workload is selected", - ); + sess.emit_note(errors::SelectCppBuildToolWorkload); } else { // visual studio is not installed - sess.note_without_error( - "you may need to install Visual Studio build tools with the \ - \"C++ build tools\" workload", - ); + sess.emit_note(errors::VisualStudioNotInstalled); } } } @@ -954,35 +942,20 @@ fn link_natively<'a>( Err(e) => { let linker_not_found = e.kind() == io::ErrorKind::NotFound; - let mut linker_error = { - if linker_not_found { - sess.struct_err(&format!("linker `{}` not found", linker_path.display())) - } else { - sess.struct_err(&format!( - "could not exec the linker `{}`", - linker_path.display() - )) - } - }; - - linker_error.note(&e.to_string()); - - if !linker_not_found { - linker_error.note(&format!("{:?}", &cmd)); + if linker_not_found { + sess.emit_err(errors::LinkerNotFound { linker_path, error: e }); + } else { + sess.emit_err(errors::UnableToExeLinker { + linker_path, + error: e, + command_formatted: format!("{:?}", &cmd), + }); } - linker_error.emit(); - if sess.target.is_like_msvc && linker_not_found { - sess.note_without_error( - "the msvc targets depend on the msvc linker \ - but `link.exe` was not found", - ); - sess.note_without_error( - "please ensure that Visual Studio 2017 or later, or Build Tools \ - for Visual Studio were installed with the Visual C++ option.", - ); - sess.note_without_error("VS Code is a different product, and is not sufficient."); + sess.emit_note(errors::MsvcMissingLinker); + sess.emit_note(errors::CheckInstalledVisualStudio); + sess.emit_note(errors::UnsufficientVSCodeProduct); } sess.abort_if_errors(); } @@ -1007,15 +980,13 @@ fn link_natively<'a>( if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); - sess.struct_warn(&format!( - "processing debug info with `dsymutil` failed: {}", - prog.status - )) - .note(&escape_string(&output)) - .emit(); + sess.emit_warning(errors::ProcessingDymutilFailed { + status: prog.status, + output: escape_string(&output), + }); } } - Err(e) => sess.fatal(&format!("unable to run `dsymutil`: {}", e)), + Err(error) => sess.emit_fatal(errors::UnableToRunDsymutil { error }), } } @@ -1092,15 +1063,14 @@ fn strip_symbols_with_external_utility<'a>( if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); - sess.struct_warn(&format!( - "stripping debug info with `{}` failed: {}", - util, prog.status - )) - .note(&escape_string(&output)) - .emit(); + sess.emit_warning(errors::StrippingDebugInfoFailed { + util, + status: prog.status, + output: escape_string(&output), + }); } } - Err(e) => sess.fatal(&format!("unable to run `{}`: {}", util, e)), + Err(error) => sess.emit_fatal(errors::UnableToRun { util, error }), } } @@ -1153,7 +1123,8 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) { if path.exists() { return session_tlib; } else { - let default_sysroot = filesearch::get_or_default_sysroot(); + let default_sysroot = + filesearch::get_or_default_sysroot().expect("Failed finding sysroot"); let default_tlib = filesearch::make_target_lib_path( &default_sysroot, sess.opts.target_triple.triple(), @@ -1251,7 +1222,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { )), (Some(linker), None) => { let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| { - sess.fatal("couldn't extract file stem from specified linker") + sess.emit_fatal(errors::LinkerFileStem); }); let flavor = if stem == "emcc" { @@ -1378,13 +1349,9 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { }) .collect(); if !lib_args.is_empty() { - sess.note_without_error( - "Link against the following native artifacts when linking \ - against this static library. The order and any duplication \ - can be significant on some platforms.", - ); + sess.emit_note(errors::StaticLibraryNativeArtifacts); // Prefix for greppability - sess.note_without_error(&format!("native-static-libs: {}", &lib_args.join(" "))); + sess.emit_note(errors::NativeStaticLibs { arguments: lib_args.join(" ") }); } } @@ -1688,14 +1655,14 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty match (crate_type, &sess.target.link_script) { (CrateType::Cdylib | CrateType::Executable, Some(script)) => { if !sess.target.linker_flavor.is_gnu() { - sess.fatal("can only use link script when linking with GNU-like linker"); + sess.emit_fatal(errors::LinkScriptUnavailable); } let file_name = ["rustc", &sess.target.llvm_target, "linkfile.ld"].join("-"); let path = tmpdir.join(file_name); - if let Err(e) = fs::write(&path, script.as_ref()) { - sess.fatal(&format!("failed to write link script to {}: {}", path.display(), e)); + if let Err(error) = fs::write(&path, script.as_ref()) { + sess.emit_fatal(errors::LinkScriptWriteFailure { path, error }); } cmd.arg("--script"); @@ -1841,8 +1808,8 @@ fn add_linked_symbol_object( let path = tmpdir.join("symbols.o"); let result = std::fs::write(&path, file.write().unwrap()); - if let Err(e) = result { - sess.fatal(&format!("failed to write {}: {}", path.display(), e)); + if let Err(error) = result { + sess.emit_fatal(errors::FailedToWrite { path, error }); } cmd.add_object(&path); } @@ -2299,14 +2266,10 @@ fn collect_natvis_visualizers( visualizer_paths.push(visualizer_out_file); } Err(error) => { - sess.warn( - format!( - "Unable to write debugger visualizer file `{}`: {} ", - visualizer_out_file.display(), - error - ) - .as_str(), - ); + sess.emit_warning(errors::UnableToWriteDebuggerVisualizer { + path: visualizer_out_file, + error, + }); } }; } @@ -2484,7 +2447,7 @@ fn add_upstream_rust_crates<'a>( let rlib = &src.rlib.as_ref().unwrap().0; archive_builder_builder .extract_bundled_libs(rlib, tmpdir, &bundled_libs) - .unwrap_or_else(|e| sess.fatal(e)); + .unwrap_or_else(|e| sess.emit_fatal(e)); } let mut last = (None, NativeLibKind::Unspecified, None); @@ -2641,7 +2604,7 @@ fn add_upstream_rust_crates<'a>( || !codegen_results.crate_info.is_no_builtins.contains(&cnum); let mut archive = archive_builder_builder.new_archive_builder(sess); - if let Err(e) = archive.add_archive( + if let Err(error) = archive.add_archive( cratepath, Box::new(move |f| { if f == METADATA_FILENAME { @@ -2681,7 +2644,7 @@ fn add_upstream_rust_crates<'a>( false }), ) { - sess.fatal(&format!("failed to build archive from rlib: {}", e)); + sess.emit_fatal(errors::RlibArchiveBuildFailure { error }); } if archive.build(&dst) { link_upstream(&dst); @@ -2813,14 +2776,14 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { ("arm", "watchos") => "watchos", (_, "macos") => "macosx", _ => { - sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os)); + sess.emit_err(errors::UnsupportedArch { arch, os }); return; } }; let sdk_root = match get_apple_sdk_root(sdk_name) { Ok(s) => s, Err(e) => { - sess.err(&e); + sess.emit_err(e); return; } }; @@ -2836,7 +2799,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { } } -fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> { +fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootError<'_>> { // Following what clang does // (https://github.com/llvm/llvm-project/blob/ // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678) @@ -2886,7 +2849,7 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> { match res { Ok(output) => Ok(output.trim().to_string()), - Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)), + Err(error) => Err(errors::AppleSdkRootError::SdkPath { sdk_name, error }), } } @@ -2919,7 +2882,7 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { } } } else { - sess.fatal("option `-Z gcc-ld` is used even though linker flavor is not gcc"); + sess.emit_fatal(errors::OptionGccOnly); } } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index c49b19bdf00..7f0c2861f7e 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1260,11 +1260,11 @@ impl<'a> Linker for WasmLd<'a> { } fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) { - self.cmd.arg("-l").arg(lib); + self.cmd.arg("--whole-archive").arg("-l").arg(lib).arg("--no-whole-archive"); } fn link_whole_rlib(&mut self, lib: &Path) { - self.cmd.arg(lib); + self.cmd.arg("--whole-archive").arg(lib).arg("--no-whole-archive"); } fn gc_sections(&mut self, _keep_metadata: bool) { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index d0ac016b02e..e3d28a1aca2 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -15,10 +15,8 @@ use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::profiling::VerboseTimingGuard; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; -use rustc_errors::{ - translation::{to_fluent_args, Translate}, - DiagnosticId, FatalError, Handler, Level, -}; +use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level}; +use rustc_errors::{DiagnosticMessage, Style}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ @@ -38,6 +36,7 @@ use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span}; use rustc_target::spec::{MergeFunctions, SanitizerSet}; use std::any::Any; +use std::borrow::Cow; use std::fs; use std::io; use std::marker::PhantomData; @@ -969,8 +968,11 @@ pub enum Message<B: WriteBackendMethods> { CodegenAborted, } +type DiagnosticArgName<'source> = Cow<'source, str>; + struct Diagnostic { - msg: String, + msg: Vec<(DiagnosticMessage, Style)>, + args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>, code: Option<DiagnosticId>, lvl: Level, } @@ -1743,15 +1745,18 @@ impl Translate for SharedEmitter { impl Emitter for SharedEmitter { fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { - let fluent_args = to_fluent_args(diag.args()); + let args: FxHashMap<Cow<'_, str>, rustc_errors::DiagnosticArgValue<'_>> = + diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect(); drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: self.translate_messages(&diag.message, &fluent_args).to_string(), + msg: diag.message.clone(), + args: args.clone(), code: diag.code.clone(), lvl: diag.level(), }))); for child in &diag.children { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: self.translate_messages(&child.message, &fluent_args).to_string(), + msg: child.message.clone(), + args: args.clone(), code: None, lvl: child.level, }))); @@ -1782,10 +1787,11 @@ impl SharedEmitterMain { match message { Ok(SharedEmitterMessage::Diagnostic(diag)) => { let handler = sess.diagnostic(); - let mut d = rustc_errors::Diagnostic::new(diag.lvl, &diag.msg); + let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msg); if let Some(code) = diag.code { d.code(code); } + d.replace_args(diag.args); handler.emit_diagnostic(&mut d); } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index e05646e1e86..8647fbace2a 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -59,7 +59,13 @@ fn push_debuginfo_type_name<'tcx>( match *t.kind() { ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), - ty::Str => output.push_str("str"), + ty::Str => { + if cpp_like_debuginfo { + output.push_str("str$") + } else { + output.push_str("str") + } + } ty::Never => { if cpp_like_debuginfo { output.push_str("never$"); @@ -152,25 +158,19 @@ fn push_debuginfo_type_name<'tcx>( } } ty::Ref(_, inner_type, mutbl) => { - // Slices and `&str` are treated like C++ pointers when computing debug - // info for MSVC debugger. However, wrapping these types' names in a synthetic type - // causes the .natvis engine for WinDbg to fail to display their data, so we opt these - // types out to aid debugging in MSVC. - let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str); - - if !cpp_like_debuginfo { - output.push('&'); - output.push_str(mutbl.prefix_str()); - } else if !is_slice_or_str { + if cpp_like_debuginfo { match mutbl { Mutability::Not => output.push_str("ref$<"), Mutability::Mut => output.push_str("ref_mut$<"), } + } else { + output.push('&'); + output.push_str(mutbl.prefix_str()); } push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); - if cpp_like_debuginfo && !is_slice_or_str { + if cpp_like_debuginfo { push_close_angle_bracket(cpp_like_debuginfo, output); } } @@ -195,7 +195,7 @@ fn push_debuginfo_type_name<'tcx>( } ty::Slice(inner_type) => { if cpp_like_debuginfo { - output.push_str("slice$<"); + output.push_str("slice2$<"); } else { output.push('['); } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index ebb531f1c43..36c94462b0b 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -354,3 +354,170 @@ impl IntoDiagnostic<'_> for LinkingFailed<'_> { diag } } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_link_exe_unexpected_error)] +pub struct LinkExeUnexpectedError; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_repair_vs_build_tools)] +pub struct RepairVSBuildTools; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_missing_cpp_build_tool_component)] +pub struct MissingCppBuildToolComponent; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_select_cpp_build_tool_workload)] +pub struct SelectCppBuildToolWorkload; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_visual_studio_not_installed)] +pub struct VisualStudioNotInstalled; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_linker_not_found)] +#[note] +pub struct LinkerNotFound { + pub linker_path: PathBuf, + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unable_to_exe_linker)] +#[note] +#[note(command_note)] +pub struct UnableToExeLinker { + pub linker_path: PathBuf, + pub error: Error, + pub command_formatted: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_msvc_missing_linker)] +pub struct MsvcMissingLinker; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_check_installed_visual_studio)] +pub struct CheckInstalledVisualStudio; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unsufficient_vs_code_product)] +pub struct UnsufficientVSCodeProduct; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_processing_dymutil_failed)] +#[note] +pub struct ProcessingDymutilFailed { + pub status: ExitStatus, + pub output: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unable_to_run_dsymutil)] +#[note] +pub struct UnableToRunDsymutil { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_stripping_debu_info_failed)] +#[note] +pub struct StrippingDebugInfoFailed<'a> { + pub util: &'a str, + pub status: ExitStatus, + pub output: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unable_to_run)] +pub struct UnableToRun<'a> { + pub util: &'a str, + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_linker_file_stem)] +pub struct LinkerFileStem; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_static_library_native_artifacts)] +pub struct StaticLibraryNativeArtifacts; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_native_static_libs)] +pub struct NativeStaticLibs { + pub arguments: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_link_script_unavailable)] +pub struct LinkScriptUnavailable; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_link_script_write_failure)] +pub struct LinkScriptWriteFailure { + pub path: PathBuf, + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_failed_to_write)] +pub struct FailedToWrite { + pub path: PathBuf, + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unable_to_write_debugger_visualizer)] +pub struct UnableToWriteDebuggerVisualizer { + pub path: PathBuf, + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_rlib_archive_build_failure)] +pub struct RlibArchiveBuildFailure { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_option_gcc_only)] +pub struct OptionGccOnly; + +#[derive(Diagnostic)] +pub enum ExtractBundledLibsError<'a> { + #[diag(codegen_ssa_extract_bundled_libs_open_file)] + OpenFile { rlib: &'a Path, error: Box<dyn std::error::Error> }, + + #[diag(codegen_ssa_extract_bundled_libs_mmap_file)] + MmapFile { rlib: &'a Path, error: Box<dyn std::error::Error> }, + + #[diag(codegen_ssa_extract_bundled_libs_parse_archive)] + ParseArchive { rlib: &'a Path, error: Box<dyn std::error::Error> }, + + #[diag(codegen_ssa_extract_bundled_libs_read_entry)] + ReadEntry { rlib: &'a Path, error: Box<dyn std::error::Error> }, + + #[diag(codegen_ssa_extract_bundled_libs_archive_member)] + ArchiveMember { rlib: &'a Path, error: Box<dyn std::error::Error> }, + + #[diag(codegen_ssa_extract_bundled_libs_convert_name)] + ConvertName { rlib: &'a Path, error: Box<dyn std::error::Error> }, + + #[diag(codegen_ssa_extract_bundled_libs_write_file)] + WriteFile { rlib: &'a Path, error: Box<dyn std::error::Error> }, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unsupported_arch)] +pub struct UnsupportedArch<'a> { + pub arch: &'a str, + pub os: &'a str, +} + +#[derive(Diagnostic)] +pub enum AppleSdkRootError<'a> { + #[diag(codegen_ssa_apple_sdk_error_sdk_path)] + SdkPath { sdk_name: &'a str, error: Error }, +} diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 9c18df5643f..8c72d6d1fbe 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -209,7 +209,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx: &mut Bx, cast_to: Ty<'tcx>, ) -> V { - let cast_to = bx.cx().immediate_backend_type(bx.cx().layout_of(cast_to)); + let cast_to_layout = bx.cx().layout_of(cast_to); + let cast_to_size = cast_to_layout.layout.size(); + let cast_to = bx.cx().immediate_backend_type(cast_to_layout); if self.layout.abi.is_uninhabited() { return bx.cx().const_undef(cast_to); } @@ -229,7 +231,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // Read the tag/niche-encoded discriminant from memory. let tag = self.project_field(bx, tag_field); - let tag = bx.load_operand(tag); + let tag_op = bx.load_operand(tag); + let tag_imm = tag_op.immediate(); // Decode the discriminant (specifically if it's niche-encoded). match *tag_encoding { @@ -242,68 +245,161 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { Int(_, signed) => !tag_scalar.is_bool() && signed, _ => false, }; - bx.intcast(tag.immediate(), cast_to, signed) + bx.intcast(tag_imm, cast_to, signed) } TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { - // Rebase from niche values to discriminants, and check - // whether the result is in range for the niche variants. - let niche_llty = bx.cx().immediate_backend_type(tag.layout); - let tag = tag.immediate(); - - // We first compute the "relative discriminant" (wrt `niche_variants`), - // that is, if `n = niche_variants.end() - niche_variants.start()`, - // we remap `niche_start..=niche_start + n` (which may wrap around) - // to (non-wrap-around) `0..=n`, to be able to check whether the - // discriminant corresponds to a niche variant with one comparison. - // We also can't go directly to the (variant index) discriminant - // and check that it is in the range `niche_variants`, because - // that might not fit in the same type, on top of needing an extra - // comparison (see also the comment on `let niche_discr`). - let relative_discr = if niche_start == 0 { - // Avoid subtracting `0`, which wouldn't work for pointers. - // FIXME(eddyb) check the actual primitive type here. - tag + // Cast to an integer so we don't have to treat a pointer as a + // special case. + let (tag, tag_llty) = if tag_scalar.primitive().is_ptr() { + let t = bx.type_isize(); + let tag = bx.ptrtoint(tag_imm, t); + (tag, t) } else { - bx.sub(tag, bx.cx().const_uint_big(niche_llty, niche_start)) + (tag_imm, bx.cx().immediate_backend_type(tag_op.layout)) }; + + let tag_size = tag_scalar.size(bx.cx()); + let max_unsigned = tag_size.unsigned_int_max(); + let max_signed = tag_size.signed_int_max() as u128; + let min_signed = max_signed + 1; let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32(); - let is_niche = if relative_max == 0 { - // Avoid calling `const_uint`, which wouldn't work for pointers. - // Also use canonical == 0 instead of non-canonical u<= 0. - // FIXME(eddyb) check the actual primitive type here. - bx.icmp(IntPredicate::IntEQ, relative_discr, bx.cx().const_null(niche_llty)) + let niche_end = niche_start.wrapping_add(relative_max as u128) & max_unsigned; + let range = tag_scalar.valid_range(bx.cx()); + + let sle = |lhs: u128, rhs: u128| -> bool { + // Signed and unsigned comparisons give the same results, + // except that in signed comparisons an integer with the + // sign bit set is less than one with the sign bit clear. + // Toggle the sign bit to do a signed comparison. + (lhs ^ min_signed) <= (rhs ^ min_signed) + }; + + // We have a subrange `niche_start..=niche_end` inside `range`. + // If the value of the tag is inside this subrange, it's a + // "niche value", an increment of the discriminant. Otherwise it + // indicates the untagged variant. + // A general algorithm to extract the discriminant from the tag + // is: + // relative_tag = tag - niche_start + // is_niche = relative_tag <= (ule) relative_max + // discr = if is_niche { + // cast(relative_tag) + niche_variants.start() + // } else { + // untagged_variant + // } + // However, we will likely be able to emit simpler code. + + // Find the least and greatest values in `range`, considered + // both as signed and unsigned. + let (low_unsigned, high_unsigned) = if range.start <= range.end { + (range.start, range.end) + } else { + (0, max_unsigned) + }; + let (low_signed, high_signed) = if sle(range.start, range.end) { + (range.start, range.end) } else { - let relative_max = bx.cx().const_uint(niche_llty, relative_max as u64); - bx.icmp(IntPredicate::IntULE, relative_discr, relative_max) + (min_signed, max_signed) + }; + + let niches_ule = niche_start <= niche_end; + let niches_sle = sle(niche_start, niche_end); + let cast_smaller = cast_to_size <= tag_size; + + // In the algorithm above, we can change + // cast(relative_tag) + niche_variants.start() + // into + // cast(tag) + (niche_variants.start() - niche_start) + // if either the casted type is no larger than the original + // type, or if the niche values are contiguous (in either the + // signed or unsigned sense). + let can_incr_after_cast = cast_smaller || niches_ule || niches_sle; + + let data_for_boundary_niche = || -> Option<(IntPredicate, u128)> { + if !can_incr_after_cast { + None + } else if niche_start == low_unsigned { + Some((IntPredicate::IntULE, niche_end)) + } else if niche_end == high_unsigned { + Some((IntPredicate::IntUGE, niche_start)) + } else if niche_start == low_signed { + Some((IntPredicate::IntSLE, niche_end)) + } else if niche_end == high_signed { + Some((IntPredicate::IntSGE, niche_start)) + } else { + None + } }; - // NOTE(eddyb) this addition needs to be performed on the final - // type, in case the niche itself can't represent all variant - // indices (e.g. `u8` niche with more than `256` variants, - // but enough uninhabited variants so that the remaining variants - // fit in the niche). - // In other words, `niche_variants.end - niche_variants.start` - // is representable in the niche, but `niche_variants.end` - // might not be, in extreme cases. - let niche_discr = { - let relative_discr = if relative_max == 0 { - // HACK(eddyb) since we have only one niche, we know which - // one it is, and we can avoid having a dynamic value here. - bx.cx().const_uint(cast_to, 0) + let (is_niche, tagged_discr, delta) = if relative_max == 0 { + // Best case scenario: only one tagged variant. This will + // likely become just a comparison and a jump. + // The algorithm is: + // is_niche = tag == niche_start + // discr = if is_niche { + // niche_start + // } else { + // untagged_variant + // } + let niche_start = bx.cx().const_uint_big(tag_llty, niche_start); + let is_niche = bx.icmp(IntPredicate::IntEQ, tag, niche_start); + let tagged_discr = + bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64); + (is_niche, tagged_discr, 0) + } else if let Some((predicate, constant)) = data_for_boundary_niche() { + // The niche values are either the lowest or the highest in + // `range`. We can avoid the first subtraction in the + // algorithm. + // The algorithm is now this: + // is_niche = tag <= niche_end + // discr = if is_niche { + // cast(tag) + (niche_variants.start() - niche_start) + // } else { + // untagged_variant + // } + // (the first line may instead be tag >= niche_start, + // and may be a signed or unsigned comparison) + let is_niche = + bx.icmp(predicate, tag, bx.cx().const_uint_big(tag_llty, constant)); + let cast_tag = if cast_smaller { + bx.intcast(tag, cast_to, false) + } else if niches_ule { + bx.zext(tag, cast_to) } else { - bx.intcast(relative_discr, cast_to, false) + bx.sext(tag, cast_to) }; - bx.add( + + let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start); + (is_niche, cast_tag, delta) + } else { + // The special cases don't apply, so we'll have to go with + // the general algorithm. + let relative_discr = bx.sub(tag, bx.cx().const_uint_big(tag_llty, niche_start)); + let cast_tag = bx.intcast(relative_discr, cast_to, false); + let is_niche = bx.icmp( + IntPredicate::IntULE, relative_discr, - bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64), - ) + bx.cx().const_uint(tag_llty, relative_max as u64), + ); + (is_niche, cast_tag, niche_variants.start().as_u32() as u128) }; - bx.select( + let tagged_discr = if delta == 0 { + tagged_discr + } else { + bx.add(tagged_discr, bx.cx().const_uint_big(cast_to, delta)) + }; + + let discr = bx.select( is_niche, - niche_discr, + tagged_discr, bx.cx().const_uint(cast_to, untagged_variant.as_u32() as u64), - ) + ); + + // In principle we could insert assumes on the possible range of `discr`, but + // currently in LLVM this seems to be a pessimization. + + discr } } } diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index bdc6a91cf6a..86481d5d758 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -22,6 +22,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn type_f32(&self) -> Self::Type; fn type_f64(&self) -> Self::Type; + fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type; fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type; fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type; fn type_kind(&self, ty: Self::Type) -> TypeKind; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 0c212cf59e1..dd00678aa0c 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -4,7 +4,7 @@ use rustc_hir::def::Namespace; use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; -use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty}; +use rustc_middle::ty::{ConstInt, Ty}; use rustc_middle::{mir, ty}; use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; @@ -567,7 +567,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(..) => { throw_inval!(TooGeneric) } - ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => { + ty::ConstKind::Error(reported) => { throw_inval!(AlreadyReported(reported)) } ty::ConstKind::Unevaluated(uv) => { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 22a61774e8c..5a8b3e30b9f 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -13,11 +13,8 @@ use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeVisitable}; use rustc_mir_dataflow::{self, Analysis}; use rustc_span::{sym, Span, Symbol}; -use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::{ - self, ObligationCauseCode, SelectionContext, TraitEngine, TraitEngineExt, -}; +use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext}; use std::mem; use std::ops::Deref; @@ -747,37 +744,28 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // "non-const" check. This is required for correctness here. { let infcx = tcx.infer_ctxt().build(); - let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); + let ocx = ObligationCtxt::new(&infcx); + let predicates = tcx.predicates_of(callee).instantiate(tcx, substs); let hir_id = tcx .hir() .local_def_id_to_hir_id(self.body.source.def_id().expect_local()); - let cause = || { - ObligationCause::new( - terminator.source_info.span, - hir_id, - ObligationCauseCode::ItemObligation(callee), - ) - }; - let normalized = infcx.partially_normalize_associated_types_in( - cause(), - param_env, - predicates, + let cause = ObligationCause::new( + terminator.source_info.span, + hir_id, + ObligationCauseCode::ItemObligation(callee), ); - - for p in normalized.obligations { - fulfill_cx.register_predicate_obligation(&infcx, p); - } - for obligation in traits::predicates_for_generics( - |_, _| cause(), + let normalized_predicates = + ocx.normalize(cause.clone(), param_env, predicates); + ocx.register_obligations(traits::predicates_for_generics( + |_, _| cause.clone(), self.param_env, - normalized.value, - ) { - fulfill_cx.register_predicate_obligation(&infcx, obligation); - } - let errors = fulfill_cx.select_all_or_error(&infcx); + normalized_predicates, + )); + + let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } } @@ -843,7 +831,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { obligation.clone(), &obligation, &e, - false, ); } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 335992342a6..d995d533ca3 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -146,6 +146,7 @@ impl Qualif for NeedsNonConstDrop { qualifs.needs_non_const_drop } + #[instrument(level = "trace", skip(cx), ret)] fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { // Avoid selecting for simple cases, such as builtin types. if ty::util::is_trivially_const_drop(ty) { @@ -174,6 +175,8 @@ impl Qualif for NeedsNonConstDrop { return true; }; + trace!(?impl_src); + if !matches!( impl_src, ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index f3ae16da43b..f48bcd90809 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -45,11 +45,10 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { // There's not really any point in promoting errorful MIR. // // This does not include MIR that failed const-checking, which we still try to promote. - if body.return_ty().references_error() { - tcx.sess.delay_span_bug(body.span, "PromoteTemps: MIR had errors"); + if let Err(_) = body.return_ty().error_reported() { + debug!("PromoteTemps: MIR had errors"); return; } - if body.source.promoted.is_some() { return; } diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 9daa21ef6b1..5afce15e26b 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -23,9 +23,9 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] } stable_deref_trait = "1.0.0" -stacker = "0.1.14" +stacker = "0.1.15" tempfile = "3.2" -thin-vec = "0.2.8" +thin-vec = "0.2.9" tracing = "0.1" [dependencies.parking_lot] diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 9c0fb8265cf..c550f246e09 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -410,6 +410,7 @@ impl<T> Lock<T> { #[cfg(parallel_compiler)] #[inline(always)] + #[track_caller] pub fn lock(&self) -> LockGuard<'_, T> { if ERROR_CHECKING { self.0.try_lock().expect("lock was already held") @@ -420,21 +421,25 @@ impl<T> Lock<T> { #[cfg(not(parallel_compiler))] #[inline(always)] + #[track_caller] pub fn lock(&self) -> LockGuard<'_, T> { self.0.borrow_mut() } #[inline(always)] + #[track_caller] pub fn with_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R { f(&mut *self.lock()) } #[inline(always)] + #[track_caller] pub fn borrow(&self) -> LockGuard<'_, T> { self.lock() } #[inline(always)] + #[track_caller] pub fn borrow_mut(&self) -> LockGuard<'_, T> { self.lock() } @@ -476,6 +481,7 @@ impl<T> RwLock<T> { #[cfg(not(parallel_compiler))] #[inline(always)] + #[track_caller] pub fn read(&self) -> ReadGuard<'_, T> { self.0.borrow() } @@ -491,6 +497,7 @@ impl<T> RwLock<T> { } #[inline(always)] + #[track_caller] pub fn with_read_lock<F: FnOnce(&T) -> R, R>(&self, f: F) -> R { f(&*self.read()) } @@ -509,6 +516,7 @@ impl<T> RwLock<T> { #[cfg(not(parallel_compiler))] #[inline(always)] + #[track_caller] pub fn write(&self) -> WriteGuard<'_, T> { self.0.borrow_mut() } @@ -524,16 +532,19 @@ impl<T> RwLock<T> { } #[inline(always)] + #[track_caller] pub fn with_write_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R { f(&mut *self.write()) } #[inline(always)] + #[track_caller] pub fn borrow(&self) -> ReadGuard<'_, T> { self.read() } #[inline(always)] + #[track_caller] pub fn borrow_mut(&self) -> WriteGuard<'_, T> { self.write() } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index cf4bcc7c158..e043368fdfe 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -6,6 +6,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(once_cell)] +#![feature(decl_macro)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] @@ -736,26 +737,58 @@ fn print_crate_info( // Any output here interferes with Cargo's parsing of other printed output NativeStaticLibs => {} LinkArgs => {} + SplitDebuginfo => { + use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked}; + + for split in &[Off, Packed, Unpacked] { + let stable = sess.target.options.supported_split_debuginfo.contains(split); + let unstable_ok = sess.unstable_options(); + if stable || unstable_ok { + println!("{}", split); + } + } + } } } Compilation::Stop } /// Prints version information -pub fn version(binary: &str, matches: &getopts::Matches) { +/// +/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate. +pub macro version($binary: literal, $matches: expr) { + fn unw(x: Option<&str>) -> &str { + x.unwrap_or("unknown") + } + $crate::version_at_macro_invocation( + $binary, + $matches, + unw(option_env!("CFG_VERSION")), + unw(option_env!("CFG_VER_HASH")), + unw(option_env!("CFG_VER_DATE")), + unw(option_env!("CFG_RELEASE")), + ) +} + +#[doc(hidden)] // use the macro instead +pub fn version_at_macro_invocation( + binary: &str, + matches: &getopts::Matches, + version: &str, + commit_hash: &str, + commit_date: &str, + release: &str, +) { let verbose = matches.opt_present("verbose"); - println!("{} {}", binary, util::version_str().unwrap_or("unknown version")); + println!("{} {}", binary, version); if verbose { - fn unw(x: Option<&str>) -> &str { - x.unwrap_or("unknown") - } println!("binary: {}", binary); - println!("commit-hash: {}", unw(util::commit_hash_str())); - println!("commit-date: {}", unw(util::commit_date_str())); + println!("commit-hash: {}", commit_hash); + println!("commit-date: {}", commit_date); println!("host: {}", config::host_triple()); - println!("release: {}", unw(util::release_str())); + println!("release: {}", release); let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); @@ -1071,7 +1104,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> { } if matches.opt_present("version") { - version("rustc", &matches); + version!("rustc", &matches); return None; } @@ -1216,7 +1249,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { format!("we would appreciate a bug report: {}", bug_report_url).into(), format!( "rustc {} running on {}", - util::version_str().unwrap_or("unknown_version"), + util::version_str!().unwrap_or("unknown_version"), config::host_triple() ) .into(), diff --git a/compiler/rustc_error_codes/src/error_codes/E0207.md b/compiler/rustc_error_codes/src/error_codes/E0207.md index 8a7923ac93f..95e7c9fc76c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0207.md +++ b/compiler/rustc_error_codes/src/error_codes/E0207.md @@ -1,4 +1,5 @@ -A type parameter that is specified for `impl` is not constrained. +A type, const or lifetime parameter that is specified for `impl` is not +constrained. Erroneous code example: @@ -14,8 +15,8 @@ impl<T: Default> Foo { } ``` -Any type parameter of an `impl` must meet at least one of -the following criteria: +Any type or const parameter of an `impl` must meet at least one of the +following criteria: - it appears in the _implementing type_ of the impl, e.g. `impl<T> Foo<T>` - for a trait impl, it appears in the _implemented trait_, e.g. @@ -23,6 +24,9 @@ the following criteria: - it is bound as an associated type, e.g. `impl<T, U> SomeTrait for T where T: AnotherTrait<AssocType=U>` +Any unconstrained lifetime parameter of an `impl` is not supported if the +lifetime parameter is used by an associated type. + ### Error example 1 Suppose we have a struct `Foo` and we would like to define some methods for it. @@ -32,7 +36,6 @@ The problem is that the parameter `T` does not appear in the implementing type (`Foo`) of the impl. In this case, we can fix the error by moving the type parameter from the `impl` to the method `get`: - ``` struct Foo; @@ -128,6 +131,70 @@ impl<T: Default> Maker<Foo<T>> for FooMaker { } ``` +### Error example 3 + +Suppose we have a struct `Foo` and we would like to define some methods for it. +The following code example has a definition which leads to a compiler error: + +```compile_fail,E0207 +struct Foo; + +impl<const T: i32> Foo { + // error: the const parameter `T` is not constrained by the impl trait, self + // type, or predicates [E0207] + fn get(&self) -> i32 { + i32::default() + } +} +``` + +The problem is that the const parameter `T` does not appear in the implementing +type (`Foo`) of the impl. In this case, we can fix the error by moving the type +parameter from the `impl` to the method `get`: + + +``` +struct Foo; + +// Move the const parameter from the impl to the method +impl Foo { + fn get<const T: i32>(&self) -> i32 { + i32::default() + } +} +``` + +### Error example 4 + +Suppose we have a struct `Foo` and a struct `Bar` that uses lifetime `'a`. We +would like to implement trait `Contains` for `Foo`. The trait `Contains` have +the associated type `B`. The following code example has a definition which +leads to a compiler error: + +```compile_fail,E0207 +struct Foo; +struct Bar<'a>; + +trait Contains { + type B; + + fn get(&self) -> i32; +} + +impl<'a> Contains for Foo { + type B = Bar<'a>; + + // error: the lifetime parameter `'a` is not constrained by the impl trait, + // self type, or predicates [E0207] + fn get(&self) -> i32 { + i32::default() + } +} +``` + +Please note that unconstrained lifetime parameters are not supported if they are +being used by an associated type. + ### Additional information For more information, please see [RFC 447]. diff --git a/compiler/rustc_error_codes/src/error_codes/E0706.md b/compiler/rustc_error_codes/src/error_codes/E0706.md index d379b8a2384..fabd855a222 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0706.md +++ b/compiler/rustc_error_codes/src/error_codes/E0706.md @@ -56,4 +56,4 @@ You might be interested in visiting the [async book] for further information. [`async-trait` crate]: https://crates.io/crates/async-trait [async-is-hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/ [Generic Associated Types]: https://github.com/rust-lang/rust/issues/44265 -[async book]: https://rust-lang.github.io/async-book/07_workarounds/06_async_in_traits.html +[async book]: https://rust-lang.github.io/async-book/07_workarounds/05_async_in_traits.html diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 67f2156f32e..de47ada8264 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -58,3 +58,68 @@ borrowck_returned_lifetime_short = borrowck_used_impl_require_static = the used `impl` has a `'static` requirement + +borrowck_capture_kind_label = + capture is {$kind_desc} because of use here + +borrowck_var_borrow_by_use_place_in_generator = + borrow occurs due to use of {$place} in closure in generator + +borrowck_var_borrow_by_use_place_in_closure = + borrow occurs due to use of {$place} in closure + +borrowck_var_borrow_by_use_place = + borrow occurs due to use of {$place} + +borrowck_borrow_due_to_use_generator = + borrow occurs due to use in generator + +borrowck_use_due_to_use_generator = + use occurs due to use in generator + +borrowck_assign_due_to_use_generator = + assign occurs due to use in generator + +borrowck_assign_part_due_to_use_generator = + assign to part occurs due to use in generator + +borrowck_borrow_due_to_use_closure = + borrow occurs due to use in closure + +borrowck_use_due_to_use_closure = + use occurs due to use in closure + +borrowck_assign_due_to_use_closure = + assign occurs due to use in closure + +borrowck_assign_part_due_to_use_closure = + assign to part occurs due to use in closure + +borrowck_capture_immute = + capture is immutable because of use here + +borrowck_capture_mut = + capture is mutable because of use here + +borrowck_capture_move = + capture is moved because of use here + +borrowck_var_move_by_use_place_in_generator = + move occurs due to use of {$place} in generator + +borrowck_var_move_by_use_place_in_closure = + move occurs due to use of {$place} in closure + +borrowck_cannot_move_when_borrowed = + cannot move out of {$place -> + [value] value + *[other] {$place} + } because it is borrowed + .label = borrow of {$borrow_place -> + [value] value + *[other] {$borrow_place} + } occurs here + .move_label = move out of {$value_place -> + [value] value + *[other] {$value_place} + } occurs here diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl new file mode 100644 index 00000000000..68a205df6c7 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -0,0 +1,58 @@ +codegen_llvm_unknown_ctarget_feature = + unknown feature specified for `-Ctarget-feature`: `{$feature}` + .note = it is still passed through to the codegen backend + .possible_feature = you might have meant: `{$rust_feature}` + .consider_filing_feature_request = consider filing a feature request + +codegen_llvm_unknown_ctarget_feature_prefix = + unknown feature specified for `-Ctarget-feature`: `{$feature}` + .note = features must begin with a `+` to enable or `-` to disable it + +codegen_llvm_error_creating_import_library = + Error creating import library for {$lib_name}: {$error} + +codegen_llvm_instrument_coverage_requires_llvm_12 = + rustc option `-C instrument-coverage` requires LLVM 12 or higher. + +codegen_llvm_symbol_already_defined = + symbol `{$symbol_name}` is already defined + +codegen_llvm_branch_protection_requires_aarch64 = + -Zbranch-protection is only supported on aarch64 + +codegen_llvm_invalid_minimum_alignment = + invalid minimum global alignment: {$err} + +codegen_llvm_linkage_const_or_mut_type = + must have type `*const T` or `*mut T` due to `#[linkage]` attribute + +codegen_llvm_sanitizer_memtag_requires_mte = + `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte` + +codegen_llvm_archive_build_failure = + failed to build archive: {$error} + +codegen_llvm_error_writing_def_file = + Error writing .DEF file: {$error} + +codegen_llvm_error_calling_dlltool = + Error calling dlltool: {$error} + +codegen_llvm_dlltool_fail_import_library = + Dlltool could not create import library: {$stdout}\n{$stderr} + +codegen_llvm_unknown_archive_kind = + Don't know how to build archive of type: {$kind} + +codegen_llvm_target_feature_disable_or_enable = + the target features {$features} must all be either enabled or disabled together + +codegen_llvm_missing_features = + add the missing features in a `target_feature` attribute + +codegen_llvm_dynamic_linking_with_lto = + cannot prefer dynamic linking when performing LTO + .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO + +codegen_llvm_fail_parsing_target_machine_config_to_target_machine = + failed to parse target machine config to target machine: {$error} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 966a421bcf0..ad0d7582101 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -119,3 +119,66 @@ codegen_ssa_thorin_object_read = {$error} codegen_ssa_thorin_object_write = {$error} codegen_ssa_thorin_gimli_read = {$error} codegen_ssa_thorin_gimli_write = {$error} + +codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error + +codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer + +codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload + +codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected + +codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload + +codegen_ssa_linker_not_found = linker `{$linker_path}` not found + .note = {$error} + +codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}` + .note = {$error} + .command_note = {$command_formatted} + +codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found + +codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option. + +codegen_ssa_unsufficient_vs_code_product = VS Code is a different product, and is not sufficient. + +codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status} + .note = {$output} + +codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error} + +codegen_ssa_stripping_debu_info_failed = stripping debug info with `{$util}` failed: {$status} + .note = {$output} + +codegen_ssa_unable_to_run = unable to run `{$util}`: {$error} + +codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker + +codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms. + +codegen_ssa_native_static_libs = native-static-libs: {$arguments} + +codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker + +codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error} + +codegen_ssa_failed_to_write = failed to write {$path}: {$error} + +codegen_ssa_unable_to_write_debugger_visualizer = Unable to write debugger visualizer file `{$path}`: {$error} + +codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error} + +codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc + +codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error} + +codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}` + +codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {error} diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 74088f4dfbe..d27edd47470 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -150,3 +150,6 @@ hir_analysis_const_bound_for_non_const_trait = hir_analysis_self_in_impl_self = `Self` is not valid in the self type of an impl block .note = replace `Self` with a different type + +hir_analysis_op_trait_generic_params = + `{$method_name}` must not have any generic parameters diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 18b3408b06a..fa975ff2c20 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -171,3 +171,4 @@ infer_msl_introduces_static = introduces a `'static` lifetime requirement infer_msl_unmet_req = because this has an unmet lifetime requirement infer_msl_trait_note = this has an implicit `'static` lifetime requirement infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement +infer_suggest_add_let_for_letchains = consider adding `let` diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 13c368d1c58..6d42b23fb3a 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -112,6 +112,9 @@ parser_missing_semicolon_before_array = expected `;`, found `[` parser_invalid_block_macro_segment = cannot use a `block` macro fragment here .label = the `block` fragment is within this context +parser_expect_dotdot_not_dotdotdot = expected `..`, found `...` + .suggestion = use `..` to fill in the rest of the fields + parser_if_expression_missing_then_block = this `if` expression is missing a block after the condition .add_then_block = add a block here .condition_possibly_unfinished = this binary operation is possibly unfinished @@ -122,6 +125,9 @@ parser_if_expression_missing_condition = missing condition for `if` expression parser_expected_expression_found_let = expected expression, found `let` statement +parser_expect_eq_instead_of_eqeq = expected `=`, found `==` + .suggestion = consider using `=` here + parser_expected_else_block = expected `{"{"}`, found {$first_tok} .label = expected an `if` or a block after this `else` .suggestion = add an `if` if this is the condition of a chained `else if` statement diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl index bc5bfe2a244..001e53d1d0e 100644 --- a/compiler/rustc_error_messages/locales/en-US/passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl @@ -47,7 +47,10 @@ passes_no_coverage_not_coverable = passes_should_be_applied_to_fn = attribute should be applied to a function definition - .label = not a function definition + .label = {$on_crate -> + [true] cannot be applied to crates + *[false] not a function definition + } passes_naked_tracked_caller = cannot use `#[track_caller]` with `#[naked]` @@ -451,8 +454,14 @@ passes_break_inside_async_block = .async_block_label = enclosing `async` block passes_outside_loop = - `{$name}` outside of a loop - .label = cannot `{$name}` outside of a loop + `{$name}` outside of a loop{$is_break -> + [true] {" or labeled block"} + *[false] {""} + } + .label = cannot `{$name}` outside of a loop{$is_break -> + [true] {" or labeled block"} + *[false] {""} + } passes_unlabeled_in_labeled_block = unlabeled `{$cf_type}` inside of a labeled block @@ -665,3 +674,36 @@ passes_missing_const_err = attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` .help = make the function or method const .label = attribute specified here + +passes_dead_codes = + { $multiple -> + *[true] multiple {$descr}s are + [false] { $num -> + [one] {$descr} {$name_list} is + *[other] {$descr}s {$name_list} are + } + } never {$participle} + +passes_change_fields_to_be_of_unit_type = + consider changing the { $num -> + [one] field + *[other] fields + } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num -> + [one] field + *[other] fields + } + +passes_parent_info = + {$num -> + [one] {$descr} + *[other] {$descr}s + } in this {$parent_descr} + +passes_ignored_derived_impls = + `{$name}` has {$trait_list_len -> + [one] a derived impl + *[other] derived impls + } for the {$trait_list_len -> + [one] trait {$trait_list}, but this is + *[other] traits {$trait_list}, but these are + } intentionally ignored during dead code analysis diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 9465051dd10..0b1b75471a6 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -30,7 +30,8 @@ use intl_memoizer::concurrent::IntlLangMemoizer; #[cfg(not(parallel_compiler))] use intl_memoizer::IntlLangMemoizer; -pub use fluent_bundle::{FluentArgs, FluentError, FluentValue}; +pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue}; + pub use unic_langid::{langid, LanguageIdentifier}; // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module. @@ -42,6 +43,7 @@ fluent_messages! { borrowck => "../locales/en-US/borrowck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", codegen_gcc => "../locales/en-US/codegen_gcc.ftl", + codegen_llvm => "../locales/en-US/codegen_llvm.ftl", codegen_ssa => "../locales/en-US/codegen_ssa.ftl", compiletest => "../locales/en-US/compiletest.ftl", const_eval => "../locales/en-US/const_eval.ftl", diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f14b8ee3254..c450c276366 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -52,7 +52,6 @@ impl Emitter for AnnotateSnippetEmitterWriter { let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &self.source_map, &mut primary_span, &mut children, &diag.level, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 45c017df918..375e3ebd77d 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -44,6 +44,15 @@ pub trait IntoDiagnosticArg { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>; } +impl<'source> IntoDiagnosticArg for DiagnosticArgValue<'source> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + match self { + DiagnosticArgValue::Str(s) => DiagnosticArgValue::Str(Cow::Owned(s.into_owned())), + DiagnosticArgValue::Number(n) => DiagnosticArgValue::Number(n), + } + } +} + impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> { fn into(self) -> FluentValue<'source> { match self { @@ -205,6 +214,22 @@ impl Diagnostic { } #[track_caller] + pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self { + Diagnostic { + level, + message: messages, + code: None, + span: MultiSpan::new(), + children: vec![], + suggestions: Ok(vec![]), + args: Default::default(), + sort_span: DUMMY_SP, + is_lint: false, + emitted_at: DiagnosticLocation::caller(), + } + } + + #[track_caller] pub fn new_with_code<M: Into<DiagnosticMessage>>( level: Level, code: Option<DiagnosticId>, @@ -717,7 +742,7 @@ impl Diagnostic { &mut self, sp: Span, msg: impl Into<SubdiagnosticMessage>, - suggestions: impl Iterator<Item = String>, + suggestions: impl IntoIterator<Item = String>, applicability: Applicability, ) -> &mut Self { self.span_suggestions_with_style( @@ -734,11 +759,11 @@ impl Diagnostic { &mut self, sp: Span, msg: impl Into<SubdiagnosticMessage>, - suggestions: impl Iterator<Item = String>, + suggestions: impl IntoIterator<Item = String>, applicability: Applicability, style: SuggestionStyle, ) -> &mut Self { - let mut suggestions: Vec<_> = suggestions.collect(); + let mut suggestions: Vec<_> = suggestions.into_iter().collect(); suggestions.sort(); debug_assert!( @@ -765,10 +790,10 @@ impl Diagnostic { pub fn multipart_suggestions( &mut self, msg: impl Into<SubdiagnosticMessage>, - suggestions: impl Iterator<Item = Vec<(Span, String)>>, + suggestions: impl IntoIterator<Item = Vec<(Span, String)>>, applicability: Applicability, ) -> &mut Self { - let suggestions: Vec<_> = suggestions.collect(); + let suggestions: Vec<_> = suggestions.into_iter().collect(); debug_assert!( !(suggestions .iter() @@ -931,6 +956,13 @@ impl Diagnostic { self } + pub fn replace_args( + &mut self, + args: FxHashMap<DiagnosticArgName<'static>, DiagnosticArgValue<'static>>, + ) { + self.args = args; + } + pub fn styled_message(&self) -> &[(DiagnosticMessage, Style)] { &self.message } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index ecf8570e81f..18cbf963494 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -482,9 +482,9 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. #[track_caller] - pub fn delay_as_bug(&mut self) { + pub fn delay_as_bug(&mut self) -> G { self.downgrade_to_delayed_bug(); - self.emit(); + self.emit() } forward!( @@ -599,13 +599,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { &mut self, sp: Span, msg: impl Into<SubdiagnosticMessage>, - suggestions: impl Iterator<Item = String>, + suggestions: impl IntoIterator<Item = String>, applicability: Applicability, ) -> &mut Self); forward!(pub fn multipart_suggestions( &mut self, msg: impl Into<SubdiagnosticMessage>, - suggestions: impl Iterator<Item = Vec<(Span, String)>>, + suggestions: impl IntoIterator<Item = Vec<(Span, String)>>, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestion_short( diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 7640b2919f7..c6035705e39 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -11,8 +11,10 @@ use rustc_target::abi::TargetDataLayoutErrors; use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple}; use std::borrow::Cow; use std::fmt; +use std::fmt::Write; use std::num::ParseIntError; use std::path::{Path, PathBuf}; +use std::process::ExitStatus; pub struct DiagnosticArgFromDisplay<'a>(pub &'a dyn fmt::Display); @@ -58,6 +60,7 @@ into_diagnostic_arg_using_display!( i128, u128, std::io::Error, + std::boxed::Box<dyn std::error::Error>, std::num::NonZeroU32, hir::Target, Edition, @@ -66,7 +69,8 @@ into_diagnostic_arg_using_display!( ParseIntError, StackProtector, &TargetTriple, - SplitDebuginfo + SplitDebuginfo, + ExitStatus, ); impl IntoDiagnosticArg for bool { @@ -103,6 +107,12 @@ impl IntoDiagnosticArg for String { } } +impl<'a> IntoDiagnosticArg for Cow<'a, str> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.into_owned())) + } +} + impl<'a> IntoDiagnosticArg for &'a Path { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Owned(self.display().to_string())) @@ -170,6 +180,37 @@ impl IntoDiagnosticArg for Level { } } +#[derive(Clone)] +pub struct DiagnosticSymbolList(Vec<Symbol>); + +impl From<Vec<Symbol>> for DiagnosticSymbolList { + fn from(v: Vec<Symbol>) -> Self { + DiagnosticSymbolList(v) + } +} + +impl IntoDiagnosticArg for DiagnosticSymbolList { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + // FIXME: replace the logic here with a real list formatter + let symbols = match &self.0[..] { + [symbol] => format!("`{symbol}`"), + [symbol, last] => { + format!("`{symbol}` and `{last}`",) + } + [symbols @ .., last] => { + let mut result = String::new(); + for symbol in symbols { + write!(result, "`{symbol}`, ").unwrap(); + } + write!(result, "and `{last}`").unwrap(); + result + } + [] => unreachable!(), + }; + DiagnosticArgValue::Str(Cow::Owned(symbols)) + } +} + impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { let mut diag; diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index b7b8fe3f25a..55c7997a513 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -314,7 +314,6 @@ pub trait Emitter: Translate { fn fix_multispans_in_extern_macros_and_render_macro_backtrace( &self, - source_map: &Option<Lrc<SourceMap>>, span: &mut MultiSpan, children: &mut Vec<SubDiagnostic>, level: &Level, @@ -340,7 +339,7 @@ pub trait Emitter: Translate { .collect(); if !backtrace { - self.fix_multispans_in_extern_macros(source_map, span, children); + self.fix_multispans_in_extern_macros(span, children); } self.render_multispans_macro_backtrace(span, children, backtrace); @@ -480,15 +479,13 @@ pub trait Emitter: Translate { // this will change the span to point at the use site. fn fix_multispans_in_extern_macros( &self, - source_map: &Option<Lrc<SourceMap>>, span: &mut MultiSpan, children: &mut Vec<SubDiagnostic>, ) { - let Some(source_map) = source_map else { return }; debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children); - self.fix_multispan_in_extern_macros(source_map, span); + self.fix_multispan_in_extern_macros(span); for child in children.iter_mut() { - self.fix_multispan_in_extern_macros(source_map, &mut child.span); + self.fix_multispan_in_extern_macros(&mut child.span); } debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children); } @@ -496,7 +493,8 @@ pub trait Emitter: Translate { // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros. // Since these locations are often difficult to read, // we move these spans from the external macros to their corresponding use site. - fn fix_multispan_in_extern_macros(&self, source_map: &Lrc<SourceMap>, span: &mut MultiSpan) { + fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) { + let Some(source_map) = self.source_map() else { return }; // First, find all the spans in external macros and point instead at their use site. let replacements: Vec<(Span, Span)> = span .primary_spans() @@ -544,7 +542,6 @@ impl Emitter for EmitterWriter { debug!("emit_diagnostic: suggestions={:?}", suggestions); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &self.sm, &mut primary_span, &mut children, &diag.level, @@ -2213,22 +2210,45 @@ impl FileWithAnnotatedLines { if let Some(ref sm) = emitter.source_map() { for span_label in msp.span_labels() { + let fixup_lo_hi = |span: Span| { + let lo = sm.lookup_char_pos(span.lo()); + let mut hi = sm.lookup_char_pos(span.hi()); + + // Watch out for "empty spans". If we get a span like 6..6, we + // want to just display a `^` at 6, so convert that to + // 6..7. This is degenerate input, but it's best to degrade + // gracefully -- and the parser likes to supply a span like + // that for EOF, in particular. + + if lo.col_display == hi.col_display && lo.line == hi.line { + hi.col_display += 1; + } + (lo, hi) + }; + if span_label.span.is_dummy() { + if let Some(span) = msp.primary_span() { + // if we don't know where to render the annotation, emit it as a note + // on the primary span. + + let (lo, hi) = fixup_lo_hi(span); + + let ann = Annotation { + start_col: lo.col_display, + end_col: hi.col_display, + is_primary: span_label.is_primary, + label: span_label + .label + .as_ref() + .map(|m| emitter.translate_message(m, args).to_string()), + annotation_type: AnnotationType::Singleline, + }; + add_annotation_to_file(&mut output, lo.file, lo.line, ann); + } continue; } - let lo = sm.lookup_char_pos(span_label.span.lo()); - let mut hi = sm.lookup_char_pos(span_label.span.hi()); - - // Watch out for "empty spans". If we get a span like 6..6, we - // want to just display a `^` at 6, so convert that to - // 6..7. This is degenerate input, but it's best to degrade - // gracefully -- and the parser likes to supply a span like - // that for EOF, in particular. - - if lo.col_display == hi.col_display && lo.line == hi.line { - hi.col_display += 1; - } + let (lo, hi) = fixup_lo_hi(span_label.span); if lo.line != hi.line { let ml = MultilineAnnotation { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f390495b53d..a8fd1a17a51 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -376,7 +376,7 @@ pub use diagnostic::{ DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted}; -pub use diagnostic_impls::DiagnosticArgFromDisplay; +pub use diagnostic_impls::{DiagnosticArgFromDisplay, DiagnosticSymbolList}; use std::backtrace::Backtrace; /// A handler deals with errors and other compiler output. diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index a7737b467b7..a452fac0747 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -1,7 +1,10 @@ use crate::snippet::Style; use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle}; use rustc_data_structures::sync::Lrc; -use rustc_error_messages::FluentArgs; +use rustc_error_messages::{ + fluent_bundle::resolver::errors::{ReferenceKind, ResolverError}, + FluentArgs, FluentError, +}; use std::borrow::Cow; /// Convert diagnostic arguments (a rustc internal type that exists to implement @@ -102,14 +105,31 @@ pub trait Translate { .or_else(|| translate_with_bundle(self.fallback_fluent_bundle())) .map(|(translated, errs)| { // Always bail out for errors with the fallback bundle. - assert!( - errs.is_empty(), - "identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}", - identifier, - attr, - args, - errs - ); + + let mut help_messages = vec![]; + + if !errs.is_empty() { + for error in &errs { + match error { + FluentError::ResolverError(ResolverError::Reference( + ReferenceKind::Message { id, .. }, + )) if args.iter().any(|(arg_id, _)| arg_id == id) => { + help_messages.push(format!("Argument `{id}` exists but was not referenced correctly. Try using `{{${id}}}` instead")); + } + _ => {} + } + } + + panic!( + "Encountered errors while formatting message for `{identifier}`\n\ + help: {}\n\ + attr: `{attr:?}`\n\ + args: `{args:?}`\n\ + errors: `{errs:?}`", + help_messages.join("\nhelp: ") + ); + } + translated }) .expect("failed to find message in primary or fallback fluent bundles") diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c8de60ccb89..1294f1e17d4 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -250,6 +250,7 @@ pub trait MultiItemModifier { span: Span, meta_item: &ast::MetaItem, item: Annotatable, + is_derive_const: bool, ) -> ExpandResult<Vec<Annotatable>, Annotatable>; } @@ -263,6 +264,7 @@ where span: Span, meta_item: &ast::MetaItem, item: Annotatable, + _is_derive_const: bool, ) -> ExpandResult<Vec<Annotatable>, Annotatable> { ExpandResult::Ready(self(ecx, span, meta_item, item)) } @@ -873,7 +875,7 @@ impl SyntaxExtension { /// Error type that denotes indeterminacy. pub struct Indeterminate; -pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>)>; +pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>, bool)>; pub trait ResolverExpand { fn next_node_id(&mut self) -> NodeId; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 57713fb3cd6..3d37e2c6568 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -337,6 +337,7 @@ pub enum InvocationKind { }, Derive { path: ast::Path, + is_const: bool, item: Annotatable, }, } @@ -478,13 +479,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { derive_invocations.reserve(derives.len()); derives .into_iter() - .map(|(path, item, _exts)| { + .map(|(path, item, _exts, is_const)| { // FIXME: Consider using the derive resolutions (`_exts`) // instead of enqueuing the derives to be resolved again later. let expn_id = LocalExpnId::fresh_empty(); derive_invocations.push(( Invocation { - kind: InvocationKind::Derive { path, item }, + kind: InvocationKind::Derive { path, item, is_const }, fragment_kind, expansion_data: ExpansionData { id: expn_id, @@ -717,7 +718,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::LegacyAttr(expander) => { match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) { Ok(meta) => { - let items = match expander.expand(self.cx, span, &meta, item) { + let items = match expander.expand(self.cx, span, &meta, item, false) { ExpandResult::Ready(items) => items, ExpandResult::Retry(item) => { // Reassemble the original invocation for retrying. @@ -749,19 +750,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } _ => unreachable!(), }, - InvocationKind::Derive { path, item } => match ext { + InvocationKind::Derive { path, item, is_const } => match ext { SyntaxExtensionKind::Derive(expander) | SyntaxExtensionKind::LegacyDerive(expander) => { if let SyntaxExtensionKind::Derive(..) = ext { self.gate_proc_macro_input(&item); } let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path }; - let items = match expander.expand(self.cx, span, &meta, item) { + let items = match expander.expand(self.cx, span, &meta, item, is_const) { ExpandResult::Ready(items) => items, ExpandResult::Retry(item) => { // Reassemble the original invocation for retrying. return ExpandResult::Retry(Invocation { - kind: InvocationKind::Derive { path: meta.path, item }, + kind: InvocationKind::Derive { path: meta.path, item, is_const }, ..invoc }); } diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs index f42576b16f5..63bafd7b046 100644 --- a/compiler/rustc_expand/src/mbe.rs +++ b/compiler/rustc_expand/src/mbe.rs @@ -52,7 +52,7 @@ impl KleeneToken { /// A Kleene-style [repetition operator](https://en.wikipedia.org/wiki/Kleene_star) /// for token sequences. #[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)] -enum KleeneOp { +pub(crate) enum KleeneOp { /// Kleene star (`*`) for zero or more repetitions ZeroOrMore, /// Kleene plus (`+`) for one or more repetitions diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index c8bdc39311c..95cec8d7ae2 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -73,17 +73,17 @@ pub(crate) use NamedMatch::*; pub(crate) use ParseResult::*; -use crate::mbe::{KleeneOp, TokenTree}; +use crate::mbe::{macro_rules::Tracker, KleeneOp, TokenTree}; use rustc_ast::token::{self, DocComment, Nonterminal, NonterminalKind, Token}; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::Lrc; +use rustc_errors::ErrorGuaranteed; use rustc_lint_defs::pluralize; use rustc_parse::parser::{NtOrTt, Parser}; +use rustc_span::symbol::Ident; use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::Span; - -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; -use rustc_span::symbol::Ident; use std::borrow::Cow; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -96,7 +96,8 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; /// /// This means a matcher can be represented by `&[MatcherLoc]`, and traversal mostly involves /// simply incrementing the current matcher position index by one. -pub(super) enum MatcherLoc { +#[derive(Debug)] +pub(crate) enum MatcherLoc { Token { token: Token, }, @@ -270,13 +271,17 @@ pub(crate) enum ParseResult<T> { Failure(Token, &'static str), /// Fatal error (malformed macro?). Abort compilation. Error(rustc_span::Span, String), - ErrorReported, + ErrorReported(ErrorGuaranteed), } /// A `ParseResult` where the `Success` variant contains a mapping of /// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping /// of metavars to the token trees they bind to. -pub(crate) type NamedParseResult = ParseResult<FxHashMap<MacroRulesNormalizedIdent, NamedMatch>>; +pub(crate) type NamedParseResult = ParseResult<NamedMatches>; + +/// Contains a mapping of `MacroRulesNormalizedIdent`s to `NamedMatch`es. +/// This represents the mapping of metavars to the token trees they bind to. +pub(crate) type NamedMatches = FxHashMap<MacroRulesNormalizedIdent, NamedMatch>; /// Count how many metavars declarations are in `matcher`. pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize { @@ -400,17 +405,21 @@ impl TtParser { /// /// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept /// track of through the mps generated. - fn parse_tt_inner( + fn parse_tt_inner<'matcher, T: Tracker<'matcher>>( &mut self, - matcher: &[MatcherLoc], + matcher: &'matcher [MatcherLoc], token: &Token, + track: &mut T, ) -> Option<NamedParseResult> { // Matcher positions that would be valid if the macro invocation was over now. Only // modified if `token == Eof`. let mut eof_mps = EofMatcherPositions::None; while let Some(mut mp) = self.cur_mps.pop() { - match &matcher[mp.idx] { + let matcher_loc = &matcher[mp.idx]; + track.before_match_loc(self, matcher_loc); + + match matcher_loc { MatcherLoc::Token { token: t } => { // If it's a doc comment, we just ignore it and move on to the next tt in the // matcher. This is a bug, but #95267 showed that existing programs rely on @@ -450,7 +459,7 @@ impl TtParser { // Try zero matches of this sequence, by skipping over it. self.cur_mps.push(MatcherPos { idx: idx_first_after, - matches: mp.matches.clone(), // a cheap clone + matches: Lrc::clone(&mp.matches), }); } @@ -463,8 +472,8 @@ impl TtParser { // sequence. If that's not possible, `ending_mp` will fail quietly when it is // processed next time around the loop. let ending_mp = MatcherPos { - idx: mp.idx + 1, // +1 skips the Kleene op - matches: mp.matches.clone(), // a cheap clone + idx: mp.idx + 1, // +1 skips the Kleene op + matches: Lrc::clone(&mp.matches), }; self.cur_mps.push(ending_mp); @@ -479,8 +488,8 @@ impl TtParser { // separator yet. Try ending the sequence. If that's not possible, `ending_mp` // will fail quietly when it is processed next time around the loop. let ending_mp = MatcherPos { - idx: mp.idx + 2, // +2 skips the separator and the Kleene op - matches: mp.matches.clone(), // a cheap clone + idx: mp.idx + 2, // +2 skips the separator and the Kleene op + matches: Lrc::clone(&mp.matches), }; self.cur_mps.push(ending_mp); @@ -552,10 +561,11 @@ impl TtParser { } /// Match the token stream from `parser` against `matcher`. - pub(super) fn parse_tt( + pub(super) fn parse_tt<'matcher, T: Tracker<'matcher>>( &mut self, parser: &mut Cow<'_, Parser<'_>>, - matcher: &[MatcherLoc], + matcher: &'matcher [MatcherLoc], + track: &mut T, ) -> NamedParseResult { // A queue of possible matcher positions. We initialize it with the matcher position in // which the "dot" is before the first token of the first token tree in `matcher`. @@ -571,7 +581,8 @@ impl TtParser { // Process `cur_mps` until either we have finished the input or we need to get some // parsing from the black-box parser done. - if let Some(res) = self.parse_tt_inner(matcher, &parser.token) { + let res = self.parse_tt_inner(matcher, &parser.token, track); + if let Some(res) = res { return res; } @@ -612,14 +623,14 @@ impl TtParser { // edition-specific matching behavior for non-terminals. let nt = match parser.to_mut().parse_nonterminal(kind) { Err(mut err) => { - err.span_label( + let guarantee = err.span_label( span, format!( "while parsing argument for this `{kind}` macro fragment" ), ) .emit(); - return ErrorReported; + return ErrorReported(guarantee); } Ok(nt) => nt, }; diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index f6fe38174f7..99af9107288 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -14,7 +14,9 @@ use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage}; +use rustc_errors::{ + Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, +}; use rustc_feature::Features; use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, @@ -33,6 +35,8 @@ use std::borrow::Cow; use std::collections::hash_map::Entry; use std::{mem, slice}; +use super::macro_parser::{NamedMatches, NamedParseResult}; + pub(crate) struct ParserAnyMacro<'a> { parser: Parser<'a>, @@ -205,8 +209,32 @@ fn trace_macros_note(cx_expansions: &mut FxIndexMap<Span, Vec<String>>, sp: Span cx_expansions.entry(sp).or_default().push(message); } +pub(super) trait Tracker<'matcher> { + /// This is called before trying to match next MatcherLoc on the current token. + fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc); + + /// This is called after an arm has been parsed, either successfully or unsuccessfully. When this is called, + /// `before_match_loc` was called at least once (with a `MatcherLoc::Eof`). + fn after_arm(&mut self, result: &NamedParseResult); + + /// For tracing. + fn description() -> &'static str; +} + +/// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to monomorphization. +struct NoopTracker; + +impl<'matcher> Tracker<'matcher> for NoopTracker { + fn before_match_loc(&mut self, _: &TtParser, _: &'matcher MatcherLoc) {} + fn after_arm(&mut self, _: &NamedParseResult) {} + fn description() -> &'static str { + "none" + } +} + /// Expands the rules based macro defined by `lhses` and `rhses` for a given /// input `arg`. +#[instrument(skip(cx, transparency, arg, lhses, rhses))] fn expand_macro<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, @@ -228,9 +256,188 @@ fn expand_macro<'cx>( trace_macros_note(&mut cx.expansions, sp, msg); } - // Which arm's failure should we report? (the one furthest along) - let mut best_failure: Option<(Token, &str)> = None; + // Track nothing for the best performance. + let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut NoopTracker); + + match try_success_result { + Ok((i, named_matches)) => { + let (rhs, rhs_span): (&mbe::Delimited, DelimSpan) = match &rhses[i] { + mbe::TokenTree::Delimited(span, delimited) => (&delimited, *span), + _ => cx.span_bug(sp, "malformed macro rhs"), + }; + let arm_span = rhses[i].span(); + + let rhs_spans = rhs.tts.iter().map(|t| t.span()).collect::<Vec<_>>(); + // rhs has holes ( `$id` and `$(...)` that need filled) + let mut tts = match transcribe(cx, &named_matches, &rhs, rhs_span, transparency) { + Ok(tts) => tts, + Err(mut err) => { + err.emit(); + return DummyResult::any(arm_span); + } + }; + + // Replace all the tokens for the corresponding positions in the macro, to maintain + // proper positions in error reporting, while maintaining the macro_backtrace. + if rhs_spans.len() == tts.len() { + tts = tts.map_enumerated(|i, tt| { + let mut tt = tt.clone(); + let mut sp = rhs_spans[i]; + sp = sp.with_ctxt(tt.span().ctxt()); + tt.set_span(sp); + tt + }); + } + + if cx.trace_macros() { + let msg = format!("to `{}`", pprust::tts_to_string(&tts)); + trace_macros_note(&mut cx.expansions, sp, msg); + } + + let mut p = Parser::new(sess, tts, false, None); + p.last_type_ascription = cx.current_expansion.prior_type_ascription; + + if is_local { + cx.resolver.record_macro_rule_usage(node_id, i); + } + + // Let the context choose how to interpret the result. + // Weird, but useful for X-macros. + return Box::new(ParserAnyMacro { + parser: p, + + // Pass along the original expansion site and the name of the macro + // so we can print a useful error message if the parse of the expanded + // macro leaves unparsed tokens. + site_span: sp, + macro_ident: name, + lint_node_id: cx.current_expansion.lint_node_id, + is_trailing_mac: cx.current_expansion.is_trailing_mac, + arm_span, + is_local, + }); + } + Err(CanRetry::No(_)) => { + debug!("Will not retry matching as an error was emitted already"); + return DummyResult::any(sp); + } + Err(CanRetry::Yes) => { + // Retry and emit a better error below. + } + } + + // An error occurred, try the expansion again, tracking the expansion closely for better diagnostics. + let mut tracker = CollectTrackerAndEmitter::new(cx, sp); + + let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut tracker); + assert!(try_success_result.is_err(), "Macro matching returned a success on the second try"); + + if let Some(result) = tracker.result { + // An irrecoverable error occured and has been emitted. + return result; + } + + let Some((token, label)) = tracker.best_failure else { + return tracker.result.expect("must have encountered Error or ErrorReported"); + }; + + let span = token.span.substitute_dummy(sp); + + let mut err = cx.struct_span_err(span, &parse_failure_msg(&token)); + err.span_label(span, label); + if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { + err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); + } + + annotate_doc_comment(&mut err, sess.source_map(), span); + + // Check whether there's a missing comma in this macro call, like `println!("{}" a);` + if let Some((arg, comma_span)) = arg.add_comma() { + for lhs in lhses { + let parser = parser_from_cx(sess, arg.clone()); + let mut tt_parser = TtParser::new(name); + + if let Success(_) = + tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, &mut NoopTracker) + { + if comma_span.is_dummy() { + err.note("you might be missing a comma"); + } else { + err.span_suggestion_short( + comma_span, + "missing comma here", + ", ", + Applicability::MachineApplicable, + ); + } + } + } + } + err.emit(); + cx.trace_macros_diag(); + DummyResult::any(sp) +} + +/// The tracker used for the slow error path that collects useful info for diagnostics. +struct CollectTrackerAndEmitter<'a, 'cx> { + cx: &'a mut ExtCtxt<'cx>, + /// Which arm's failure should we report? (the one furthest along) + best_failure: Option<(Token, &'static str)>, + root_span: Span, + result: Option<Box<dyn MacResult + 'cx>>, +} + +impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx> { + fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) { + // Empty for now. + } + + fn after_arm(&mut self, result: &NamedParseResult) { + match result { + Success(_) => { + unreachable!("should not collect detailed info for successful macro match"); + } + Failure(token, msg) => match self.best_failure { + Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {} + _ => self.best_failure = Some((token.clone(), msg)), + }, + Error(err_sp, msg) => { + let span = err_sp.substitute_dummy(self.root_span); + self.cx.struct_span_err(span, msg).emit(); + self.result = Some(DummyResult::any(span)); + } + ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)), + } + } + + fn description() -> &'static str { + "detailed" + } +} + +impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx> { + fn new(cx: &'a mut ExtCtxt<'cx>, root_span: Span) -> Self { + Self { cx, best_failure: None, root_span, result: None } + } +} + +enum CanRetry { + Yes, + /// We are not allowed to retry macro expansion as a fatal error has been emitted already. + No(ErrorGuaranteed), +} +/// Try expanding the macro. Returns the index of the successful arm and its named_matches if it was successful, +/// and nothing if it failed. On failure, it's the callers job to use `track` accordingly to record all errors +/// correctly. +#[instrument(level = "debug", skip(sess, arg, lhses, track), fields(tracking = %T::description()))] +fn try_match_macro<'matcher, T: Tracker<'matcher>>( + sess: &ParseSess, + name: Ident, + arg: &TokenStream, + lhses: &'matcher [Vec<MatcherLoc>], + track: &mut T, +) -> Result<(usize, NamedMatches), CanRetry> { // We create a base parser that can be used for the "black box" parts. // Every iteration needs a fresh copy of that parser. However, the parser // is not mutated on many of the iterations, particularly when dealing with @@ -252,125 +459,52 @@ fn expand_macro<'cx>( // this situation.) // FIXME(Nilstrieb): Stop recovery from happening on this parser and retry later with recovery if the macro failed to match. let parser = parser_from_cx(sess, arg.clone()); - // Try each arm's matchers. let mut tt_parser = TtParser::new(name); for (i, lhs) in lhses.iter().enumerate() { + let _tracing_span = trace_span!("Matching arm", %i); + // Take a snapshot of the state of pre-expansion gating at this point. // This is used so that if a matcher is not `Success(..)`ful, // then the spans which became gated when parsing the unsuccessful matcher // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut()); - match tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs) { + let result = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, track); + + track.after_arm(&result); + + match result { Success(named_matches) => { + debug!("Parsed arm successfully"); // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. sess.gated_spans.merge(gated_spans_snapshot); - let (rhs, rhs_span): (&mbe::Delimited, DelimSpan) = match &rhses[i] { - mbe::TokenTree::Delimited(span, delimited) => (&delimited, *span), - _ => cx.span_bug(sp, "malformed macro rhs"), - }; - let arm_span = rhses[i].span(); - - let rhs_spans = rhs.tts.iter().map(|t| t.span()).collect::<Vec<_>>(); - // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = match transcribe(cx, &named_matches, &rhs, rhs_span, transparency) { - Ok(tts) => tts, - Err(mut err) => { - err.emit(); - return DummyResult::any(arm_span); - } - }; - - // Replace all the tokens for the corresponding positions in the macro, to maintain - // proper positions in error reporting, while maintaining the macro_backtrace. - if rhs_spans.len() == tts.len() { - tts = tts.map_enumerated(|i, tt| { - let mut tt = tt.clone(); - let mut sp = rhs_spans[i]; - sp = sp.with_ctxt(tt.span().ctxt()); - tt.set_span(sp); - tt - }); - } - - if cx.trace_macros() { - let msg = format!("to `{}`", pprust::tts_to_string(&tts)); - trace_macros_note(&mut cx.expansions, sp, msg); - } - - let mut p = Parser::new(sess, tts, false, None); - p.last_type_ascription = cx.current_expansion.prior_type_ascription; - - if is_local { - cx.resolver.record_macro_rule_usage(node_id, i); - } - - // Let the context choose how to interpret the result. - // Weird, but useful for X-macros. - return Box::new(ParserAnyMacro { - parser: p, - - // Pass along the original expansion site and the name of the macro - // so we can print a useful error message if the parse of the expanded - // macro leaves unparsed tokens. - site_span: sp, - macro_ident: name, - lint_node_id: cx.current_expansion.lint_node_id, - is_trailing_mac: cx.current_expansion.is_trailing_mac, - arm_span, - is_local, - }); + return Ok((i, named_matches)); } - Failure(token, msg) => match best_failure { - Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {} - _ => best_failure = Some((token, msg)), - }, - Error(err_sp, ref msg) => { - let span = err_sp.substitute_dummy(sp); - cx.struct_span_err(span, &msg).emit(); - return DummyResult::any(span); + Failure(_, _) => { + trace!("Failed to match arm, trying the next one"); + // Try the next arm. + } + Error(_, _) => { + debug!("Fatal error occurred during matching"); + // We haven't emitted an error yet, so we can retry. + return Err(CanRetry::Yes); + } + ErrorReported(guarantee) => { + debug!("Fatal error occurred and was reported during matching"); + // An error has been reported already, we cannot retry as that would cause duplicate errors. + return Err(CanRetry::No(guarantee)); } - ErrorReported => return DummyResult::any(sp), } // The matcher was not `Success(..)`ful. // Restore to the state before snapshotting and maybe try again. mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut()); } - drop(parser); - let (token, label) = best_failure.expect("ran no matchers"); - let span = token.span.substitute_dummy(sp); - let mut err = cx.struct_span_err(span, &parse_failure_msg(&token)); - err.span_label(span, label); - if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { - err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); - } - annotate_doc_comment(&mut err, sess.source_map(), span); - // Check whether there's a missing comma in this macro call, like `println!("{}" a);` - if let Some((arg, comma_span)) = arg.add_comma() { - for lhs in lhses { - let parser = parser_from_cx(sess, arg.clone()); - if let Success(_) = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs) { - if comma_span.is_dummy() { - err.note("you might be missing a comma"); - } else { - err.span_suggestion_short( - comma_span, - "missing comma here", - ", ", - Applicability::MachineApplicable, - ); - } - } - } - } - err.emit(); - cx.trace_macros_diag(); - DummyResult::any(sp) + Err(CanRetry::Yes) } // Note that macro-by-example's input is also matched against a token tree: @@ -452,28 +586,29 @@ pub fn compile_declarative_macro( let parser = Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS); let mut tt_parser = TtParser::new(Ident::with_dummy_span(if macro_rules { kw::MacroRules } else { kw::Macro })); - let argument_map = match tt_parser.parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) { - Success(m) => m, - Failure(token, msg) => { - let s = parse_failure_msg(&token); - let sp = token.span.substitute_dummy(def.span); - let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s); - err.span_label(sp, msg); - annotate_doc_comment(&mut err, sess.source_map(), sp); - err.emit(); - return dummy_syn_ext(); - } - Error(sp, msg) => { - sess.parse_sess - .span_diagnostic - .struct_span_err(sp.substitute_dummy(def.span), &msg) - .emit(); - return dummy_syn_ext(); - } - ErrorReported => { - return dummy_syn_ext(); - } - }; + let argument_map = + match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) { + Success(m) => m, + Failure(token, msg) => { + let s = parse_failure_msg(&token); + let sp = token.span.substitute_dummy(def.span); + let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s); + err.span_label(sp, msg); + annotate_doc_comment(&mut err, sess.source_map(), sp); + err.emit(); + return dummy_syn_ext(); + } + Error(sp, msg) => { + sess.parse_sess + .span_diagnostic + .struct_span_err(sp.substitute_dummy(def.span), &msg) + .emit(); + return dummy_syn_ext(); + } + ErrorReported(_) => { + return dummy_syn_ext(); + } + }; let mut valid = true; diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 1a2ab9d190e..e9a69192068 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -112,6 +112,7 @@ impl MultiItemModifier for DeriveProcMacro { span: Span, _meta_item: &ast::MetaItem, item: Annotatable, + _is_derive_const: bool, ) -> ExpandResult<Vec<Annotatable>, Annotatable> { // We need special handling for statement items // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index cc2858d3f73..a929f6cb0a5 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -525,6 +525,13 @@ impl server::TokenStream for Rustc<'_, '_> { ast::ExprKind::Lit(l) => { Ok(tokenstream::TokenStream::token_alone(token::Literal(l.token_lit), l.span)) } + ast::ExprKind::IncludedBytes(bytes) => { + let lit = ast::Lit::from_included_bytes(bytes, expr.span); + Ok(tokenstream::TokenStream::token_alone( + token::TokenKind::Literal(lit.token_lit), + expr.span, + )) + } ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind { ast::ExprKind::Lit(l) => match l.token_lit { token::Lit { kind: token::Integer | token::Float, .. } => { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index db289a64046..c2aa096a993 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -191,6 +191,8 @@ declare_features! ( (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), + /// Allows `#[instruction_set(_)]` attribute. + (accepted, isa_attribute, "CURRENT_RUSTC_VERSION", Some(74727), None), /// Allows some increased flexibility in the name resolution rules, /// especially around globs and shadowing (RFC 1560). (accepted, item_like_imports, "1.15.0", Some(35120), None), diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 7900f150048..a0e16b18061 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -152,6 +152,8 @@ declare_features! ( (active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None), /// Allows identifying the `compiler_builtins` crate. (active, compiler_builtins, "1.13.0", None, None), + /// Allows writing custom MIR + (active, custom_mir, "1.65.0", None, None), /// Outputs useful `assert!` messages (active, generic_assert, "1.63.0", None, None), /// Allows using the `rust-intrinsic`'s "ABI". @@ -427,8 +429,6 @@ declare_features! ( (incomplete, inline_const_pat, "1.58.0", Some(76001), None), /// Allows using `pointer` and `reference` in intra-doc links (active, intra_doc_pointers, "1.51.0", Some(80896), None), - /// Allows `#[instruction_set(_)]` attribute - (active, isa_attribute, "1.48.0", Some(74727), None), // Allows setting the threshold for the `large_assignments` lint. (active, large_assignments, "1.52.0", Some(83518), None), /// Allows `if/while p && let q = r && ...` chains. @@ -512,9 +512,9 @@ declare_features! ( (active, thread_local, "1.0.0", Some(29594), None), /// Allows defining `trait X = A + B;` alias items. (active, trait_alias, "1.24.0", Some(41517), None), - /// Allows upcasting trait objects via supertraits. - /// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. - (incomplete, trait_upcasting, "1.56.0", Some(65991), None), + /// Allows dyn upcasting trait objects via supertraits. + /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. + (active, trait_upcasting, "1.56.0", Some(65991), None), /// Allows #[repr(transparent)] on unions (RFC 2645). (active, transparent_unions, "1.37.0", Some(60405), None), /// Allows inconsistent bounds in where clauses. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 14c8e3c458c..dc3a7495684 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -391,6 +391,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ DuplicatesOk, @only_local: true, ), ungated!(track_caller, Normal, template!(Word), WarnFollowing), + ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding), gated!( no_sanitize, Normal, template!(List: "address, memory, thread"), DuplicatesOk, @@ -452,11 +453,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute, experimental!(optimize), ), - // RFC 2867 - gated!( - instruction_set, Normal, template!(List: "set"), ErrorPreceding, - isa_attribute, experimental!(instruction_set) - ), gated!( ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice) @@ -814,6 +810,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk), + gated!( + custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#), + ErrorFollowing, "the `#[custom_mir]` attribute is just used for the Rust test suite", + ), rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ef00c1ffc30..82e260d158b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -388,6 +388,8 @@ impl<'hir> GenericArgs<'hir> { } #[inline] + /// This function returns the number of type and const generic params. + /// It should only be used for diagnostics. pub fn num_generic_params(&self) -> usize { self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count() } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index d852893ad5d..3ef58d7d705 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -358,6 +358,9 @@ pub trait Visitor<'v>: Sized { fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) { walk_where_predicate(self, predicate) } + fn visit_fn_ret_ty(&mut self, ret_ty: &'v FnRetTy<'v>) { + walk_fn_ret_ty(self, ret_ty) + } fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) { walk_fn_decl(self, fd) } @@ -903,7 +906,7 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: & for ty in function_declaration.inputs { visitor.visit_ty(ty) } - walk_fn_ret_ty(visitor, &function_declaration.output) + visitor.visit_fn_ret_ty(&function_declaration.output) } pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) { diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 9dd9bf05540..4518cf30acd 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -274,7 +274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, - None, + ty::BoundConstness::NotConst, ); if let Some(b) = item_segment.args().bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); @@ -324,7 +324,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option<Ty<'tcx>>, - constness: Option<ty::BoundConstness>, + constness: ty::BoundConstness, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, @@ -538,7 +538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &mut substs_ctx, ); - if let Some(ty::BoundConstness::ConstIfConst) = constness + if let ty::BoundConstness::ConstIfConst = constness && generics.has_self && !tcx.has_attr(def_id, sym::const_trait) { tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } ); @@ -611,7 +611,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, - None, + ty::BoundConstness::NotConst, ); if let Some(b) = item_segment.args().bindings.first() { @@ -641,7 +641,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_ref.path.segments.last().unwrap(), true, - Some(constness), + constness, ) } @@ -668,7 +668,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, Some(self_ty), - Some(constness), + constness, ); let tcx = self.tcx(); @@ -798,7 +798,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment<'_>, is_impl: bool, - constness: Option<ty::BoundConstness>, + constness: ty::BoundConstness, ) -> ty::TraitRef<'tcx> { let (substs, _) = self.create_substs_for_ast_trait_ref( span, @@ -822,7 +822,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, is_impl: bool, - constness: Option<ty::BoundConstness>, + constness: ty::BoundConstness, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl); @@ -1201,7 +1201,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (_, _) => { let got = if let Some(_) = term.ty() { "type" } else { "constant" }; let expected = def_kind.descr(assoc_item_def_id); - tcx.sess + let reported = tcx + .sess .struct_span_err( binding.span, &format!("expected {expected} bound, found {got}"), @@ -1212,11 +1213,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) .emit(); term = match def_kind { - hir::def::DefKind::AssocTy => tcx.ty_error().into(), + hir::def::DefKind::AssocTy => { + tcx.ty_error_with_guaranteed(reported).into() + } hir::def::DefKind::AssocConst => tcx - .const_error( + .const_error_with_guaranteed( tcx.bound_type_of(assoc_item_def_id) .subst(tcx, projection_ty.skip_binder().substs), + reported, ) .into(), _ => unreachable!(), @@ -1334,8 +1338,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|&(trait_ref, _, _)| trait_ref.def_id()) .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) .map(|trait_ref| tcx.def_span(trait_ref)); - tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); - return tcx.ty_error(); + let reported = + tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); + return tcx.ty_error_with_guaranteed(reported); } // Check that there are no gross object safety violations; @@ -1345,14 +1350,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let object_safety_violations = astconv_object_safety_violations(tcx, item.trait_ref().def_id()); if !object_safety_violations.is_empty() { - report_object_safety_error( + let reported = report_object_safety_error( tcx, span, item.trait_ref().def_id(), &object_safety_violations, ) .emit(); - return tcx.ty_error(); + return tcx.ty_error_with_guaranteed(reported); } } @@ -1910,6 +1915,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } + + // see if we can satisfy using an inherent associated type + for impl_ in tcx.inherent_impls(adt_def.did()) { + let assoc_ty = tcx.associated_items(impl_).find_by_name_and_kind( + tcx, + assoc_ident, + ty::AssocKind::Type, + *impl_, + ); + if let Some(assoc_ty) = assoc_ty { + let ty = tcx.type_of(assoc_ty.def_id); + return Ok((ty, DefKind::AssocTy, assoc_ty.def_id)); + } + } } // Find the type of the associated item, and the trait where the associated @@ -1979,7 +1998,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } err.emit() - } else if let Some(reported) = qself_ty.error_reported() { + } else if let Err(reported) = qself_ty.error_reported() { reported } else { // Don't print `TyErr` to the user. @@ -2098,13 +2117,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "Type" }; - self.report_ambiguous_associated_type( + let reported = self.report_ambiguous_associated_type( span, type_name, &path_str, item_segment.ident.name, ); - return tcx.ty_error(); + return tcx.ty_error_with_guaranteed(reported) }; debug!("qpath_to_ty: self_type={:?}", self_ty); @@ -2115,7 +2134,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_segment, false, - Some(constness), + constness, ); let item_substs = self.create_substs_for_associated_item( @@ -2546,8 +2565,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { err.span_note(impl_.self_ty.span, "not a concrete type"); } - err.emit(); - tcx.ty_error() + tcx.ty_error_with_guaranteed(err.emit()) } else { self.normalize_ty(span, ty) } @@ -2686,7 +2704,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &GenericArgs::none(), true, None, - None, + ty::BoundConstness::NotConst, ); EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id))) .subst(tcx, substs) @@ -2962,7 +2980,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) { for br in referenced_regions.difference(&constrained_regions) { let br_name = match *br { - ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) | ty::BrEnv => { + ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) | ty::BrEnv => { "an anonymous lifetime".to_string() } ty::BrNamed(_, name) => format!("lifetime `{}`", name), @@ -2970,7 +2988,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut err = generate_err(&br_name); - if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) = *br { + if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) = *br { // The only way for an anonymous lifetime to wind up // in the return type but **also** be unconstrained is // if it only appears in "associated types" in the diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 133bbd52b91..0ba5e615101 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -26,6 +26,7 @@ use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVE use rustc_span::symbol::sym; use rustc_span::{self, Span}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -471,7 +472,7 @@ fn check_opaque_meets_bounds<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } match origin { // Checked when type checking the function containing them. @@ -655,7 +656,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { // an error would be reported if this fails. - let _ = traits::OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id()); + let _ = OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id()); } pub(super) fn check_specialization_validity<'tcx>( diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index aeaf7a6cfe1..7c99896b457 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -1,7 +1,7 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use hir::def_id::{DefId, LocalDefId}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -9,14 +9,15 @@ use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{self, TyCtxtInferExt}; +use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::util::ExplicitSelf; -use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::{ - self, AssocItem, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, + self, AssocItem, DefIdTree, TraitRef, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitable, }; +use rustc_middle::ty::{FnSig, InternalSubsts}; use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; @@ -256,7 +257,7 @@ fn compare_predicate_entailment<'tcx>( // Compute placeholder form of impl and trait method tys. let tcx = infcx.tcx; - let mut wf_tys = FxHashSet::default(); + let mut wf_tys = FxIndexSet::default(); let impl_sig = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, @@ -303,109 +304,26 @@ fn compare_predicate_entailment<'tcx>( } if let Err(terr) = result { - debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); + debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); - let (impl_err_span, trait_err_span) = - extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m); - - cause.span = impl_err_span; - - let mut diag = struct_span_err!( - tcx.sess, - cause.span(), - E0053, - "method `{}` has an incompatible type for trait", - trait_m.name - ); - match &terr { - TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0) - if trait_m.fn_has_self_parameter => - { - let ty = trait_sig.inputs()[0]; - let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) { - ExplicitSelf::ByValue => "self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), - _ => format!("self: {ty}"), - }; - - // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the - // span points only at the type `Box<Self`>, but we want to cover the whole - // argument pattern and type. - let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { - ImplItemKind::Fn(ref sig, body) => tcx - .hir() - .body_param_names(body) - .zip(sig.decl.inputs.iter()) - .map(|(param, ty)| param.span.to(ty.span)) - .next() - .unwrap_or(impl_err_span), - _ => bug!("{:?} is not a method", impl_m), - }; - - diag.span_suggestion( - span, - "change the self-receiver type to match the trait", - sugg, - Applicability::MachineApplicable, - ); - } - TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => { - if trait_sig.inputs().len() == *i { - // Suggestion to change output type. We do not suggest in `async` functions - // to avoid complex logic or incorrect output. - match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { - ImplItemKind::Fn(ref sig, _) - if sig.header.asyncness == hir::IsAsync::NotAsync => - { - let msg = "change the output type to match the trait"; - let ap = Applicability::MachineApplicable; - match sig.decl.output { - hir::FnRetTy::DefaultReturn(sp) => { - let sugg = format!("-> {} ", trait_sig.output()); - diag.span_suggestion_verbose(sp, msg, sugg, ap); - } - hir::FnRetTy::Return(hir_ty) => { - let sugg = trait_sig.output(); - diag.span_suggestion(hir_ty.span, msg, sugg, ap); - } - }; - } - _ => {} - }; - } else if let Some(trait_ty) = trait_sig.inputs().get(*i) { - diag.span_suggestion( - impl_err_span, - "change the parameter type to match the trait", - trait_ty, - Applicability::MachineApplicable, - ); - } - } - _ => {} - } - - infcx.err_ctxt().note_type_err( - &mut diag, - &cause, - trait_err_span.map(|sp| (sp, "type in trait".to_owned())), - Some(infer::ValuePairs::Terms(ExpectedFound { - expected: trait_fty.into(), - found: impl_fty.into(), - })), + let emitted = report_trait_method_mismatch( + tcx, + &mut cause, + &infcx, terr, - false, - false, + (trait_m, trait_fty), + (impl_m, impl_fty), + &trait_sig, + &impl_trait_ref, ); - - return Err(diag.emit()); + return Err(emitted); } // Check that all obligations are satisfied by the implementation's // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } @@ -424,6 +342,7 @@ fn compare_predicate_entailment<'tcx>( Ok(()) } +#[instrument(skip(tcx), level = "debug", ret)] pub fn collect_trait_impl_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -437,7 +356,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); - let cause = ObligationCause::new( + let mut cause = ObligationCause::new( return_span, impl_m_hir_id, ObligationCauseCode::CompareImplItemObligation { @@ -479,7 +398,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( let trait_sig = ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_sig); let trait_return_ty = trait_sig.output(); - let wf_tys = FxHashSet::from_iter( + let wf_tys = FxIndexSet::from_iter( unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()), ); @@ -514,23 +433,35 @@ pub fn collect_trait_impl_trait_tys<'tcx>( } } + debug!(?trait_sig, ?impl_sig, "equating function signatures"); + + let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); + let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); + // Unify the whole function signature. We need to do this to fully infer // the lifetimes of the return type, but do this after unifying just the // return types, since we want to avoid duplicating errors from // `compare_predicate_entailment`. - match infcx - .at(&cause, param_env) - .eq(tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)), tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig))) - { + match infcx.at(&cause, param_env).eq(trait_fty, impl_fty) { Ok(infer::InferOk { value: (), obligations }) => { ocx.register_obligations(obligations); } Err(terr) => { - let guar = tcx.sess.delay_span_bug( - return_span, - format!("could not unify `{trait_sig}` and `{impl_sig}`: {terr:?}"), + // This function gets called during `compare_predicate_entailment` when normalizing a + // signature that contains RPITIT. When the method signatures don't match, we have to + // emit an error now because `compare_predicate_entailment` will not report the error + // when normalization fails. + let emitted = report_trait_method_mismatch( + tcx, + &mut cause, + infcx, + terr, + (trait_m, trait_fty), + (impl_m, impl_fty), + &trait_sig, + &impl_trait_ref, ); - return Err(guar); + return Err(emitted); } } @@ -538,7 +469,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( // RPITs. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } @@ -611,11 +542,11 @@ pub fn collect_trait_impl_trait_tys<'tcx>( collected_tys.insert(def_id, ty); } Err(err) => { - tcx.sess.delay_span_bug( + let reported = tcx.sess.delay_span_bug( return_span, format!("could not fully resolve: {ty} => {err:?}"), ); - collected_tys.insert(def_id, tcx.ty_error()); + collected_tys.insert(def_id, tcx.ty_error_with_guaranteed(reported)); } } } @@ -690,6 +621,112 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { } } +fn report_trait_method_mismatch<'tcx>( + tcx: TyCtxt<'tcx>, + cause: &mut ObligationCause<'tcx>, + infcx: &InferCtxt<'tcx>, + terr: TypeError<'tcx>, + (trait_m, trait_fty): (&AssocItem, Ty<'tcx>), + (impl_m, impl_fty): (&AssocItem, Ty<'tcx>), + trait_sig: &FnSig<'tcx>, + impl_trait_ref: &TraitRef<'tcx>, +) -> ErrorGuaranteed { + let (impl_err_span, trait_err_span) = + extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m); + + cause.span = impl_err_span; + + let mut diag = struct_span_err!( + tcx.sess, + cause.span(), + E0053, + "method `{}` has an incompatible type for trait", + trait_m.name + ); + match &terr { + TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0) + if trait_m.fn_has_self_parameter => + { + let ty = trait_sig.inputs()[0]; + let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) { + ExplicitSelf::ByValue => "self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), + _ => format!("self: {ty}"), + }; + + // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the + // span points only at the type `Box<Self`>, but we want to cover the whole + // argument pattern and type. + let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { + ImplItemKind::Fn(ref sig, body) => tcx + .hir() + .body_param_names(body) + .zip(sig.decl.inputs.iter()) + .map(|(param, ty)| param.span.to(ty.span)) + .next() + .unwrap_or(impl_err_span), + _ => bug!("{:?} is not a method", impl_m), + }; + + diag.span_suggestion( + span, + "change the self-receiver type to match the trait", + sugg, + Applicability::MachineApplicable, + ); + } + TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => { + if trait_sig.inputs().len() == *i { + // Suggestion to change output type. We do not suggest in `async` functions + // to avoid complex logic or incorrect output. + match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { + ImplItemKind::Fn(ref sig, _) + if sig.header.asyncness == hir::IsAsync::NotAsync => + { + let msg = "change the output type to match the trait"; + let ap = Applicability::MachineApplicable; + match sig.decl.output { + hir::FnRetTy::DefaultReturn(sp) => { + let sugg = format!("-> {} ", trait_sig.output()); + diag.span_suggestion_verbose(sp, msg, sugg, ap); + } + hir::FnRetTy::Return(hir_ty) => { + let sugg = trait_sig.output(); + diag.span_suggestion(hir_ty.span, msg, sugg, ap); + } + }; + } + _ => {} + }; + } else if let Some(trait_ty) = trait_sig.inputs().get(*i) { + diag.span_suggestion( + impl_err_span, + "change the parameter type to match the trait", + trait_ty, + Applicability::MachineApplicable, + ); + } + } + _ => {} + } + + infcx.err_ctxt().note_type_err( + &mut diag, + &cause, + trait_err_span.map(|sp| (sp, "type in trait".to_owned())), + Some(infer::ValuePairs::Terms(ExpectedFound { + expected: trait_fty.into(), + found: impl_fty.into(), + })), + terr, + false, + false, + ); + + return diag.emit(); +} + fn check_region_bounds_on_impl_item<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, @@ -1431,7 +1468,7 @@ pub(crate) fn raw_compare_const_impl<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None, false)); + return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None)); } // FIXME return `ErrorReported` if region obligations error? @@ -1549,7 +1586,7 @@ fn compare_type_predicate_entailment<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } @@ -1655,13 +1692,10 @@ pub fn check_type_bounds<'tcx>( GenericParamDefKind::Const { .. } => { let bound_var = ty::BoundVariableKind::Const; bound_vars.push(bound_var); - tcx.mk_const(ty::ConstS { - ty: tcx.type_of(param.def_id), - kind: ty::ConstKind::Bound( - ty::INNERMOST, - ty::BoundVar::from_usize(bound_vars.len() - 1), - ), - }) + tcx.mk_const( + ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(bound_vars.len() - 1)), + tcx.type_of(param.def_id), + ) .into() } }); @@ -1772,7 +1806,7 @@ pub fn check_type_bounds<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 609095c9cea..69e54b41d4c 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -134,15 +134,18 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let name_str = intrinsic_name.as_str(); let bound_vars = tcx.mk_bound_variable_kinds( - [ty::BoundVariableKind::Region(ty::BrAnon(0)), ty::BoundVariableKind::Region(ty::BrEnv)] - .iter() - .copied(), + [ + ty::BoundVariableKind::Region(ty::BrAnon(0, None)), + ty::BoundVariableKind::Region(ty::BrEnv), + ] + .iter() + .copied(), ); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { let region = tcx.mk_region(ty::ReLateBound( ty::INNERMOST, - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }, + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }, )); let env_region = tcx.mk_region(ty::ReLateBound( ty::INNERMOST, @@ -364,7 +367,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ); let discriminant_def_id = assoc_items[0]; - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }; ( 1, vec![ @@ -418,7 +422,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), sym::raw_eq => { - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }; let param_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)); (1, vec![param_ty; 2], tcx.types.bool) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0117bdd0ba8..837ff0bdf3e 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1,7 +1,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use hir::def::DefKind; use rustc_ast as ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -21,6 +21,7 @@ use rustc_middle::ty::{GenericArgKind, InternalSubsts}; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use rustc_target::spec::abi::Abi; use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; @@ -104,7 +105,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( f(&mut wfcx); let errors = wfcx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); return; } @@ -116,7 +117,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { - let node = tcx.hir().expect_owner(def_id); + let node = tcx.hir().owner(def_id); match node { hir::OwnerNode::Crate(_) => {} hir::OwnerNode::Item(item) => check_item(tcx, item), @@ -411,7 +412,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe .iter() .copied() .collect::<Vec<_>>(), - &FxHashSet::default(), + &FxIndexSet::default(), gat_def_id.def_id, gat_generics, ) @@ -461,10 +462,10 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe .into_iter() .filter(|clause| match clause.kind().skip_binder() { ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => { - !region_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b) + !region_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b) } ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => { - !ty_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b) + !ty_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b) } _ => bug!("Unexpected PredicateKind"), }) @@ -546,7 +547,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>( param_env: ty::ParamEnv<'tcx>, item_hir: hir::HirId, to_check: T, - wf_tys: &FxHashSet<Ty<'tcx>>, + wf_tys: &FxIndexSet<Ty<'tcx>>, gat_def_id: LocalDefId, gat_generics: &'tcx ty::Generics, ) -> Option<FxHashSet<ty::Predicate<'tcx>>> { @@ -653,7 +654,7 @@ fn ty_known_to_outlive<'tcx>( tcx: TyCtxt<'tcx>, id: hir::HirId, param_env: ty::ParamEnv<'tcx>, - wf_tys: &FxHashSet<Ty<'tcx>>, + wf_tys: &FxIndexSet<Ty<'tcx>>, ty: Ty<'tcx>, region: ty::Region<'tcx>, ) -> bool { @@ -670,7 +671,7 @@ fn region_known_to_outlive<'tcx>( tcx: TyCtxt<'tcx>, id: hir::HirId, param_env: ty::ParamEnv<'tcx>, - wf_tys: &FxHashSet<Ty<'tcx>>, + wf_tys: &FxIndexSet<Ty<'tcx>>, region_a: ty::Region<'tcx>, region_b: ty::Region<'tcx>, ) -> bool { @@ -694,7 +695,7 @@ fn resolve_regions_with_wf_tys<'tcx>( tcx: TyCtxt<'tcx>, id: hir::HirId, param_env: ty::ParamEnv<'tcx>, - wf_tys: &FxHashSet<Ty<'tcx>>, + wf_tys: &FxIndexSet<Ty<'tcx>>, add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>), ) -> bool { // Unfortunately, we have to use a new `InferCtxt` each call, because @@ -1542,6 +1543,33 @@ fn check_fn_or_method<'tcx>( sig.output(), hir_decl.output.span(), ); + + if sig.abi == Abi::RustCall { + let span = tcx.def_span(def_id); + let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None; + let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 }); + // Check that the argument is a tuple + if let Some(ty) = inputs.next() { + wfcx.register_bound( + ObligationCause::new(span, wfcx.body_id, ObligationCauseCode::RustCall), + wfcx.param_env, + *ty, + tcx.require_lang_item(hir::LangItem::Tuple, Some(span)), + ); + } else { + tcx.sess.span_err( + hir_decl.inputs.last().map_or(span, |input| input.span), + "functions with the \"rust-call\" ABI must take a single non-self tuple argument", + ); + } + // No more inputs other than the `self` type and the tuple type + if inputs.next().is_some() { + tcx.sess.span_err( + hir_decl.inputs.last().map_or(span, |input| input.span), + "functions with the \"rust-call\" ABI must take a single non-self tuple argument", + ); + } + } } /// Basically `check_associated_type_bounds`, but separated for now and should be @@ -1680,8 +1708,7 @@ fn receiver_is_valid<'tcx>( return true; } - let mut autoderef = - Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty, span); + let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty); // The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`. if arbitrary_self_types_enabled { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index b6c91d425df..6f74ef3ccad 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -321,7 +321,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: }), ); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } // Finally, resolve all regions. @@ -561,7 +561,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, source, &[target.into()]); let errors = traits::fully_solve_obligation(&infcx, predicate); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } // Finally, resolve all regions. diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index bb45c3823d8..71c932d747b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -23,9 +23,7 @@ pub(crate) fn orphan_check_impl( impl_def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - if let Some(err) = trait_ref.error_reported() { - return Err(err); - } + trait_ref.error_reported()?; let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id); if tcx.trait_is_auto(trait_ref.def_id) { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 25faacadf3d..0e7a5ebf5ab 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -512,8 +512,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } _ => {} } - err.emit(); - self.tcx().ty_error() + self.tcx().ty_error_with_guaranteed(err.emit()) } } @@ -645,12 +644,6 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } } - // Desugared from `impl Trait`, so visited by the function's return type. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), - .. - }) => {} - // Don't call `type_of` on opaque types, since that depends on type // checking function bodies. `check_item_type` ensures that it's called // instead. @@ -658,27 +651,32 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure().generics_of(def_id); tcx.ensure().predicates_of(def_id); tcx.ensure().explicit_item_bounds(def_id); + tcx.ensure().item_bounds(def_id); } - hir::ItemKind::TyAlias(..) - | hir::ItemKind::Static(..) - | hir::ItemKind::Const(..) - | hir::ItemKind::Fn(..) => { + + hir::ItemKind::TyAlias(..) => { tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); tcx.ensure().predicates_of(def_id); - match it.kind { - hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id), - hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id), - hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => { - if !is_suggestable_infer_ty(ty) { - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_item(it); - placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr()); - } - } - _ => (), + } + + hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..) => { + tcx.ensure().generics_of(def_id); + tcx.ensure().type_of(def_id); + tcx.ensure().predicates_of(def_id); + if !is_suggestable_infer_ty(ty) { + let mut visitor = HirPlaceholderCollector::default(); + visitor.visit_item(it); + placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr()); } } + + hir::ItemKind::Fn(..) => { + tcx.ensure().generics_of(def_id); + tcx.ensure().type_of(def_id); + tcx.ensure().predicates_of(def_id); + tcx.ensure().fn_sig(def_id); + } } } diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index 3f263a6de24..6ee7aa9cdac 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -18,7 +18,7 @@ use rustc_middle::bug; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_lifetime::*; -use rustc_middle::ty::{self, DefIdTree, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -94,11 +94,6 @@ struct LifetimeContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, map: &'a mut NamedRegionMap, scope: ScopeRef<'a>, - - /// Indicates that we only care about the definition of a trait. This should - /// be false if the `Item` we are resolving lifetimes for is not a trait or - /// we eventually need lifetimes resolve for trait items. - trait_definition_only: bool, } #[derive(Debug)] @@ -166,7 +161,9 @@ enum Scope<'a> { s: ScopeRef<'a>, }, - Root, + Root { + opt_parent_item: Option<LocalDefId>, + }, } #[derive(Copy, Clone, Debug)] @@ -214,95 +211,58 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("s", &"..") .finish(), Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(), - Scope::Root => f.debug_struct("Root").finish(), + Scope::Root { opt_parent_item } => { + f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish() + } } } } type ScopeRef<'a> = &'a Scope<'a>; -const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root; - pub(crate) fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { - resolve_lifetimes_trait_definition, resolve_lifetimes, - named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id), + named_region_map: |tcx, id| tcx.resolve_lifetimes(id).defs.get(&id), is_late_bound_map, object_lifetime_default, - late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id), + late_bound_vars_map: |tcx, id| tcx.resolve_lifetimes(id).late_bound_vars.get(&id), ..*providers }; } -/// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items. -/// Also does not generate any diagnostics. -/// -/// This is ultimately a subset of the `resolve_lifetimes` work. It effectively -/// resolves lifetimes only within the trait "header" -- that is, the trait -/// and supertrait list. In contrast, `resolve_lifetimes` resolves all the -/// lifetimes within the trait and its items. There is room to refactor this, -/// for example to resolve lifetimes for each trait item in separate queries, -/// but it's convenient to do the entire trait at once because the lifetimes -/// from the trait definition are in scope within the trait items as well. -/// -/// The reason for this separate call is to resolve what would otherwise -/// be a cycle. Consider this example: -/// -/// ```ignore UNSOLVED (maybe @jackh726 knows what lifetime parameter to give Sub) -/// trait Base<'a> { -/// type BaseItem; -/// } -/// trait Sub<'b>: for<'a> Base<'a> { -/// type SubItem: Sub<BaseItem = &'b u32>; -/// } -/// ``` -/// -/// When we resolve `Sub` and all its items, we also have to resolve `Sub<BaseItem = &'b u32>`. -/// To figure out the index of `'b`, we have to know about the supertraits -/// of `Sub` so that we can determine that the `for<'a>` will be in scope. -/// (This is because we -- currently at least -- flatten all the late-bound -/// lifetimes into a single binder.) This requires us to resolve the -/// *trait definition* of `Sub`; basically just enough lifetime information -/// to look at the supertraits. -#[instrument(level = "debug", skip(tcx))] -fn resolve_lifetimes_trait_definition( - tcx: TyCtxt<'_>, - local_def_id: LocalDefId, -) -> ResolveLifetimes { - convert_named_region_map(do_resolve(tcx, local_def_id, true)) -} - /// Computes the `ResolveLifetimes` map that contains data for an entire `Item`. /// You should not read the result of this query directly, but rather use /// `named_region_map`, `is_late_bound_map`, etc. #[instrument(level = "debug", skip(tcx))] -fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes { - convert_named_region_map(do_resolve(tcx, local_def_id, false)) -} - -fn do_resolve( - tcx: TyCtxt<'_>, - local_def_id: LocalDefId, - trait_definition_only: bool, -) -> NamedRegionMap { - let item = tcx.hir().expect_item(local_def_id); +fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLifetimes { let mut named_region_map = NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() }; let mut visitor = LifetimeContext { tcx, map: &mut named_region_map, - scope: ROOT_SCOPE, - trait_definition_only, + scope: &Scope::Root { opt_parent_item: None }, }; - visitor.visit_item(item); - - named_region_map -} + match tcx.hir().owner(local_def_id) { + hir::OwnerNode::Item(item) => visitor.visit_item(item), + hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), + hir::OwnerNode::TraitItem(item) => { + let scope = + Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) }; + visitor.scope = &scope; + visitor.visit_trait_item(item) + } + hir::OwnerNode::ImplItem(item) => { + let scope = + Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) }; + visitor.scope = &scope; + visitor.visit_impl_item(item) + } + hir::OwnerNode::Crate(_) => {} + } -fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes { let mut rl = ResolveLifetimes::default(); for (hir_id, v) in named_region_map.defs { @@ -319,53 +279,6 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime rl } -/// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution. -/// There are two important things this does. -/// First, we have to resolve lifetimes for -/// the entire *`Item`* that contains this owner, because that's the largest "scope" -/// where we can have relevant lifetimes. -/// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition` -/// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics. -/// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner -/// other than the trait itself (like the trait methods or associated types), then we just use the regular -/// `resolve_lifetimes`. -fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: hir::OwnerId) -> &'tcx ResolveLifetimes { - let item_id = item_for(tcx, def_id.def_id); - let local_def_id = item_id.owner_id.def_id; - if item_id.owner_id == def_id { - let item = tcx.hir().item(item_id); - match item.kind { - hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(local_def_id), - _ => tcx.resolve_lifetimes(local_def_id), - } - } else { - tcx.resolve_lifetimes(local_def_id) - } -} - -/// Finds the `Item` that contains the given `LocalDefId` -fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> hir::ItemId { - match tcx.hir().find_by_def_id(local_def_id) { - Some(Node::Item(item)) => { - return item.item_id(); - } - _ => {} - } - let item = { - let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id); - let mut parent_iter = tcx.hir().parent_iter(hir_id); - loop { - let node = parent_iter.next().map(|n| n.1); - match node { - Some(hir::Node::Item(item)) => break item.item_id(), - Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."), - _ => {} - } - } - }; - item -} - fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind { match region { Region::LateBound(_, _, def_id) => { @@ -383,7 +296,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let mut supertrait_lifetimes = vec![]; loop { match scope { - Scope::Body { .. } | Scope::Root => { + Scope::Body { .. } | Scope::Root { .. } => { break (vec![], BinderScopeType::Normal); } @@ -414,21 +327,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { - type NestedFilter = nested_filter::All; + type NestedFilter = nested_filter::OnlyBodies; fn nested_visit_map(&mut self) -> Self::Map { self.tcx.hir() } - // We want to nest trait/impl items in their parent, but nothing else. - fn visit_nested_item(&mut self, _: hir::ItemId) {} - - fn visit_trait_item_ref(&mut self, ii: &'tcx hir::TraitItemRef) { - if !self.trait_definition_only { - intravisit::walk_trait_item_ref(self, ii) - } - } - fn visit_nested_body(&mut self, body: hir::BodyId) { let body = self.tcx.hir().body(body); self.with(Scope::Body { id: body.id(), s: self.scope }, |this| { @@ -548,7 +452,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { intravisit::walk_item(this, item) }); } - hir::ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => { + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias, .. + }) => { // Opaque types are visited when we visit the // `TyKind::OpaqueDef`, so that they have the lifetimes from // their parent opaque_ty in scope. @@ -557,34 +463,53 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // their owner, we can keep going until we find the Item that owns that. We then // conservatively add all resolved lifetimes. Otherwise we run into problems in // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`. - for (_hir_id, node) in self.tcx.hir().parent_iter(item.owner_id.into()) { - match node { - hir::Node::Item(parent_item) => { - let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes( - item_for(self.tcx, parent_item.owner_id.def_id).owner_id.def_id, - ); - // We need to add *all* deps, since opaque tys may want them from *us* - for (&owner, defs) in resolved_lifetimes.defs.iter() { - defs.iter().for_each(|(&local_id, region)| { - self.map.defs.insert(hir::HirId { owner, local_id }, *region); - }); - } - for (&owner, late_bound_vars) in - resolved_lifetimes.late_bound_vars.iter() - { - late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| { - self.record_late_bound_vars( - hir::HirId { owner, local_id }, - late_bound_vars.clone(), - ); - }); - } - break; + let parent_item = self.tcx.hir().get_parent_item(item.hir_id()); + let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(parent_item); + // We need to add *all* deps, since opaque tys may want them from *us* + for (&owner, defs) in resolved_lifetimes.defs.iter() { + defs.iter().for_each(|(&local_id, region)| { + self.map.defs.insert(hir::HirId { owner, local_id }, *region); + }); + } + for (&owner, late_bound_vars) in resolved_lifetimes.late_bound_vars.iter() { + late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| { + self.record_late_bound_vars( + hir::HirId { owner, local_id }, + late_bound_vars.clone(), + ); + }); + } + } + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_), + generics, + .. + }) => { + // We want to start our early-bound indices at the end of the parent scope, + // not including any parent `impl Trait`s. + let mut lifetimes = FxIndexMap::default(); + debug!(?generics.params); + for param in generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => { + let (def_id, reg) = Region::early(self.tcx.hir(), ¶m); + lifetimes.insert(def_id, reg); } - hir::Node::Crate(_) => bug!("No Item about an OpaqueTy"), - _ => {} + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {} } } + + let scope = Scope::Binder { + hir_id: item.hir_id(), + lifetimes, + s: self.scope, + scope_type: BinderScopeType::Normal, + where_bound_origin: None, + }; + self.with(scope, |this| { + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |this| intravisit::walk_item(this, item)) + }); } hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Enum(_, ref generics) @@ -609,7 +534,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir_id: item.hir_id(), lifetimes, scope_type: BinderScopeType::Normal, - s: ROOT_SCOPE, + s: self.scope, where_bound_origin: None, }; self.with(scope, |this| { @@ -712,7 +637,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // ^ ^ this gets resolved in the scope of // the opaque_ty generics let opaque_ty = self.tcx.hir().item(item_id); - let (generics, bounds) = match opaque_ty.kind { + match opaque_ty.kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. @@ -733,10 +658,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), - ref generics, - bounds, .. - }) => (generics, bounds), + }) => {} ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), }; @@ -766,65 +689,28 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // Ensure that the parent of the def is an item, not HRTB let parent_id = self.tcx.hir().get_parent_node(hir_id); if !parent_id.is_owner() { - if !self.trait_definition_only { - struct_span_err!( - self.tcx.sess, - lifetime.span, - E0657, - "`impl Trait` can only capture lifetimes \ - bound at the fn or impl level" - ) - .emit(); - } + struct_span_err!( + self.tcx.sess, + lifetime.span, + E0657, + "`impl Trait` can only capture lifetimes bound at the fn or impl level" + ) + .emit(); self.uninsert_lifetime_on_error(lifetime, def.unwrap()); } if let hir::Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy { .. }, .. }) = self.tcx.hir().get(parent_id) { - if !self.trait_definition_only { - let mut err = self.tcx.sess.struct_span_err( - lifetime.span, - "higher kinded lifetime bounds on nested opaque types are not supported yet", - ); - err.span_note(self.tcx.def_span(def_id), "lifetime declared here"); - err.emit(); - } + let mut err = self.tcx.sess.struct_span_err( + lifetime.span, + "higher kinded lifetime bounds on nested opaque types are not supported yet", + ); + err.span_note(self.tcx.def_span(def_id), "lifetime declared here"); + err.emit(); self.uninsert_lifetime_on_error(lifetime, def.unwrap()); } } - - // We want to start our early-bound indices at the end of the parent scope, - // not including any parent `impl Trait`s. - let mut lifetimes = FxIndexMap::default(); - debug!(?generics.params); - for param in generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => { - let (def_id, reg) = Region::early(self.tcx.hir(), ¶m); - lifetimes.insert(def_id, reg); - } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {} - } - } - self.record_late_bound_vars(ty.hir_id, vec![]); - - let scope = Scope::Binder { - hir_id: ty.hir_id, - lifetimes, - s: self.scope, - scope_type: BinderScopeType::Normal, - where_bound_origin: None, - }; - self.with(scope, |this| { - let scope = Scope::TraitRefBoundary { s: this.scope }; - this.with(scope, |this| { - this.visit_generics(generics); - for bound in bounds { - this.visit_param_bound(bound); - } - }) - }); } _ => intravisit::walk_ty(self, ty), } @@ -1193,12 +1079,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>), { let LifetimeContext { tcx, map, .. } = self; - let mut this = LifetimeContext { - tcx: *tcx, - map, - scope: &wrap_scope, - trait_definition_only: self.trait_definition_only, - }; + let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope }; let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope)); { let _enter = span.enter(); @@ -1303,7 +1184,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { scope = s; } - Scope::Root => { + Scope::Root { opt_parent_item } => { + if let Some(parent_item) = opt_parent_item + && let parent_generics = self.tcx.generics_of(parent_item) + && parent_generics.param_def_id_to_index.contains_key(®ion_def_id.to_def_id()) + { + break Some(Region::EarlyBound(region_def_id.to_def_id())); + } break None; } @@ -1377,11 +1264,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } else if let Some(body_id) = outermost_body { let fn_id = self.tcx.hir().body_owner(body_id); match self.tcx.hir().get(fn_id) { - Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. }) - | Node::TraitItem(&hir::TraitItem { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) + | Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) - | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => { + | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) + | Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { let scope = self.tcx.hir().local_def_id(fn_id); def = Region::Free(scope.to_def_id(), def.id().unwrap()); } @@ -1416,7 +1304,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { err.emit(); return; } - Scope::Root => break, + Scope::Root { .. } => break, Scope::Binder { s, .. } | Scope::Body { s, .. } | Scope::Elision { s, .. } @@ -1494,7 +1382,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let mut scope = self.scope; loop { match *scope { - Scope::Root => break false, + Scope::Root { .. } => break false, Scope::Body { .. } => break true, @@ -1731,7 +1619,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { scope = s; } - Scope::Root | Scope::Elision { .. } => break Region::Static, + Scope::Root { .. } | Scope::Elision { .. } => break Region::Static, Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return, @@ -1780,7 +1668,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< let mut late_bound = FxIndexSet::default(); - let mut constrained_by_input = ConstrainedCollector::default(); + let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx }; for arg_ty in decl.inputs { constrained_by_input.visit_ty(arg_ty); } @@ -1833,12 +1721,65 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< debug!(?late_bound); return Some(tcx.arena.alloc(late_bound)); - #[derive(Default)] - struct ConstrainedCollector { + /// Visits a `ty::Ty` collecting information about what generic parameters are constrained. + /// + /// The visitor does not operate on `hir::Ty` so that it can be called on the rhs of a `type Alias<...> = ...;` + /// which may live in a separate crate so there would not be any hir available. Instead we use the `type_of` + /// query to obtain a `ty::Ty` which will be present even in cross crate scenarios. It also naturally + /// handles cycle detection as we go through the query system. + /// + /// This is necessary in the first place for the following case: + /// ``` + /// type Alias<'a, T> = <T as Trait<'a>>::Assoc; + /// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... } + /// ``` + /// + /// If we conservatively considered `'a` unconstrained then we could break users who had written code before + /// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound + /// causing an error during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc` + /// but appears in the output type `<() as Trait<'a>>::Assoc`. + /// + /// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not. + /// + /// See #100508 #85533 #47511 for additional context + struct ConstrainedCollectorPostAstConv { + arg_is_constrained: Box<[bool]>, + } + + use std::ops::ControlFlow; + use ty::Ty; + impl<'tcx> TypeVisitor<'tcx> for ConstrainedCollectorPostAstConv { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> { + match t.kind() { + ty::Param(param_ty) => { + self.arg_is_constrained[param_ty.index as usize] = true; + } + ty::Projection(_) => return ControlFlow::Continue(()), + _ => (), + } + t.super_visit_with(self) + } + + fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow<!> { + ControlFlow::Continue(()) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<!> { + debug!("r={:?}", r.kind()); + if let ty::RegionKind::ReEarlyBound(region) = r.kind() { + self.arg_is_constrained[region.index as usize] = true; + } + + ControlFlow::Continue(()) + } + } + + struct ConstrainedCollector<'tcx> { + tcx: TyCtxt<'tcx>, regions: FxHashSet<LocalDefId>, } - impl<'v> Visitor<'v> for ConstrainedCollector { + impl<'v> Visitor<'v> for ConstrainedCollector<'_> { fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { match ty.kind { hir::TyKind::Path( @@ -1849,6 +1790,47 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< // (defined above) } + hir::TyKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span }, + )) => { + // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider + // substs to be unconstrained. + let generics = self.tcx.generics_of(alias_def); + let mut walker = ConstrainedCollectorPostAstConv { + arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(), + }; + walker.visit_ty(self.tcx.type_of(alias_def)); + + match segments.last() { + Some(hir::PathSegment { args: Some(args), .. }) => { + let tcx = self.tcx; + for constrained_arg in + args.args.iter().enumerate().flat_map(|(n, arg)| { + match walker.arg_is_constrained.get(n) { + Some(true) => Some(arg), + Some(false) => None, + None => { + tcx.sess.delay_span_bug( + *span, + format!( + "Incorrect generic arg count for alias {:?}", + alias_def + ), + ); + None + } + } + }) + { + self.visit_generic_arg(constrained_arg); + } + } + Some(_) => (), + None => bug!("Path with no segments or self type"), + } + } + hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => { // consider only the lifetimes on the final // segment; I am not sure it's even currently diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index c29a645eb4a..2402495c2e4 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -698,7 +698,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T } let Some(hidden) = locator.found else { - tcx.sess.emit_err(UnconstrainedOpaqueType { + let reported = tcx.sess.emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), name: tcx.item_name(tcx.local_parent(def_id).to_def_id()), what: match tcx.hir().get(scope) { @@ -708,7 +708,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T _ => "item", }, }); - return tcx.ty_error(); + return tcx.ty_error_with_guaranteed(reported); }; // Only check against typeck if we didn't already error diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index e806e94879d..55cca0cd2d7 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -69,6 +69,7 @@ use crate::constrained_generic_params as cgp; use crate::errors::SubstsOnOverriddenImpl; use rustc_data_structures::fx::FxHashSet; +use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::TyCtxtInferExt; @@ -80,6 +81,7 @@ use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt}; +use tracing::instrument; pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { if let Some(node) = parent_specialization_node(tcx, impl_def_id) { @@ -103,13 +105,11 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti } /// Check that `impl1` is a sound specialization +#[instrument(level = "debug", skip(tcx))] fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) { if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) { let impl2_def_id = impl2_node.def_id(); - debug!( - "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)", - impl1_def_id, impl2_def_id, impl2_substs - ); + debug!(?impl2_def_id, ?impl2_substs); let parent_substs = if impl2_node.is_from_trait() { impl2_substs.to_vec() @@ -118,12 +118,33 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node }; let span = tcx.def_span(impl1_def_id); + check_constness(tcx, impl1_def_id, impl2_node, span); check_static_lifetimes(tcx, &parent_substs, span); check_duplicate_params(tcx, impl1_substs, &parent_substs, span); check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span); } } +/// Check that the specializing impl `impl1` is at least as const as the base +/// impl `impl2` +fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) { + if impl2_node.is_from_trait() { + // This isn't a specialization + return; + } + + let impl1_constness = tcx.constness(impl1_def_id.to_def_id()); + let impl2_constness = tcx.constness(impl2_node.def_id()); + + if let hir::Constness::Const = impl2_constness { + if let hir::Constness::NotConst = impl1_constness { + tcx.sess + .struct_span_err(span, "cannot specialize on const impl with non-const impl") + .emit(); + } + } +} + /// Given a specializing impl `impl1`, and the base impl `impl2`, returns two /// substitutions `(S1, S2)` that equate their trait references. The returned /// types are expressed in terms of the generics of `impl1`. @@ -155,7 +176,7 @@ fn get_impl_substs<'tcx>( let errors = ocx.select_all_or_error(); if !errors.is_empty() { - ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None); return None; } @@ -278,15 +299,15 @@ fn check_static_lifetimes<'tcx>( /// Check whether predicates on the specializing impl (`impl1`) are allowed. /// -/// Each predicate `P` must be: +/// Each predicate `P` must be one of: /// -/// * global (not reference any parameters) -/// * `T: Tr` predicate where `Tr` is an always-applicable trait -/// * on the base `impl impl2` -/// * Currently this check is done using syntactic equality, which is -/// conservative but generally sufficient. -/// * a well-formed predicate of a type argument of the trait being implemented, +/// * Global (not reference any parameters). +/// * A `T: Tr` predicate where `Tr` is an always-applicable trait. +/// * Present on the base impl `impl2`. +/// * This check is done using the `trait_predicates_eq` function below. +/// * A well-formed predicate of a type argument of the trait being implemented, /// including the `Self`-type. +#[instrument(level = "debug", skip(tcx))] fn check_predicates<'tcx>( tcx: TyCtxt<'tcx>, impl1_def_id: LocalDefId, @@ -322,10 +343,7 @@ fn check_predicates<'tcx>( .map(|obligation| obligation.predicate) .collect() }; - debug!( - "check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)", - impl1_predicates, impl2_predicates, - ); + debug!(?impl1_predicates, ?impl2_predicates); // Since impls of always applicable traits don't get to assume anything, we // can also assume their supertraits apply. @@ -373,25 +391,83 @@ fn check_predicates<'tcx>( ); for (predicate, span) in impl1_predicates { - if !impl2_predicates.contains(&predicate) { + if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) { check_specialization_on(tcx, predicate, span) } } } +/// Checks if some predicate on the specializing impl (`predicate1`) is the same +/// as some predicate on the base impl (`predicate2`). +/// +/// This basically just checks syntactic equivalence, but is a little more +/// forgiving since we want to equate `T: Tr` with `T: ~const Tr` so this can work: +/// +/// ```ignore (illustrative) +/// #[rustc_specialization_trait] +/// trait Specialize { } +/// +/// impl<T: Bound> Tr for T { } +/// impl<T: ~const Bound + Specialize> const Tr for T { } +/// ``` +/// +/// However, we *don't* want to allow the reverse, i.e., when the bound on the +/// specializing impl is not as const as the bound on the base impl: +/// +/// ```ignore (illustrative) +/// impl<T: ~const Bound> const Tr for T { } +/// impl<T: Bound + Specialize> const Tr for T { } // should be T: ~const Bound +/// ``` +/// +/// So we make that check in this function and try to raise a helpful error message. +fn trait_predicates_eq<'tcx>( + tcx: TyCtxt<'tcx>, + predicate1: ty::Predicate<'tcx>, + predicate2: ty::Predicate<'tcx>, + span: Span, +) -> bool { + let pred1_kind = predicate1.kind().skip_binder(); + let pred2_kind = predicate2.kind().skip_binder(); + let (trait_pred1, trait_pred2) = match (pred1_kind, pred2_kind) { + (ty::PredicateKind::Trait(pred1), ty::PredicateKind::Trait(pred2)) => (pred1, pred2), + // Just use plain syntactic equivalence if either of the predicates aren't + // trait predicates or have bound vars. + _ => return predicate1 == predicate2, + }; + + let predicates_equal_modulo_constness = { + let pred1_unconsted = + ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred1 }; + let pred2_unconsted = + ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred2 }; + pred1_unconsted == pred2_unconsted + }; + + if !predicates_equal_modulo_constness { + return false; + } + + // Check that the predicate on the specializing impl is at least as const as + // the one on the base. + match (trait_pred2.constness, trait_pred1.constness) { + (ty::BoundConstness::ConstIfConst, ty::BoundConstness::NotConst) => { + tcx.sess.struct_span_err(span, "missing `~const` qualifier for specialization").emit(); + } + _ => {} + } + + true +} + +#[instrument(level = "debug", skip(tcx))] fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) { - debug!("can_specialize_on(predicate = {:?})", predicate); match predicate.kind().skip_binder() { // Global predicates are either always true or always false, so we // are fine to specialize on. _ if predicate.is_global() => (), // We allow specializing on explicitly marked traits with no associated // items. - ty::PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: _, - }) => { + ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: _, polarity: _ }) => { if !matches!( trait_predicate_kind(tcx, predicate), Some(TraitSpecializationKind::Marker) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index bd1a461b935..664d3a3a1db 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -173,7 +173,7 @@ fn require_same_types<'tcx>( match &errors[..] { [] => true, errors => { - infcx.err_ctxt().report_fulfillment_errors(errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(errors, None); false } } @@ -336,7 +336,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ocx.register_bound(cause, param_env, norm_return_ty, term_did); let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); error = true; } // now we can take the return type of the given main function diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 2b15d4dcd08..6a4a6a5b0a5 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -1,6 +1,6 @@ use crate::coercion::{AsCoercionSite, CoerceMany}; use crate::{Diverges, Expectation, FnCtxt, Needs}; -use rustc_errors::{Applicability, MultiSpan}; +use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir::{self as hir, ExprKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; @@ -137,55 +137,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(&arm.body), arm_ty, Some(&mut |err| { - let Some(ret) = self - .tcx - .hir() - .find_by_def_id(self.body_id.owner.def_id) - .and_then(|owner| owner.fn_decl()) - .map(|decl| decl.output.span()) - else { return; }; - let Expectation::IsLast(stmt) = orig_expected else { - return - }; - let can_coerce_to_return_ty = match self.ret_coercion.as_ref() { - Some(ret_coercion) if self.in_tail_expr => { - let ret_ty = ret_coercion.borrow().expected_ty(); - let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); - self.can_coerce(arm_ty, ret_ty) - && prior_arm.map_or(true, |(_, t, _)| self.can_coerce(t, ret_ty)) - // The match arms need to unify for the case of `impl Trait`. - && !matches!(ret_ty.kind(), ty::Opaque(..)) - } - _ => false, - }; - if !can_coerce_to_return_ty { - return; - } - - let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi()); - let mut ret_span: MultiSpan = semi_span.into(); - ret_span.push_span_label( - expr.span, - "this could be implicitly returned but it is a statement, not a \ - tail expression", - ); - ret_span - .push_span_label(ret, "the `match` arms can conform to this return type"); - ret_span.push_span_label( - semi_span, - "the `match` is a statement because of this semicolon, consider \ - removing it", - ); - err.span_note( - ret_span, - "you might have meant to return the `match` expression", - ); - err.tool_only_span_suggestion( - semi_span, - "remove this semicolon", - "", - Applicability::MaybeIncorrect, - ); + self.suggest_removing_semicolon_for_coerce( + err, + expr, + orig_expected, + arm_ty, + prior_arm, + ) }), false, ); @@ -219,6 +177,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { coercion.complete(self) } + fn suggest_removing_semicolon_for_coerce( + &self, + diag: &mut Diagnostic, + expr: &hir::Expr<'tcx>, + expectation: Expectation<'tcx>, + arm_ty: Ty<'tcx>, + prior_arm: Option<(Option<hir::HirId>, Ty<'tcx>, Span)>, + ) { + let hir = self.tcx.hir(); + + // First, check that we're actually in the tail of a function. + let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, _), .. }) = + hir.get(self.body_id) else { return; }; + let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), .. }) + = block.innermost_block().stmts.last() else { return; }; + if last_expr.hir_id != expr.hir_id { + return; + } + + // Next, make sure that we have no type expectation. + let Some(ret) = hir + .find_by_def_id(self.body_id.owner.def_id) + .and_then(|owner| owner.fn_decl()) + .map(|decl| decl.output.span()) else { return; }; + let Expectation::IsLast(stmt) = expectation else { + return; + }; + + let can_coerce_to_return_ty = match self.ret_coercion.as_ref() { + Some(ret_coercion) => { + let ret_ty = ret_coercion.borrow().expected_ty(); + let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); + self.can_coerce(arm_ty, ret_ty) + && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty)) + // The match arms need to unify for the case of `impl Trait`. + && !matches!(ret_ty.kind(), ty::Opaque(..)) + } + _ => false, + }; + if !can_coerce_to_return_ty { + return; + } + + let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi()); + let mut ret_span: MultiSpan = semi_span.into(); + ret_span.push_span_label( + expr.span, + "this could be implicitly returned but it is a statement, not a \ + tail expression", + ); + ret_span.push_span_label(ret, "the `match` arms can conform to this return type"); + ret_span.push_span_label( + semi_span, + "the `match` is a statement because of this semicolon, consider \ + removing it", + ); + diag.span_note(ret_span, "you might have meant to return the `match` expression"); + diag.tool_only_span_suggestion( + semi_span, + "remove this semicolon", + "", + Applicability::MaybeIncorrect, + ); + } + /// When the previously checked expression (the scrutinee) diverges, /// warn the user about the match arms being unreachable. fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm<'tcx>]) { @@ -491,11 +514,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .. } = self.type_var_origin(expected)? else { return None; }; - let sig = *self - .typeck_results - .borrow() - .liberated_fn_sigs() - .get(hir::HirId::make_owner(self.body_id.owner.def_id))?; + let sig = self.body_fn_sig()?; let substs = sig.output().walk().find_map(|arg| { if let ty::GenericArgKind::Type(ty) = arg.unpack() diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 59c366ad7d7..41b52a4c4a9 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -12,18 +12,7 @@ use std::iter; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { - Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span) - } - - /// Like `autoderef`, but provides a custom `Span` to use for calls to - /// an overloaded `Deref` operator - pub fn autoderef_overloaded_span( - &'a self, - span: Span, - base_ty: Ty<'tcx>, - overloaded_span: Span, - ) -> Autoderef<'a, 'tcx> { - Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span) + Autoderef::new(self, self.param_env, self.body_id, span, base_ty) } pub fn try_overloaded_deref( @@ -55,11 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |InferOk { value: method, obligations: o }| { obligations.extend(o); if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() { - Some(OverloadedDeref { - region, - mutbl, - span: autoderef.overloaded_span(), - }) + Some(OverloadedDeref { region, mutbl, span: autoderef.span() }) } else { None } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 1b33f2f02b8..2b019c8c9b7 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -129,6 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { output } + #[instrument(level = "debug", skip(self, call_expr, callee_expr, arg_exprs, autoderef), ret)] fn try_overloaded_call_step( &self, call_expr: &'tcx hir::Expr<'tcx>, @@ -138,10 +139,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option<CallStep<'tcx>> { let adjusted_ty = self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); - debug!( - "try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", - call_expr, adjusted_ty - ); // If the callee is a bare function or a closure, then we're all set. match *adjusted_ty.kind() { @@ -471,6 +468,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_id, ); + if fn_sig.abi == abi::Abi::RustCall { + let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span); + if let Some(ty) = fn_sig.inputs().last().copied() { + self.register_bound( + ty, + self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)), + traits::ObligationCause::new(sp, self.body_id, traits::RustCall), + ); + } else { + self.tcx.sess.span_err( + sp, + "functions with the \"rust-call\" ABI must take a single non-self tuple argument", + ); + } + } + fn_sig.output() } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index d1dab0540be..7d3129f7ea7 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -94,10 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("pointer_kind({:?}, {:?})", t, span); let t = self.resolve_vars_if_possible(t); - - if let Some(reported) = t.error_reported() { - return Err(reported); - } + t.error_reported()?; if self.type_is_sized_modulo_regions(self.param_env, t, span) { return Ok(Some(PointerKind::Thin)); @@ -222,8 +219,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // inference is more completely known. match cast_ty.kind() { ty::Dynamic(_, _, ty::Dyn) | ty::Slice(..) => { - let reported = check.report_cast_to_unsized_type(fcx); - Err(reported) + Err(check.report_cast_to_unsized_type(fcx)) } _ => Ok(check), } @@ -614,10 +610,11 @@ impl<'a, 'tcx> CastCheck<'tcx> { } fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx>) -> ErrorGuaranteed { - if let Some(reported) = - self.cast_ty.error_reported().or_else(|| self.expr_ty.error_reported()) - { - return reported; + if let Err(err) = self.cast_ty.error_reported() { + return err; + } + if let Err(err) = self.expr_ty.error_reported() { + return err; } let tstr = fcx.ty_to_string(self.cast_ty); diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index b706d786b52..3c57e33f6f7 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -6,13 +6,11 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ImplicitSelfKind, ItemKind, Node}; use rustc_hir_analysis::check::fn_maybe_err; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::RegionVariableOrigin; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use std::cell::RefCell; @@ -31,13 +29,11 @@ pub(super) fn check_fn<'a, 'tcx>( fn_id: hir::HirId, body: &'tcx hir::Body<'tcx>, can_be_generator: Option<hir::Movability>, - return_type_pre_known: bool, ) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) { // Create the function context. This is either derived from scratch or, // in the case of closures, based on the outer context. let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id); fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id)); - fcx.return_type_pre_known = return_type_pre_known; let tcx = fcx.tcx; let hir = tcx.hir(); @@ -51,9 +47,6 @@ pub(super) fn check_fn<'a, 'tcx>( decl.output.span(), param_env, )); - // If we replaced declared_ret_ty with infer vars, then we must be inferring - // an opaque type, so set a flag so we can improve diagnostics. - fcx.return_type_has_opaque = ret_ty != declared_ret_ty; fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); @@ -61,41 +54,6 @@ pub(super) fn check_fn<'a, 'tcx>( fn_maybe_err(tcx, span, fn_sig.abi); - if fn_sig.abi == Abi::RustCall { - let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 }; - - let err = || { - let item = match tcx.hir().get(fn_id) { - Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header), - Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(header, ..), .. - }) => Some(header), - Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(header, ..), - .. - }) => Some(header), - // Closures are RustCall, but they tuple their arguments, so shouldn't be checked - Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None, - node => bug!("Item being checked wasn't a function/closure: {:?}", node), - }; - - if let Some(header) = item { - tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple"); - } - }; - - if fn_sig.inputs().len() != expected_args { - err() - } else { - // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on - // This will probably require wide-scale changes to support a TupleKind obligation - // We can't resolve this without knowing the type of the param - if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) { - err() - } - } - } - if body.generator_kind.is_some() && can_be_generator.is_some() { let yield_ty = fcx .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); @@ -142,7 +100,6 @@ pub(super) fn check_fn<'a, 'tcx>( inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); - fcx.in_tail_expr = true; if let ty::Dynamic(..) = declared_ret_ty.kind() { // FIXME: We need to verify that the return type is `Sized` after the return expression has // been evaluated so that we have types available for all the nodes being returned, but that @@ -161,7 +118,6 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); fcx.check_return_expr(&body.value, false); } - fcx.in_tail_expr = false; // We insert the deferred_generator_interiors entry after visiting the body. // This ensures that all nested generators appear before the entry of this generator. diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index a5a45f75e0e..3001e799476 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -10,18 +10,20 @@ use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; +use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::ArgKind; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use std::cmp; use std::iter; /// What signature do we *expect* the closure to have from context? -#[derive(Debug)] +#[derive(Debug, Clone, TypeFoldable, TypeVisitable)] struct ExpectedSig<'tcx> { /// Span that gave us this expectation, if we know that. cause_span: Option<Span>, @@ -82,8 +84,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?bound_sig, ?liberated_sig); - let return_type_pre_known = !liberated_sig.output().is_ty_infer(); - let generator_types = check_fn( self, self.param_env.without_const(), @@ -92,7 +92,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.hir_id, body, gen, - return_type_pre_known, ) .1; @@ -225,33 +224,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expected_vid: ty::TyVid, ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) { - let expected_sig = - self.obligations_for_self_ty(expected_vid).find_map(|(_, obligation)| { - debug!(?obligation.predicate); - - let bound_predicate = obligation.predicate.kind(); - if let ty::PredicateKind::Projection(proj_predicate) = - obligation.predicate.kind().skip_binder() - { - // Given a Projection predicate, we can potentially infer - // the complete signature. + let mut expected_sig = None; + let mut expected_kind = None; + + for obligation in traits::elaborate_obligations( + self.tcx, + // Reverse the obligations here, since `elaborate_*` uses a stack, + // and we want to keep inference generally in the same order of + // the registered obligations. + self.obligations_for_self_ty(expected_vid).rev().collect(), + ) { + debug!(?obligation.predicate); + let bound_predicate = obligation.predicate.kind(); + + // Given a Projection predicate, we can potentially infer + // the complete signature. + if expected_sig.is_none() + && let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() + { + expected_sig = self.normalize_associated_types_in( + obligation.cause.span, self.deduce_sig_from_projection( - Some(obligation.cause.span), + Some(obligation.cause.span), bound_predicate.rebind(proj_predicate), - ) - } else { - None - } - }); + ), + ); + } - // Even if we can't infer the full signature, we may be able to - // infer the kind. This can occur when we elaborate a predicate - // like `F : Fn<A>`. Note that due to subtyping we could encounter - // many viable options, so pick the most restrictive. - let expected_kind = self - .obligations_for_self_ty(expected_vid) - .filter_map(|(tr, _)| self.tcx.fn_trait_kind_from_lang_item(tr.def_id())) - .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur)))); + // Even if we can't infer the full signature, we may be able to + // infer the kind. This can occur when we elaborate a predicate + // like `F : Fn<A>`. Note that due to subtyping we could encounter + // many viable options, so pick the most restrictive. + let trait_def_id = match bound_predicate.skip_binder() { + ty::PredicateKind::Projection(data) => { + Some(data.projection_ty.trait_def_id(self.tcx)) + } + ty::PredicateKind::Trait(data) => Some(data.def_id()), + _ => None, + }; + if let Some(closure_kind) = + trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_lang_item(def_id)) + { + expected_kind = Some( + expected_kind + .map_or_else(|| closure_kind, |current| cmp::min(current, closure_kind)), + ); + } + } (expected_sig, expected_kind) } @@ -689,7 +708,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let output_ty = match *ret_ty.kind() { ty::Infer(ty::TyVar(ret_vid)) => { - self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| { + self.obligations_for_self_ty(ret_vid).find_map(|obligation| { get_future_output(obligation.predicate, obligation.cause.span) })? } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 86597a703e8..71949b42118 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -62,6 +62,7 @@ use rustc_span::{self, BytePos, DesugaringKind, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; +use rustc_trait_selection::traits::TraitEngineExt as _; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; use smallvec::{smallvec, SmallVec}; @@ -705,12 +706,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Object safety violations or miscellaneous. Err(err) => { - self.err_ctxt().report_selection_error( - obligation.clone(), - &obligation, - &err, - false, - ); + self.err_ctxt().report_selection_error(obligation.clone(), &obligation, &err); // Treat this like an obligation and follow through // with the unsizing - the lack of a coercion should // be silent, as it causes a type mismatch later. @@ -1043,7 +1039,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Ok(ok) = coerce.coerce(source, target) else { return false; }; - let mut fcx = traits::FulfillmentContext::new_in_snapshot(); + let mut fcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx); fcx.register_predicate_obligations(self, ok.obligations); fcx.select_where_possible(&self).is_empty() }) @@ -1644,9 +1640,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if visitor.ret_exprs.len() > 0 && let Some(expr) = expression { self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs); } - err.emit_unless(unsized_return); + let reported = err.emit_unless(unsized_return); - self.final_ty = Some(fcx.tcx.ty_error()); + self.final_ty = Some(fcx.tcx.ty_error_with_guaranteed(reported)); } } } @@ -1782,7 +1778,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // may occur at the first return expression we see in the closure // (if it conflicts with the declared return type). Skip adding a // note in this case, since it would be incorrect. - && !fcx.return_type_pre_known + && let Some(fn_sig) = fcx.body_fn_sig() + && fn_sig.output().is_ty_var() { err.span_note( sp, diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 16febfc46da..9ca7730daa6 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -30,6 +30,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, error: Option<TypeError<'tcx>>, ) { + if expr_ty == expected { + return; + } + self.annotate_expected_due_to_let_ty(err, expr, error); // Use `||` to give these suggestions a precedence @@ -42,7 +46,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty) || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected) || self.suggest_copied_or_cloned(err, expr, expr_ty, expected) - || self.suggest_into(err, expr, expr_ty, expected); + || self.suggest_into(err, expr, expr_ty, expected) + || self.suggest_option_to_bool(err, expr, expr_ty, expected) + || self.suggest_floating_point_literal(err, expr, expected); self.note_type_is_not_clone(err, expected, expr_ty, expr); self.note_need_for_fn_pointer(err, expected, expr_ty); diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index cfb408396da..afac6e7d94a 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -125,3 +125,11 @@ pub struct AddMissingParenthesesInRange { #[suggestion_part(code = ")")] pub right: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_op_trait_generic_params)] +pub struct OpMethodGenericParams { + #[primary_span] + pub span: Span, + pub method_name: String, +} diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9fde62a81a1..e948d832e32 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -80,14 +80,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // coercions from ! to `expected`. if ty.is_never() { if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) { - self.tcx().sess.delay_span_bug( + let reported = self.tcx().sess.delay_span_bug( expr.span, "expression with never type wound up being adjusted", ); return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] { target.to_owned() } else { - self.tcx().ty_error() + self.tcx().ty_error_with_guaranteed(reported) }; } @@ -103,8 +103,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { - let expr = expr.peel_drop_temps(); - self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty, None); + // FIXME(compiler-errors): We probably should fold some of the + // `suggest_` functions from `emit_coerce_suggestions` into here, + // since some of those aren't necessarily just coerce suggestions. + let _ = self.suggest_deref_ref_or_into( + &mut err, + expr.peel_drop_temps(), + expected_ty, + ty, + None, + ) || self.suggest_option_to_bool(&mut err, expr, ty, expected_ty); extend_err(&mut err); err.emit(); } @@ -220,7 +228,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Hide the outer diverging and has_errors flags. let old_diverges = self.diverges.replace(Diverges::Maybe); - let old_has_errors = self.has_errors.replace(false); let ty = ensure_sufficient_stack(|| match &expr.kind { hir::ExprKind::Path( @@ -259,7 +266,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Combine the diverging and has_error flags. self.diverges.set(self.diverges.get() | old_diverges); - self.has_errors.set(self.has_errors.get() | old_has_errors); debug!("type of {} is...", self.tcx.hir().node_to_string(expr.hir_id)); debug!("... {:?}, expected is {:?}", ty, expected); @@ -398,8 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } - err.emit(); - oprnd_t = tcx.ty_error(); + oprnd_t = tcx.ty_error_with_guaranteed(err.emit()); } } hir::UnOp::Not => { @@ -840,10 +845,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_expr_ty, ); - if self.return_type_has_opaque { + if let Some(fn_sig) = self.body_fn_sig() + && fn_sig.output().has_opaque_types() + { // Point any obligations that were registered due to opaque type // inference at the return expression. - self.select_obligations_where_possible(false, |errors| { + self.select_obligations_where_possible(|errors| { self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty); }); } @@ -1097,12 +1104,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the assignment expression itself is ill-formed, don't // bother emitting another error - if lhs_ty.references_error() || rhs_ty.references_error() { - err.delay_as_bug() - } else { - err.emit(); - } - return self.tcx.ty_error(); + let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error()); + return self.tcx.ty_error_with_guaranteed(reported); } let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); @@ -2738,7 +2741,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some((index_ty, element_ty)) => { // two-phase not needed because index_ty is never mutable self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); - self.select_obligations_where_possible(false, |errors| { + self.select_obligations_where_possible(|errors| { self.point_at_index_if_possible(errors, idx.span) }); element_ty @@ -2777,8 +2780,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - err.emit(); - self.tcx.ty_error() + let reported = err.emit(); + self.tcx.ty_error_with_guaranteed(reported) } } } diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 747ecb036b2..5d44092a5f6 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -7,16 +7,16 @@ use rustc_data_structures::{ use rustc_middle::ty::{self, Ty}; impl<'tcx> FnCtxt<'_, 'tcx> { - /// Performs type inference fallback, returning true if any fallback - /// occurs. - pub(super) fn type_inference_fallback(&self) -> bool { + /// Performs type inference fallback, setting `FnCtxt::fallback_has_occurred` + /// if fallback has occurred. + pub(super) fn type_inference_fallback(&self) { debug!( "type-inference-fallback start obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations() ); // All type checking constraints were added, try to fallback unsolved variables. - self.select_obligations_where_possible(false, |_| {}); + self.select_obligations_where_possible(|_| {}); debug!( "type-inference-fallback post selection obligations: {:#?}", @@ -26,18 +26,17 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // Check if we have any unsolved variables. If not, no need for fallback. let unsolved_variables = self.unsolved_variables(); if unsolved_variables.is_empty() { - return false; + return; } let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables); - let mut fallback_has_occurred = false; // We do fallback in two passes, to try to generate // better error messages. // The first time, we do *not* replace opaque types. for ty in unsolved_variables { debug!("unsolved_variable = {:?}", ty); - fallback_has_occurred |= self.fallback_if_possible(ty, &diverging_fallback); + self.fallback_if_possible(ty, &diverging_fallback); } // We now see if we can make progress. This might cause us to @@ -63,9 +62,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // If we had tried to fallback the opaque inference variable to `MyType`, // we will generate a confusing type-check error that does not explicitly // refer to opaque types. - self.select_obligations_where_possible(fallback_has_occurred, |_| {}); - - fallback_has_occurred + self.select_obligations_where_possible(|_| {}); } // Tries to apply a fallback to `ty` if it is an unsolved variable. @@ -81,12 +78,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // Fallback becomes very dubious if we have encountered // type-checking errors. In that case, fallback to Error. // - // The return value indicates whether fallback has occurred. + // Sets `FnCtxt::fallback_has_occurred` if fallback is performed + // during this call. fn fallback_if_possible( &self, ty: Ty<'tcx>, diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>, - ) -> bool { + ) { // Careful: we do NOT shallow-resolve `ty`. We know that `ty` // is an unsolved variable, and we determine its fallback // based solely on how it was created, not what other type @@ -111,7 +109,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64, _ => match diverging_fallback.get(&ty) { Some(&fallback_ty) => fallback_ty, - None => return false, + None => return, }, }; debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback); @@ -122,7 +120,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .map(|origin| origin.span) .unwrap_or(rustc_span::DUMMY_SP); self.demand_eqtype(span, ty, fallback); - true + self.fallback_has_occurred.set(true); } /// The "diverging fallback" system is rather complicated. This is diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 6a1cffe3e60..c6bd771fad2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -18,11 +18,12 @@ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryRespons use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::{InferOk, InferResult}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ - self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPolyTraitRef, - ToPredicate, Ty, UserType, + self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, + UserType, }; use rustc_middle::ty::{GenericArgKind, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts}; use rustc_session::lint; @@ -32,9 +33,7 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::{ - self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt, -}; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt}; use std::collections::hash_map::Entry; use std::slice; @@ -106,7 +105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // possible. This can help substantially when there are // indirect dependencies that don't seem worth tracking // precisely. - self.select_obligations_where_possible(false, mutate_fulfillment_errors); + self.select_obligations_where_possible(mutate_fulfillment_errors); self.resolve_vars_if_possible(ty) } @@ -143,7 +142,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().node_types_mut().insert(id, ty); if ty.references_error() { - self.has_errors.set(true); self.set_tainted_by_errors(); } } @@ -601,7 +599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) { let mut generators = self.deferred_generator_interiors.borrow_mut(); for (body_id, interior, kind) in generators.drain(..) { - self.select_obligations_where_possible(false, |_| {}); + self.select_obligations_where_possible(|_| {}); crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind); } } @@ -612,25 +610,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !errors.is_empty() { self.adjust_fulfillment_errors_for_expr_obligation(&mut errors); - self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id, false); + self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id); } } /// Select as many obligations as we can at present. pub(in super::super) fn select_obligations_where_possible( &self, - fallback_has_occurred: bool, mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>), ) { let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self); if !result.is_empty() { mutate_fulfillment_errors(&mut result); self.adjust_fulfillment_errors_for_expr_obligation(&mut result); - self.err_ctxt().report_fulfillment_errors( - &result, - self.inh.body_id, - fallback_has_occurred, - ); + self.err_ctxt().report_fulfillment_errors(&result, self.inh.body_id); } } @@ -650,12 +643,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn self_type_matches_expected_vid( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - expected_vid: ty::TyVid, - ) -> bool { - let self_ty = self.shallow_resolve(trait_ref.skip_binder().self_ty()); + fn self_type_matches_expected_vid(&self, self_ty: Ty<'tcx>, expected_vid: ty::TyVid) -> bool { + let self_ty = self.shallow_resolve(self_ty); debug!(?self_ty); match *self_ty.kind() { @@ -674,54 +663,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn obligations_for_self_ty<'b>( &'b self, self_ty: ty::TyVid, - ) -> impl Iterator<Item = (ty::PolyTraitRef<'tcx>, traits::PredicateObligation<'tcx>)> - + Captures<'tcx> - + 'b { + ) -> impl DoubleEndedIterator<Item = traits::PredicateObligation<'tcx>> + Captures<'tcx> + 'b + { // FIXME: consider using `sub_root_var` here so we // can see through subtyping. let ty_var_root = self.root_var(self_ty); trace!("pending_obligations = {:#?}", self.fulfillment_cx.borrow().pending_obligations()); - self.fulfillment_cx - .borrow() - .pending_obligations() - .into_iter() - .filter_map(move |obligation| { - let bound_predicate = obligation.predicate.kind(); - match bound_predicate.skip_binder() { - ty::PredicateKind::Projection(data) => Some(( - bound_predicate.rebind(data).required_poly_trait_ref(self.tcx), - obligation, - )), - ty::PredicateKind::Trait(data) => { - Some((bound_predicate.rebind(data).to_poly_trait_ref(), obligation)) - } - ty::PredicateKind::Subtype(..) => None, - ty::PredicateKind::Coerce(..) => None, - ty::PredicateKind::RegionOutlives(..) => None, - ty::PredicateKind::TypeOutlives(..) => None, - ty::PredicateKind::WellFormed(..) => None, - ty::PredicateKind::ObjectSafe(..) => None, - ty::PredicateKind::ConstEvaluatable(..) => None, - ty::PredicateKind::ConstEquate(..) => None, - // N.B., this predicate is created by breaking down a - // `ClosureType: FnFoo()` predicate, where - // `ClosureType` represents some `Closure`. It can't - // possibly be referring to the current closure, - // because we haven't produced the `Closure` for - // this closure yet; this is exactly why the other - // code is looking for a self type of an unresolved - // inference variable. - ty::PredicateKind::ClosureKind(..) => None, - ty::PredicateKind::TypeWellFormedFromEnv(..) => None, + self.fulfillment_cx.borrow().pending_obligations().into_iter().filter_map( + move |obligation| match &obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Projection(data) + if self.self_type_matches_expected_vid( + data.projection_ty.self_ty(), + ty_var_root, + ) => + { + Some(obligation) } - }) - .filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root)) + ty::PredicateKind::Trait(data) + if self.self_type_matches_expected_vid(data.self_ty(), ty_var_root) => + { + Some(obligation) + } + + ty::PredicateKind::Trait(..) + | ty::PredicateKind::Projection(..) + | ty::PredicateKind::Subtype(..) + | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::RegionOutlives(..) + | ty::PredicateKind::TypeOutlives(..) + | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::ConstEquate(..) + // N.B., this predicate is created by breaking down a + // `ClosureType: FnFoo()` predicate, where + // `ClosureType` represents some `Closure`. It can't + // possibly be referring to the current closure, + // because we haven't produced the `Closure` for + // this closure yet; this is exactly why the other + // code is looking for a self type of an unresolved + // inference variable. + | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, + }, + ) } pub(in super::super) fn type_var_is_sized(&self, self_ty: ty::TyVid) -> bool { - self.obligations_for_self_ty(self_ty) - .any(|(tr, _)| Some(tr.def_id()) == self.tcx.lang_items().sized_trait()) + let sized_did = self.tcx.lang_items().sized_trait(); + self.obligations_for_self_ty(self_ty).any(|obligation| { + match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Trait(data) => Some(data.def_id()) == sized_did, + _ => false, + } + }) } pub(in super::super) fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> { @@ -769,34 +765,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expect_args = self .fudge_inference_if_ok(|| { + let ocx = ObligationCtxt::new_in_snapshot(self); + // Attempt to apply a subtyping relationship between the formal // return type (likely containing type variables if the function // is polymorphic) and the expected return type. // No argument expectations are produced if unification fails. let origin = self.misc(call_span); - let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret); - - // FIXME(#27336) can't use ? here, Try::from_error doesn't default - // to identity so the resulting type is not constrained. - match ures { - Ok(ok) => { - // Process any obligations locally as much as - // we can. We don't care if some things turn - // out unconstrained or ambiguous, as we're - // just trying to get hints here. - let errors = self.save_and_restore_in_snapshot_flag(|_| { - let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx); - for obligation in ok.obligations { - fulfill.register_predicate_obligation(self, obligation); - } - fulfill.select_where_possible(self) - }); - - if !errors.is_empty() { - return Err(()); - } - } - Err(_) => return Err(()), + ocx.sup(&origin, self.param_env, ret_ty, formal_ret)?; + if !ocx.select_where_possible().is_empty() { + return Err(TypeError::Mismatch); } // Record all the argument types, with the substitutions @@ -1215,9 +1193,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - err.emit(); - - return (tcx.ty_error(), res); + let reported = err.emit(); + return (tcx.ty_error_with_guaranteed(reported), res); } } } else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8e0fcb56c7f..8cf70eb5431 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -136,6 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tuple_arguments, Some(method.def_id), ); + method.sig.output() } @@ -214,7 +215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "cannot use call notation; the first type parameter \ for the function trait is neither a tuple nor unit" ) - .emit(); + .delay_as_bug(); (self.err_args(provided_args.len()), None) } } @@ -344,7 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // an "opportunistic" trait resolution of any trait bounds on // the call. This helps coercions. if check_closures { - self.select_obligations_where_possible(false, |_| {}) + self.select_obligations_where_possible(|_| {}) } // Check each argument, to satisfy the input it was provided for @@ -596,6 +597,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; + let mk_trace = |span, (formal_ty, expected_ty), provided_ty| { + let mismatched_ty = if expected_ty == provided_ty { + // If expected == provided, then we must have failed to sup + // the formal type. Avoid printing out "expected Ty, found Ty" + // in that case. + formal_ty + } else { + expected_ty + }; + TypeTrace::types(&self.misc(span), true, mismatched_ty, provided_ty) + }; + // The algorithm here is inspired by levenshtein distance and longest common subsequence. // We'll try to detect 4 different types of mistakes: // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs @@ -660,10 +673,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // A tuple wrap suggestion actually occurs within, // so don't do anything special here. err = self.err_ctxt().report_and_explain_type_error( - TypeTrace::types( - &self.misc(*lo), - true, - formal_and_expected_inputs[mismatch_idx.into()].1, + mk_trace( + *lo, + formal_and_expected_inputs[mismatch_idx.into()], provided_arg_tys[mismatch_idx.into()].0, ), terr, @@ -747,9 +759,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { errors.drain_filter(|error| { let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false }; let (provided_ty, provided_span) = provided_arg_tys[*provided_idx]; - let (expected_ty, _) = formal_and_expected_inputs[*expected_idx]; - let cause = &self.misc(provided_span); - let trace = TypeTrace::types(cause, true, expected_ty, provided_ty); + let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty); if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) { self.err_ctxt().report_and_explain_type_error(trace, *e).emit(); return true; @@ -773,8 +783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx]; let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx]; - let cause = &self.misc(provided_arg_span); - let trace = TypeTrace::types(cause, true, expected_ty, provided_ty); + let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty); let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err); self.emit_coerce_suggestions( &mut err, @@ -846,8 +855,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx]; let (provided_ty, provided_span) = provided_arg_tys[provided_idx]; if let Compatibility::Incompatible(error) = compatibility { - let cause = &self.misc(provided_span); - let trace = TypeTrace::types(cause, true, expected_ty, provided_ty); + let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty); if let Some(e) = error { self.err_ctxt().note_type_err( &mut err, @@ -1334,7 +1342,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Hide the outer diverging and `has_errors` flags. let old_diverges = self.diverges.replace(Diverges::Maybe); - let old_has_errors = self.has_errors.replace(false); match stmt.kind { hir::StmtKind::Local(l) => { @@ -1364,7 +1371,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Combine the diverging and `has_error` flags. self.diverges.set(self.diverges.get() | old_diverges); - self.has_errors.set(self.has_errors.get() | old_has_errors); } pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { @@ -1544,11 +1550,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.diverges.set(prev_diverges); } - let mut ty = ctxt.coerce.unwrap().complete(self); - - if self.has_errors.get() || ty.references_error() { - ty = self.tcx.ty_error() - } + let ty = ctxt.coerce.unwrap().complete(self); self.write_ty(blk.hir_id, ty); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index c36c01e1b46..d5e4b6de581 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -68,10 +68,6 @@ pub struct FnCtxt<'a, 'tcx> { /// any). pub(super) ret_coercion: Option<RefCell<DynamicCoerceMany<'tcx>>>, - /// Used exclusively to reduce cost of advanced evaluation used for - /// more helpful diagnostics. - pub(super) in_tail_expr: bool, - /// First span of a return site that we find. Used in error messages. pub(super) ret_coercion_span: Cell<Option<Span>>, @@ -112,21 +108,11 @@ pub struct FnCtxt<'a, 'tcx> { /// the diverges flag is set to something other than `Maybe`. pub(super) diverges: Cell<Diverges>, - /// Whether any child nodes have any type errors. - pub(super) has_errors: Cell<bool>, - pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>, pub(super) inh: &'a Inherited<'tcx>, - /// True if the function or closure's return type is known before - /// entering the function/closure, i.e. if the return type is - /// either given explicitly or inferred from, say, an `Fn*` trait - /// bound. Used for diagnostic purposes only. - pub(super) return_type_pre_known: bool, - - /// True if the return type has an Opaque type - pub(super) return_type_has_opaque: bool, + pub(super) fallback_has_occurred: Cell<bool>, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -140,19 +126,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param_env, err_count_on_creation: inh.tcx.sess.err_count(), ret_coercion: None, - in_tail_expr: false, ret_coercion_span: Cell::new(None), resume_yield_tys: None, ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)), diverges: Cell::new(Diverges::Maybe), - has_errors: Cell::new(false), enclosing_breakables: RefCell::new(EnclosingBreakables { stack: Vec::new(), by_id: Default::default(), }), inh, - return_type_pre_known: true, - return_type_has_opaque: false, + fallback_has_occurred: Cell::new(false), } } @@ -174,7 +157,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> { - TypeErrCtxt { infcx: &self.infcx, typeck_results: Some(self.typeck_results.borrow()) } + TypeErrCtxt { + infcx: &self.infcx, + typeck_results: Some(self.typeck_results.borrow()), + fallback_has_occurred: self.fallback_has_occurred.get(), + } } pub fn errors_reported_since_creation(&self) -> bool { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 4db9c56f98f..06e6e4350fc 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -13,7 +13,7 @@ use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::{self, TyCtxtInferExt}; use rustc_infer::traits::{self, StatementAsExpression}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Binder, IsSuggestable, ToPredicate, Ty}; +use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::symbol::sym; use rustc_span::Span; @@ -22,6 +22,14 @@ use rustc_trait_selection::traits::error_reporting::DefIdOrName; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + pub(crate) fn body_fn_sig(&self) -> Option<ty::FnSig<'tcx>> { + self.typeck_results + .borrow() + .liberated_fn_sigs() + .get(self.tcx.hir().get_parent_node(self.body_id)) + .copied() + } + pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) { err.span_suggestion_short( span.shrink_to_hi(), @@ -366,7 +374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let annotation_span = ty.span; err.span_suggestion( annotation_span.with_hi(annotation_span.lo()), - format!("alternatively, consider changing the type annotation"), + "alternatively, consider changing the type annotation", suggest_annotation, Applicability::MaybeIncorrect, ); @@ -1108,6 +1116,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + /// When expecting a `bool` and finding an `Option`, suggests using `let Some(..)` or `.is_some()` + pub(crate) fn suggest_option_to_bool( + &self, + diag: &mut Diagnostic, + expr: &hir::Expr<'_>, + expr_ty: Ty<'tcx>, + expected_ty: Ty<'tcx>, + ) -> bool { + if !expected_ty.is_bool() { + return false; + } + + let ty::Adt(def, _) = expr_ty.peel_refs().kind() else { return false; }; + if !self.tcx.is_diagnostic_item(sym::Option, def.did()) { + return false; + } + + let hir = self.tcx.hir(); + let cond_parent = hir.parent_iter(expr.hir_id).skip_while(|(_, node)| { + matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(op, _, _), .. }) if op.node == hir::BinOpKind::And) + }).next(); + // Don't suggest: + // `let Some(_) = a.is_some() && b` + // ++++++++++ + // since the user probably just misunderstood how `let else` + // and `&&` work together. + if let Some((_, hir::Node::Local(local))) = cond_parent + && let hir::PatKind::Path(qpath) | hir::PatKind::TupleStruct(qpath, _, _) = &local.pat.kind + && let hir::QPath::Resolved(None, path) = qpath + && let Some(did) = path.res.opt_def_id() + .and_then(|did| self.tcx.opt_parent(did)) + .and_then(|did| self.tcx.opt_parent(did)) + && self.tcx.is_diagnostic_item(sym::Option, did) + { + return false; + } + + diag.span_suggestion( + expr.span.shrink_to_hi(), + "use `Option::is_some` to test if the `Option` has a value", + ".is_some()", + Applicability::MachineApplicable, + ); + + true + } + /// Suggest wrapping the block in square brackets instead of curly braces /// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`. pub(crate) fn suggest_block_to_brackets( @@ -1149,6 +1204,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + #[instrument(skip(self, err))] + pub(crate) fn suggest_floating_point_literal( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + expected_ty: Ty<'tcx>, + ) -> bool { + if !expected_ty.is_floating_point() { + return false; + } + match expr.kind { + ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [start, end], _) => { + err.span_suggestion_verbose( + start.span.shrink_to_hi().with_hi(end.span.lo()), + "remove the unnecessary `.` operator for a floating point literal", + '.', + Applicability::MaybeIncorrect, + ); + true + } + ExprKind::Struct(QPath::LangItem(LangItem::RangeFrom, ..), [start], _) => { + err.span_suggestion_verbose( + expr.span.with_lo(start.span.hi()), + "remove the unnecessary `.` operator for a floating point literal", + '.', + Applicability::MaybeIncorrect, + ); + true + } + ExprKind::Struct(QPath::LangItem(LangItem::RangeTo, ..), [end], _) => { + err.span_suggestion_verbose( + expr.span.until(end.span), + "remove the unnecessary `.` operator and add an integer part for a floating point literal", + "0.", + Applicability::MaybeIncorrect, + ); + true + } + _ => false, + } + } + fn is_loop(&self, id: hir::HirId) -> bool { let node = self.tcx.hir().get(id); matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. })) diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index b7dd599cd43..7bbfb70f2c3 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -13,10 +13,13 @@ use rustc_hir::def_id::DefId; use rustc_hir::hir_id::HirIdSet; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind}; +use rustc_infer::infer::RegionVariableOrigin; use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData}; -use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::fold::FnMutDelegate; +use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable}; use rustc_span::symbol::sym; use rustc_span::Span; +use smallvec::{smallvec, SmallVec}; mod drop_ranges; @@ -211,31 +214,57 @@ pub fn resolve_interior<'a, 'tcx>( debug!("types in generator {:?}, span = {:?}", types, body.value.span); - let mut counter = 0; + // We want to deduplicate if the lifetimes are the same modulo some non-informative counter. + // So, we need to actually do two passes: first by type to anonymize (preserving information + // required for diagnostics), then a second pass over all captured types to reassign disjoint + // region indices. let mut captured_tys = FxHashSet::default(); let type_causes: Vec<_> = types .into_iter() .filter_map(|mut cause| { - // Erase regions and canonicalize late-bound regions to deduplicate as many types as we - // can. + // Replace all regions inside the generator interior with late bound regions. + // Note that each region slot in the types gets a new fresh late bound region, + // which means that none of the regions inside relate to any other, even if + // typeck had previously found constraints that would cause them to be related. + + let mut counter = 0; + let mut mk_bound_region = |span| { + let kind = ty::BrAnon(counter, span); + let var = ty::BoundVar::from_u32(counter); + counter += 1; + ty::BoundRegion { var, kind } + }; let ty = fcx.normalize_associated_types_in(cause.span, cause.ty); - let erased = fcx.tcx.erase_regions(ty); - if captured_tys.insert(erased) { - // Replace all regions inside the generator interior with late bound regions. - // Note that each region slot in the types gets a new fresh late bound region, - // which means that none of the regions inside relate to any other, even if - // typeck had previously found constraints that would cause them to be related. - let folded = fcx.tcx.fold_regions(erased, |_, current_depth| { - let br = ty::BoundRegion { - var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon(counter), - }; - let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); - counter += 1; - r - }); - - cause.ty = folded; + let ty = fcx.tcx.fold_regions(ty, |region, current_depth| { + let br = match region.kind() { + ty::ReVar(vid) => { + let origin = fcx.region_var_origin(vid); + match origin { + RegionVariableOrigin::EarlyBoundRegion(span, _) => { + mk_bound_region(Some(span)) + } + _ => mk_bound_region(None), + } + } + // FIXME: these should use `BrNamed` + ty::ReEarlyBound(region) => { + mk_bound_region(Some(fcx.tcx.def_span(region.def_id))) + } + ty::ReLateBound(_, ty::BoundRegion { kind, .. }) + | ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind { + ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span), + ty::BoundRegionKind::BrNamed(def_id, _) => { + mk_bound_region(Some(fcx.tcx.def_span(def_id))) + } + ty::BoundRegionKind::BrEnv => mk_bound_region(None), + }, + _ => mk_bound_region(None), + }; + let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); + r + }); + if captured_tys.insert(ty) { + cause.ty = ty; Some(cause) } else { None @@ -243,11 +272,38 @@ pub fn resolve_interior<'a, 'tcx>( }) .collect(); + let mut bound_vars: SmallVec<[BoundVariableKind; 4]> = smallvec![]; + let mut counter = 0; + // Optimization: If there is only one captured type, then we don't actually + // need to fold and reindex (since the first type doesn't change). + let type_causes = if captured_tys.len() > 0 { + // Optimization: Use `replace_escaping_bound_vars_uncached` instead of + // `fold_regions`, since we only have late bound regions, and it skips + // types without bound regions. + fcx.tcx.replace_escaping_bound_vars_uncached( + type_causes, + FnMutDelegate { + regions: &mut |br| { + let kind = match br.kind { + ty::BrAnon(_, span) => ty::BrAnon(counter, span), + _ => br.kind, + }; + let var = ty::BoundVar::from_usize(bound_vars.len()); + bound_vars.push(ty::BoundVariableKind::Region(kind)); + counter += 1; + fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind })) + }, + types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"), + consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"), + }, + ) + } else { + type_causes + }; + // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); - let bound_vars = fcx.tcx.mk_bound_variable_kinds( - (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), - ); + let bound_vars = fcx.tcx.mk_bound_variable_kinds(bound_vars.iter()); let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone())); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 959c5486645..183e80f2e08 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -209,6 +209,7 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T typeck_with_fallback(tcx, def_id, fallback) } +#[instrument(level = "debug", skip(tcx, fallback), ret)] fn typeck_with_fallback<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, @@ -250,7 +251,7 @@ fn typeck_with_fallback<'tcx>( param_env, fn_sig, ); - check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0 + check_fn(&inh, param_env, fn_sig, decl, id, body, None).0 } else { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); let expected_type = body_ty @@ -316,12 +317,12 @@ fn typeck_with_fallback<'tcx>( fcx }; - let fallback_has_occurred = fcx.type_inference_fallback(); + fcx.type_inference_fallback(); // Even though coercion casts provide type hints, we check casts after fallback for // backwards compatibility. This makes fallback a stronger type hint than a cast coercion. fcx.check_casts(); - fcx.select_obligations_where_possible(fallback_has_occurred, |_| {}); + fcx.select_obligations_where_possible(|_| {}); // Closure and generator analysis may run after fallback // because they don't constrain other type variables. @@ -458,7 +459,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<' /// # fn f(x: (isize, isize)) {} /// f((1, 2)); /// ``` -#[derive(Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq, PartialEq)] enum TupleArgumentsFlag { DontTupleArguments, TupleArguments, diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index be4ea998622..d996d6ec610 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -151,8 +151,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ) -> Ty<'tcx> { // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various typeck results. - let mut autoderef = - self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span); + let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty); let Some((ty, n)) = autoderef.nth(pick.autoderefs) else { return self.tcx.ty_error_with_message( rustc_span::DUMMY_SP, diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index a1278edefbb..4a8b7749365 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -10,6 +10,7 @@ mod suggest; pub use self::suggest::SelfSource; pub use self::MethodError::*; +use crate::errors::OpMethodGenericParams; use crate::{Expectation, FnCtxt}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic}; @@ -55,8 +56,7 @@ pub enum MethodError<'tcx> { // not-in-scope traits which may work. PrivateMatch(DefKind, DefId, Vec<DefId>), - // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have - // forgotten to import a trait. + // Found a `Self: Sized` bound where `Self` is a trait object. IllegalSizedBound(Vec<DefId>, bool, Span), // Found a match, but the return type is wrong @@ -444,7 +444,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let def_id = method_item.def_id; let generics = tcx.generics_of(def_id); - assert_eq!(generics.params.len(), 0); + + if generics.params.len() != 0 { + tcx.sess.emit_fatal(OpMethodGenericParams { + span: tcx.def_span(method_item.def_id), + method_name: m_name.to_string(), + }); + } debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); let mut obligations = vec![]; diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 28aa2302f88..3fcd073f597 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -475,10 +475,9 @@ fn method_autoderef_steps<'tcx>( let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal); let ParamEnvAnd { param_env, value: self_ty } = goal; - let mut autoderef = - Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty, DUMMY_SP) - .include_raw_pointers() - .silence_errors(); + let mut autoderef = Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty) + .include_raw_pointers() + .silence_errors(); let mut reached_raw_pointer = false; let mut steps: Vec<_> = autoderef .by_ref() @@ -1019,7 +1018,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let out_of_scope_traits = match self.pick_core() { Some(Ok(p)) => vec![p.item.container_id(self.tcx)], - //Some(Ok(p)) => p.iter().map(|p| p.item.container().id()).collect(), Some(Err(MethodError::Ambiguity(v))) => v .into_iter() .map(|source| match source { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 6c21ed902d0..43a5145b7e7 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -14,19 +14,26 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; -use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{ + type_variable::{TypeVariableOrigin, TypeVariableOriginKind}, + RegionVariableOrigin, +}; +use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::with_crate_prefix; -use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{ + self, DefIdTree, GenericArg, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable, +}; use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span}; +use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote; use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{ - FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote, + FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, }; use std::cmp::Ordering; @@ -248,7 +255,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match error { MethodError::NoMatch(NoMatchData { - static_candidates: mut static_sources, + mut static_candidates, unsatisfied_predicates, out_of_scope_traits, lev_candidate, @@ -279,7 +286,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { return None; } - span = item_name.span; // Don't show generic arguments when the method can't be found in any implementation (#81576). @@ -288,9 +294,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if generics.len() > 0 { let mut autoderef = self.autoderef(span, actual); let candidate_found = autoderef.any(|(ty, _)| { - if let ty::Adt(adt_deref, _) = ty.kind() { + if let ty::Adt(adt_def, _) = ty.kind() { self.tcx - .inherent_impls(adt_deref.did()) + .inherent_impls(adt_def.did()) .iter() .filter_map(|def_id| self.associated_value(*def_id, item_name)) .count() @@ -348,15 +354,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let ty_span = match actual.kind() { - ty::Param(param_type) => { - let generics = self.tcx.generics_of(self.body_id.owner.to_def_id()); - let type_param = generics.type_param(param_type, self.tcx); - Some(self.tcx.def_span(type_param.def_id)) - } + ty::Param(param_type) => Some( + param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()), + ), ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())), _ => None, }; - if let Some(span) = ty_span { err.span_label( span, @@ -386,7 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut custom_span_label = false; - if !static_sources.is_empty() { + if !static_candidates.is_empty() { err.note( "found the following associated functions; to be used as methods, \ functions must have a `self` parameter", @@ -394,37 +397,127 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(span, "this is an associated function, not a method"); custom_span_label = true; } - if static_sources.len() == 1 { - let ty_str = - if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) { - // When the "method" is resolved through dereferencing, we really want the - // original type that has the associated function for accurate suggestions. - // (#61411) - let ty = tcx.at(span).type_of(*impl_did); - match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { - (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => { - // Use `actual` as it will have more `substs` filled in. - self.ty_to_value_string(actual.peel_refs()) + if static_candidates.len() == 1 { + let mut has_unsuggestable_args = false; + let ty_str = if let Some(CandidateSource::Impl(impl_did)) = + static_candidates.get(0) + { + // When the "method" is resolved through dereferencing, we really want the + // original type that has the associated function for accurate suggestions. + // (#61411) + let ty = tcx.at(span).type_of(*impl_did); + match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { + (ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => { + // If there are any inferred arguments, (`{integer}`), we should replace + // them with underscores to allow the compiler to infer them + let infer_substs: Vec<GenericArg<'_>> = substs + .into_iter() + .map(|arg| { + if !arg.is_suggestable(tcx, true) { + has_unsuggestable_args = true; + match arg.unpack() { + GenericArgKind::Lifetime(_) => self + .next_region_var(RegionVariableOrigin::MiscVariable( + rustc_span::DUMMY_SP, + )) + .into(), + GenericArgKind::Type(_) => self + .next_ty_var(TypeVariableOrigin { + span: rustc_span::DUMMY_SP, + kind: TypeVariableOriginKind::MiscVariable, + }) + .into(), + GenericArgKind::Const(arg) => self + .next_const_var( + arg.ty(), + ConstVariableOrigin { + span: rustc_span::DUMMY_SP, + kind: ConstVariableOriginKind::MiscVariable, + }, + ) + .into(), + } + } else { + arg + } + }) + .collect::<Vec<_>>(); + + tcx.value_path_str_with_substs( + def_actual.did(), + tcx.intern_substs(&infer_substs), + ) + } + _ => self.ty_to_value_string(ty.peel_refs()), + } + } else { + self.ty_to_value_string(actual.peel_refs()) + }; + if let SelfSource::MethodCall(_) = source { + let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) && + let Some(assoc) = self.associated_value(*impl_did, item_name) { + let sig = self.tcx.fn_sig(assoc.def_id); + if let Some(first) = sig.inputs().skip_binder().get(0) { + if first.peel_refs() == rcvr_ty.peel_refs() { + None + } else { + Some(if first.is_region_ptr() { + if first.is_mutable_ptr() { "&mut " } else { "&" } + } else { + "" + }) } - _ => self.ty_to_value_string(ty.peel_refs()), + } else { + None } } else { - self.ty_to_value_string(actual.peel_refs()) + None + }; + let mut applicability = Applicability::MachineApplicable; + let args = if let Some((receiver, args)) = args { + // The first arg is the same kind as the receiver + let explicit_args = if first_arg.is_some() { + std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>() + } else { + // There is no `Self` kind to infer the arguments from + if has_unsuggestable_args { + applicability = Applicability::HasPlaceholders; + } + args.iter().collect() + }; + format!( + "({}{})", + first_arg.unwrap_or(""), + explicit_args + .iter() + .map(|arg| tcx + .sess + .source_map() + .span_to_snippet(arg.span) + .unwrap_or_else(|_| { + applicability = Applicability::HasPlaceholders; + "_".to_owned() + })) + .collect::<Vec<_>>() + .join(", "), + ) + } else { + applicability = Applicability::HasPlaceholders; + "(...)".to_owned() }; - if let SelfSource::MethodCall(expr) = source { err.span_suggestion( - expr.span.to(span), + sugg_span, "use associated function syntax instead", - format!("{}::{}", ty_str, item_name), - Applicability::MachineApplicable, + format!("{}::{}{}", ty_str, item_name, args), + applicability, ); } else { err.help(&format!("try with `{}::{}`", ty_str, item_name,)); } - report_candidates(span, &mut err, &mut static_sources, sugg_span); - } else if static_sources.len() > 1 { - report_candidates(span, &mut err, &mut static_sources, sugg_span); + report_candidates(span, &mut err, &mut static_candidates, sugg_span); + } else if static_candidates.len() > 1 { + report_candidates(span, &mut err, &mut static_candidates, sugg_span); } let mut bound_spans = vec![]; @@ -496,24 +589,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let (ty::Param(_), ty::PredicateKind::Trait(p)) = (self_ty.kind(), parent_pred.kind().skip_binder()) { + let hir = self.tcx.hir(); let node = match p.trait_ref.self_ty().kind() { ty::Param(_) => { // Account for `fn` items like in `issue-35677.rs` to // suggest restricting its type params. - let did = self.tcx.hir().body_owner_def_id(hir::BodyId { - hir_id: self.body_id, - }); - Some( - self.tcx - .hir() - .get(self.tcx.hir().local_def_id_to_hir_id(did)), - ) + let parent_body = + hir.body_owner(hir::BodyId { hir_id: self.body_id }); + Some(hir.get(parent_body)) + } + ty::Adt(def, _) => { + def.did().as_local().map(|def_id| hir.get_by_def_id(def_id)) } - ty::Adt(def, _) => def.did().as_local().map(|def_id| { - self.tcx - .hir() - .get(self.tcx.hir().local_def_id_to_hir_id(def_id)) - }), _ => None, }; if let Some(hir::Node::Item(hir::Item { kind, .. })) = node { @@ -605,7 +692,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c))) .filter_map(|(p, parent, c)| match c.code() { - ObligationCauseCode::ImplDerivedObligation(ref data) => { + ObligationCauseCode::ImplDerivedObligation(data) => { Some((&data.derived, p, parent, data.impl_def_id, data)) } _ => None, @@ -621,22 +708,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Unmet obligation comes from a `derive` macro, point at it once to // avoid multiple span labels pointing at the same place. Some(Node::Item(hir::Item { - kind: hir::ItemKind::Trait(..), - ident, - .. - })) if matches!( - ident.span.ctxt().outer_expn_data().kind, - ExpnKind::Macro(MacroKind::Derive, _) - ) => - { - let span = ident.span.ctxt().outer_expn_data().call_site; - let mut spans: MultiSpan = span.into(); - spans.push_span_label(span, derive_msg); - let entry = spanned_predicates.entry(spans); - entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); - } - - Some(Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), .. })) if matches!( @@ -659,34 +730,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); } - // Unmet obligation coming from a `trait`. - Some(Node::Item(hir::Item { - kind: hir::ItemKind::Trait(..), - ident, - span: item_span, - .. - })) if !matches!( - ident.span.ctxt().outer_expn_data().kind, - ExpnKind::Macro(MacroKind::Derive, _) - ) => - { - if let Some(pred) = parent_p { - // Done to add the "doesn't satisfy" `span_label`. - let _ = format_pred(*pred); - } - skip_list.insert(p); - let mut spans = if cause.span != *item_span { - let mut spans: MultiSpan = cause.span.into(); - spans.push_span_label(cause.span, unsatisfied_msg); - spans - } else { - ident.span.into() - }; - spans.push_span_label(ident.span, "in this trait"); - let entry = spanned_predicates.entry(spans); - entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); - } - // Unmet obligation coming from an `impl`. Some(Node::Item(hir::Item { kind: @@ -695,19 +738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }), span: item_span, .. - })) if !matches!( - self_ty.span.ctxt().outer_expn_data().kind, - ExpnKind::Macro(MacroKind::Derive, _) - ) && !matches!( - of_trait.as_ref().map(|t| t - .path - .span - .ctxt() - .outer_expn_data() - .kind), - Some(ExpnKind::Macro(MacroKind::Derive, _)) - ) => - { + })) => { let sized_pred = unsatisfied_predicates.iter().any(|(pred, _, _)| { match pred.kind().skip_binder() { @@ -759,7 +790,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let entry = spanned_predicates.entry(spans); entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); } - _ => {} + Some(_) => unreachable!(), + None => (), } } let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect(); @@ -863,7 +895,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .on_unimplemented_note(trait_ref, &obligation); (message, label) }) - .unwrap_or((None, None)) + .unwrap() } else { (None, None) }; @@ -972,7 +1004,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the method name is the name of a field with a function or closure type, // give a helping note that it has to be called as `(x.f)(...)`. if let SelfSource::MethodCall(expr) = source { - if !self.suggest_field_call(span, rcvr_ty, expr, item_name, &mut err) + if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err) && lev_candidate.is_none() && !custom_span_label { @@ -982,10 +1014,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { label_span_not_found(&mut err); } - // Don't suggest (for example) `expr.field.method()` if `expr.method()` - // doesn't exist due to unsatisfied predicates. + // Don't suggest (for example) `expr.field.clone()` if `expr.clone()` + // can't be called due to `typeof(expr): Clone` not holding. if unsatisfied_predicates.is_empty() { - self.check_for_field_method(&mut err, source, span, actual, item_name); + self.suggest_calling_method_on_field(&mut err, source, span, actual, item_name); } self.check_for_inner_self(&mut err, source, span, actual, item_name); @@ -1007,7 +1039,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source, out_of_scope_traits, &unsatisfied_predicates, - &static_sources, + &static_candidates, unsatisfied_bounds, ); } @@ -1146,7 +1178,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } - fn suggest_field_call( + /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with + /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`. + fn suggest_calling_field_as_fn( &self, span: Span, rcvr_ty: Ty<'tcx>, @@ -1408,7 +1442,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - fn check_for_field_method( + /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()` + fn suggest_calling_method_on_field( &self, err: &mut Diagnostic, source: SelfSource<'tcx>, @@ -1865,6 +1900,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::Str | ty::Projection(_) | ty::Param(_) => format!("{deref_ty}"), + // we need to test something like <&[_]>::len + // and Vec::function(); + // <&[_]>::len doesn't need an extra "<>" between + // but for Adt type like Vec::function() + // we would suggest <[_]>::function(); + _ if self.tcx.sess.source_map().span_wrapped_by_angle_bracket(ty.span) => format!("{deref_ty}"), _ => format!("<{deref_ty}>"), }; err.span_suggestion_verbose( @@ -1887,7 +1928,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Print out the type for use in value namespace. fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String { match ty.kind() { - ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)), + ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs), _ => self.ty_to_string(ty), } } @@ -2021,7 +2062,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let mut alt_rcvr_sugg = false; if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) { - debug!(?span, ?item_name, ?rcvr_ty, ?rcvr); + debug!( + "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}", + span, item_name, rcvr_ty, rcvr + ); let skippable = [ self.tcx.lang_items().clone_trait(), self.tcx.lang_items().deref_trait(), @@ -2060,7 +2104,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // suggestions are generally misleading (see #94218). break; } - _ => {} + Err(_) => (), } for (rcvr_ty, pre) in &[ diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 89573997693..38b3dd218a9 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -19,7 +19,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::{FulfillmentError, TraitEngine, TraitEngineExt}; +use rustc_trait_selection::traits::FulfillmentError; use rustc_type_ir::sty::TyKind::*; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -529,8 +529,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - err.emit(); - self.tcx.ty_error() + let reported = err.emit(); + self.tcx.ty_error_with_guaranteed(reported) } }; @@ -772,7 +772,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match (method, trait_did) { (Some(ok), _) => { let method = self.register_infer_ok_obligations(ok); - self.select_obligations_where_possible(false, |_| {}); + self.select_obligations_where_possible(|_| {}); Ok(method) } (None, None) => Err(vec![]), @@ -785,9 +785,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { other_ty_expr, expected, ); - let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx); - fulfill.register_predicate_obligation(self, obligation); - Err(fulfill.select_where_possible(&self.infcx)) + Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation)) } } } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index ea90da4a6dc..eb10f3e2c10 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -19,7 +19,6 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, DUMMY_SP}; -use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::{ObligationCause, Pattern}; use ty::VariantDef; @@ -1278,12 +1277,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) { - err.emit(); + let reported = err.emit(); // Walk subpatterns with an expected type of `err` in this case to silence // further errors being emitted when using the bindings. #50333 - let element_tys_iter = (0..max_len).map(|_| tcx.ty_error()); + let element_tys_iter = (0..max_len).map(|_| tcx.ty_error_with_guaranteed(reported)); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat(elem, tcx.ty_error(), def_bm, ti); + self.check_pat(elem, tcx.ty_error_with_guaranteed(reported), def_bm, ti); } tcx.mk_tup(element_tys_iter) } else { @@ -2132,7 +2131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let ty::Array(..) | ty::Slice(..) = ty.kind() { err.help("the semantics of slice patterns changed recently; see issue #62254"); - } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span) + } else if self.autoderef(span, expected_ty) .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..))) && let (Some(span), true) = (ti.span, ti.origin_expr) && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index ba8cf6926f3..952ea14887f 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -90,8 +90,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - err.emit(); - Some((self.tcx.ty_error(), self.tcx.ty_error())) + let reported = err.emit(); + Some(( + self.tcx.ty_error_with_guaranteed(reported), + self.tcx.ty_error_with_guaranteed(reported), + )) } /// To type-check `base_expr[index_expr]`, we progressively autoderef diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index bb04e1c49ba..ec4eeb8caa2 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -180,6 +180,18 @@ pub enum SourceKindMultiSuggestion<'a> { }, } +#[derive(Subdiagnostic)] +#[suggestion( + infer_suggest_add_let_for_letchains, + style = "verbose", + applicability = "machine-applicable", + code = "let " +)] +pub(crate) struct SuggAddLetForLetChains { + #[primary_span] + pub span: Span, +} + impl<'a> SourceKindMultiSuggestion<'a> { pub fn new_fully_qualified( span: Span, diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 6a29d85627a..7aaa5ce2f42 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -89,10 +89,13 @@ impl<'a> DescriptionCtx<'a> { }; me.span = Some(sp); } - ty::BrAnon(idx) => { + ty::BrAnon(idx, span) => { me.kind = "anon_num_here"; me.num_arg = idx+1; - me.span = Some(tcx.def_span(scope)); + me.span = match span { + Some(_) => span, + None => Some(tcx.def_span(scope)), + } }, _ => { me.kind = "defined_here_reg"; diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index a3ff7036340..3dc0d60b1eb 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -495,7 +495,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { } ty::ConstKind::Bound(debruijn, _) => { if debruijn >= self.binder_index { - bug!("escaping bound type during canonicalization") + bug!("escaping bound const during canonicalization") } else { return ct; } @@ -738,7 +738,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); - let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32()) }; + let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) }; let region = ty::ReLateBound(self.binder_index, br); self.tcx().mk_region(region) } @@ -773,10 +773,10 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { self.fold_const(bound_to) } else { let var = self.canonical_var(info, const_var.into()); - self.tcx().mk_const(ty::ConstS { - kind: ty::ConstKind::Bound(self.binder_index, var), - ty: self.fold_ty(const_var.ty()), - }) + self.tcx().mk_const( + ty::ConstKind::Bound(self.binder_index, var), + self.fold_ty(const_var.ty()), + ) } } } diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index cbd6481f9cb..0794792d8cb 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -147,12 +147,7 @@ impl<'tcx> InferCtxt<'tcx> { CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, name }, ty) => { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, name }; - self.tcx - .mk_const(ty::ConstS { - kind: ty::ConstKind::Placeholder(placeholder_mapped), - ty, - }) - .into() + self.tcx.mk_const(ty::ConstKind::Placeholder(placeholder_mapped), ty).into() } } } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index b5427f639c1..a973bf54b05 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -741,10 +741,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { substs, substs, )?; - Ok(self.tcx().mk_const(ty::ConstS { - ty: c.ty(), - kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }), - })) + Ok(self.tcx().mk_const( + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }), + c.ty(), + )) } _ => relate::super_relate_consts(self, c, c), } @@ -955,10 +955,10 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { substs, )?; - Ok(self.tcx().mk_const(ty::ConstS { - ty: c.ty(), - kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }), - })) + Ok(self.tcx().mk_const( + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }), + c.ty(), + )) } _ => relate::super_relate_consts(self, c, c), } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 9ff703e521f..22f32251f6d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength //! Error Reporting Code for the inference engine //! //! Because of the way inference, and in particular region inference, @@ -58,12 +59,15 @@ use crate::traits::{ StatementAsExpression, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use crate::errors::SuggAddLetForLetChains; +use hir::intravisit::{walk_expr, walk_stmt}; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::Node; use rustc_middle::dep_graph::DepContext; @@ -91,6 +95,7 @@ pub mod nice_region_error; pub struct TypeErrCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>, + pub fallback_has_occurred: bool, } impl TypeErrCtxt<'_, '_> { @@ -206,9 +211,12 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>( }; (text, sp) } - ty::BrAnon(idx) => ( + ty::BrAnon(idx, span) => ( format!("the anonymous lifetime #{} defined here", idx + 1), - tcx.def_span(scope) + match span { + Some(span) => span, + None => tcx.def_span(scope) + } ), _ => ( format!("the lifetime `{}` as defined here", region), @@ -1498,9 +1506,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { values = None; } struct OpaqueTypesVisitor<'tcx> { - types: FxHashMap<TyCategory, FxHashSet<Span>>, - expected: FxHashMap<TyCategory, FxHashSet<Span>>, - found: FxHashMap<TyCategory, FxHashSet<Span>>, + types: FxIndexMap<TyCategory, FxIndexSet<Span>>, + expected: FxIndexMap<TyCategory, FxIndexSet<Span>>, + found: FxIndexMap<TyCategory, FxIndexSet<Span>>, ignore_span: Span, tcx: TyCtxt<'tcx>, } @@ -1538,7 +1546,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, err: &mut Diagnostic, target: &str, - types: &FxHashMap<TyCategory, FxHashSet<Span>>, + types: &FxIndexMap<TyCategory, FxIndexSet<Span>>, ) { for (key, values) in types.iter() { let count = values.len(); @@ -2332,6 +2340,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } } + // For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`, + // we try to suggest to add the missing `let` for `if let Some(..) = expr` + (ty::Bool, ty::Tuple(list)) => if list.len() == 0 { + self.suggest_let_for_letchains(&mut err, &trace.cause, span); + } _ => {} } } @@ -2356,6 +2369,67 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { diag } + /// Try to find code with pattern `if Some(..) = expr` + /// use a `visitor` to mark the `if` which its span contains given error span, + /// and then try to find a assignment in the `cond` part, which span is equal with error span + fn suggest_let_for_letchains( + &self, + err: &mut Diagnostic, + cause: &ObligationCause<'_>, + span: Span, + ) { + let hir = self.tcx.hir(); + let fn_hir_id = hir.get_parent_node(cause.body_id); + if let Some(node) = self.tcx.hir().find(fn_hir_id) && + let hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(_sig, _, body_id), .. + }) = node { + let body = hir.body(*body_id); + + /// Find the if expression with given span + struct IfVisitor { + pub result: bool, + pub found_if: bool, + pub err_span: Span, + } + + impl<'v> Visitor<'v> for IfVisitor { + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { + if self.result { return; } + match ex.kind { + hir::ExprKind::If(cond, _, _) => { + self.found_if = true; + walk_expr(self, cond); + self.found_if = false; + } + _ => walk_expr(self, ex), + } + } + + fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) { + if let hir::StmtKind::Local(hir::Local { + span, pat: hir::Pat{..}, ty: None, init: Some(_), .. + }) = &ex.kind + && self.found_if + && span.eq(&self.err_span) { + self.result = true; + } + walk_stmt(self, ex); + } + + fn visit_body(&mut self, body: &'v hir::Body<'v>) { + hir::intravisit::walk_body(self, body); + } + } + + let mut visitor = IfVisitor { err_span: span, found_if: false, result: false }; + visitor.visit_body(&body); + if visitor.result { + err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()}); + } + } + } + fn emit_tuple_wrap_err( &self, err: &mut Diagnostic, @@ -3254,7 +3328,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if blk.expr.is_some() { return false; } - let mut shadowed = FxHashSet::default(); + let mut shadowed = FxIndexSet::default(); let mut candidate_idents = vec![]; let mut find_compatible_candidates = |pat: &hir::Pat<'_>| { if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index c5f2a1a3f7d..1067ccda20c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -9,7 +9,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::ObligationCauseCode; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; @@ -73,7 +73,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Next, let's figure out the set of trait objects with implicit static bounds let ty = self.tcx().type_of(*impl_def_id); - let mut v = super::static_impl_trait::TraitObjectVisitor(FxHashSet::default()); + let mut v = super::static_impl_trait::TraitObjectVisitor(FxIndexSet::default()); v.visit_ty(ty); let mut traits = vec![]; for matching_def_id in v.0 { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index aaf5a7af00a..8a0e332f9c7 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -10,6 +10,7 @@ pub mod find_anon_type; mod mismatched_static_lifetime; mod named_anon_conflict; mod placeholder_error; +mod placeholder_relation; mod static_impl_trait; mod trait_impl_difference; mod util; @@ -52,7 +53,9 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of // the nice region errors are required when running under the MIR borrow checker. - self.try_report_named_anon_conflict().or_else(|| self.try_report_placeholder_conflict()) + self.try_report_named_anon_conflict() + .or_else(|| self.try_report_placeholder_conflict()) + .or_else(|| self.try_report_placeholder_relation()) } pub fn try_report(&self) -> Option<ErrorGuaranteed> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 76cb76d9ff4..3fe7c1598fc 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let is_impl_item = region_info.is_impl_item; match br { - ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) => {} + ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) => {} _ => { /* not an anonymous region */ debug!("try_report_named_anon_conflict: not an anonymous region"); diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs new file mode 100644 index 00000000000..c42240f2172 --- /dev/null +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs @@ -0,0 +1,79 @@ +use crate::infer::{ + error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin, +}; +use rustc_data_structures::intern::Interned; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; +use rustc_middle::ty::{self, RePlaceholder, Region}; + +impl<'tcx> NiceRegionError<'_, 'tcx> { + /// Emitted wwhen given a `ConcreteFailure` when relating two placeholders. + pub(super) fn try_report_placeholder_relation( + &self, + ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { + match &self.error { + Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::RelateRegionParamBound(span), + Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)), + Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)), + )) => { + let msg = "lifetime bound not satisfied"; + let mut err = self.tcx().sess.struct_span_err(*span, msg); + let (sub_span, sub_symbol) = match sub_name { + ty::BrNamed(def_id, symbol) => { + (Some(self.tcx().def_span(def_id)), Some(symbol)) + } + ty::BrAnon(_, span) => (*span, None), + ty::BrEnv => (None, None), + }; + let (sup_span, sup_symbol) = match sup_name { + ty::BrNamed(def_id, symbol) => { + (Some(self.tcx().def_span(def_id)), Some(symbol)) + } + ty::BrAnon(_, span) => (*span, None), + ty::BrEnv => (None, None), + }; + match (sub_span, sup_span, sub_symbol, sup_symbol) { + (Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => { + err.span_note( + sub_span, + format!("the lifetime `{sub_symbol}` defined here..."), + ); + err.span_note( + sup_span, + format!("...must outlive the lifetime `{sup_symbol}` defined here"), + ); + } + (Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => { + err.span_note(sub_span, format!("the lifetime defined here...")); + err.span_note( + sup_span, + format!("...must outlive the lifetime `{sup_symbol}` defined here"), + ); + } + (Some(sub_span), Some(sup_span), Some(sub_symbol), _) => { + err.span_note( + sub_span, + format!("the lifetime `{sub_symbol}` defined here..."), + ); + err.span_note( + sup_span, + format!("...must outlive the lifetime defined here"), + ); + } + (Some(sub_span), Some(sup_span), _, _) => { + err.span_note(sub_span, format!("the lifetime defined here...")); + err.span_note( + sup_span, + format!("...must outlive the lifetime defined here"), + ); + } + _ => {} + } + err.note("this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)"); + Some(err) + } + + _ => None, + } + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 9bf755d7fcd..b4efe8da125 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -4,7 +4,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; @@ -236,7 +236,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static` // lifetime as above, but called using a fully-qualified path to the method: // `Foo::qux(bar)`. - let mut v = TraitObjectVisitor(FxHashSet::default()); + let mut v = TraitObjectVisitor(FxIndexSet::default()); v.visit_ty(param.param_ty); if let Some((ident, self_ty)) = self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0) @@ -408,7 +408,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { fn get_impl_ident_and_self_ty_from_trait( &self, def_id: DefId, - trait_objects: &FxHashSet<DefId>, + trait_objects: &FxIndexSet<DefId>, ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { let tcx = self.tcx(); match tcx.hir().get_if_local(def_id) { @@ -490,7 +490,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { return false; }; - let mut v = TraitObjectVisitor(FxHashSet::default()); + let mut v = TraitObjectVisitor(FxIndexSet::default()); v.visit_ty(ty); // Get the `Ident` of the method being called and the corresponding `impl` (to point at @@ -506,7 +506,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { fn suggest_constrain_dyn_trait_in_impl( &self, err: &mut Diagnostic, - found_dids: &FxHashSet<DefId>, + found_dids: &FxIndexSet<DefId>, ident: Ident, self_ty: &hir::Ty<'_>, ) -> bool { @@ -538,7 +538,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } /// Collect all the trait objects in a type that could have received an implicit `'static` lifetime. -pub struct TraitObjectVisitor(pub FxHashSet<DefId>); +pub struct TraitObjectVisitor(pub FxIndexSet<DefId>); impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index f1461d7010d..fd26d7d29c5 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -149,6 +149,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { region: ty::BoundRegionKind, ) -> bool { let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty); + // We are only checking is any region meets the condition so order doesn't matter + #[allow(rustc::potential_query_instability)] late_bound_regions.iter().any(|r| *r == region) } diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index 28c87a1159f..d739323de77 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -94,13 +94,13 @@ impl<'tcx> InferCtxt<'tcx> { })) }, consts: &mut |bound_var: ty::BoundVar, ty| { - self.tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Placeholder(ty::PlaceholderConst { + self.tcx.mk_const( + ty::ConstKind::Placeholder(ty::PlaceholderConst { universe: next_universe, name: bound_var, }), ty, - }) + ) }, }; 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 5f13b2b3deb..ba990acfe6f 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -842,6 +842,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // are placeholders as upper bounds, but the universe of the // variable `'a`, or some variable that `'a` has to outlive, doesn't // permit those placeholders. + // + // We only iterate to find the min, which means it doesn't cause reproducibility issues + #[allow(rustc::potential_query_instability)] let min_universe = lower_vid_bounds .into_iter() .map(|vid| self.var_infos[vid].universe) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index ffb020398b8..fd3b3e4d59f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -10,6 +10,7 @@ pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt}; +use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::Rollback; @@ -294,7 +295,7 @@ pub struct InferCtxt<'tcx> { /// the set of predicates on which errors have been reported, to /// avoid reporting the same error twice. - pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<ty::Predicate<'tcx>>>>, + pub reported_trait_errors: RefCell<FxIndexMap<Span, Vec<ty::Predicate<'tcx>>>>, pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>, @@ -677,9 +678,9 @@ pub struct CombinedSnapshot<'tcx> { impl<'tcx> InferCtxt<'tcx> { /// Creates a `TypeErrCtxt` for emitting various inference errors. - /// During typeck, use `FnCtxt::infer_err` instead. + /// During typeck, use `FnCtxt::err_ctxt` instead. pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> { - TypeErrCtxt { infcx: self, typeck_results: None } + TypeErrCtxt { infcx: self, typeck_results: None, fallback_has_occurred: false } } /// calls `tcx.try_unify_abstract_consts` after @@ -777,32 +778,6 @@ impl<'tcx> InferCtxt<'tcx> { } } - /// Clear the "currently in a snapshot" flag, invoke the closure, - /// then restore the flag to its original value. This flag is a - /// debugging measure designed to detect cases where we start a - /// snapshot, create type variables, and register obligations - /// which may involve those type variables in the fulfillment cx, - /// potentially leaving "dangling type variables" behind. - /// In such cases, an assertion will fail when attempting to - /// register obligations, within a snapshot. Very useful, much - /// better than grovelling through megabytes of `RUSTC_LOG` output. - /// - /// HOWEVER, in some cases the flag is unhelpful. In particular, we - /// sometimes create a "mini-fulfilment-cx" in which we enroll - /// obligations. As long as this fulfillment cx is fully drained - /// before we return, this is not a problem, as there won't be any - /// escaping obligations in the main cx. In those cases, you can - /// use this function. - pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R - where - F: FnOnce(&Self) -> R, - { - let flag = self.in_snapshot.replace(false); - let result = func(self); - self.in_snapshot.set(flag); - result - } - fn start_snapshot(&self) -> CombinedSnapshot<'tcx> { debug!("start_snapshot()"); @@ -2065,13 +2040,13 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>( if ty.has_non_region_param() || ty.has_non_region_infer() { bug!("const `{ct}`'s type should not reference params or types"); } - tcx.mk_const(ty::ConstS { - ty, - kind: ty::ConstKind::Placeholder(ty::PlaceholderConst { + tcx.mk_const( + ty::ConstKind::Placeholder(ty::PlaceholderConst { universe: ty::UniverseIndex::ROOT, name: ty::BoundVar::from_usize(idx), }), - }) + ty, + ) .into() } _ => arg, diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 90858e3072a..22b4bbb17d4 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -1,6 +1,7 @@ use super::*; use crate::infer::CombinedSnapshot; use rustc_data_structures::{ + fx::FxIndexMap, graph::{scc::Sccs, vec_graph::VecGraph}, undo_log::UndoLogs, }; @@ -371,7 +372,7 @@ rustc_index::newtype_index! { /// an edge `R1 -> R2` in the graph. struct MiniGraph<'tcx> { /// Map from a region to the index of the node in the graph. - nodes: FxHashMap<ty::Region<'tcx>, LeakCheckNode>, + nodes: FxIndexMap<ty::Region<'tcx>, LeakCheckNode>, /// Map from node index to SCC, and stores the successors of each SCC. All /// the regions in the same SCC are equal to one another, and if `S1 -> S2`, @@ -388,7 +389,7 @@ impl<'tcx> MiniGraph<'tcx> { where 'tcx: 'a, { - let mut nodes = FxHashMap::default(); + let mut nodes = FxIndexMap::default(); let mut edges = Vec::new(); // Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter. @@ -438,7 +439,7 @@ impl<'tcx> MiniGraph<'tcx> { } fn add_node( - nodes: &mut FxHashMap<ty::Region<'tcx>, LeakCheckNode>, + nodes: &mut FxIndexMap<ty::Region<'tcx>, LeakCheckNode>, r: ty::Region<'tcx>, ) -> LeakCheckNode { let l = nodes.len(); diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 67b3da68720..985c5d360db 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -7,7 +7,7 @@ use super::{ InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::UndoLogs; @@ -125,7 +125,7 @@ pub struct RegionConstraintData<'tcx> { /// we record the fact that `'a <= 'b` is implied by the fn /// signature, and then ignore the constraint when solving /// equations. This is a bit of a hack but seems to work. - pub givens: FxHashSet<(Region<'tcx>, ty::RegionVid)>, + pub givens: FxIndexSet<(Region<'tcx>, ty::RegionVid)>, } /// Represents a constraint that influences the inference process. diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index e040634edb0..4c119a44355 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -12,7 +12,6 @@ //! //! This API is completely unstable and subject to change. -#![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index f8b5009a58d..4d53519581b 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -1,7 +1,7 @@ use super::ObjectSafetyViolation; use crate::infer::InferCtxt; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -56,7 +56,7 @@ pub fn report_object_safety_error<'tcx>( ); err.span_label(span, format!("`{}` cannot be made into an object", trait_str)); - let mut reported_violations = FxHashSet::default(); + let mut reported_violations = FxIndexSet::default(); let mut multi_span = vec![]; let mut messages = vec![]; for violation in violations { diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 6a4c5b4d373..2e526733df9 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -48,12 +48,6 @@ rustc_resolve = { path = "../rustc_resolve" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } -[target.'cfg(unix)'.dependencies] -libc = "0.2" - -[target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["libloaderapi"] } - [dev-dependencies] rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index a41a749ee68..542b638bbd7 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,4 +1,5 @@ #![feature(box_patterns)] +#![feature(decl_macro)] #![feature(internal_output_capture)] #![feature(thread_spawn_unchecked)] #![feature(once_cell)] diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 4c236c693d0..9bf7778bfb2 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -4,21 +4,16 @@ use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> { - let mut finder = Finder { tcx, decls: None }; + let mut decls = None; for id in tcx.hir().items() { - let attrs = finder.tcx.hir().attrs(id.hir_id()); - if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) { - finder.decls = Some(id.owner_id.def_id); + let attrs = tcx.hir().attrs(id.hir_id()); + if tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) { + decls = Some(id.owner_id.def_id); } } - finder.decls -} - -struct Finder<'tcx> { - tcx: TyCtxt<'tcx>, - decls: Option<LocalDefId>, + decls } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 519b8a7fc7c..2fe3fb2fa56 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -9,6 +9,7 @@ use rustc_session as session; use rustc_session::config::CheckCfg; use rustc_session::config::{self, CrateType}; use rustc_session::config::{ErrorOutputType, Input, OutputFilenames}; +use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; use rustc_session::parse::CrateConfig; use rustc_session::{early_error, filesearch, output, Session}; @@ -78,7 +79,7 @@ pub fn create_session( let bundle = match rustc_errors::fluent_bundle( sopts.maybe_sysroot.clone(), - sysroot_candidates(), + sysroot_candidates().to_vec(), sopts.unstable_opts.translate_lang.clone(), sopts.unstable_opts.translate_additional_ftl.as_deref(), sopts.unstable_opts.translate_directionality_markers, @@ -273,100 +274,6 @@ fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> { }) } -fn sysroot_candidates() -> Vec<PathBuf> { - let target = session::config::host_triple(); - let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()]; - let path = current_dll_path().and_then(|s| s.canonicalize().ok()); - if let Some(dll) = path { - // use `parent` twice to chop off the file name and then also the - // directory containing the dll which should be either `lib` or `bin`. - if let Some(path) = dll.parent().and_then(|p| p.parent()) { - // The original `path` pointed at the `rustc_driver` crate's dll. - // Now that dll should only be in one of two locations. The first is - // in the compiler's libdir, for example `$sysroot/lib/*.dll`. The - // other is the target's libdir, for example - // `$sysroot/lib/rustlib/$target/lib/*.dll`. - // - // We don't know which, so let's assume that if our `path` above - // ends in `$target` we *could* be in the target libdir, and always - // assume that we may be in the main libdir. - sysroot_candidates.push(path.to_owned()); - - if path.ends_with(target) { - sysroot_candidates.extend( - path.parent() // chop off `$target` - .and_then(|p| p.parent()) // chop off `rustlib` - .and_then(|p| p.parent()) // chop off `lib` - .map(|s| s.to_owned()), - ); - } - } - } - - return sysroot_candidates; - - #[cfg(unix)] - fn current_dll_path() -> Option<PathBuf> { - use std::ffi::{CStr, OsStr}; - use std::os::unix::prelude::*; - - unsafe { - let addr = current_dll_path as usize as *mut _; - let mut info = mem::zeroed(); - if libc::dladdr(addr, &mut info) == 0 { - info!("dladdr failed"); - return None; - } - if info.dli_fname.is_null() { - info!("dladdr returned null pointer"); - return None; - } - let bytes = CStr::from_ptr(info.dli_fname).to_bytes(); - let os = OsStr::from_bytes(bytes); - Some(PathBuf::from(os)) - } - } - - #[cfg(windows)] - fn current_dll_path() -> Option<PathBuf> { - use std::ffi::OsString; - use std::io; - use std::os::windows::prelude::*; - use std::ptr; - - use winapi::um::libloaderapi::{ - GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - }; - - unsafe { - let mut module = ptr::null_mut(); - let r = GetModuleHandleExW( - GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - current_dll_path as usize as *mut _, - &mut module, - ); - if r == 0 { - info!("GetModuleHandleExW failed: {}", io::Error::last_os_error()); - return None; - } - let mut space = Vec::with_capacity(1024); - let r = GetModuleFileNameW(module, space.as_mut_ptr(), space.capacity() as u32); - if r == 0 { - info!("GetModuleFileNameW failed: {}", io::Error::last_os_error()); - return None; - } - let r = r as usize; - if r >= space.capacity() { - info!("our buffer was too small? {}", io::Error::last_os_error()); - return None; - } - space.set_len(r); - let os = OsString::from_wide(&space); - Some(PathBuf::from(os)) - } - } -} - fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> MakeBackendFn { // For now we only allow this function to be called once as it'll dlopen a // few things, which seems to work best if we only do that once. In @@ -420,7 +327,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M let mut file: Option<PathBuf> = None; let expected_names = &[ - format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE")), + format!("rustc_codegen_{}-{}", backend_name, env!("CFG_RELEASE")), format!("rustc_codegen_{}", backend_name), ]; for entry in d.filter_map(|e| e.ok()) { @@ -647,22 +554,12 @@ pub fn build_output_filenames( } } -/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" -pub fn version_str() -> Option<&'static str> { +/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" when invoked by an in-tree tool. +pub macro version_str() { option_env!("CFG_VERSION") } -/// Returns a version string such as "0.12.0-dev". -pub fn release_str() -> Option<&'static str> { - option_env!("CFG_RELEASE") -} - -/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built. -pub fn commit_hash_str() -> Option<&'static str> { - option_env!("CFG_VER_HASH") -} - -/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string. -pub fn commit_date_str() -> Option<&'static str> { - option_env!("CFG_VER_DATE") +/// Returns the version string for `rustc` itself (which may be different from a tool version). +pub fn rustc_version_str() -> Option<&'static str> { + version_str!() } diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 51515976e4e..d4140cb295f 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -88,7 +88,9 @@ pub enum TokenKind { /// tokens. UnknownPrefix, - /// Examples: `"12_u8"`, `"1.0e-40"`, `b"123`. + /// Examples: `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid + /// suffix, but may be present here on string and float literals. Users of + /// this type will need to check for and reject that case. /// /// See [LiteralKind] for more details. Literal { kind: LiteralKind, suffix_start: u32 }, @@ -203,13 +205,13 @@ pub enum RawStrError { #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum Base { /// Literal starts with "0b". - Binary, + Binary = 2, /// Literal starts with "0o". - Octal, - /// Literal starts with "0x". - Hexadecimal, + Octal = 8, /// Literal doesn't contain a prefix. - Decimal, + Decimal = 10, + /// Literal starts with "0x". + Hexadecimal = 16, } /// `rustc` allows files to have a shebang, e.g. "#!/usr/bin/rustrun", @@ -840,12 +842,13 @@ impl Cursor<'_> { self.eat_decimal_digits() } - // Eats the suffix of the literal, e.g. "_u8". + // Eats the suffix of the literal, e.g. "u8". fn eat_literal_suffix(&mut self) { self.eat_identifier(); } - // Eats the identifier. + // Eats the identifier. Note: succeeds on `_`, which isn't a valid + // identifer. fn eat_identifier(&mut self) { if !is_id_start(self.first()) { return; diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 8f64b5f5158..e405013dcab 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -52,10 +52,8 @@ pub enum EscapeError { /// Unicode escape code in byte literal. UnicodeEscapeInByte, - /// Non-ascii character in byte literal. + /// Non-ascii character in byte literal, byte string literal, or raw byte string literal. NonAsciiCharInByte, - /// Non-ascii character in byte string literal. - NonAsciiCharInByteString, /// After a line ending with '\', the next line contains whitespace /// characters that are not skipped. @@ -78,54 +76,33 @@ impl EscapeError { /// Takes a contents of a literal (without quotes) and produces a /// sequence of escaped characters or errors. /// Values are returned through invoking of the provided callback. -pub fn unescape_literal<F>(literal_text: &str, mode: Mode, callback: &mut F) +pub fn unescape_literal<F>(src: &str, mode: Mode, callback: &mut F) where F: FnMut(Range<usize>, Result<char, EscapeError>), { match mode { Mode::Char | Mode::Byte => { - let mut chars = literal_text.chars(); - let result = unescape_char_or_byte(&mut chars, mode); - // The Chars iterator moved forward. - callback(0..(literal_text.len() - chars.as_str().len()), result); + let mut chars = src.chars(); + let res = unescape_char_or_byte(&mut chars, mode == Mode::Byte); + callback(0..(src.len() - chars.as_str().len()), res); } - Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(literal_text, mode, callback), - // NOTE: Raw strings do not perform any explicit character escaping, here we - // only translate CRLF to LF and produce errors on bare CR. + Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(src, mode == Mode::ByteStr, callback), Mode::RawStr | Mode::RawByteStr => { - unescape_raw_str_or_raw_byte_str(literal_text, mode, callback) + unescape_raw_str_or_raw_byte_str(src, mode == Mode::RawByteStr, callback) } } } -/// Takes a contents of a byte, byte string or raw byte string (without quotes) -/// and produces a sequence of bytes or errors. -/// Values are returned through invoking of the provided callback. -pub fn unescape_byte_literal<F>(literal_text: &str, mode: Mode, callback: &mut F) -where - F: FnMut(Range<usize>, Result<u8, EscapeError>), -{ - debug_assert!(mode.is_bytes()); - unescape_literal(literal_text, mode, &mut |range, result| { - callback(range, result.map(byte_from_char)); - }) -} - /// Takes a contents of a char literal (without quotes), and returns an -/// unescaped char or an error -pub fn unescape_char(literal_text: &str) -> Result<char, (usize, EscapeError)> { - let mut chars = literal_text.chars(); - unescape_char_or_byte(&mut chars, Mode::Char) - .map_err(|err| (literal_text.len() - chars.as_str().len(), err)) +/// unescaped char or an error. +pub fn unescape_char(src: &str) -> Result<char, EscapeError> { + unescape_char_or_byte(&mut src.chars(), false) } /// Takes a contents of a byte literal (without quotes), and returns an /// unescaped byte or an error. -pub fn unescape_byte(literal_text: &str) -> Result<u8, (usize, EscapeError)> { - let mut chars = literal_text.chars(); - unescape_char_or_byte(&mut chars, Mode::Byte) - .map(byte_from_char) - .map_err(|err| (literal_text.len() - chars.as_str().len(), err)) +pub fn unescape_byte(src: &str) -> Result<u8, EscapeError> { + unescape_char_or_byte(&mut src.chars(), true).map(byte_from_char) } /// What kind of literal do we parse. @@ -147,7 +124,7 @@ impl Mode { } } - pub fn is_bytes(self) -> bool { + pub fn is_byte(self) -> bool { match self { Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true, Mode::Char | Mode::Str | Mode::RawStr => false, @@ -155,12 +132,9 @@ impl Mode { } } -fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> { +fn scan_escape(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError> { // Previous character was '\\', unescape what follows. - - let second_char = chars.next().ok_or(EscapeError::LoneSlash)?; - - let res = match second_char { + let res = match chars.next().ok_or(EscapeError::LoneSlash)? { '"' => '"', 'n' => '\n', 'r' => '\r', @@ -181,7 +155,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> { let value = hi * 16 + lo; // For a non-byte literal verify that it is within ASCII range. - if !mode.is_bytes() && !is_ascii(value) { + if !is_byte && !is_ascii(value) { return Err(EscapeError::OutOfRangeHexEscape); } let value = value as u8; @@ -217,7 +191,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> { // Incorrect syntax has higher priority for error reporting // than unallowed value for a literal. - if mode.is_bytes() { + if is_byte { return Err(EscapeError::UnicodeEscapeInByte); } @@ -249,23 +223,22 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> { } #[inline] -fn ascii_check(first_char: char, mode: Mode) -> Result<char, EscapeError> { - if mode.is_bytes() && !first_char.is_ascii() { +fn ascii_check(c: char, is_byte: bool) -> Result<char, EscapeError> { + if is_byte && !c.is_ascii() { // Byte literal can't be a non-ascii character. Err(EscapeError::NonAsciiCharInByte) } else { - Ok(first_char) + Ok(c) } } -fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> { - debug_assert!(mode == Mode::Char || mode == Mode::Byte); - let first_char = chars.next().ok_or(EscapeError::ZeroChars)?; - let res = match first_char { - '\\' => scan_escape(chars, mode), +fn unescape_char_or_byte(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError> { + let c = chars.next().ok_or(EscapeError::ZeroChars)?; + let res = match c { + '\\' => scan_escape(chars, is_byte), '\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(first_char, mode), + _ => ascii_check(c, is_byte), }?; if chars.next().is_some() { return Err(EscapeError::MoreThanOneChar); @@ -275,20 +248,20 @@ fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, Esca /// Takes a contents of a string literal (without quotes) and produces a /// sequence of escaped characters or errors. -fn unescape_str_or_byte_str<F>(src: &str, mode: Mode, callback: &mut F) +fn unescape_str_or_byte_str<F>(src: &str, is_byte: bool, callback: &mut F) where F: FnMut(Range<usize>, Result<char, EscapeError>), { - debug_assert!(mode == Mode::Str || mode == Mode::ByteStr); - let initial_len = src.len(); let mut chars = src.chars(); - while let Some(first_char) = chars.next() { - let start = initial_len - chars.as_str().len() - first_char.len_utf8(); - let unescaped_char = match first_char { + // The `start` and `end` computation here is complicated because + // `skip_ascii_whitespace` makes us to skip over chars without counting + // them in the range computation. + while let Some(c) = chars.next() { + let start = src.len() - chars.as_str().len() - c.len_utf8(); + let res = match c { '\\' => { - let second_char = chars.clone().next(); - match second_char { + match chars.clone().next() { Some('\n') => { // Rust language specification requires us to skip whitespaces // if unescaped '\' character is followed by '\n'. @@ -297,17 +270,17 @@ where skip_ascii_whitespace(&mut chars, start, callback); continue; } - _ => scan_escape(&mut chars, mode), + _ => scan_escape(&mut chars, is_byte), } } '\n' => Ok('\n'), '\t' => Ok('\t'), '"' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(first_char, mode), + _ => ascii_check(c, is_byte), }; - let end = initial_len - chars.as_str().len(); - callback(start..end, unescaped_char); + let end = src.len() - chars.as_str().len(); + callback(start..end, res); } fn skip_ascii_whitespace<F>(chars: &mut Chars<'_>, start: usize, callback: &mut F) @@ -340,30 +313,29 @@ where /// Takes a contents of a string literal (without quotes) and produces a /// sequence of characters or errors. /// NOTE: Raw strings do not perform any explicit character escaping, here we -/// only translate CRLF to LF and produce errors on bare CR. -fn unescape_raw_str_or_raw_byte_str<F>(literal_text: &str, mode: Mode, callback: &mut F) +/// only produce errors on bare CR. +fn unescape_raw_str_or_raw_byte_str<F>(src: &str, is_byte: bool, callback: &mut F) where F: FnMut(Range<usize>, Result<char, EscapeError>), { - debug_assert!(mode == Mode::RawStr || mode == Mode::RawByteStr); - let initial_len = literal_text.len(); - - let mut chars = literal_text.chars(); - while let Some(curr) = chars.next() { - let start = initial_len - chars.as_str().len() - curr.len_utf8(); + let mut chars = src.chars(); - let result = match curr { + // The `start` and `end` computation here matches the one in + // `unescape_str_or_byte_str` for consistency, even though this function + // doesn't have to worry about skipping any chars. + while let Some(c) = chars.next() { + let start = src.len() - chars.as_str().len() - c.len_utf8(); + let res = match c { '\r' => Err(EscapeError::BareCarriageReturnInRawString), - c if mode.is_bytes() && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString), - c => Ok(c), + _ => ascii_check(c, is_byte), }; - let end = initial_len - chars.as_str().len(); - - callback(start..end, result); + let end = src.len() - chars.as_str().len(); + callback(start..end, res); } } -fn byte_from_char(c: char) -> u8 { +#[inline] +pub fn byte_from_char(c: char) -> u8 { let res = c as u32; debug_assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr"); res as u8 diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs index fa61554afde..c7ca8fd16ae 100644 --- a/compiler/rustc_lexer/src/unescape/tests.rs +++ b/compiler/rustc_lexer/src/unescape/tests.rs @@ -3,8 +3,7 @@ use super::*; #[test] fn test_unescape_char_bad() { fn check(literal_text: &str, expected_error: EscapeError) { - let actual_result = unescape_char(literal_text).map_err(|(_offset, err)| err); - assert_eq!(actual_result, Err(expected_error)); + assert_eq!(unescape_char(literal_text), Err(expected_error)); } check("", EscapeError::ZeroChars); @@ -68,8 +67,7 @@ fn test_unescape_char_bad() { #[test] fn test_unescape_char_good() { fn check(literal_text: &str, expected_char: char) { - let actual_result = unescape_char(literal_text); - assert_eq!(actual_result, Ok(expected_char)); + assert_eq!(unescape_char(literal_text), Ok(expected_char)); } check("a", 'a'); @@ -149,8 +147,7 @@ fn test_unescape_str_good() { #[test] fn test_unescape_byte_bad() { fn check(literal_text: &str, expected_error: EscapeError) { - let actual_result = unescape_byte(literal_text).map_err(|(_offset, err)| err); - assert_eq!(actual_result, Err(expected_error)); + assert_eq!(unescape_byte(literal_text), Err(expected_error)); } check("", EscapeError::ZeroChars); @@ -219,8 +216,7 @@ fn test_unescape_byte_bad() { #[test] fn test_unescape_byte_good() { fn check(literal_text: &str, expected_byte: u8) { - let actual_result = unescape_byte(literal_text); - assert_eq!(actual_result, Ok(expected_byte)); + assert_eq!(unescape_byte(literal_text), Ok(expected_byte)); } check("a", b'a'); @@ -246,10 +242,10 @@ fn test_unescape_byte_good() { fn test_unescape_byte_str_good() { fn check(literal_text: &str, expected: &[u8]) { let mut buf = Ok(Vec::with_capacity(literal_text.len())); - unescape_byte_literal(literal_text, Mode::ByteStr, &mut |range, c| { + unescape_literal(literal_text, Mode::ByteStr, &mut |range, c| { if let Ok(b) = &mut buf { match c { - Ok(c) => b.push(c), + Ok(c) => b.push(byte_from_char(c)), Err(e) => buf = Err((range, e)), } } @@ -280,18 +276,13 @@ fn test_unescape_raw_str() { #[test] fn test_unescape_raw_byte_str() { - fn check(literal: &str, expected: &[(Range<usize>, Result<u8, EscapeError>)]) { + fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) { let mut unescaped = Vec::with_capacity(literal.len()); - unescape_byte_literal(literal, Mode::RawByteStr, &mut |range, res| { - unescaped.push((range, res)) - }); + unescape_literal(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res))); assert_eq!(unescaped, expected); } check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]); - check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByteString))]); - check( - "🦀a", - &[(0..4, Err(EscapeError::NonAsciiCharInByteString)), (4..5, Ok(byte_from_char('a')))], - ); + check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByte))]); + check("🦀a", &[(0..4, Err(EscapeError::NonAsciiCharInByte)), (4..5, Ok('a'))]); } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index cec0003ffea..28f6ac61c5b 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -579,6 +579,7 @@ pub trait LintContext: Sized { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] fn lookup_with_diagnostics( &self, lint: &'static Lint, @@ -882,6 +883,7 @@ pub trait LintContext: Sized { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] fn lookup<S: Into<MultiSpan>>( &self, lint: &'static Lint, @@ -908,6 +910,7 @@ pub trait LintContext: Sized { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] fn struct_span_lint<S: Into<MultiSpan>>( &self, lint: &'static Lint, @@ -933,6 +936,7 @@ pub trait LintContext: Sized { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] fn lint( &self, lint: &'static Lint, diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index ed8d424e0c6..4187850153c 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -3,11 +3,9 @@ use crate::{LateContext, LateLintPass, LintContext}; use hir::{Expr, Pat}; use rustc_errors::{Applicability, DelayDm}; use rustc_hir as hir; -use rustc_infer::traits::TraitEngine; use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause}; use rustc_middle::ty::{self, List}; use rustc_span::{sym, Span}; -use rustc_trait_selection::traits::TraitEngineExt; declare_lint! { /// The `for_loops_over_fallibles` lint checks for `for` loops over `Option` or `Result` values. @@ -160,24 +158,19 @@ fn suggest_question_mark<'tcx>( let ty = substs.type_at(0); let infcx = cx.tcx.infer_ctxt().build(); - let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); - let cause = ObligationCause::new( span, body_id.hir_id, rustc_infer::traits::ObligationCauseCode::MiscObligation, ); - fulfill_cx.register_bound( + let errors = rustc_trait_selection::traits::fully_solve_bound( &infcx, + cause, ty::ParamEnv::empty(), // Erase any region vids from the type, which may not be resolved infcx.tcx.erase_regions(ty), into_iterator_did, - cause, ); - // Select all, including ambiguous predicates - let errors = fulfill_cx.select_all_or_error(&infcx); - errors.is_empty() } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index db0a3419e6a..efae2669006 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -163,7 +163,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe // Otherwise, we need to visit the attributes in source code order, so we fetch HIR and do // a standard visit. // FIXME(#102522) Just iterate on attrs once that iteration order matches HIR's. - _ => match tcx.hir().expect_owner(owner) { + _ => match tcx.hir().owner(owner) { hir::OwnerNode::Item(item) => levels.visit_item(item), hir::OwnerNode::ForeignItem(item) => levels.visit_foreign_item(item), hir::OwnerNode::TraitItem(item) => levels.visit_trait_item(item), @@ -1073,6 +1073,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] pub(crate) fn struct_lint( &self, lint: &'static Lint, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 5288fc542d7..ebb7de70e05 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -36,6 +36,7 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(rustc_attrs)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 46706e49844..ff0fb9bae92 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_infer::traits::util::elaborate_predicates_with_span; use rustc_middle::ty::adjustment; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, DefIdTree, Ty}; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; @@ -87,17 +87,33 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]); impl<'tcx> LateLintPass<'tcx> for UnusedResults { fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { - let expr = match s.kind { - hir::StmtKind::Semi(ref expr) => &**expr, - _ => return, - }; + let hir::StmtKind::Semi(expr) = s.kind else { return; }; if let hir::ExprKind::Ret(..) = expr.kind { return; } + if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind + && let ty = cx.typeck_results().expr_ty(&await_expr) + && let ty::Opaque(future_def_id, _) = ty.kind() + && cx.tcx.ty_is_opaque_future(ty) + // FIXME: This also includes non-async fns that return `impl Future`. + && let async_fn_def_id = cx.tcx.parent(*future_def_id) + && check_must_use_def( + cx, + async_fn_def_id, + expr.span, + "output of future returned by ", + "", + ) + { + // We have a bare `foo().await;` on an opaque type from an async function that was + // annotated with `#[must_use]`. + return; + } + let ty = cx.typeck_results().expr_ty(&expr); - let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", 1); + let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, expr.span, "", "", 1); let mut fn_warned = false; let mut op_warned = false; @@ -119,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { _ => None, }; if let Some(def_id) = maybe_def_id { - fn_warned = check_must_use_def(cx, def_id, s.span, "return value of ", ""); + fn_warned = check_must_use_def(cx, def_id, expr.span, "return value of ", ""); } else if type_permits_lack_of_use { // We don't warn about unused unit or uninhabited types. // (See https://github.com/rust-lang/rust/issues/43806 for details.) @@ -565,10 +581,24 @@ trait UnusedDelimLint { lint.set_arg("delim", Self::DELIM_STR); lint.set_arg("item", msg); if let Some((lo, hi)) = spans { - let replacement = vec![ - (lo, if keep_space.0 { " ".into() } else { "".into() }), - (hi, if keep_space.1 { " ".into() } else { "".into() }), - ]; + let sm = cx.sess().source_map(); + let lo_replace = + if keep_space.0 && + let Ok(snip) = sm.span_to_prev_source(lo) && !snip.ends_with(" ") { + " ".to_string() + } else { + "".to_string() + }; + + let hi_replace = + if keep_space.1 && + let Ok(snip) = sm.span_to_next_source(hi) && !snip.starts_with(" ") { + " ".to_string() + } else { + "".to_string() + }; + + let replacement = vec![(lo, lo_replace), (hi, hi_replace)]; lint.multipart_suggestion( fluent::suggestion, replacement, @@ -765,6 +795,7 @@ impl UnusedParens { value: &ast::Pat, avoid_or: bool, avoid_mut: bool, + keep_space: (bool, bool), ) { use ast::{BindingAnnotation, PatKind}; @@ -789,7 +820,7 @@ impl UnusedParens { } else { None }; - self.emit_unused_delims(cx, value.span, spans, "pattern", (false, false)); + self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space); } } } @@ -798,7 +829,7 @@ impl EarlyLintPass for UnusedParens { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { match e.kind { ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => { - self.check_unused_parens_pat(cx, pat, false, false); + self.check_unused_parens_pat(cx, pat, false, false, (true, true)); } // We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already // handle a hard error for them during AST lowering in `lower_expr_mut`, but we still @@ -842,6 +873,7 @@ impl EarlyLintPass for UnusedParens { fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) { use ast::{Mutability, PatKind::*}; + let keep_space = (false, false); match &p.kind { // Do not lint on `(..)` as that will result in the other arms being useless. Paren(_) @@ -849,33 +881,33 @@ impl EarlyLintPass for UnusedParens { | Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {}, // These are list-like patterns; parens can always be removed. TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { - self.check_unused_parens_pat(cx, p, false, false); + self.check_unused_parens_pat(cx, p, false, false, keep_space); }, Struct(_, _, fps, _) => for f in fps { - self.check_unused_parens_pat(cx, &f.pat, false, false); + self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space); }, // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106. - Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false), + Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space), // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342. // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106. - Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not), + Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space), } } fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { if let StmtKind::Local(ref local) = s.kind { - self.check_unused_parens_pat(cx, &local.pat, true, false); + self.check_unused_parens_pat(cx, &local.pat, true, false, (false, false)); } <Self as UnusedDelimLint>::check_stmt(self, cx, s) } fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) { - self.check_unused_parens_pat(cx, ¶m.pat, true, false); + self.check_unused_parens_pat(cx, ¶m.pat, true, false, (false, false)); } fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { - self.check_unused_parens_pat(cx, &arm.pat, false, false); + self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false)); } fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) { diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 015c1c52bef..727cfc4416e 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -76,7 +76,6 @@ enum LLVMRustAttribute { OptimizeNone = 24, ReturnsTwice = 25, ReadNone = 26, - InaccessibleMemOnly = 27, SanitizeHWAddress = 28, WillReturn = 29, StackProtectReq = 30, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 6f36281af23..0d9b5a57b69 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -8,6 +8,9 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsARM.h" #include "llvm/IR/Mangler.h" +#if LLVM_VERSION_GE(16, 0) +#include "llvm/IR/ModRef.h" +#endif #include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ObjectFile.h" @@ -213,8 +216,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::ReturnsTwice; case ReadNone: return Attribute::ReadNone; - case InaccessibleMemOnly: - return Attribute::InaccessibleMemOnly; case SanitizeHWAddress: return Attribute::SanitizeHWAddress; case WillReturn: @@ -379,6 +380,43 @@ extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, uint64 #endif } +// Simplified representation of `MemoryEffects` across the FFI boundary. +// +// Each variant corresponds to one of the static factory methods on `MemoryEffects`. +enum class LLVMRustMemoryEffects { + None, + ReadOnly, + InaccessibleMemOnly, +}; + +extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C, + LLVMRustMemoryEffects Effects) { +#if LLVM_VERSION_GE(16, 0) + switch (Effects) { + case LLVMRustMemoryEffects::None: + return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::none())); + case LLVMRustMemoryEffects::ReadOnly: + return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::readOnly())); + case LLVMRustMemoryEffects::InaccessibleMemOnly: + return wrap(Attribute::getWithMemoryEffects(*unwrap(C), + MemoryEffects::inaccessibleMemOnly())); + default: + report_fatal_error("bad MemoryEffects."); + } +#else + switch (Effects) { + case LLVMRustMemoryEffects::None: + return wrap(Attribute::get(*unwrap(C), Attribute::ReadNone)); + case LLVMRustMemoryEffects::ReadOnly: + return wrap(Attribute::get(*unwrap(C), Attribute::ReadOnly)); + case LLVMRustMemoryEffects::InaccessibleMemOnly: + return wrap(Attribute::get(*unwrap(C), Attribute::InaccessibleMemOnly)); + default: + report_fatal_error("bad MemoryEffects."); + } +#endif +} + // Enable a fast-math flag // // https://llvm.org/docs/LangRef.html#fast-math-flags diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs index 0b1ededa775..4612f54e4b1 100644 --- a/compiler/rustc_macros/src/diagnostics/error.rs +++ b/compiler/rustc_macros/src/diagnostics/error.rs @@ -84,7 +84,7 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { } } -/// Emit a error diagnostic for an invalid attribute (optionally performing additional decoration +/// Emit an error diagnostic for an invalid attribute (optionally performing additional decoration /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// /// For methods that return a `Result<_, DiagnosticDeriveError>`: @@ -126,7 +126,7 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag } } -/// Emit a error diagnostic for an invalid nested attribute (optionally performing additional +/// Emit an error diagnostic for an invalid nested attribute (optionally performing additional /// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// /// For methods that return a `Result<_, DiagnosticDeriveError>`: diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index de916ea8c49..8e7d0cf2ab1 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -32,7 +32,7 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.8" +thin-vec = "0.2.9" tracing = "0.1" [features] diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 83a4d16d7a9..14f50ae87de 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -353,6 +353,10 @@ impl<'hir> Map<'hir> { node.node.generics() } + pub fn owner(self, id: OwnerId) -> OwnerNode<'hir> { + self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node + } + pub fn item(self, id: ItemId) -> &'hir Item<'hir> { self.tcx.hir_owner(id.owner_id).unwrap().node.expect_item() } @@ -822,8 +826,11 @@ impl<'hir> Map<'hir> { ) } - pub fn expect_owner(self, id: OwnerId) -> OwnerNode<'hir> { - self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node + pub fn expect_owner(self, def_id: LocalDefId) -> OwnerNode<'hir> { + self.tcx + .hir_owner(OwnerId { def_id }) + .unwrap_or_else(|| bug!("expected owner for {:?}", def_id)) + .node } pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index d3cf519b633..0331d764b38 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -336,15 +336,17 @@ impl<'tcx> CanonicalVarValues<'tcx> { tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into() } GenericArgKind::Lifetime(..) => { - let br = - ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(i), + kind: ty::BrAnon(i, None), + }; tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() } GenericArgKind::Const(ct) => tcx - .mk_const(ty::ConstS { - ty: ct.ty(), - kind: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)), - }) + .mk_const( + ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)), + ct.ty(), + ) .into(), }) .collect(), diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 79522bd0b2b..51df42f6d14 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -276,7 +276,7 @@ pub fn explain_lint_level_source( /// The innermost function for emitting lints. /// -/// If you are loocking to implement a lint, look for higher level functions, +/// If you are looking to implement a lint, look for higher level functions, /// for example: /// - [`TyCtxt::emit_spanned_lint`] /// - [`TyCtxt::struct_span_lint_hir`] diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index ffbd6d10da6..3a91522d362 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -1,12 +1,14 @@ //! A pass that checks to make sure private fields and methods aren't used //! outside their scopes. This pass will also generate a set of exported items //! which are available for use externally when compiled as a library. -use crate::ty::{DefIdTree, Visibility}; +use crate::ty::{DefIdTree, TyCtxt, Visibility}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_hir::def::DefKind; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_span::def_id::LocalDefId; +use std::hash::Hash; /// Represents the levels of effective visibility an item can have. /// @@ -74,9 +76,9 @@ impl EffectiveVisibility { } /// Holds a map of effective visibilities for reachable HIR nodes. -#[derive(Default, Clone, Debug)] -pub struct EffectiveVisibilities { - map: FxHashMap<LocalDefId, EffectiveVisibility>, +#[derive(Clone, Debug)] +pub struct EffectiveVisibilities<Id = LocalDefId> { + map: FxHashMap<Id, EffectiveVisibility>, } impl EffectiveVisibilities { @@ -111,12 +113,30 @@ impl EffectiveVisibilities { }) } - pub fn effective_vis(&self, id: LocalDefId) -> Option<&EffectiveVisibility> { - self.map.get(&id) - } - - pub fn iter(&self) -> impl Iterator<Item = (&LocalDefId, &EffectiveVisibility)> { - self.map.iter() + // FIXME: Share code with `fn update`. + pub fn update_eff_vis( + &mut self, + def_id: LocalDefId, + eff_vis: &EffectiveVisibility, + tree: impl DefIdTree, + ) { + use std::collections::hash_map::Entry; + match self.map.entry(def_id) { + Entry::Occupied(mut occupied) => { + let old_eff_vis = occupied.get_mut(); + for l in Level::all_levels() { + let vis_at_level = eff_vis.at_level(l); + let old_vis_at_level = old_eff_vis.at_level_mut(l); + if vis_at_level != old_vis_at_level + && vis_at_level.is_at_least(*old_vis_at_level, tree) + { + *old_vis_at_level = *vis_at_level + } + } + old_eff_vis + } + Entry::Vacant(vacant) => vacant.insert(*eff_vis), + }; } pub fn set_public_at_level( @@ -137,26 +157,82 @@ impl EffectiveVisibilities { self.map.insert(id, effective_vis); } + pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) { + if !cfg!(debug_assertions) { + return; + } + for (&def_id, ev) in &self.map { + // More direct visibility levels can never go farther than less direct ones, + // neither of effective visibilities can go farther than nominal visibility, + // and all effective visibilities are larger or equal than private visibility. + let private_vis = Visibility::Restricted(tcx.parent_module_from_def_id(def_id)); + let span = tcx.def_span(def_id.to_def_id()); + if !ev.direct.is_at_least(private_vis, tcx) { + span_bug!(span, "private {:?} > direct {:?}", private_vis, ev.direct); + } + if !ev.reexported.is_at_least(ev.direct, tcx) { + span_bug!(span, "direct {:?} > reexported {:?}", ev.direct, ev.reexported); + } + if !ev.reachable.is_at_least(ev.reexported, tcx) { + span_bug!(span, "reexported {:?} > reachable {:?}", ev.reexported, ev.reachable); + } + if !ev.reachable_through_impl_trait.is_at_least(ev.reachable, tcx) { + span_bug!( + span, + "reachable {:?} > reachable_through_impl_trait {:?}", + ev.reachable, + ev.reachable_through_impl_trait + ); + } + let nominal_vis = tcx.visibility(def_id); + let def_kind = tcx.opt_def_kind(def_id); + // FIXME: `rustc_privacy` is not yet updated for the new logic and can set + // effective visibilities that are larger than the nominal one. + if !nominal_vis.is_at_least(ev.reachable_through_impl_trait, tcx) && early { + span_bug!( + span, + "{:?}: reachable_through_impl_trait {:?} > nominal {:?}", + def_id, + ev.reachable_through_impl_trait, + nominal_vis + ); + } + // Fully private items are never put into the table, this is important for performance. + // FIXME: Fully private `mod` items are currently put into the table. + if ev.reachable_through_impl_trait == private_vis && def_kind != Some(DefKind::Mod) { + span_bug!(span, "fully private item in the table {:?}: {:?}", def_id, ev.direct); + } + } + } +} + +impl<Id: Eq + Hash> EffectiveVisibilities<Id> { + pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> { + self.map.iter() + } + + pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { + self.map.get(&id) + } + // `parent_id` is not necessarily a parent in source code tree, // it is the node from which the maximum effective visibility is inherited. pub fn update( &mut self, - id: LocalDefId, + id: Id, nominal_vis: Visibility, - default_vis: impl FnOnce() -> Visibility, - parent_id: LocalDefId, + default_vis: Visibility, + inherited_eff_vis: Option<EffectiveVisibility>, level: Level, tree: impl DefIdTree, ) -> bool { let mut changed = false; - let mut current_effective_vis = self.effective_vis(id).copied().unwrap_or_else(|| { - if id.is_top_level_module() { - EffectiveVisibility::from_vis(Visibility::Public) - } else { - EffectiveVisibility::from_vis(default_vis()) - } - }); - if let Some(inherited_effective_vis) = self.effective_vis(parent_id) { + let mut current_effective_vis = self + .map + .get(&id) + .copied() + .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis)); + if let Some(inherited_effective_vis) = inherited_eff_vis { let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.at_level(level); let mut calculated_effective_vis = inherited_effective_vis_at_prev_level; @@ -194,6 +270,12 @@ impl EffectiveVisibilities { } } +impl<Id> Default for EffectiveVisibilities<Id> { + fn default() -> Self { + EffectiveVisibilities { map: Default::default() } + } +} + impl<'a> HashStable<StableHashingContext<'a>> for EffectiveVisibilities { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let EffectiveVisibilities { ref map } = *self; diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 5e3dfcbcc49..32ec5855769 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -106,6 +106,7 @@ use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{HashMapExt, Lock}; use rustc_data_structures::tiny_list::TinyList; +use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -176,7 +177,7 @@ pub enum LitToConstError { /// This is used for graceful error handling (`delay_span_bug`) in /// type checking (`Const::from_anon_const`). TypeError, - Reported, + Reported(ErrorGuaranteed), } #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 068daaadbda..a4495d2934d 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -138,6 +138,48 @@ impl MirPhase { } } } + + /// Parses an `MirPhase` from a pair of strings. Panics if this isn't possible for any reason. + pub fn parse(dialect: String, phase: Option<String>) -> Self { + match &*dialect.to_ascii_lowercase() { + "built" => { + assert!(phase.is_none(), "Cannot specify a phase for `Built` MIR"); + MirPhase::Built + } + "analysis" => Self::Analysis(AnalysisPhase::parse(phase)), + "runtime" => Self::Runtime(RuntimePhase::parse(phase)), + _ => panic!("Unknown MIR dialect {}", dialect), + } + } +} + +impl AnalysisPhase { + pub fn parse(phase: Option<String>) -> Self { + let Some(phase) = phase else { + return Self::Initial; + }; + + match &*phase.to_ascii_lowercase() { + "initial" => Self::Initial, + "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup, + _ => panic!("Unknown analysis phase {}", phase), + } + } +} + +impl RuntimePhase { + pub fn parse(phase: Option<String>) -> Self { + let Some(phase) = phase else { + return Self::Initial; + }; + + match &*phase.to_ascii_lowercase() { + "initial" => Self::Initial, + "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup, + "optimized" => Self::Optimized, + _ => panic!("Unknown runtime phase {}", phase), + } + } } impl Display for MirPhase { @@ -293,6 +335,13 @@ pub struct Body<'tcx> { /// potentially allow things like `[u8; std::mem::size_of::<T>() * 0]` due to this. pub is_polymorphic: bool, + /// The phase at which this MIR should be "injected" into the compilation process. + /// + /// Everything that comes before this `MirPhase` should be skipped. + /// + /// This is only `Some` if the function that this body comes from was annotated with `rustc_custom_mir`. + pub injection_phase: Option<MirPhase>, + pub tainted_by_errors: Option<ErrorGuaranteed>, } @@ -339,6 +388,7 @@ impl<'tcx> Body<'tcx> { span, required_consts: Vec::new(), is_polymorphic: false, + injection_phase: None, tainted_by_errors, }; body.is_polymorphic = body.has_non_region_param(); @@ -366,6 +416,7 @@ impl<'tcx> Body<'tcx> { required_consts: Vec::new(), var_debug_info: Vec::new(), is_polymorphic: false, + injection_phase: None, tainted_by_errors: None, }; body.is_polymorphic = body.has_non_region_param(); @@ -508,6 +559,14 @@ impl<'tcx> Body<'tcx> { pub fn generator_kind(&self) -> Option<GeneratorKind> { self.generator.as_ref().map(|generator| generator.generator_kind) } + + #[inline] + pub fn should_skip(&self) -> bool { + let Some(injection_phase) = self.injection_phase else { + return false; + }; + injection_phase > self.phase + } } #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)] @@ -1898,6 +1957,7 @@ impl BorrowKind { } } + // FIXME: won't be used after diagnostic migration pub fn describe_mutability(&self) -> &str { match *self { BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => "immutable", @@ -2192,7 +2252,9 @@ impl<'tcx> ConstantKind<'tcx> { match tcx.const_eval_resolve(param_env, uneval, None) { Ok(val) => Self::Val(val, ty), Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self, - Err(_) => Self::Ty(tcx.const_error(ty)), + Err(ErrorHandled::Reported(guar)) => { + Self::Ty(tcx.const_error_with_guaranteed(ty, guar)) + } } } } @@ -2414,10 +2476,8 @@ impl<'tcx> ConstantKind<'tcx> { let generics = tcx.generics_of(item_def_id.to_def_id()); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.hir().name(hir_id); - let ty_const = tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Param(ty::ParamConst::new(index, name)), - ty, - }); + let ty_const = + tcx.mk_const(ty::ConstKind::Param(ty::ParamConst::new(index, name)), ty); debug!(?ty_const); return Self::Ty(ty_const); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 33acaed435b..1564cf414bd 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -271,6 +271,10 @@ rustc_queries! { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } + /// Look up all native libraries this crate depends on. + /// These are assembled from the following places: + /// - `extern` blocks (depending on their `link` attributes) + /// - the `libs` (`-l`) option query native_libraries(_: CrateNum) -> Vec<NativeLib> { arena_cache desc { "looking up the native libraries of a linked crate" } @@ -1539,6 +1543,7 @@ rustc_queries! { desc { "available upstream drop-glue for `{:?}`", substs } } + /// Returns a list of all `extern` blocks of a crate. query foreign_modules(_: CrateNum) -> FxHashMap<DefId, ForeignModule> { arena_cache desc { "looking up the foreign modules of a linked crate" } @@ -1550,9 +1555,12 @@ rustc_queries! { query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> { desc { "looking up the entry function of a crate" } } + + /// Finds the `rustc_proc_macro_decls` item of a crate. query proc_macro_decls_static(_: ()) -> Option<LocalDefId> { - desc { "looking up the derive registrar for a crate" } + desc { "looking up the proc macro declarations for a crate" } } + // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. // Changing the name should cause a compiler error, but in case that changes, be aware. query crate_hash(_: CrateNum) -> Svh { @@ -1560,17 +1568,24 @@ rustc_queries! { desc { "looking up the hash a crate" } separate_provide_extern } + + /// Gets the hash for the host proc macro. Used to support -Z dual-proc-macro. query crate_host_hash(_: CrateNum) -> Option<Svh> { eval_always desc { "looking up the hash of a host version of a crate" } separate_provide_extern } + + /// Gets the extra data to put in each output filename for a crate. + /// For example, compiling the `foo` crate with `extra-filename=-a` creates a `libfoo-b.rlib` file. query extra_filename(_: CrateNum) -> String { arena_cache eval_always desc { "looking up the extra filename for a crate" } separate_provide_extern } + + /// Gets the paths where the crate came from in the file system. query crate_extern_paths(_: CrateNum) -> Vec<PathBuf> { arena_cache eval_always @@ -1594,23 +1609,15 @@ rustc_queries! { separate_provide_extern } + /// Get the corresponding native library from the `native_libraries` query query native_library(def_id: DefId) -> Option<&'tcx NativeLib> { desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) } } - /// Does lifetime resolution, but does not descend into trait items. This - /// should only be used for resolving lifetimes of on trait definitions, - /// and is used to avoid cycles. Importantly, `resolve_lifetimes` still visits - /// the same lifetimes and is responsible for diagnostics. - /// See `rustc_resolve::late::lifetimes for details. - query resolve_lifetimes_trait_definition(_: LocalDefId) -> ResolveLifetimes { - arena_cache - desc { "resolving lifetimes for a trait definition" } - } /// Does lifetime resolution on items. Importantly, we can't resolve /// lifetimes directly on things like trait methods, because of trait params. /// See `rustc_resolve::late::lifetimes for details. - query resolve_lifetimes(_: LocalDefId) -> ResolveLifetimes { + query resolve_lifetimes(_: hir::OwnerId) -> ResolveLifetimes { arena_cache desc { "resolving lifetimes" } } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index e73d44bbb36..05382bd887c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -203,13 +203,20 @@ pub struct UnifyReceiverContext<'tcx> { pub substs: SubstsRef<'tcx>, } -#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, Default)] +#[derive(Clone, PartialEq, Eq, Hash, Lift, Default)] pub struct InternedObligationCauseCode<'tcx> { /// `None` for `ObligationCauseCode::MiscObligation` (a common case, occurs ~60% of /// the time). `Some` otherwise. code: Option<Lrc<ObligationCauseCode<'tcx>>>, } +impl<'tcx> std::fmt::Debug for InternedObligationCauseCode<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let cause: &ObligationCauseCode<'_> = self; + cause.fmt(f) + } +} + impl<'tcx> ObligationCauseCode<'tcx> { #[inline(always)] fn into(self) -> InternedObligationCauseCode<'tcx> { @@ -431,6 +438,8 @@ pub enum ObligationCauseCode<'tcx> { }, AscribeUserTypeProvePredicate(Span), + + RustCall, } /// The 'location' at which we try to perform HIR-based wf checking. @@ -567,9 +576,6 @@ pub enum SelectionError<'tcx> { /// Signaling that an error has already been emitted, to avoid /// multiple errors being shown. ErrorReporting, - /// Multiple applicable `impl`s where found. The `DefId`s correspond to - /// all the `impl`s' Items. - Ambiguous(Vec<DefId>), } /// When performing resolution, it is typically the case that there diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index f1c21588261..cccedc9ec6e 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -262,7 +262,7 @@ pub fn ancestors<'tcx>( if let Some(reported) = specialization_graph.has_errored { Err(reported) - } else if let Some(reported) = tcx.type_of(start_from_impl).error_reported() { + } else if let Err(reported) = tcx.type_of(start_from_impl).error_reported() { Err(reported) } else { Ok(Ancestors { diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 1aa4df77800..e5bcd5fb27a 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -1,7 +1,7 @@ //! A subset of a mir body used for const evaluatability checking. use crate::mir; use crate::ty::visit::TypeVisitable; -use crate::ty::{self, DelaySpanBugEmitted, EarlyBinder, SubstsRef, Ty, TyCtxt}; +use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use std::cmp; @@ -43,7 +43,7 @@ impl<'tcx> AbstractConst<'tcx> { ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> { match ct.kind() { ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv), - ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported), + ty::ConstKind::Error(reported) => Err(reported), _ => Ok(None), } } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 14ec88b7e0d..7263e8306cf 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -310,7 +310,8 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> { fn decode(decoder: &mut D) -> Self { - decoder.interner().mk_const(Decodable::decode(decoder)) + let consts: ty::ConstS<'tcx> = Decodable::decode(decoder); + decoder.interner().mk_const(consts.kind, consts.ty) } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index f998e608344..e2e2761501b 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -2,7 +2,6 @@ use crate::mir::interpret::LitToConstInput; use crate::mir::ConstantKind; use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_data_structures::intern::Interned; -use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; @@ -77,13 +76,13 @@ impl<'tcx> Const<'tcx> { match Self::try_eval_lit_or_param(tcx, ty, expr) { Some(v) => v, - None => tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { + None => tcx.mk_const( + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), }), ty, - }), + ), } } @@ -138,10 +137,7 @@ impl<'tcx> Const<'tcx> { let generics = tcx.generics_of(item_def_id.to_def_id()); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.hir().name(hir_id); - Some(tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Param(ty::ParamConst::new(index, name)), - ty, - })) + Some(tcx.mk_const(ty::ConstKind::Param(ty::ParamConst::new(index, name)), ty)) } _ => None, } @@ -150,7 +146,7 @@ impl<'tcx> Const<'tcx> { /// Interns the given value as a constant. #[inline] pub fn from_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Self { - tcx.mk_const(ConstS { kind: ConstKind::Value(val), ty }) + tcx.mk_const(ConstKind::Value(val), ty) } /// Panics if self.kind != ty::ConstKind::Value @@ -228,7 +224,7 @@ impl<'tcx> Const<'tcx> { if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) { match val { Ok(val) => Const::from_value(tcx, val, self.ty()), - Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()), + Err(guar) => tcx.const_error_with_guaranteed(self.ty(), guar), } } else { // Either the constant isn't evaluatable or ValTree creation failed. @@ -243,7 +239,7 @@ impl<'tcx> Const<'tcx> { if let Some(val) = self.kind().try_eval_for_mir(tcx, param_env) { match val { Ok(const_val) => ConstantKind::from_value(const_val, self.ty()), - Err(ErrorGuaranteed { .. }) => ConstantKind::Ty(tcx.const_error(self.ty())), + Err(guar) => ConstantKind::Ty(tcx.const_error_with_guaranteed(self.ty(), guar)), } } else { ConstantKind::Ty(self) diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 4ab761e0715..c1c613f6c60 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -69,7 +69,7 @@ pub enum ConstKind<'tcx> { /// A placeholder for a const which could not be computed; this is /// propagated to avoid useless error messages. - Error(ty::DelaySpanBugEmitted), + Error(ErrorGuaranteed), } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8e24f4813a7..2a93df771e1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -117,7 +117,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type BoundTy = ty::BoundTy; type PlaceholderType = ty::PlaceholderType; type InferTy = InferTy; - type DelaySpanBugEmitted = DelaySpanBugEmitted; + type ErrorGuaranteed = ErrorGuaranteed; type PredicateKind = ty::PredicateKind<'tcx>; type AllocId = crate::mir::interpret::AllocId; @@ -128,15 +128,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PlaceholderRegion = ty::PlaceholderRegion; } -/// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s -/// except through the error-reporting functions on a [`tcx`][TyCtxt]. -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] -#[derive(TyEncodable, TyDecodable, HashStable)] -pub struct DelaySpanBugEmitted { - pub reported: ErrorGuaranteed, - _priv: (), -} - type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>; pub struct CtxtInterners<'tcx> { @@ -1292,6 +1283,12 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` + #[track_caller] + pub fn ty_error_with_guaranteed(self, reported: ErrorGuaranteed) -> Ty<'tcx> { + self.mk_ty(Error(reported)) + } + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. #[track_caller] pub fn ty_error(self) -> Ty<'tcx> { @@ -1303,7 +1300,17 @@ impl<'tcx> TyCtxt<'tcx> { #[track_caller] pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> { let reported = self.sess.delay_span_bug(span, msg); - self.mk_ty(Error(DelaySpanBugEmitted { reported, _priv: () })) + self.mk_ty(Error(reported)) + } + + /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed` + #[track_caller] + pub fn const_error_with_guaranteed( + self, + ty: Ty<'tcx>, + reported: ErrorGuaranteed, + ) -> Const<'tcx> { + self.mk_const(ty::ConstKind::Error(reported), ty) } /// Like [TyCtxt::ty_error] but for constants. @@ -1325,10 +1332,7 @@ impl<'tcx> TyCtxt<'tcx> { msg: &str, ) -> Const<'tcx> { let reported = self.sess.delay_span_bug(span, msg); - self.mk_const(ty::ConstS { - kind: ty::ConstKind::Error(DelaySpanBugEmitted { reported, _priv: () }), - ty, - }) + self.mk_const(ty::ConstKind::Error(reported), ty) } pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool { @@ -2243,7 +2247,7 @@ macro_rules! direct_interners { direct_interners! { region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>, - const_: mk_const(ConstS<'tcx>): Const -> Const<'tcx>, + const_: mk_const_internal(ConstS<'tcx>): Const -> Const<'tcx>, const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: intern_layout(LayoutS<'tcx>): Layout -> Layout<'tcx>, adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>, @@ -2582,8 +2586,13 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] + pub fn mk_const(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + self.mk_const_internal(ty::ConstS { kind, ty }) + } + + #[inline] pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - self.mk_const(ty::ConstS { kind: ty::ConstKind::Infer(InferConst::Var(v)), ty }) + self.mk_const(ty::ConstKind::Infer(InferConst::Var(v)), ty) } #[inline] @@ -2603,7 +2612,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_const_infer(self, ic: InferConst<'tcx>, ty: Ty<'tcx>) -> ty::Const<'tcx> { - self.mk_const(ty::ConstS { kind: ty::ConstKind::Infer(ic), ty }) + self.mk_const(ty::ConstKind::Infer(ic), ty) } #[inline] @@ -2613,7 +2622,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_const_param(self, index: u32, name: Symbol, ty: Ty<'tcx>) -> Const<'tcx> { - self.mk_const(ty::ConstS { kind: ty::ConstKind::Param(ParamConst { index, name }), ty }) + self.mk_const(ty::ConstKind::Param(ParamConst { index, name }), ty) } pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { @@ -2820,7 +2829,9 @@ impl<'tcx> TyCtxt<'tcx> { span: impl Into<MultiSpan>, decorator: impl for<'a> DecorateLint<'a, ()>, ) { - self.struct_span_lint_hir(lint, hir_id, span, decorator.msg(), |diag| { + let msg = decorator.msg(); + let (level, src) = self.lint_level_at_node(lint, hir_id); + struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| { decorator.decorate_lint(diag) }) } @@ -2830,6 +2841,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] pub fn struct_span_lint_hir( self, lint: &'static Lint, @@ -2860,6 +2872,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] pub fn struct_lint_node( self, lint: &'static Lint, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 4e6cdb78602..dc13374f992 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -430,7 +430,9 @@ impl<'tcx> TyCtxt<'tcx> { (ty::Projection(_), ty::Projection(_)) => { diag.note("an associated type was expected, but a different one was found"); } - (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) => { + (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) + if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder => + { let generics = self.generics_of(body_owner_def_id); let p_span = self.def_span(generics.type_param(p, self).def_id); if !sp.contains(p_span) { diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 54f1499eb3d..2842b3c3102 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -566,10 +566,7 @@ impl<'tcx> TyCtxt<'tcx> { )) }, consts: &mut |c, ty: Ty<'tcx>| { - self.mk_const(ty::ConstS { - kind: ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), - ty, - }) + self.mk_const(ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), ty) }, }, ) @@ -601,7 +598,7 @@ impl<'tcx> TyCtxt<'tcx> { .replace_late_bound_regions(sig, |_| { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon(counter), + kind: ty::BrAnon(counter, None), }; let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br)); counter += 1; @@ -609,7 +606,7 @@ impl<'tcx> TyCtxt<'tcx> { }) .0; let bound_vars = self.mk_bound_variable_kinds( - (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))), ); Binder::bind_with_vars(inner, bound_vars) } @@ -629,7 +626,9 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let kind = entry - .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(index as u32))) + .or_insert_with(|| { + ty::BoundVariableKind::Region(ty::BrAnon(index as u32, None)) + }) .expect_region(); let br = ty::BoundRegion { var, kind }; self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) @@ -648,7 +647,7 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const(); - self.tcx.mk_const(ty::ConstS { ty, kind: ty::ConstKind::Bound(ty::INNERMOST, var) }) + self.tcx.mk_const(ty::ConstKind::Bound(ty::INNERMOST, var), ty) } } @@ -732,10 +731,7 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> { ct } else { let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Bound(debruijn, bound_ct), - ty: ct.ty(), - }) + self.tcx.mk_const(ty::ConstKind::Bound(debruijn, bound_ct), ct.ty()) } } else { ct.super_fold_with(self) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 6c1414f7b8a..ae0f158ede9 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -511,12 +511,12 @@ impl<'tcx> Instance<'tcx> { Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap() } + #[instrument(level = "debug", skip(tcx), ret)] pub fn fn_once_adapter_instance( tcx: TyCtxt<'tcx>, closure_did: DefId, substs: ty::SubstsRef<'tcx>, ) -> Option<Instance<'tcx>> { - debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs); let fn_once = tcx.require_lang_item(LangItem::FnOnce, None); let call_once = tcx .associated_items(fn_once) @@ -536,7 +536,7 @@ impl<'tcx> Instance<'tcx> { assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]); - debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig); + debug!(?self_ty, ?sig); Some(Instance { def, substs }) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 3312f44c67b..c74d6bc3774 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -189,8 +189,8 @@ pub enum LayoutError<'tcx> { NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), } -impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> { - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> { +impl IntoDiagnostic<'_, !> for LayoutError<'_> { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { let mut diag = handler.struct_fatal(""); match self { @@ -1126,8 +1126,8 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> { } } -impl<'tcx> IntoDiagnostic<'tcx, !> for FnAbiError<'tcx> { - fn into_diagnostic(self, handler: &'tcx Handler) -> DiagnosticBuilder<'tcx, !> { +impl IntoDiagnostic<'_, !> for FnAbiError<'_> { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { handler.struct_fatal(self.to_string()) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a42d0570613..18eb06b83c9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -80,7 +80,7 @@ pub use self::consts::{ }; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, - CtxtInterners, DeducedParamAttrs, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData, + CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData, GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex, }; @@ -2506,6 +2506,10 @@ impl<'tcx> TyCtxt<'tcx> { self.trait_def(trait_def_id).has_auto_impl } + pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { + self.trait_is_auto(trait_def_id) || self.lang_items().sized_trait() == Some(trait_def_id) + } + /// Returns layout of a generator. Layout might be unavailable if the /// generator is tainted by errors. pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> { @@ -2550,11 +2554,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` /// with the name of the crate containing the impl. - pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> { - if let Some(impl_did) = impl_did.as_local() { - Ok(self.def_span(impl_did)) + pub fn span_of_impl(self, impl_def_id: DefId) -> Result<Span, Symbol> { + if let Some(impl_def_id) = impl_def_id.as_local() { + Ok(self.def_span(impl_def_id)) } else { - Err(self.crate_name(impl_did.krate)) + Err(self.crate_name(impl_def_id.krate)) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fab85c39d25..2432b517519 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1659,6 +1659,12 @@ impl<'t> TyCtxt<'t> { debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer() } + + pub fn value_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String { + let ns = guess_def_namespace(self, def_id); + debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns); + FmtPrinter::new(self, ns).print_value_path(def_id, substs).unwrap().into_buffer() + } } impl fmt::Write for FmtPrinter<'_, '_> { @@ -2115,7 +2121,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound match kind { - ty::BrAnon(_) | ty::BrEnv => r, + ty::BrAnon(..) | ty::BrEnv => r, _ => { // Index doesn't matter, since this is just for naming and these never get bound let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind }; @@ -2226,10 +2232,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { let ty::BoundVariableKind::Region(var) = var else { // This doesn't really matter because it doesn't get used, // it's just an empty value - return ty::BrAnon(0); + return ty::BrAnon(0, None); }; match var { - ty::BrAnon(_) | ty::BrEnv => { + ty::BrAnon(..) | ty::BrEnv => { start_or_continue(&mut self, "for<", ", "); let name = next_name(&self); debug!(?name); @@ -2271,7 +2277,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { binder_level_idx: ty::DebruijnIndex, br: ty::BoundRegion| { let (name, kind) = match br.kind { - ty::BrAnon(_) | ty::BrEnv => { + ty::BrAnon(..) | ty::BrEnv => { let name = next_name(&self); if let Some(lt_idx) = lifetime_idx { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index b25b4bd4fe3..c083a405e3c 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -639,10 +639,10 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( au.substs, bu.substs, )?; - return Ok(tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: au.def, substs }), - ty: a.ty(), - })); + return Ok(tcx.mk_const( + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: au.def, substs }), + a.ty(), + )); } _ => false, }; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 2cad333e3f5..9f0598d0ba8 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { impl fmt::Debug for ty::BoundRegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::BrAnon(n) => write!(f, "BrAnon({:?})", n), + ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"), ty::BrNamed(did, name) => { if did.is_crate_root() { write!(f, "BrNamed({})", name) @@ -240,7 +240,6 @@ TrivialTypeTraversalAndLiftImpls! { Field, interpret::Scalar, rustc_target::abi::Size, - ty::DelaySpanBugEmitted, rustc_type_ir::DebruijnIndex, ty::BoundVar, ty::Placeholder<ty::BoundVar>, @@ -806,7 +805,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Const<'tcx> { let ty = self.ty().try_fold_with(folder)?; let kind = self.kind().try_fold_with(folder)?; if ty != self.ty() || kind != self.kind() { - Ok(folder.tcx().mk_const(ty::ConstS { ty, kind })) + Ok(folder.tcx().mk_const(kind, ty)) } else { Ok(self) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index cf420bafeb1..49d82b503a4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -20,6 +20,7 @@ use rustc_hir::def_id::DefId; use rustc_index::vec::Idx; use rustc_macros::HashStable; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::Span; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi; use std::borrow::Cow; @@ -58,7 +59,7 @@ pub struct FreeRegion { #[derive(HashStable)] pub enum BoundRegionKind { /// An anonymous region parameter for a given fn (&T) - BrAnon(u32), + BrAnon(u32, Option<Span>), /// Named region parameters for functions (a in &'a T) /// @@ -1282,6 +1283,12 @@ impl<'tcx> ParamTy { pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { tcx.mk_ty_param(self.index, self.name) } + + pub fn span_from_generics(&self, tcx: TyCtxt<'tcx>, item_with_generics: DefId) -> Span { + let generics = tcx.generics_of(item_with_generics); + let type_param = generics.type_param(self, tcx); + tcx.def_span(type_param.def_id) + } } #[derive(Copy, Clone, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)] diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 0660e9b79a7..2bcb2d82484 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -506,6 +506,9 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> { } } +/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)` +/// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call +/// `subst`. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable)] pub struct EarlyBinder<T>(pub T); diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index c09f71f9a6d..5e366ef703f 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -95,11 +95,15 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { fn references_error(&self) -> bool { self.has_type_flags(TypeFlags::HAS_ERROR) } - fn error_reported(&self) -> Option<ErrorGuaranteed> { + fn error_reported(&self) -> Result<(), ErrorGuaranteed> { if self.references_error() { - Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()) + if let Some(reported) = ty::tls::with(|tcx| tcx.sess.has_errors()) { + Err(reported) + } else { + bug!("expect tcx.sess.has_errors return true"); + } } else { - None + Ok(()) } } fn has_non_region_param(&self) -> bool { diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index f4b4c3fb05a..f4562cdfb88 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -185,7 +185,8 @@ fn find_item_ty_spans( }); if check_params && let Some(args) = path.segments.last().unwrap().args { let params_in_repr = tcx.params_in_repr(def_id); - for (i, arg) in args.args.iter().enumerate() { + // the domain size check is needed because the HIR may not be well-formed at this point + for (i, arg) in args.args.iter().enumerate().take(params_in_repr.domain_size()) { if let hir::GenericArg::Type(ty) = arg && params_in_repr.contains(i as u32) { find_item_ty_spans(tcx, ty, needle, spans, seen_representable); } diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs new file mode 100644 index 00000000000..68d8766c907 --- /dev/null +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -0,0 +1,155 @@ +//! Provides the implementation of the `custom_mir` attribute. +//! +//! Up until MIR building, this attribute has absolutely no effect. The `mir!` macro is a normal +//! decl macro that expands like any other, and the code goes through parsing, name resolution and +//! type checking like all other code. In MIR building we finally detect whether this attribute is +//! present, and if so we branch off into this module, which implements the attribute by +//! implementing a custom lowering from THIR to MIR. +//! +//! The result of this lowering is returned "normally" from the `mir_built` query, with the only +//! notable difference being that the `injected` field in the body is set. Various components of the +//! MIR pipeline, like borrowck and the pass manager will then consult this field (via +//! `body.should_skip()`) to skip the parts of the MIR pipeline that precede the MIR phase the user +//! specified. +//! +//! This file defines the general framework for the custom parsing. The parsing for all the +//! "top-level" constructs can be found in the `parse` submodule, while the parsing for statements, +//! terminators, and everything below can be found in the `parse::instruction` submodule. +//! + +use rustc_ast::Attribute; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::DefId; +use rustc_index::vec::IndexVec; +use rustc_middle::{ + mir::*, + thir::*, + ty::{Ty, TyCtxt}, +}; +use rustc_span::Span; + +mod parse; + +pub(super) fn build_custom_mir<'tcx>( + tcx: TyCtxt<'tcx>, + did: DefId, + thir: &Thir<'tcx>, + expr: ExprId, + params: &IndexVec<ParamId, Param<'tcx>>, + return_ty: Ty<'tcx>, + return_ty_span: Span, + span: Span, + attr: &Attribute, +) -> Body<'tcx> { + let mut body = Body { + basic_blocks: BasicBlocks::new(IndexVec::new()), + source: MirSource::item(did), + phase: MirPhase::Built, + source_scopes: IndexVec::new(), + generator: None, + local_decls: LocalDecls::new(), + user_type_annotations: IndexVec::new(), + arg_count: params.len(), + spread_arg: None, + var_debug_info: Vec::new(), + span, + required_consts: Vec::new(), + is_polymorphic: false, + tainted_by_errors: None, + injection_phase: None, + pass_count: 1, + }; + + body.local_decls.push(LocalDecl::new(return_ty, return_ty_span)); + body.basic_blocks_mut().push(BasicBlockData::new(None)); + body.source_scopes.push(SourceScopeData { + span, + parent_scope: None, + inlined: None, + inlined_parent_scope: None, + local_data: ClearCrossCrate::Clear, + }); + body.injection_phase = Some(parse_attribute(attr)); + + let mut pctxt = ParseCtxt { + tcx, + thir, + source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }, + body: &mut body, + local_map: FxHashMap::default(), + block_map: FxHashMap::default(), + }; + + let res = (|| { + pctxt.parse_args(¶ms)?; + pctxt.parse_body(expr) + })(); + if let Err(err) = res { + tcx.sess.diagnostic().span_fatal( + err.span, + format!("Could not parse {}, found: {:?}", err.expected, err.item_description), + ) + } + + body +} + +fn parse_attribute(attr: &Attribute) -> MirPhase { + let meta_items = attr.meta_item_list().unwrap(); + let mut dialect: Option<String> = None; + let mut phase: Option<String> = None; + + for nested in meta_items { + let name = nested.name_or_empty(); + let value = nested.value_str().unwrap().as_str().to_string(); + match name.as_str() { + "dialect" => { + assert!(dialect.is_none()); + dialect = Some(value); + } + "phase" => { + assert!(phase.is_none()); + phase = Some(value); + } + other => { + panic!("Unexpected key {}", other); + } + } + } + + let Some(dialect) = dialect else { + assert!(phase.is_none()); + return MirPhase::Built; + }; + + MirPhase::parse(dialect, phase) +} + +struct ParseCtxt<'tcx, 'body> { + tcx: TyCtxt<'tcx>, + thir: &'body Thir<'tcx>, + source_info: SourceInfo, + + body: &'body mut Body<'tcx>, + local_map: FxHashMap<LocalVarId, Local>, + block_map: FxHashMap<LocalVarId, BasicBlock>, +} + +struct ParseError { + span: Span, + item_description: String, + expected: String, +} + +impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { + fn expr_error(&self, expr: ExprId, expected: &'static str) -> ParseError { + let expr = &self.thir[expr]; + ParseError { + span: expr.span, + item_description: format!("{:?}", expr.kind), + expected: expected.to_string(), + } + } +} + +type PResult<T> = Result<T, ParseError>; diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs new file mode 100644 index 00000000000..52cb0a4826d --- /dev/null +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -0,0 +1,245 @@ +use rustc_index::vec::IndexVec; +use rustc_middle::{mir::*, thir::*, ty::Ty}; +use rustc_span::Span; + +use super::{PResult, ParseCtxt, ParseError}; + +mod instruction; + +/// Helper macro for parsing custom MIR. +/// +/// Example usage looks something like: +/// ```rust,ignore (incomplete example) +/// parse_by_kind!( +/// self, // : &ParseCtxt +/// expr_id, // what you're matching against +/// "assignment", // the thing you're trying to parse +/// @call("mir_assign", args) => { args[0] }, // match invocations of the `mir_assign` special function +/// ExprKind::Assign { lhs, .. } => { lhs }, // match thir assignment expressions +/// // no need for fallthrough case - reasonable error is automatically generated +/// ) +/// ``` +macro_rules! parse_by_kind { + ( + $self:ident, + $expr_id:expr, + $expected:literal, + $( + @call($name:literal, $args:ident) => $call_expr:expr, + )* + $( + $pat:pat => $expr:expr, + )* + ) => {{ + let expr_id = $self.preparse($expr_id); + let expr = &$self.thir[expr_id]; + match &expr.kind { + $( + ExprKind::Call { ty, fun: _, args: $args, .. } if { + match ty.kind() { + ty::FnDef(did, _) => { + $self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did) + } + _ => false, + } + } => $call_expr, + )* + $( + $pat => $expr, + )* + #[allow(unreachable_patterns)] + _ => return Err($self.expr_error(expr_id, $expected)) + } + }}; +} +pub(crate) use parse_by_kind; + +impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { + /// Expressions should only ever be matched on after preparsing them. This removes extra scopes + /// we don't care about. + fn preparse(&self, expr_id: ExprId) -> ExprId { + let expr = &self.thir[expr_id]; + match expr.kind { + ExprKind::Scope { value, .. } => self.preparse(value), + _ => expr_id, + } + } + + fn statement_as_expr(&self, stmt_id: StmtId) -> PResult<ExprId> { + match &self.thir[stmt_id].kind { + StmtKind::Expr { expr, .. } => Ok(*expr), + kind @ StmtKind::Let { pattern, .. } => { + return Err(ParseError { + span: pattern.span, + item_description: format!("{:?}", kind), + expected: "expression".to_string(), + }); + } + } + } + + pub fn parse_args(&mut self, params: &IndexVec<ParamId, Param<'tcx>>) -> PResult<()> { + for param in params.iter() { + let (var, span) = { + let pat = param.pat.as_ref().unwrap(); + match &pat.kind { + PatKind::Binding { var, .. } => (*var, pat.span), + _ => { + return Err(ParseError { + span: pat.span, + item_description: format!("{:?}", pat.kind), + expected: "local".to_string(), + }); + } + } + }; + let decl = LocalDecl::new(param.ty, span); + let local = self.body.local_decls.push(decl); + self.local_map.insert(var, local); + } + + Ok(()) + } + + /// Bodies are of the form: + /// + /// ```text + /// { + /// let bb1: BasicBlock; + /// let bb2: BasicBlock; + /// { + /// let RET: _; + /// let local1; + /// let local2; + /// + /// { + /// { // entry block + /// statement1; + /// terminator1 + /// }; + /// + /// bb1 = { + /// statement2; + /// terminator2 + /// }; + /// + /// bb2 = { + /// statement3; + /// terminator3 + /// } + /// + /// RET + /// } + /// } + /// } + /// ``` + /// + /// This allows us to easily parse the basic blocks declarations, local declarations, and + /// basic block definitions in order. + pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> { + let body = parse_by_kind!(self, expr_id, "whole body", + ExprKind::Block { block } => self.thir[*block].expr.unwrap(), + ); + let (block_decls, rest) = parse_by_kind!(self, body, "body with block decls", + ExprKind::Block { block } => { + let block = &self.thir[*block]; + (&block.stmts, block.expr.unwrap()) + }, + ); + self.parse_block_decls(block_decls.iter().copied())?; + + let (local_decls, rest) = parse_by_kind!(self, rest, "body with local decls", + ExprKind::Block { block } => { + let block = &self.thir[*block]; + (&block.stmts, block.expr.unwrap()) + }, + ); + self.parse_local_decls(local_decls.iter().copied())?; + + let block_defs = parse_by_kind!(self, rest, "body with block defs", + ExprKind::Block { block } => &self.thir[*block].stmts, + ); + for (i, block_def) in block_defs.iter().enumerate() { + let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?; + self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block; + } + + Ok(()) + } + + fn parse_block_decls(&mut self, stmts: impl Iterator<Item = StmtId>) -> PResult<()> { + for stmt in stmts { + let (var, _, _) = self.parse_let_statement(stmt)?; + let data = BasicBlockData::new(None); + let block = self.body.basic_blocks_mut().push(data); + self.block_map.insert(var, block); + } + + Ok(()) + } + + fn parse_local_decls(&mut self, mut stmts: impl Iterator<Item = StmtId>) -> PResult<()> { + let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?; + self.local_map.insert(ret_var, Local::from_u32(0)); + + for stmt in stmts { + let (var, ty, span) = self.parse_let_statement(stmt)?; + let decl = LocalDecl::new(ty, span); + let local = self.body.local_decls.push(decl); + self.local_map.insert(var, local); + } + + Ok(()) + } + + fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'tcx>, Span)> { + let pattern = match &self.thir[stmt_id].kind { + StmtKind::Let { pattern, .. } => pattern, + StmtKind::Expr { expr, .. } => { + return Err(self.expr_error(*expr, "let statement")); + } + }; + + self.parse_var(pattern) + } + + fn parse_var(&mut self, mut pat: &Pat<'tcx>) -> PResult<(LocalVarId, Ty<'tcx>, Span)> { + // Make sure we throw out any `AscribeUserType` we find + loop { + match &pat.kind { + PatKind::Binding { var, ty, .. } => break Ok((*var, *ty, pat.span)), + PatKind::AscribeUserType { subpattern, .. } => { + pat = subpattern; + } + _ => { + break Err(ParseError { + span: pat.span, + item_description: format!("{:?}", pat.kind), + expected: "local".to_string(), + }); + } + } + } + } + + fn parse_block_def(&self, expr_id: ExprId) -> PResult<BasicBlockData<'tcx>> { + let block = parse_by_kind!(self, expr_id, "basic block", + ExprKind::Block { block } => &self.thir[*block], + ); + + let mut data = BasicBlockData::new(None); + for stmt_id in &*block.stmts { + let stmt = self.statement_as_expr(*stmt_id)?; + let statement = self.parse_statement(stmt)?; + data.statements.push(Statement { source_info: self.source_info, kind: statement }); + } + + let Some(trailing) = block.expr else { + return Err(self.expr_error(expr_id, "terminator")) + }; + let terminator = self.parse_terminator(trailing)?; + data.terminator = Some(Terminator { source_info: self.source_info, kind: terminator }); + + Ok(data) + } +} diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs new file mode 100644 index 00000000000..6d6176584f5 --- /dev/null +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -0,0 +1,72 @@ +use rustc_middle::{mir::*, thir::*, ty}; + +use super::{parse_by_kind, PResult, ParseCtxt}; + +impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { + pub fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> { + parse_by_kind!(self, expr_id, "statement", + @call("mir_retag", args) => { + Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?))) + }, + @call("mir_retag_raw", args) => { + Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?))) + }, + ExprKind::Assign { lhs, rhs } => { + let lhs = self.parse_place(*lhs)?; + let rhs = self.parse_rvalue(*rhs)?; + Ok(StatementKind::Assign(Box::new((lhs, rhs)))) + }, + ) + } + + pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> { + parse_by_kind!(self, expr_id, "terminator", + @call("mir_return", _args) => { + Ok(TerminatorKind::Return) + }, + @call("mir_goto", args) => { + Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } ) + }, + ) + } + + fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> { + parse_by_kind!(self, expr_id, "rvalue", + ExprKind::Borrow { borrow_kind, arg } => Ok( + Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?) + ), + ExprKind::AddressOf { mutability, arg } => Ok( + Rvalue::AddressOf(*mutability, self.parse_place(*arg)?) + ), + _ => self.parse_operand(expr_id).map(Rvalue::Use), + ) + } + + fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> { + parse_by_kind!(self, expr_id, "operand", + @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move), + _ => self.parse_place(expr_id).map(Operand::Copy), + ) + } + + fn parse_place(&self, expr_id: ExprId) -> PResult<Place<'tcx>> { + parse_by_kind!(self, expr_id, "place", + ExprKind::Deref { arg } => Ok( + self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx) + ), + _ => self.parse_local(expr_id).map(Place::from), + ) + } + + fn parse_local(&self, expr_id: ExprId) -> PResult<Local> { + parse_by_kind!(self, expr_id, "local", + ExprKind::VarRef { id } => Ok(self.local_map[id]), + ) + } + + fn parse_block(&self, expr_id: ExprId) -> PResult<BasicBlock> { + parse_by_kind!(self, expr_id, "basic block", + ExprKind::VarRef { id } => Ok(self.block_map[id]), + ) + } +} diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 37dc1ad9f0d..7d8a940bde5 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -9,6 +9,7 @@ use rustc_middle::mir::interpret::{ use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, TyCtxt}; +use rustc_span::DUMMY_SP; use rustc_target::abi::Size; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -26,7 +27,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let literal = match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { Ok(c) => c, - Err(LitToConstError::Reported) => ConstantKind::Ty(tcx.const_error(ty)), + Err(LitToConstError::Reported(guar)) => { + ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar)) + } Err(LitToConstError::TypeError) => { bug!("encountered type error in `lit_to_mir_constant") } @@ -74,8 +77,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { user_ty, span, literal } } ExprKind::ConstParam { param, def_id: _ } => { - let const_param = - tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Param(param), ty: expr.ty }); + let const_param = tcx.mk_const(ty::ConstKind::Param(param), expr.ty); let literal = ConstantKind::Ty(const_param); Constant { user_ty: None, span, literal } @@ -106,7 +108,15 @@ pub(crate) fn lit_to_mir_constant<'tcx>( let LitToConstInput { lit, ty, neg } = lit_input; let trunc = |n| { let param_ty = ty::ParamEnv::reveal_all().and(ty); - let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size; + let width = tcx + .layout_of(param_ty) + .map_err(|_| { + LitToConstError::Reported(tcx.sess.delay_span_bug( + DUMMY_SP, + format!("couldn't compute width of literal: {:?}", lit_input.lit), + )) + })? + .size; trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); let result = width.truncate(n); trace!("trunc result: {}", result); @@ -137,12 +147,20 @@ pub(crate) fn lit_to_mir_constant<'tcx>( (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })? } - (ast::LitKind::Float(n, _), ty::Float(fty)) => { - parse_float_into_constval(*n, *fty, neg).ok_or(LitToConstError::Reported)? - } + (ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float_into_constval(*n, *fty, neg) + .ok_or_else(|| { + LitToConstError::Reported(tcx.sess.delay_span_bug( + DUMMY_SP, + format!("couldn't parse float literal: {:?}", lit_input.lit), + )) + })?, (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)), (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)), - (ast::LitKind::Err, _) => return Err(LitToConstError::Reported), + (ast::LitKind::Err, _) => { + return Err(LitToConstError::Reported( + tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"), + )); + } _ => return Err(LitToConstError::TypeError), }; diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 3f813e0af0d..dfd8649cb97 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -364,12 +364,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let arm_block = this.bind_pattern( outer_source_info, candidate, - arm.guard.as_ref(), &fake_borrow_temps, scrutinee_span, - Some(arm.span), - Some(arm.scope), - Some(match_scope), + Some((arm, match_scope)), false, ); @@ -410,12 +407,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, outer_source_info: SourceInfo, candidate: Candidate<'_, 'tcx>, - guard: Option<&Guard<'tcx>>, fake_borrow_temps: &[(Place<'tcx>, Local)], scrutinee_span: Span, - arm_span: Option<Span>, - arm_scope: Option<region::Scope>, - match_scope: Option<region::Scope>, + arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>, storages_alive: bool, ) -> BasicBlock { if candidate.subcandidates.is_empty() { @@ -424,11 +418,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.bind_and_guard_matched_candidate( candidate, &[], - guard, fake_borrow_temps, scrutinee_span, - arm_span, - match_scope, + arm_match_scope, true, storages_alive, ) @@ -449,6 +441,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // we lower the guard. let target_block = self.cfg.start_new_block(); let mut schedule_drops = true; + let arm = arm_match_scope.unzip().0; // We keep a stack of all of the bindings and type ascriptions // from the parent candidates that we visit, that also need to // be bound for each candidate. @@ -456,21 +449,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate, &mut Vec::new(), &mut |leaf_candidate, parent_bindings| { - if let Some(arm_scope) = arm_scope { - self.clear_top_scope(arm_scope); + if let Some(arm) = arm { + self.clear_top_scope(arm.scope); } let binding_end = self.bind_and_guard_matched_candidate( leaf_candidate, parent_bindings, - guard, &fake_borrow_temps, scrutinee_span, - arm_span, - match_scope, + arm_match_scope, schedule_drops, storages_alive, ); - if arm_scope.is_none() { + if arm.is_none() { schedule_drops = false; } self.cfg.goto(binding_end, outer_source_info, target_block); @@ -636,12 +627,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.bind_pattern( self.source_info(irrefutable_pat.span), candidate, - None, &fake_borrow_temps, irrefutable_pat.span, None, - None, - None, false, ) .unit() @@ -1820,12 +1808,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let post_guard_block = self.bind_pattern( self.source_info(pat.span), guard_candidate, - None, &fake_borrow_temps, expr.span, None, - None, - None, false, ); @@ -1844,11 +1829,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, candidate: Candidate<'pat, 'tcx>, parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)], - guard: Option<&Guard<'tcx>>, fake_borrows: &[(Place<'tcx>, Local)], scrutinee_span: Span, - arm_span: Option<Span>, - match_scope: Option<region::Scope>, + arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>, schedule_drops: bool, storages_alive: bool, ) -> BasicBlock { @@ -1960,7 +1943,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // the reference that we create for the arm. // * So we eagerly create the reference for the arm and then take a // reference to that. - if let Some(guard) = guard { + if let Some((arm, match_scope)) = arm_match_scope + && let Some(guard) = &arm.guard + { let tcx = self.tcx; let bindings = parent_bindings .iter() @@ -1981,8 +1966,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow); } - let arm_span = arm_span.unwrap(); - let match_scope = match_scope.unwrap(); let mut guard_span = rustc_span::DUMMY_SP; let (post_guard_block, otherwise_post_guard_block) = @@ -1995,13 +1978,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { e, None, match_scope, - this.source_info(arm_span), + this.source_info(arm.span), ) } Guard::IfLet(ref pat, scrutinee) => { let s = &this.thir[scrutinee]; guard_span = s.span; - this.lower_let_expr(block, s, pat, match_scope, None, arm_span) + this.lower_let_expr(block, s, pat, match_scope, None, arm.span) } }); @@ -2317,24 +2300,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let matching = this.bind_pattern( this.source_info(pattern.span), candidate, - None, &fake_borrow_temps, initializer_span, None, - None, - None, true, ); // This block is for the failure case let failure = this.bind_pattern( this.source_info(else_block_span), wildcard, - None, &fake_borrow_temps, initializer_span, None, - None, - None, true, ); this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span)); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index cbcf9cd129f..437ac8d82a1 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -481,6 +481,22 @@ fn construct_fn<'tcx>( (None, fn_sig.output()) }; + if let Some(custom_mir_attr) = + tcx.hir().attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir) + { + return custom::build_custom_mir( + tcx, + fn_def.did.to_def_id(), + thir, + expr, + arguments, + return_ty, + return_ty_span, + span, + custom_mir_attr, + ); + } + let infcx = tcx.infer_ctxt().build(); let mut builder = Builder::new( thir, @@ -1033,6 +1049,7 @@ pub(crate) fn parse_float_into_scalar( mod block; mod cfg; +mod custom; mod expr; mod matches; mod misc; diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index f626571b5b2..85e8801bda3 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -1,6 +1,7 @@ use rustc_ast as ast; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt}; +use rustc_span::DUMMY_SP; pub(crate) fn lit_to_const<'tcx>( tcx: TyCtxt<'tcx>, @@ -10,7 +11,15 @@ pub(crate) fn lit_to_const<'tcx>( let trunc = |n| { let param_ty = ParamEnv::reveal_all().and(ty); - let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size; + let width = tcx + .layout_of(param_ty) + .map_err(|_| { + LitToConstError::Reported(tcx.sess.delay_span_bug( + DUMMY_SP, + format!("couldn't compute width of literal: {:?}", lit_input.lit), + )) + })? + .size; trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); let result = width.truncate(n); trace!("trunc result: {}", result); @@ -44,7 +53,11 @@ pub(crate) fn lit_to_const<'tcx>( } (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()), (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()), - (ast::LitKind::Err, _) => return Err(LitToConstError::Reported), + (ast::LitKind::Err, _) => { + return Err(LitToConstError::Reported( + tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"), + )); + } _ => return Err(LitToConstError::TypeError), }; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index c7a7c3e3fa8..c4639d3a513 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -51,11 +51,17 @@ impl<'tcx> Cx<'tcx> { trace!(?expr.ty); // Now apply adjustments, if any. - for adjustment in self.typeck_results.expr_adjustments(hir_expr) { - trace!(?expr, ?adjustment); - let span = expr.span; - expr = - self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span)); + if self.apply_adjustments { + for adjustment in self.typeck_results.expr_adjustments(hir_expr) { + trace!(?expr, ?adjustment); + let span = expr.span; + expr = self.apply_adjustment( + hir_expr, + expr, + adjustment, + adjustment_span.unwrap_or(span), + ); + } } trace!(?expr.ty, "after adjustments"); diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 1d95d6b53fb..b5c4b7b137d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -80,6 +80,9 @@ struct Cx<'tcx> { /// for the receiver. adjustment_span: Option<(HirId, Span)>, + /// False to indicate that adjustments should not be applied. Only used for `custom_mir` + apply_adjustments: bool, + /// The `DefId` of the owner of this body. body_owner: DefId, } @@ -87,6 +90,8 @@ struct Cx<'tcx> { impl<'tcx> Cx<'tcx> { fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> { let typeck_results = tcx.typeck_opt_const_arg(def); + let did = def.did; + let hir = tcx.hir(); Cx { tcx, thir: Thir::new(), @@ -94,8 +99,12 @@ impl<'tcx> Cx<'tcx> { region_scope_tree: tcx.region_scope_tree(def.did), typeck_results, rvalue_scopes: &typeck_results.rvalue_scopes, - body_owner: def.did.to_def_id(), + body_owner: did.to_def_id(), adjustment_span: None, + apply_adjustments: hir + .attrs(hir.local_def_id_to_hir_id(did)) + .iter() + .all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir), } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 2526522a25c..776c748c7e5 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -614,7 +614,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_mir_constant(lit_input) { Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, false).kind, - Err(LitToConstError::Reported) => PatKind::Wild, + Err(LitToConstError::Reported(_)) => PatKind::Wild, Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 23403628c53..14d265a402e 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -407,9 +407,8 @@ where self.drop_ladder(fields, succ, unwind).0 } + #[instrument(level = "debug", ret)] fn open_drop_for_box(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock { - debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs); - // drop glue is sent straight to codegen // box cannot be directly dereferenced let unique_ty = adt.non_enum_variant().fields[0].ty(self.tcx(), substs); @@ -431,8 +430,8 @@ where self.drop_subpath(interior, interior_path, succ, unwind_succ) } + #[instrument(level = "debug", ret)] fn open_drop_for_adt(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock { - debug!("open_drop_for_adt({:?}, {:?}, {:?})", self, adt, substs); if adt.variants().is_empty() { return self.elaborator.patch().new_block(BasicBlockData { statements: vec![], diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 959fcf8d89e..e783d189137 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -4,6 +4,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::HirId; use rustc_hir::intravisit; +use rustc_hir::{BlockCheckMode, ExprKind, Node}; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; @@ -470,6 +471,14 @@ fn unsafety_check_result<'tcx>( // `mir_built` force this. let body = &tcx.mir_built(def).borrow(); + if body.should_skip() { + return tcx.arena.alloc(UnsafetyCheckResult { + violations: Vec::new(), + used_unsafe_blocks: FxHashSet::default(), + unused_unsafes: Some(Vec::new()), + }); + } + let param_env = tcx.param_env(def.did); let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env); @@ -517,24 +526,48 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() { let (description, note) = details.description_and_note(); - // Report an error. - let unsafe_fn_msg = - if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" }; - match kind { UnsafetyViolationKind::General => { // once - struct_span_err!( + let unsafe_fn_msg = if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { + " function or" + } else { + "" + }; + + let mut err = struct_span_err!( tcx.sess, source_info.span, E0133, "{} is unsafe and requires unsafe{} block", description, unsafe_fn_msg, - ) - .span_label(source_info.span, description) - .note(note) - .emit(); + ); + err.span_label(source_info.span, description).note(note); + let note_non_inherited = tcx.hir().parent_iter(lint_root).find(|(id, node)| { + if let Node::Expr(block) = node + && let ExprKind::Block(block, _) = block.kind + && let BlockCheckMode::UnsafeBlock(_) = block.rules + { + true + } + else if let Some(sig) = tcx.hir().fn_sig_by_hir_id(*id) + && sig.header.is_unsafe() + { + true + } else { + false + } + }); + if let Some((id, _)) = note_non_inherited { + let span = tcx.hir().span(id); + err.span_label( + tcx.sess.source_map().guess_head_span(span), + "items do not inherit unsafety from separate enclosing items", + ); + } + + err.emit(); } UnsafetyViolationKind::UnsafeFn => tcx.struct_span_lint_hir( UNSAFE_OP_IN_UNSAFE_FN, diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 230c6a7cb4b..27dbc3e22c9 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -96,45 +96,48 @@ fn run_passes_inner<'tcx>( phase_change: Option<MirPhase>, validate_each: bool, ) { - let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir; + let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip(); let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); - for pass in passes { - let name = pass.name(); - - let overridden = - overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| { - trace!( - pass = %name, - "{} as requested by flag", - if *polarity { "Running" } else { "Not running" }, - ); - *polarity - }); - if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) { - continue; + if !body.should_skip() { + for pass in passes { + let name = pass.name(); + + let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map( + |(_name, polarity)| { + trace!( + pass = %name, + "{} as requested by flag", + if *polarity { "Running" } else { "Not running" }, + ); + *polarity + }, + ); + if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) { + continue; + } + + let dump_enabled = pass.is_mir_dump_enabled(); + + if dump_enabled { + dump_mir_for_pass(tcx, body, &name, false); + } + if validate { + validate_body(tcx, body, format!("before pass {}", name)); + } + + pass.run_pass(tcx, body); + + if dump_enabled { + dump_mir_for_pass(tcx, body, &name, true); + } + if validate { + validate_body(tcx, body, format!("after pass {}", name)); + } + + body.pass_count += 1; } - - let dump_enabled = pass.is_mir_dump_enabled(); - - if dump_enabled { - dump_mir_for_pass(tcx, body, &name, false); - } - if validate { - validate_body(tcx, body, format!("before pass {}", name)); - } - - pass.run_pass(tcx, body); - - if dump_enabled { - dump_mir_for_pass(tcx, body, &name, true); - } - if validate { - validate_body(tcx, body, format!("after pass {}", name)); - } - - body.pass_count += 1; } if let Some(new_phase) = phase_change { diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs index cc75947d9dd..0ea8f2ba93f 100644 --- a/compiler/rustc_mir_transform/src/required_consts.rs +++ b/compiler/rustc_mir_transform/src/required_consts.rs @@ -17,7 +17,7 @@ impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { let literal = constant.literal; match literal { ConstantKind::Ty(c) => match c.kind() { - ConstKind::Param(_) => {} + ConstKind::Param(_) | ConstKind::Error(_) => {} _ => bug!("only ConstKind::Param should be encountered here, got {:#?}", c), }, ConstantKind::Unevaluated(..) => self.required_consts.push(*constant), diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index bf590674144..a0ff7550fae 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -569,17 +569,13 @@ impl<'tcx> CloneShimBuilder<'tcx> { /// Builds a "call" shim for `instance`. The shim calls the function specified by `call_kind`, /// first adjusting its first argument according to `rcvr_adjustment`. +#[instrument(level = "debug", skip(tcx), ret)] fn build_call_shim<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>, rcvr_adjustment: Option<Adjustment>, call_kind: CallKind<'tcx>, ) -> Body<'tcx> { - debug!( - "build_call_shim(instance={:?}, rcvr_adjustment={:?}, call_kind={:?})", - instance, rcvr_adjustment, call_kind - ); - // `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used // to substitute into the signature of the shim. It is not necessary for users of this // MIR body to perform further substitutions (see `InstanceDef::has_polymorphic_mir_body`). @@ -641,7 +637,7 @@ fn build_call_shim<'tcx>( let span = tcx.def_span(def_id); - debug!("build_call_shim: sig={:?}", sig); + debug!(?sig); let mut local_decls = local_decls_for_sig(&sig, span); let source_info = SourceInfo::outermost(span); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 3cfddd75462..58ddb807059 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1336,6 +1336,10 @@ fn create_mono_items_for_default_impls<'tcx>( ) { match item.kind { hir::ItemKind::Impl(ref impl_) => { + if matches!(impl_.polarity, hir::ImplPolarity::Negative(_)) { + return; + } + for param in impl_.generics.params { match param.kind { hir::GenericParamKind::Lifetime { .. } => {} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index dc204902842..d59982f7063 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -369,6 +369,15 @@ pub(crate) struct MissingSemicolonBeforeArray { } #[derive(Diagnostic)] +#[diag(parser_expect_dotdot_not_dotdotdot)] +pub(crate) struct MissingDotDot { + #[primary_span] + pub token_span: Span, + #[suggestion(applicability = "maybe-incorrect", code = "..", style = "verbose")] + pub sugg_span: Span, +} + +#[derive(Diagnostic)] #[diag(parser_invalid_block_macro_segment)] pub(crate) struct InvalidBlockMacroSegment { #[primary_span] @@ -412,6 +421,15 @@ pub(crate) struct ExpectedExpressionFoundLet { } #[derive(Diagnostic)] +#[diag(parser_expect_eq_instead_of_eqeq)] +pub(crate) struct ExpectedEqForLetExpr { + #[primary_span] + pub span: Span, + #[suggestion(applicability = "maybe-incorrect", code = "=", style = "verbose")] + pub sugg_span: Span, +} + +#[derive(Diagnostic)] #[diag(parser_expected_else_block)] pub(crate) struct ExpectedElseBlock { #[primary_span] @@ -1147,10 +1165,12 @@ pub(crate) struct ParenthesesInForHead { #[derive(Subdiagnostic)] #[multipart_suggestion(suggestion, applicability = "machine-applicable")] pub(crate) struct ParenthesesInForHeadSugg { - #[suggestion_part(code = "")] + #[suggestion_part(code = "{left_snippet}")] pub left: Span, - #[suggestion_part(code = "")] + pub left_snippet: String, + #[suggestion_part(code = "{right_snippet}")] pub right: Span, + pub right_snippet: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 462bce16ad7..645262bd2f1 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -175,20 +175,10 @@ impl<'a> StringReader<'a> { if string == "_" { self.sess .span_diagnostic - .struct_span_warn( + .struct_span_err( self.mk_sp(suffix_start, self.pos), "underscore literal suffix is not allowed", ) - .warn( - "this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!", - ) - .note( - "see issue #42326 \ - <https://github.com/rust-lang/rust/issues/42326> \ - for more information", - ) .emit(); None } else { @@ -363,55 +353,55 @@ impl<'a> StringReader<'a> { fn cook_lexer_literal( &self, start: BytePos, - suffix_start: BytePos, + end: BytePos, kind: rustc_lexer::LiteralKind, ) -> (token::LitKind, Symbol) { - // prefix means `"` or `br"` or `r###"`, ... - let (lit_kind, mode, prefix_len, postfix_len) = match kind { + match kind { rustc_lexer::LiteralKind::Char { terminated } => { if !terminated { self.sess.span_diagnostic.span_fatal_with_code( - self.mk_sp(start, suffix_start), + self.mk_sp(start, end), "unterminated character literal", error_code!(E0762), ) } - (token::Char, Mode::Char, 1, 1) // ' ' + self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' ' } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { self.sess.span_diagnostic.span_fatal_with_code( - self.mk_sp(start + BytePos(1), suffix_start), + self.mk_sp(start + BytePos(1), end), "unterminated byte constant", error_code!(E0763), ) } - (token::Byte, Mode::Byte, 2, 1) // b' ' + self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' ' } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { self.sess.span_diagnostic.span_fatal_with_code( - self.mk_sp(start, suffix_start), + self.mk_sp(start, end), "unterminated double quote string", error_code!(E0765), ) } - (token::Str, Mode::Str, 1, 1) // " " + self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " " } rustc_lexer::LiteralKind::ByteStr { terminated } => { if !terminated { self.sess.span_diagnostic.span_fatal_with_code( - self.mk_sp(start + BytePos(1), suffix_start), + self.mk_sp(start + BytePos(1), end), "unterminated double quote byte string", error_code!(E0766), ) } - (token::ByteStr, Mode::ByteStr, 2, 1) // b" " + self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" " } rustc_lexer::LiteralKind::RawStr { n_hashes } => { if let Some(n_hashes) = n_hashes { let n = u32::from(n_hashes); - (token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "## + let kind = token::StrRaw(n_hashes); + self.cook_quoted(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "## } else { self.report_raw_str_error(start, 1); } @@ -419,56 +409,59 @@ impl<'a> StringReader<'a> { rustc_lexer::LiteralKind::RawByteStr { n_hashes } => { if let Some(n_hashes) = n_hashes { let n = u32::from(n_hashes); - (token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "## + let kind = token::ByteStrRaw(n_hashes); + self.cook_quoted(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "## } else { self.report_raw_str_error(start, 2); } } rustc_lexer::LiteralKind::Int { base, empty_int } => { - return if empty_int { + if empty_int { self.sess .span_diagnostic .struct_span_err_with_code( - self.mk_sp(start, suffix_start), + self.mk_sp(start, end), "no valid digits found for number", error_code!(E0768), ) .emit(); (token::Integer, sym::integer(0)) } else { - self.validate_int_literal(base, start, suffix_start); - (token::Integer, self.symbol_from_to(start, suffix_start)) - }; + if matches!(base, Base::Binary | Base::Octal) { + let base = base as u32; + let s = self.str_from_to(start + BytePos(2), end); + for (idx, c) in s.char_indices() { + if c != '_' && c.to_digit(base).is_none() { + self.err_span_( + start + BytePos::from_usize(2 + idx), + start + BytePos::from_usize(2 + idx + c.len_utf8()), + &format!("invalid digit for a base {} literal", base), + ); + } + } + } + (token::Integer, self.symbol_from_to(start, end)) + } } rustc_lexer::LiteralKind::Float { base, empty_exponent } => { if empty_exponent { self.err_span_(start, self.pos, "expected at least one digit in exponent"); } - match base { - Base::Hexadecimal => self.err_span_( - start, - suffix_start, - "hexadecimal float literal is not supported", - ), + Base::Hexadecimal => { + self.err_span_(start, end, "hexadecimal float literal is not supported") + } Base::Octal => { - self.err_span_(start, suffix_start, "octal float literal is not supported") + self.err_span_(start, end, "octal float literal is not supported") } Base::Binary => { - self.err_span_(start, suffix_start, "binary float literal is not supported") + self.err_span_(start, end, "binary float literal is not supported") } - _ => (), + _ => {} } - - let id = self.symbol_from_to(start, suffix_start); - return (token::Float, id); + (token::Float, self.symbol_from_to(start, end)) } - }; - let content_start = start + BytePos(prefix_len); - let content_end = suffix_start - BytePos(postfix_len); - let id = self.symbol_from_to(content_start, content_end); - self.validate_literal_escape(mode, content_start, content_end, prefix_len, postfix_len); - (lit_kind, id) + } } #[inline] @@ -659,20 +652,22 @@ impl<'a> StringReader<'a> { ) } - fn validate_literal_escape( + fn cook_quoted( &self, + kind: token::LitKind, mode: Mode, - content_start: BytePos, - content_end: BytePos, + start: BytePos, + end: BytePos, prefix_len: u32, postfix_len: u32, - ) { + ) -> (token::LitKind, Symbol) { + let content_start = start + BytePos(prefix_len); + let content_end = end - BytePos(postfix_len); let lit_content = self.str_from_to(content_start, content_end); unescape::unescape_literal(lit_content, mode, &mut |range, result| { // Here we only check for errors. The actual unescaping is done later. if let Err(err) = result { - let span_with_quotes = self - .mk_sp(content_start - BytePos(prefix_len), content_end + BytePos(postfix_len)); + let span_with_quotes = self.mk_sp(start, end); let (start, end) = (range.start as u32, range.end as u32); let lo = content_start + BytePos(start); let hi = lo + BytePos(end - start); @@ -688,23 +683,7 @@ impl<'a> StringReader<'a> { ); } }); - } - - fn validate_int_literal(&self, base: Base, content_start: BytePos, content_end: BytePos) { - let base = match base { - Base::Binary => 2, - Base::Octal => 8, - _ => return, - }; - let s = self.str_from_to(content_start + BytePos(2), content_end); - for (idx, c) in s.char_indices() { - let idx = idx as u32; - if c != '_' && c.to_digit(base).is_none() { - let lo = content_start + BytePos(2 + idx); - let hi = content_start + BytePos(2 + idx + c.len_utf8() as u32); - self.err_span_(lo, hi, &format!("invalid digit for a base {} literal", base)); - } - } + (kind, Symbol::intern(lit_content)) } } diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index f075de71426..6373f5b4fd6 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -108,7 +108,7 @@ pub(crate) fn emit_unescape_error( } if !has_help { - let (prefix, msg) = if mode.is_bytes() { + let (prefix, msg) = if mode.is_byte() { ("b", "if you meant to write a byte string literal, use double quotes") } else { ("", "if you meant to write a `str` literal, use double quotes") @@ -142,7 +142,7 @@ pub(crate) fn emit_unescape_error( EscapeError::EscapeOnlyChar => { let (c, char_span) = last_char(); - let msg = if mode.is_bytes() { + let msg = if mode.is_byte() { "byte constant must be escaped" } else { "character constant must be escaped" @@ -182,11 +182,11 @@ pub(crate) fn emit_unescape_error( let (c, span) = last_char(); let label = - if mode.is_bytes() { "unknown byte escape" } else { "unknown character escape" }; + if mode.is_byte() { "unknown byte escape" } else { "unknown character escape" }; let ec = escaped_char(c); let mut diag = handler.struct_span_err(span, &format!("{}: `{}`", label, ec)); diag.span_label(span, label); - if c == '{' || c == '}' && !mode.is_bytes() { + if c == '{' || c == '}' && !mode.is_byte() { diag.help( "if used in a formatting string, curly braces are escaped with `{{` and `}}`", ); @@ -196,7 +196,7 @@ pub(crate) fn emit_unescape_error( version control settings", ); } else { - if !mode.is_bytes() { + if !mode.is_byte() { diag.span_suggestion( span_with_quotes, "if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal", @@ -231,16 +231,23 @@ pub(crate) fn emit_unescape_error( .emit(); } EscapeError::NonAsciiCharInByte => { - assert!(mode.is_bytes()); let (c, span) = last_char(); - let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant"); + let desc = match mode { + Mode::Byte => "byte literal", + Mode::ByteStr => "byte string literal", + Mode::RawByteStr => "raw byte string literal", + _ => panic!("non-is_byte literal paired with NonAsciiCharInByte"), + }; + let mut err = handler.struct_span_err(span, format!("non-ASCII character in {}", desc)); let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 { format!(" but is {:?}", c) } else { String::new() }; - err.span_label(span, &format!("byte constant must be ASCII{}", postfix)); - if (c as u32) <= 0xFF { + err.span_label(span, &format!("must be ASCII{}", postfix)); + // Note: the \\xHH suggestions are not given for raw byte string + // literals, because they are araw and so cannot use any escapes. + if (c as u32) <= 0xFF && mode != Mode::RawByteStr { err.span_suggestion( span, &format!( @@ -250,9 +257,9 @@ pub(crate) fn emit_unescape_error( format!("\\x{:X}", c as u32), Applicability::MaybeIncorrect, ); - } else if matches!(mode, Mode::Byte) { + } else if mode == Mode::Byte { err.span_label(span, "this multibyte character does not fit into a single byte"); - } else if matches!(mode, Mode::ByteStr) { + } else if mode != Mode::RawByteStr { let mut utf8 = String::new(); utf8.push(c); err.span_suggestion( @@ -270,19 +277,6 @@ pub(crate) fn emit_unescape_error( } err.emit(); } - EscapeError::NonAsciiCharInByteString => { - assert!(mode.is_bytes()); - let (c, span) = last_char(); - let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 { - format!(" but is {:?}", c) - } else { - String::new() - }; - handler - .struct_span_err(span, "raw byte string must be ASCII") - .span_label(span, &format!("must be ASCII{}", postfix)) - .emit(); - } EscapeError::OutOfRangeHexEscape => { handler .struct_span_err(span, "out of range hex escape") diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 7dc4fd0044f..0bbe073fe2a 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1653,15 +1653,29 @@ impl<'a> Parser<'a> { (token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => { self.bump(); + let sm = self.sess.source_map(); + let left = begin_par_sp; + let right = self.prev_token.span; + let left_snippet = if let Ok(snip) = sm.span_to_prev_source(left) && + !snip.ends_with(" ") { + " ".to_string() + } else { + "".to_string() + }; + + let right_snippet = if let Ok(snip) = sm.span_to_next_source(right) && + !snip.starts_with(" ") { + " ".to_string() + } else { + "".to_string() + }; + self.sess.emit_err(ParenthesesInForHead { - span: vec![begin_par_sp, self.prev_token.span], + span: vec![left, right], // With e.g. `for (x) in y)` this would replace `(x) in y)` // with `x) in y)` which is syntactically invalid. // However, this is prevented before we get here. - sugg: ParenthesesInForHeadSugg { - left: begin_par_sp, - right: self.prev_token.span, - }, + sugg: ParenthesesInForHeadSugg { left, right, left_snippet, right_snippet }, }); // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint. @@ -2468,11 +2482,15 @@ impl<'a> Parser<'a> { } pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool { - let Some(label) = self.eat_label().filter(|_| { - self.eat(&token::Colon) && self.token.kind == token::OpenDelim(Delimiter::Brace) - }) else { + // Check for `'a : {` + if !(self.check_lifetime() + && self.look_ahead(1, |tok| tok.kind == token::Colon) + && self.look_ahead(2, |tok| tok.kind == token::OpenDelim(Delimiter::Brace))) + { return false; - }; + } + let label = self.eat_label().expect("just checked if a label exists"); + self.bump(); // eat `:` let span = label.ident.span.to(self.prev_token.span); let mut err = self.struct_span_err(span, "block label not supported here"); err.span_label(span, "not supported here"); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0eb633f6416..7355730c9eb 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -9,9 +9,9 @@ use crate::errors::{ ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncMoveOrderIncorrect, BinaryFloatLiteralNotSupported, BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric, ComparisonOrShiftInterpretedAsGenericSugg, - DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedExpressionFoundLet, - FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, - HexadecimalFloatLiteralNotSupported, IfExpressionMissingCondition, + DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedEqForLetExpr, + ExpectedExpressionFoundLet, FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, + FoundExprWouldBeStmt, HexadecimalFloatLiteralNotSupported, IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, IntLiteralTooLarge, InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, InvalidIntLiteralWidth, @@ -20,9 +20,9 @@ use crate::errors::{ InvalidNumLiteralSuffix, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, - MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, - NotAsNegationOperator, NotAsNegationOperatorSub, OctalFloatLiteralNotSupported, - OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, + MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, + NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub, + OctalFloatLiteralNotSupported, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere, StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, @@ -33,6 +33,7 @@ use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::Spacing; +use rustc_ast::util::case::Case; use rustc_ast::util::classify; use rustc_ast::util::literal::LitError; use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity}; @@ -833,16 +834,11 @@ impl<'a> Parser<'a> { ("cast", None) }; - // Save the memory location of expr before parsing any following postfix operators. - // This will be compared with the memory location of the output expression. - // If they different we can assume we parsed another expression because the existing expression is not reallocated. - let addr_before = &*cast_expr as *const _ as usize; let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?; - let changed = addr_before != &*with_postfix as *const _ as usize; // Check if an illegal postfix operator has been added after the cast. - // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. - if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || changed { + // If the resulting expression is not a cast, it is an illegal postfix operator. + if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) { let msg = format!( "{cast_kind} cannot be followed by {}", match with_postfix.kind { @@ -2095,7 +2091,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; let asyncness = if self.token.uninterpolated_span().rust_2018() { - self.parse_asyncness() + self.parse_asyncness(Case::Sensitive) } else { Async::No }; @@ -2334,7 +2330,15 @@ impl<'a> Parser<'a> { RecoverColon::Yes, CommaRecoveryMode::LikelyTuple, )?; - self.expect(&token::Eq)?; + if self.token == token::EqEq { + self.sess.emit_err(ExpectedEqForLetExpr { + span: self.token.span, + sugg_span: self.token.span, + }); + self.bump(); + } else { + self.expect(&token::Eq)?; + } let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| { this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) })?; @@ -2880,7 +2884,7 @@ impl<'a> Parser<'a> { }; while self.token != token::CloseDelim(close_delim) { - if self.eat(&token::DotDot) { + if self.eat(&token::DotDot) || self.recover_struct_field_dots(close_delim) { let exp_span = self.prev_token.span; // We permit `.. }` on the left-hand side of a destructuring assignment. if self.check(&token::CloseDelim(close_delim)) { @@ -3027,6 +3031,18 @@ impl<'a> Parser<'a> { self.recover_stmt(); } + fn recover_struct_field_dots(&mut self, close_delim: Delimiter) -> bool { + if !self.look_ahead(1, |t| *t == token::CloseDelim(close_delim)) + && self.eat(&token::DotDotDot) + { + // recover from typo of `...`, suggest `..` + let span = self.prev_token.span; + self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span }); + return true; + } + false + } + /// Parses `ident (COLON expr)?`. fn parse_expr_field(&mut self) -> PResult<'a, ExprField> { let attrs = self.parse_outer_attributes()?; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index bda301c52e9..494f0cf56a8 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -8,6 +8,7 @@ use rustc_ast::ast::*; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; +use rustc_ast::util::case::Case; use rustc_ast::{self as ast, AttrVec, Attribute, DUMMY_NODE_ID}; use rustc_ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; use rustc_ast::{BindingAnnotation, Block, FnDecl, FnSig, Param, SelfKind}; @@ -34,7 +35,7 @@ impl<'a> Parser<'a> { /// Parses a `mod <foo> { ... }` or `mod <foo>;` item. fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> { - let unsafety = self.parse_unsafety(); + let unsafety = self.parse_unsafety(Case::Sensitive); self.expect_keyword(kw::Mod)?; let id = self.parse_ident()?; let mod_kind = if self.eat(&token::Semi) { @@ -143,8 +144,15 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let mut def = self.parse_defaultness(); - let kind = - self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, fn_parse_mode)?; + let kind = self.parse_item_kind( + &mut attrs, + mac_allowed, + lo, + &vis, + &mut def, + fn_parse_mode, + Case::Sensitive, + )?; if let Some((ident, kind)) = kind { self.error_on_unconsumed_default(def, &kind); let span = lo.to(self.prev_token.span); @@ -205,16 +213,17 @@ impl<'a> Parser<'a> { vis: &Visibility, def: &mut Defaultness, fn_parse_mode: FnParseMode, + case: Case, ) -> PResult<'a, Option<ItemInfo>> { let def_final = def == &Defaultness::Final; - let mut def = || mem::replace(def, Defaultness::Final); + let mut def_ = || mem::replace(def, Defaultness::Final); - let info = if self.eat_keyword(kw::Use) { + let info = if self.eat_keyword_case(kw::Use, case) { self.parse_use_item()? - } else if self.check_fn_front_matter(def_final) { + } else if self.check_fn_front_matter(def_final, case) { // FUNCTION ITEM let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo, vis)?; - (ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body }))) + (ident, ItemKind::Fn(Box::new(Fn { defaultness: def_(), sig, generics, body }))) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { // EXTERN CRATE @@ -225,7 +234,7 @@ impl<'a> Parser<'a> { } } else if self.is_unsafe_foreign_mod() { // EXTERN BLOCK - let unsafety = self.parse_unsafety(); + let unsafety = self.parse_unsafety(Case::Sensitive); self.expect_keyword(kw::Extern)?; self.parse_item_foreign_mod(attrs, unsafety)? } else if self.is_static_global() { @@ -234,15 +243,15 @@ impl<'a> Parser<'a> { let m = self.parse_mutability(); let (ident, ty, expr) = self.parse_item_global(Some(m))?; (ident, ItemKind::Static(ty, m, expr)) - } else if let Const::Yes(const_span) = self.parse_constness() { + } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { // recover from `const impl`, suggest `impl const` - self.recover_const_impl(const_span, attrs, def())? + self.recover_const_impl(const_span, attrs, def_())? } else { self.recover_const_mut(const_span); let (ident, ty, expr) = self.parse_item_global(None)?; - (ident, ItemKind::Const(def(), ty, expr)) + (ident, ItemKind::Const(def_(), ty, expr)) } } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() { // TRAIT ITEM @@ -251,7 +260,7 @@ impl<'a> Parser<'a> { || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) { // IMPL ITEM - self.parse_item_impl(attrs, def())? + self.parse_item_impl(attrs, def_())? } else if self.check_keyword(kw::Mod) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Mod]) { @@ -259,7 +268,7 @@ impl<'a> Parser<'a> { self.parse_item_mod(attrs)? } else if self.eat_keyword(kw::Type) { // TYPE ITEM - self.parse_type_alias(def())? + self.parse_type_alias(def_())? } else if self.eat_keyword(kw::Enum) { // ENUM ITEM self.parse_item_enum()? @@ -286,6 +295,19 @@ impl<'a> Parser<'a> { } else if self.isnt_macro_invocation() && vis.kind.is_pub() { self.recover_missing_kw_before_item()?; return Ok(None); + } else if self.isnt_macro_invocation() && case == Case::Sensitive { + _ = def_; + + // Recover wrong cased keywords + return self.parse_item_kind( + attrs, + macros_allowed, + lo, + vis, + def, + fn_parse_mode, + Case::Insensitive, + ); } else if macros_allowed && self.check_path() { // MACRO INVOCATION ITEM (Ident::empty(), ItemKind::MacCall(P(self.parse_item_macro(vis)?))) @@ -538,7 +560,7 @@ impl<'a> Parser<'a> { attrs: &mut AttrVec, defaultness: Defaultness, ) -> PResult<'a, ItemInfo> { - let unsafety = self.parse_unsafety(); + let unsafety = self.parse_unsafety(Case::Sensitive); self.expect_keyword(kw::Impl)?; // First, parse generic parameters if necessary. @@ -552,7 +574,7 @@ impl<'a> Parser<'a> { generics }; - let constness = self.parse_constness(); + let constness = self.parse_constness(Case::Sensitive); if let Const::Yes(span) = constness { self.sess.gated_spans.gate(sym::const_trait_impl, span); } @@ -796,7 +818,7 @@ impl<'a> Parser<'a> { /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> { - let unsafety = self.parse_unsafety(); + let unsafety = self.parse_unsafety(Case::Sensitive); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No }; @@ -971,6 +993,23 @@ impl<'a> Parser<'a> { if self.eat(&token::ModSep) { self.parse_use_tree_glob_or_nested()? } else { + // Recover from using a colon as path separator. + while self.eat_noexpect(&token::Colon) { + self.struct_span_err(self.prev_token.span, "expected `::`, found `:`") + .span_suggestion_short( + self.prev_token.span, + "use double colon", + "::", + Applicability::MachineApplicable, + ) + .note_once("import paths are delimited using `::`") + .emit(); + + // We parse the rest of the path and append it to the original prefix. + self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?; + prefix.span = lo.to(self.prev_token.span); + } + UseTreeKind::Simple(self.parse_rename()?, DUMMY_NODE_ID, DUMMY_NODE_ID) } }; @@ -1745,7 +1784,7 @@ impl<'a> Parser<'a> { let (ident, is_raw) = self.ident_or_err()?; if !is_raw && ident.is_reserved() { let snapshot = self.create_snapshot_for_diagnostic(); - let err = if self.check_fn_front_matter(false) { + let err = if self.check_fn_front_matter(false, Case::Sensitive) { let inherited_vis = Visibility { span: rustc_span::DUMMY_SP, kind: VisibilityKind::Inherited, @@ -2155,7 +2194,7 @@ impl<'a> Parser<'a> { /// /// `check_pub` adds additional `pub` to the checks in case users place it /// wrongly, can be used to ensure `pub` never comes after `default`. - pub(super) fn check_fn_front_matter(&mut self, check_pub: bool) -> bool { + pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool { // We use an over-approximation here. // `const const`, `fn const` won't parse, but we're not stepping over other syntax either. // `pub` is added in case users got confused with the ordering like `async pub fn`, @@ -2165,23 +2204,30 @@ impl<'a> Parser<'a> { } else { &[kw::Const, kw::Async, kw::Unsafe, kw::Extern] }; - self.check_keyword(kw::Fn) // Definitely an `fn`. + self.check_keyword_case(kw::Fn, case) // Definitely an `fn`. // `$qual fn` or `$qual $qual`: - || quals.iter().any(|&kw| self.check_keyword(kw)) + || quals.iter().any(|&kw| self.check_keyword_case(kw, case)) && self.look_ahead(1, |t| { // `$qual fn`, e.g. `const fn` or `async fn`. - t.is_keyword(kw::Fn) + t.is_keyword_case(kw::Fn, case) // Two qualifiers `$qual $qual` is enough, e.g. `async unsafe`. - || t.is_non_raw_ident_where(|i| quals.contains(&i.name) - // Rule out 2015 `const async: T = val`. - && i.is_reserved() + || ( + ( + t.is_non_raw_ident_where(|i| + quals.contains(&i.name) + // Rule out 2015 `const async: T = val`. + && i.is_reserved() + ) + || case == Case::Insensitive + && t.is_non_raw_ident_where(|i| quals.iter().any(|qual| qual.as_str() == i.name.as_str().to_lowercase())) + ) // Rule out unsafe extern block. && !self.is_unsafe_foreign_mod()) }) // `extern ABI fn` - || self.check_keyword(kw::Extern) + || self.check_keyword_case(kw::Extern, case) && self.look_ahead(1, |t| t.can_begin_literal_maybe_minus()) - && self.look_ahead(2, |t| t.is_keyword(kw::Fn)) + && self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) } /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, @@ -2197,22 +2243,22 @@ impl<'a> Parser<'a> { /// `Visibility::Inherited` when no visibility is known. pub(super) fn parse_fn_front_matter(&mut self, orig_vis: &Visibility) -> PResult<'a, FnHeader> { let sp_start = self.token.span; - let constness = self.parse_constness(); + let constness = self.parse_constness(Case::Insensitive); let async_start_sp = self.token.span; - let asyncness = self.parse_asyncness(); + let asyncness = self.parse_asyncness(Case::Insensitive); let unsafe_start_sp = self.token.span; - let unsafety = self.parse_unsafety(); + let unsafety = self.parse_unsafety(Case::Insensitive); let ext_start_sp = self.token.span; - let ext = self.parse_extern(); + let ext = self.parse_extern(Case::Insensitive); if let Async::Yes { span, .. } = asyncness { self.ban_async_in_2015(span); } - if !self.eat_keyword(kw::Fn) { + if !self.eat_keyword_case(kw::Fn, Case::Insensitive) { // It is possible for `expect_one_of` to recover given the contents of // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't // account for this. diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 2e59c005e31..14dc490fb02 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -22,6 +22,7 @@ use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind}; use rustc_ast::tokenstream::AttributesData; use rustc_ast::tokenstream::{self, DelimSpan, Spacing}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::util::case::Case; use rustc_ast::AttrId; use rustc_ast::DUMMY_NODE_ID; use rustc_ast::{self as ast, AnonConst, AttrStyle, AttrVec, Const, Extern}; @@ -636,6 +637,20 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw) } + fn check_keyword_case(&mut self, kw: Symbol, case: Case) -> bool { + if self.check_keyword(kw) { + return true; + } + + if case == Case::Insensitive + && let Some((ident, /* is_raw */ false)) = self.token.ident() + && ident.as_str().to_lowercase() == kw.as_str().to_lowercase() { + true + } else { + false + } + } + /// If the next token is the given keyword, eats it and returns `true`. /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes. // Public for rustfmt usage. @@ -648,6 +663,33 @@ impl<'a> Parser<'a> { } } + /// Eats a keyword, optionally ignoring the case. + /// If the case differs (and is ignored) an error is issued. + /// This is useful for recovery. + fn eat_keyword_case(&mut self, kw: Symbol, case: Case) -> bool { + if self.eat_keyword(kw) { + return true; + } + + if case == Case::Insensitive + && let Some((ident, /* is_raw */ false)) = self.token.ident() + && ident.as_str().to_lowercase() == kw.as_str().to_lowercase() { + self + .struct_span_err(ident.span, format!("keyword `{kw}` is written in a wrong case")) + .span_suggestion( + ident.span, + "write it in the correct case", + kw, + Applicability::MachineApplicable + ).emit(); + + self.bump(); + return true; + } + + false + } + fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool { if self.token.is_keyword(kw) { self.bump(); @@ -1127,8 +1169,8 @@ impl<'a> Parser<'a> { } /// Parses asyncness: `async` or nothing. - fn parse_asyncness(&mut self) -> Async { - if self.eat_keyword(kw::Async) { + fn parse_asyncness(&mut self, case: Case) -> Async { + if self.eat_keyword_case(kw::Async, case) { let span = self.prev_token.uninterpolated_span(); Async::Yes { span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID } } else { @@ -1137,8 +1179,8 @@ impl<'a> Parser<'a> { } /// Parses unsafety: `unsafe` or nothing. - fn parse_unsafety(&mut self) -> Unsafe { - if self.eat_keyword(kw::Unsafe) { + fn parse_unsafety(&mut self, case: Case) -> Unsafe { + if self.eat_keyword_case(kw::Unsafe, case) { Unsafe::Yes(self.prev_token.uninterpolated_span()) } else { Unsafe::No @@ -1146,10 +1188,10 @@ impl<'a> Parser<'a> { } /// Parses constness: `const` or nothing. - fn parse_constness(&mut self) -> Const { + fn parse_constness(&mut self, case: Case) -> Const { // Avoid const blocks to be parsed as const items if self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace)) - && self.eat_keyword(kw::Const) + && self.eat_keyword_case(kw::Const, case) { Const::Yes(self.prev_token.uninterpolated_span()) } else { @@ -1404,8 +1446,8 @@ impl<'a> Parser<'a> { } /// Parses `extern string_literal?`. - fn parse_extern(&mut self) -> Extern { - if self.eat_keyword(kw::Extern) { + fn parse_extern(&mut self, case: Case) -> Extern { + if self.eat_keyword_case(kw::Extern, case) { let mut extern_span = self.prev_token.span; let abi = self.parse_abi(); if let Some(abi) = abi { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index fdc1af27f82..d46565dea89 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -631,7 +631,9 @@ impl<'a> Parser<'a> { /// - A single-segment path. pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool { match &expr.kind { - ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) => true, + ast::ExprKind::Block(_, _) + | ast::ExprKind::Lit(_) + | ast::ExprKind::IncludedBytes(..) => true, ast::ExprKind::Unary(ast::UnOp::Neg, expr) => { matches!(expr.kind, ast::ExprKind::Lit(_)) } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 2a8512acf8c..4d78c5bd0e2 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -4,6 +4,7 @@ use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; +use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind, @@ -267,7 +268,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Underscore) { // A type to be inferred `_` TyKind::Infer - } else if self.check_fn_front_matter(false) { + } else if self.check_fn_front_matter(false, Case::Sensitive) { // Function pointer type self.parse_ty_bare_fn(lo, Vec::new(), recover_return_sign)? } else if self.check_keyword(kw::For) { @@ -275,7 +276,7 @@ impl<'a> Parser<'a> { // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` // `for<'lt> Trait1<'lt> + Trait2 + 'a` let lifetime_defs = self.parse_late_bound_lifetime_defs()?; - if self.check_fn_front_matter(false) { + if self.check_fn_front_matter(false, Case::Sensitive) { self.parse_ty_bare_fn(lo, lifetime_defs, recover_return_sign)? } else { let path = self.parse_path(PathStyle::Type)?; @@ -401,7 +402,7 @@ impl<'a> Parser<'a> { .span_suggestions( span.shrink_to_hi(), "add `mut` or `const` here", - ["mut ".to_string(), "const ".to_string()].into_iter(), + ["mut ".to_string(), "const ".to_string()], Applicability::HasPlaceholders, ) .emit(); diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 1394993abad..54bf4d1d6b7 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -819,19 +819,19 @@ fn find_skips_from_snippet( }; fn find_skips(snippet: &str, is_raw: bool) -> Vec<usize> { - let mut s = snippet.char_indices().peekable(); + let mut s = snippet.char_indices(); let mut skips = vec![]; while let Some((pos, c)) = s.next() { - match (c, s.peek()) { + match (c, s.clone().next()) { // skip whitespace and empty lines ending in '\\' ('\\', Some((next_pos, '\n'))) if !is_raw => { skips.push(pos); - skips.push(*next_pos); + skips.push(next_pos); let _ = s.next(); - while let Some((pos, c)) = s.peek() { + while let Some((pos, c)) = s.clone().next() { if matches!(c, ' ' | '\n' | '\t') { - skips.push(*pos); + skips.push(pos); let _ = s.next(); } else { break; @@ -839,7 +839,7 @@ fn find_skips_from_snippet( } } ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => { - skips.push(*next_pos); + skips.push(next_pos); let _ = s.next(); } ('\\', Some((_, 'x'))) if !is_raw => { @@ -858,19 +858,30 @@ fn find_skips_from_snippet( } if let Some((next_pos, next_c)) = s.next() { if next_c == '{' { - skips.push(next_pos); - let mut i = 0; // consume up to 6 hexanumeric chars + closing `}` - while let (Some((next_pos, c)), true) = (s.next(), i < 7) { - if c.is_digit(16) { - skips.push(next_pos); - } else if c == '}' { - skips.push(next_pos); - break; - } else { - break; - } - i += 1; + // consume up to 6 hexanumeric chars + let digits_len = + s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).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 + for pos in (next_pos..).take(required_skips + 2) { + skips.push(pos) } + + s.nth(digits_len); } else if next_c.is_digit(16) { skips.push(next_pos); // We suggest adding `{` and `}` when appropriate, accept it here as if diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 27a57adf964..2b6ff0a5cb9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -119,13 +119,13 @@ impl CheckAttrVisitor<'_> { } sym::naked => self.check_naked(hir_id, attr, span, target), sym::rustc_legacy_const_generics => { - self.check_rustc_legacy_const_generics(&attr, span, target, item) + self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item) } sym::rustc_lint_query_instability => { - self.check_rustc_lint_query_instability(&attr, span, target) + self.check_rustc_lint_query_instability(hir_id, &attr, span, target) } sym::rustc_lint_diagnostics => { - self.check_rustc_lint_diagnostics(&attr, span, target) + self.check_rustc_lint_diagnostics(hir_id, &attr, span, target) } sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(&attr, span, target), sym::rustc_lint_opt_deny_field_access => { @@ -135,11 +135,13 @@ impl CheckAttrVisitor<'_> { | sym::rustc_dirty | sym::rustc_if_this_changed | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr), - sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target), + sym::cmse_nonsecure_entry => { + self.check_cmse_nonsecure_entry(hir_id, attr, span, target) + } sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target), sym::const_trait => self.check_const_trait(attr, span, target), sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), - sym::must_use => self.check_must_use(hir_id, &attr, span, target), + sym::must_use => self.check_must_use(hir_id, &attr, target), sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target), sym::rustc_allow_incoherent_impl => { self.check_allow_incoherent_impl(&attr, span, target) @@ -386,6 +388,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -393,7 +396,13 @@ impl CheckAttrVisitor<'_> { } /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition. - fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_cmse_nonsecure_entry( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { match target { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, @@ -401,6 +410,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -465,9 +475,11 @@ impl CheckAttrVisitor<'_> { true } _ => { - self.tcx - .sess - .emit_err(errors::TrackedCallerWrongLocation { attr_span, defn_span: span }); + self.tcx.sess.emit_err(errors::TrackedCallerWrongLocation { + attr_span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); false } } @@ -576,6 +588,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -1163,17 +1176,7 @@ impl CheckAttrVisitor<'_> { } /// Warns against some misuses of `#[must_use]` - fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { - let node = self.tcx.hir().get(hir_id); - if let Some(kind) = node.fn_kind() && let rustc_hir::IsAsync::Async = kind.asyncness() { - self.tcx.emit_spanned_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span, - errors::MustUseAsync { span } - ); - } - + fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool { if !matches!( target, Target::Fn @@ -1240,7 +1243,7 @@ impl CheckAttrVisitor<'_> { UNUSED_ATTRIBUTES, hir_id, attr.span, - errors::Cold { span }, + errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID }, ); } } @@ -1376,6 +1379,7 @@ impl CheckAttrVisitor<'_> { /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. fn check_rustc_legacy_const_generics( &self, + hir_id: HirId, attr: &Attribute, span: Span, target: Target, @@ -1386,6 +1390,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); return false; } @@ -1450,12 +1455,19 @@ impl CheckAttrVisitor<'_> { /// Helper function for checking that the provided attribute is only applied to a function or /// method. - fn check_applied_to_fn_or_method(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_applied_to_fn_or_method( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { let is_function = matches!(target, Target::Fn | Target::Method(..)); if !is_function { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } else { @@ -1467,17 +1479,24 @@ impl CheckAttrVisitor<'_> { /// or method. fn check_rustc_lint_query_instability( &self, + hir_id: HirId, attr: &Attribute, span: Span, target: Target, ) -> bool { - self.check_applied_to_fn_or_method(attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or /// method. - fn check_rustc_lint_diagnostics(&self, attr: &Attribute, span: Span, target: Target) -> bool { - self.check_applied_to_fn_or_method(attr, span, target) + fn check_rustc_lint_diagnostics( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct. diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index b779edbc30f..21b487d8ca1 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -4,7 +4,7 @@ use itertools::Itertools; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{pluralize, Applicability, MultiSpan}; +use rustc_errors::MultiSpan; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -18,7 +18,10 @@ use rustc_session::lint; use rustc_span::symbol::{sym, Symbol}; use std::mem; -use crate::errors::UselessAssignment; +use crate::errors::{ + ChangeFieldsToBeOfUnitType, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, + UselessAssignment, +}; // Any local node that may call something in its body block should be // explored. For example, if it's a live Node::Item that is a @@ -693,99 +696,89 @@ impl<'tcx> DeadVisitor<'tcx> { parent_item: Option<LocalDefId>, is_positional: bool, ) { - if let Some(&first_id) = dead_codes.first() { - let tcx = self.tcx; - let names: Vec<_> = dead_codes - .iter() - .map(|&def_id| tcx.item_name(def_id.to_def_id()).to_string()) - .collect(); - let spans: Vec<_> = dead_codes - .iter() - .map(|&def_id| match tcx.def_ident_span(def_id) { - Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()), - None => tcx.def_span(def_id), + let Some(&first_id) = dead_codes.first() else { + return; + }; + let tcx = self.tcx; + let names: Vec<_> = + dead_codes.iter().map(|&def_id| tcx.item_name(def_id.to_def_id())).collect(); + let spans: Vec<_> = dead_codes + .iter() + .map(|&def_id| match tcx.def_ident_span(def_id) { + Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()), + None => tcx.def_span(def_id), + }) + .collect(); + + let descr = tcx.def_kind(first_id).descr(first_id.to_def_id()); + let num = dead_codes.len(); + let multiple = num > 6; + let name_list = names.into(); + + let lint = if is_positional { + lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS + } else { + lint::builtin::DEAD_CODE + }; + + let parent_info = if let Some(parent_item) = parent_item { + let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id()); + Some(ParentInfo { + num, + descr, + parent_descr, + span: tcx.def_ident_span(parent_item).unwrap(), + }) + } else { + None + }; + + let encl_def_id = parent_item.unwrap_or(first_id); + let ignored_derived_impls = + if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) { + let trait_list = ign_traits + .iter() + .map(|(trait_id, _)| self.tcx.item_name(*trait_id)) + .collect::<Vec<_>>(); + let trait_list_len = trait_list.len(); + Some(IgnoredDerivedImpls { + name: self.tcx.item_name(encl_def_id.to_def_id()), + trait_list: trait_list.into(), + trait_list_len, }) - .collect(); - - let descr = tcx.def_kind(first_id).descr(first_id.to_def_id()); - let span_len = dead_codes.len(); - let names = match &names[..] { - _ if span_len > 6 => String::new(), - [name] => format!("`{name}` "), - [names @ .., last] => { - format!( - "{} and `{last}` ", - names.iter().map(|name| format!("`{name}`")).join(", ") - ) - } - [] => unreachable!(), + } else { + None }; - let msg = format!( - "{these}{descr}{s} {names}{are} never {participle}", - these = if span_len > 6 { "multiple " } else { "" }, - s = pluralize!(span_len), - are = pluralize!("is", span_len), - ); - - tcx.struct_span_lint_hir( - if is_positional { - lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS - } else { - lint::builtin::DEAD_CODE - }, - tcx.hir().local_def_id_to_hir_id(first_id), - MultiSpan::from_spans(spans.clone()), - msg, - |err| { - if is_positional { - err.multipart_suggestion( - &format!( - "consider changing the field{s} to be of unit type to \ - suppress this warning while preserving the field \ - numbering, or remove the field{s}", - s = pluralize!(span_len) - ), - spans.iter().map(|sp| (*sp, "()".to_string())).collect(), - // "HasPlaceholders" because applying this fix by itself isn't - // enough: All constructor calls have to be adjusted as well - Applicability::HasPlaceholders, - ); - } - if let Some(parent_item) = parent_item { - let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id()); - err.span_label( - tcx.def_ident_span(parent_item).unwrap(), - format!("{descr}{s} in this {parent_descr}", s = pluralize!(span_len)), - ); - } + let diag = if is_positional { + MultipleDeadCodes::UnusedTupleStructFields { + multiple, + num, + descr, + participle, + name_list, + change_fields_suggestion: ChangeFieldsToBeOfUnitType { num, spans: spans.clone() }, + parent_info, + ignored_derived_impls, + } + } else { + MultipleDeadCodes::DeadCodes { + multiple, + num, + descr, + participle, + name_list, + parent_info, + ignored_derived_impls, + } + }; - let encl_def_id = parent_item.unwrap_or(first_id); - if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) { - let traits_str = ign_traits - .iter() - .map(|(trait_id, _)| format!("`{}`", self.tcx.item_name(*trait_id))) - .collect::<Vec<_>>() - .join(" and "); - let plural_s = pluralize!(ign_traits.len()); - let article = if ign_traits.len() > 1 { "" } else { "a " }; - let is_are = if ign_traits.len() > 1 { "these are" } else { "this is" }; - let msg = format!( - "`{}` has {}derived impl{} for the trait{} {}, but {} \ - intentionally ignored during dead code analysis", - self.tcx.item_name(encl_def_id.to_def_id()), - article, - plural_s, - plural_s, - traits_str, - is_are - ); - err.note(&msg); - } - err - }, - ); - } + self.tcx.emit_spanned_lint( + lint, + tcx.hir().local_def_id_to_hir_id(first_id), + MultiSpan::from_spans(spans.clone()), + diag, + ); } fn warn_dead_fields_and_variants( diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index fb883ae2ed0..c6cd69add28 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -4,7 +4,9 @@ use std::{ }; use rustc_ast::Label; -use rustc_errors::{error_code, Applicability, ErrorGuaranteed, IntoDiagnostic, MultiSpan}; +use rustc_errors::{ + error_code, Applicability, DiagnosticSymbolList, ErrorGuaranteed, IntoDiagnostic, MultiSpan, +}; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{MainDefinition, Ty}; @@ -79,6 +81,7 @@ pub struct AttrShouldBeAppliedToFn { pub attr_span: Span, #[label] pub defn_span: Span, + pub on_crate: bool, } #[derive(Diagnostic)] @@ -95,6 +98,7 @@ pub struct TrackedCallerWrongLocation { pub attr_span: Span, #[label] pub defn_span: Span, + pub on_crate: bool, } #[derive(Diagnostic)] @@ -365,6 +369,7 @@ pub struct MustNotSuspend { pub struct Cold { #[label] pub span: Span, + pub on_crate: bool, } #[derive(LintDiagnostic)] @@ -954,6 +959,7 @@ pub struct OutsideLoop<'a> { #[label] pub span: Span, pub name: &'a str, + pub is_break: bool, } #[derive(Diagnostic)] @@ -1446,3 +1452,59 @@ pub struct MissingConstErr { #[label] pub const_span: Span, } + +#[derive(LintDiagnostic)] +pub enum MultipleDeadCodes<'tcx> { + #[diag(passes_dead_codes)] + DeadCodes { + multiple: bool, + num: usize, + descr: &'tcx str, + participle: &'tcx str, + name_list: DiagnosticSymbolList, + #[subdiagnostic] + parent_info: Option<ParentInfo<'tcx>>, + #[subdiagnostic] + ignored_derived_impls: Option<IgnoredDerivedImpls>, + }, + #[diag(passes_dead_codes)] + UnusedTupleStructFields { + multiple: bool, + num: usize, + descr: &'tcx str, + participle: &'tcx str, + name_list: DiagnosticSymbolList, + #[subdiagnostic] + change_fields_suggestion: ChangeFieldsToBeOfUnitType, + #[subdiagnostic] + parent_info: Option<ParentInfo<'tcx>>, + #[subdiagnostic] + ignored_derived_impls: Option<IgnoredDerivedImpls>, + }, +} + +#[derive(Subdiagnostic)] +#[label(passes_parent_info)] +pub struct ParentInfo<'tcx> { + pub num: usize, + pub descr: &'tcx str, + pub parent_descr: &'tcx str, + #[primary_span] + pub span: Span, +} + +#[derive(Subdiagnostic)] +#[note(passes_ignored_derived_impls)] +pub struct IgnoredDerivedImpls { + pub name: Symbol, + pub trait_list: DiagnosticSymbolList, + pub trait_list_len: usize, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(passes_change_fields_to_be_of_unit_type, applicability = "has-placeholders")] +pub struct ChangeFieldsToBeOfUnitType { + pub num: usize, + #[suggestion_part(code = "()")] + pub spans: Vec<Span>, +} diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 33220fd2b39..140f02c046a 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -560,13 +560,14 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_expr(&mut self, e: &'v ast::Expr) { + #[rustfmt::skip] record_variants!( (self, e, e.kind, Id::None, ast, Expr, ExprKind), [ Box, Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let, If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign, AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret, - InlineAsm, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, Err + InlineAsm, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err ] ); ast_visit::walk_expr(self, e) diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 15f60f626c8..6e621b7eb5e 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -5,8 +5,6 @@ //! This API is completely unstable and subject to change. #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(iter_intersperse)] #![feature(let_chains)] diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index c6fe40f72fc..c181de48a9a 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -87,6 +87,7 @@ use self::VarKind::*; use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; +use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::*; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -1690,7 +1691,7 @@ impl<'tcx> Liveness<'_, 'tcx> { &self, name: &str, opt_body: Option<&hir::Body<'_>>, - err: &mut rustc_errors::DiagnosticBuilder<'_, ()>, + err: &mut Diagnostic, ) -> bool { let mut has_litstring = false; let Some(opt_body) = opt_body else {return false;}; diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 077194ec687..b4cf19e4a34 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -193,7 +193,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name }); } Normal | AnonConst => { - self.sess.emit_err(OutsideLoop { span, name }); + self.sess.emit_err(OutsideLoop { span, name, is_break: name == "break" }); } } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 865d6306bd3..e17f85c1aae 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -959,6 +959,10 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { for variant in def.variants.iter() { let variant_id = self.tcx.hir().local_def_id(variant.id); self.effective_visibility_diagnostic(variant_id); + if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { + let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); + self.effective_visibility_diagnostic(ctor_def_id); + } for field in variant.data.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); self.effective_visibility_diagnostic(def_id); @@ -966,6 +970,10 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { } } hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { + if let Some(ctor_hir_id) = def.ctor_hir_id() { + let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); + self.effective_visibility_diagnostic(ctor_def_id); + } for field in def.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); self.effective_visibility_diagnostic(def_id); @@ -2131,6 +2139,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { changed: false, }; + visitor.effective_visibilities.check_invariants(tcx, true); loop { tcx.hir().walk_toplevel_module(&mut visitor); if visitor.changed { @@ -2139,6 +2148,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { break; } } + visitor.effective_visibilities.check_invariants(tcx, false); let mut check_visitor = TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities }; diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index e7f12caaf33..b2111a1262a 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -21,7 +21,7 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -thin-vec = "0.2.8" +thin-vec = "0.2.9" tracing = "0.1" [features] diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 11d4c97e71c..18cb0e0ca0b 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -36,7 +36,7 @@ mod keys; use keys::Key; pub use rustc_query_system::query::QueryConfig; -pub(crate) use rustc_query_system::query::{QueryDescription, QueryVTable}; +pub(crate) use rustc_query_system::query::QueryVTable; mod on_disk_cache; pub use on_disk_cache::OnDiskCache; diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 8b14ce210a2..eaed9aeb850 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -119,12 +119,11 @@ pub type EncodedDepNodeIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; struct SourceFileIndex(u32); #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)] -pub struct AbsoluteBytePos(u32); +pub struct AbsoluteBytePos(u64); impl AbsoluteBytePos { fn new(pos: usize) -> AbsoluteBytePos { - debug_assert!(pos <= u32::MAX as usize); - AbsoluteBytePos(pos as u32) + AbsoluteBytePos(pos.try_into().expect("Incremental cache file size overflowed u64.")) } fn to_usize(self) -> usize { @@ -1063,7 +1062,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>( query_result_index: &mut EncodedDepNodeIndex, ) where CTX: QueryContext + 'tcx, - Q: super::QueryDescription<CTX>, + Q: super::QueryConfig<CTX>, Q::Value: Encodable<CacheEncoder<'a, 'tcx>>, { let _timer = tcx diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 1d17f422196..992e777904e 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -17,8 +17,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ - force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap, - QuerySideEffects, QueryStackFrame, + force_query, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame, }; use rustc_query_system::{LayoutOfDepth, QueryOverflow, Value}; use rustc_serialize::Decodable; @@ -340,7 +339,7 @@ pub(crate) fn create_query_frame< fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) where - Q: QueryDescription<QueryCtxt<'tcx>>, + Q: QueryConfig<QueryCtxt<'tcx>>, Q::Key: DepNodeParams<TyCtxt<'tcx>>, { debug_assert!(tcx.dep_graph.is_green(&dep_node)); @@ -365,7 +364,7 @@ where fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where - Q: QueryDescription<QueryCtxt<'tcx>>, + Q: QueryConfig<QueryCtxt<'tcx>>, Q::Key: DepNodeParams<TyCtxt<'tcx>>, Q::Value: Value<TyCtxt<'tcx>>, { @@ -398,12 +397,9 @@ where } } -pub(crate) fn query_callback<'tcx, Q: QueryConfig>( - is_anon: bool, - is_eval_always: bool, -) -> DepKindStruct<'tcx> +pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx> where - Q: QueryDescription<QueryCtxt<'tcx>>, + Q: QueryConfig<QueryCtxt<'tcx>>, Q::Key: DepNodeParams<TyCtxt<'tcx>>, { let fingerprint_style = Q::Key::fingerprint_style(); @@ -458,14 +454,12 @@ macro_rules! define_queries { })* } - $(impl<'tcx> QueryConfig for queries::$name<'tcx> { + $(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> { type Key = query_keys::$name<'tcx>; type Value = query_values::$name<'tcx>; type Stored = query_stored::$name<'tcx>; const NAME: &'static str = stringify!($name); - } - impl<'tcx> QueryDescription<QueryCtxt<'tcx>> for queries::$name<'tcx> { #[inline] fn cache_on_disk(tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool { ::rustc_middle::query::cached::$name(tcx, key) @@ -662,12 +656,15 @@ macro_rules! define_queries_struct { local_providers: Box<Providers>, extern_providers: Box<ExternProviders>, query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>, - pub on_disk_cache: Option<OnDiskCache<'tcx>>, - jobs: AtomicU64, - $($(#[$attr])* $name: QueryState<<queries::$name<'tcx> as QueryConfig>::Key>,)* + $( + $(#[$attr])* + $name: QueryState< + <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key + >, + )* } impl<'tcx> Queries<'tcx> { @@ -704,7 +701,7 @@ macro_rules! define_queries_struct { &'tcx self, tcx: TyCtxt<'tcx>, span: Span, - key: <queries::$name<'tcx> as QueryConfig>::Key, + key: <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key, mode: QueryMode, ) -> Option<query_stored::$name<'tcx>> { let qcx = QueryCtxt { tcx, queries: self }; diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 2cc311d48c8..81114f2cd82 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -19,18 +19,18 @@ impl QueryKeyStringCache { } } -struct QueryKeyStringBuilder<'p, 'c, 'tcx> { +struct QueryKeyStringBuilder<'p, 'tcx> { profiler: &'p SelfProfiler, tcx: TyCtxt<'tcx>, - string_cache: &'c mut QueryKeyStringCache, + string_cache: &'p mut QueryKeyStringCache, } -impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> { +impl<'p, 'tcx> QueryKeyStringBuilder<'p, 'tcx> { fn new( profiler: &'p SelfProfiler, tcx: TyCtxt<'tcx>, - string_cache: &'c mut QueryKeyStringCache, - ) -> QueryKeyStringBuilder<'p, 'c, 'tcx> { + string_cache: &'p mut QueryKeyStringCache, + ) -> QueryKeyStringBuilder<'p, 'tcx> { QueryKeyStringBuilder { profiler, tcx, string_cache } } @@ -99,7 +99,7 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> { } trait IntoSelfProfilingString { - fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId; + fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId; } // The default implementation of `IntoSelfProfilingString` just uses `Debug` @@ -109,7 +109,7 @@ trait IntoSelfProfilingString { impl<T: Debug> IntoSelfProfilingString for T { default fn to_self_profile_string( &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, + builder: &mut QueryKeyStringBuilder<'_, '_>, ) -> StringId { let s = format!("{:?}", self); builder.profiler.alloc_string(&s[..]) @@ -117,60 +117,42 @@ impl<T: Debug> IntoSelfProfilingString for T { } impl<T: SpecIntoSelfProfilingString> IntoSelfProfilingString for T { - fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId { + fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { self.spec_to_self_profile_string(builder) } } #[rustc_specialization_trait] trait SpecIntoSelfProfilingString: Debug { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId; + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId; } impl SpecIntoSelfProfilingString for DefId { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { builder.def_id_to_string_id(*self) } } impl SpecIntoSelfProfilingString for CrateNum { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { builder.def_id_to_string_id(self.as_def_id()) } } impl SpecIntoSelfProfilingString for DefIndex { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self }) } } impl SpecIntoSelfProfilingString for LocalDefId { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: self.local_def_index }) } } impl<T: SpecIntoSelfProfilingString> SpecIntoSelfProfilingString for WithOptConstParam<T> { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { // We print `WithOptConstParam` values as tuples to make them shorter // and more readable, without losing information: // @@ -205,10 +187,7 @@ where T0: SpecIntoSelfProfilingString, T1: SpecIntoSelfProfilingString, { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { let val0 = self.0.to_self_profile_string(builder); let val1 = self.1.to_self_profile_string(builder); diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index faddad74171..028756b5a0a 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -22,7 +22,7 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.8" +thin-vec = "0.2.9" tracing = "0.1" [features] diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_query_system/src/cache.rs index d592812f79b..7cc885be2ba 100644 --- a/compiler/rustc_query_system/src/cache.rs +++ b/compiler/rustc_query_system/src/cache.rs @@ -26,7 +26,7 @@ impl<Key, Value> Cache<Key, Value> { } impl<Key: Eq + Hash, Value: Clone> Cache<Key, Value> { - pub fn get<CTX: DepContext>(&self, key: &Key, tcx: CTX) -> Option<Value> { + pub fn get<Tcx: DepContext>(&self, key: &Key, tcx: Tcx) -> Option<Value> { Some(self.hashmap.borrow().get(key)?.get(tcx)) } @@ -46,7 +46,7 @@ impl<T: Clone> WithDepNode<T> { WithDepNode { dep_node, cached_value } } - pub fn get<CTX: DepContext>(&self, tcx: CTX) -> T { + pub fn get<Tcx: DepContext>(&self, tcx: Tcx) -> T { tcx.dep_graph().read_index(self.dep_node); self.cached_value.clone() } diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 5c6ce0556eb..d79c5816a9c 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -61,18 +61,18 @@ impl<K: DepKind> DepNode<K> { /// Creates a new, parameterless DepNode. This method will assert /// that the DepNode corresponding to the given DepKind actually /// does not require any parameters. - pub fn new_no_params<Ctxt>(tcx: Ctxt, kind: K) -> DepNode<K> + pub fn new_no_params<Tcx>(tcx: Tcx, kind: K) -> DepNode<K> where - Ctxt: super::DepContext<DepKind = K>, + Tcx: super::DepContext<DepKind = K>, { debug_assert_eq!(tcx.fingerprint_style(kind), FingerprintStyle::Unit); DepNode { kind, hash: Fingerprint::ZERO.into() } } - pub fn construct<Ctxt, Key>(tcx: Ctxt, kind: K, arg: &Key) -> DepNode<K> + pub fn construct<Tcx, Key>(tcx: Tcx, kind: K, arg: &Key) -> DepNode<K> where - Ctxt: super::DepContext<DepKind = K>, - Key: DepNodeParams<Ctxt>, + Tcx: super::DepContext<DepKind = K>, + Key: DepNodeParams<Tcx>, { let hash = arg.to_fingerprint(tcx); let dep_node = DepNode { kind, hash: hash.into() }; @@ -93,9 +93,9 @@ impl<K: DepKind> DepNode<K> { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - pub fn from_def_path_hash<Ctxt>(tcx: Ctxt, def_path_hash: DefPathHash, kind: K) -> Self + pub fn from_def_path_hash<Tcx>(tcx: Tcx, def_path_hash: DefPathHash, kind: K) -> Self where - Ctxt: super::DepContext<DepKind = K>, + Tcx: super::DepContext<DepKind = K>, { debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); DepNode { kind, hash: def_path_hash.0.into() } @@ -108,18 +108,18 @@ impl<K: DepKind> fmt::Debug for DepNode<K> { } } -pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized { +pub trait DepNodeParams<Tcx: DepContext>: fmt::Debug + Sized { fn fingerprint_style() -> FingerprintStyle; /// This method turns the parameters of a DepNodeConstructor into an opaque /// Fingerprint to be used in DepNode. /// Not all DepNodeParams support being turned into a Fingerprint (they /// don't need to if the corresponding DepNode is anonymous). - fn to_fingerprint(&self, _: Ctxt) -> Fingerprint { + fn to_fingerprint(&self, _: Tcx) -> Fingerprint { panic!("Not implemented. Accidentally called on anonymous node?") } - fn to_debug_str(&self, _: Ctxt) -> String { + fn to_debug_str(&self, _: Tcx) -> String { format!("{:?}", self) } @@ -129,10 +129,10 @@ pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized { /// `fingerprint_style()` is not `FingerprintStyle::Opaque`. /// It is always valid to return `None` here, in which case incremental /// compilation will treat the query as having changed instead of forcing it. - fn recover(tcx: Ctxt, dep_node: &DepNode<Ctxt::DepKind>) -> Option<Self>; + fn recover(tcx: Tcx, dep_node: &DepNode<Tcx::DepKind>) -> Option<Self>; } -impl<Ctxt: DepContext, T> DepNodeParams<Ctxt> for T +impl<Tcx: DepContext, T> DepNodeParams<Tcx> for T where T: for<'a> HashStable<StableHashingContext<'a>> + fmt::Debug, { @@ -142,7 +142,7 @@ where } #[inline(always)] - default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint { + default fn to_fingerprint(&self, tcx: Tcx) -> Fingerprint { tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); self.hash_stable(&mut hcx, &mut hasher); @@ -151,12 +151,12 @@ where } #[inline(always)] - default fn to_debug_str(&self, _: Ctxt) -> String { + default fn to_debug_str(&self, _: Tcx) -> String { format!("{:?}", *self) } #[inline(always)] - default fn recover(_: Ctxt, _: &DepNode<Ctxt::DepKind>) -> Option<Self> { + default fn recover(_: Tcx, _: &DepNode<Tcx::DepKind>) -> Option<Self> { None } } @@ -166,7 +166,7 @@ where /// Information is retrieved by indexing the `DEP_KINDS` array using the integer value /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual /// jump table instead of large matches. -pub struct DepKindStruct<CTX: DepContext> { +pub struct DepKindStruct<Tcx: DepContext> { /// Anonymous queries cannot be replayed from one compiler invocation to the next. /// When their result is needed, it is recomputed. They are useful for fine-grained /// dependency tracking, and caching within one compiler invocation. @@ -216,10 +216,10 @@ pub struct DepKindStruct<CTX: DepContext> { /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` /// is actually a `DefPathHash`, and can therefore just look up the corresponding /// `DefId` in `tcx.def_path_hash_to_def_id`. - pub force_from_dep_node: Option<fn(tcx: CTX, dep_node: DepNode<CTX::DepKind>) -> bool>, + pub force_from_dep_node: Option<fn(tcx: Tcx, dep_node: DepNode<Tcx::DepKind>) -> bool>, /// Invoke a query to put the on-disk cached value in memory. - pub try_load_from_on_disk_cache: Option<fn(CTX, DepNode<CTX::DepKind>)>, + pub try_load_from_on_disk_cache: Option<fn(Tcx, DepNode<Tcx::DepKind>)>, } /// A "work product" corresponds to a `.o` (or other) file that we diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 8ff56132749..d86c0bebdcd 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -377,9 +377,9 @@ impl<K: DepKind> DepGraph<K> { /// Executes something within an "anonymous" task, that is, a task the /// `DepNode` of which is determined by the list of inputs it read from. - pub fn with_anon_task<Ctxt: DepContext<DepKind = K>, OP, R>( + pub fn with_anon_task<Tcx: DepContext<DepKind = K>, OP, R>( &self, - cx: Ctxt, + cx: Tcx, dep_kind: K, op: OP, ) -> (R, DepNodeIndex) @@ -571,12 +571,12 @@ impl<K: DepKind> DepGraph<K> { /// A node will have an index, when it's already been marked green, or when we can mark it /// green. This function will mark the current task as a reader of the specified node, when /// a node index can be found for that node. - pub fn try_mark_green<Ctxt: QueryContext<DepKind = K>>( + pub fn try_mark_green<Qcx: QueryContext<DepKind = K>>( &self, - tcx: Ctxt, + qcx: Qcx, dep_node: &DepNode<K>, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { - debug_assert!(!tcx.dep_context().is_eval_always(dep_node.kind)); + debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); // Return None if the dep graph is disabled let data = self.data.as_ref()?; @@ -592,15 +592,16 @@ impl<K: DepKind> DepGraph<K> { // in the previous compilation session too, so we can try to // mark it as green by recursively marking all of its // dependencies green. - self.try_mark_previous_green(tcx, data, prev_index, &dep_node) + self.try_mark_previous_green(qcx, data, prev_index, &dep_node) .map(|dep_node_index| (prev_index, dep_node_index)) } } } - fn try_mark_parent_green<Ctxt: QueryContext<DepKind = K>>( + #[instrument(skip(self, qcx, data, parent_dep_node_index), level = "debug")] + fn try_mark_parent_green<Qcx: QueryContext<DepKind = K>>( &self, - tcx: Ctxt, + qcx: Qcx, data: &DepGraphData<K>, parent_dep_node_index: SerializedDepNodeIndex, dep_node: &DepNode<K>, @@ -613,11 +614,7 @@ impl<K: DepKind> DepGraph<K> { // This dependency has been marked as green before, we are // still fine and can continue with checking the other // dependencies. - debug!( - "try_mark_previous_green({:?}) --- found dependency {:?} to \ - be immediately green", - dep_node, dep_dep_node, - ); + debug!("dependency {dep_dep_node:?} was immediately green"); return Some(()); } Some(DepNodeColor::Red) => { @@ -625,10 +622,7 @@ impl<K: DepKind> DepGraph<K> { // compared to the previous compilation session. We cannot // mark the DepNode as green and also don't need to bother // with checking any of the other dependencies. - debug!( - "try_mark_previous_green({:?}) - END - dependency {:?} was immediately red", - dep_node, dep_dep_node, - ); + debug!("dependency {dep_dep_node:?} was immediately red"); return None; } None => {} @@ -636,35 +630,26 @@ impl<K: DepKind> DepGraph<K> { // We don't know the state of this dependency. If it isn't // an eval_always node, let's try to mark it green recursively. - if !tcx.dep_context().is_eval_always(dep_dep_node.kind) { + if !qcx.dep_context().is_eval_always(dep_dep_node.kind) { debug!( - "try_mark_previous_green({:?}) --- state of dependency {:?} ({}) \ - is unknown, trying to mark it green", - dep_node, dep_dep_node, dep_dep_node.hash, + "state of dependency {:?} ({}) is unknown, trying to mark it green", + dep_dep_node, dep_dep_node.hash, ); let node_index = - self.try_mark_previous_green(tcx, data, parent_dep_node_index, dep_dep_node); + self.try_mark_previous_green(qcx, data, parent_dep_node_index, dep_dep_node); + if node_index.is_some() { - debug!( - "try_mark_previous_green({:?}) --- managed to MARK dependency {:?} as green", - dep_node, dep_dep_node - ); + debug!("managed to MARK dependency {dep_dep_node:?} as green",); return Some(()); } } // We failed to mark it green, so we try to force the query. - debug!( - "try_mark_previous_green({:?}) --- trying to force dependency {:?}", - dep_node, dep_dep_node - ); - if !tcx.dep_context().try_force_from_dep_node(*dep_dep_node) { + debug!("trying to force dependency {dep_dep_node:?}"); + if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node) { // The DepNode could not be forced. - debug!( - "try_mark_previous_green({:?}) - END - dependency {:?} could not be forced", - dep_node, dep_dep_node - ); + debug!("dependency {dep_dep_node:?} could not be forced"); return None; } @@ -672,23 +657,17 @@ impl<K: DepKind> DepGraph<K> { match dep_dep_node_color { Some(DepNodeColor::Green(_)) => { - debug!( - "try_mark_previous_green({:?}) --- managed to FORCE dependency {:?} to green", - dep_node, dep_dep_node - ); + debug!("managed to FORCE dependency {dep_dep_node:?} to green"); return Some(()); } Some(DepNodeColor::Red) => { - debug!( - "try_mark_previous_green({:?}) - END - dependency {:?} was red after forcing", - dep_node, dep_dep_node - ); + debug!("dependency {dep_dep_node:?} was red after forcing",); return None; } None => {} } - if !tcx.dep_context().sess().has_errors_or_delayed_span_bugs() { + if !qcx.dep_context().sess().has_errors_or_delayed_span_bugs() { panic!("try_mark_previous_green() - Forcing the DepNode should have set its color") } @@ -702,23 +681,19 @@ impl<K: DepKind> DepGraph<K> { // invalid state will not be persisted to the // incremental compilation cache because of // compilation errors being present. - debug!( - "try_mark_previous_green({:?}) - END - dependency {:?} resulted in compilation error", - dep_node, dep_dep_node - ); + debug!("dependency {dep_dep_node:?} resulted in compilation error",); return None; } /// Try to mark a dep-node which existed in the previous compilation session as green. - fn try_mark_previous_green<Ctxt: QueryContext<DepKind = K>>( + #[instrument(skip(self, qcx, data, prev_dep_node_index), level = "debug")] + fn try_mark_previous_green<Qcx: QueryContext<DepKind = K>>( &self, - tcx: Ctxt, + qcx: Qcx, data: &DepGraphData<K>, prev_dep_node_index: SerializedDepNodeIndex, dep_node: &DepNode<K>, ) -> Option<DepNodeIndex> { - debug!("try_mark_previous_green({:?}) - BEGIN", dep_node); - #[cfg(not(parallel_compiler))] { debug_assert!(!self.dep_node_exists(dep_node)); @@ -726,14 +701,14 @@ impl<K: DepKind> DepGraph<K> { } // We never try to mark eval_always nodes as green - debug_assert!(!tcx.dep_context().is_eval_always(dep_node.kind)); + debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); debug_assert_eq!(data.previous.index_to_node(prev_dep_node_index), *dep_node); let prev_deps = data.previous.edge_targets_from(prev_dep_node_index); for &dep_dep_node_index in prev_deps { - self.try_mark_parent_green(tcx, data, dep_dep_node_index, dep_node)? + self.try_mark_parent_green(qcx, data, dep_dep_node_index, dep_node)? } // If we got here without hitting a `return` that means that all @@ -745,7 +720,7 @@ impl<K: DepKind> DepGraph<K> { // We allocating an entry for the node in the current dependency graph and // adding all the appropriate edges imported from the previous graph let dep_node_index = data.current.promote_node_and_deps_to_current( - tcx.dep_context().profiler(), + qcx.dep_context().profiler(), &data.previous, prev_dep_node_index, ); @@ -754,7 +729,7 @@ impl<K: DepKind> DepGraph<K> { // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere // Maybe store a list on disk and encode this fact in the DepNodeState - let side_effects = tcx.load_side_effects(prev_dep_node_index); + let side_effects = qcx.load_side_effects(prev_dep_node_index); #[cfg(not(parallel_compiler))] debug_assert!( @@ -765,14 +740,14 @@ impl<K: DepKind> DepGraph<K> { ); if !side_effects.is_empty() { - self.emit_side_effects(tcx, data, dep_node_index, side_effects); + self.emit_side_effects(qcx, data, dep_node_index, side_effects); } // ... and finally storing a "Green" entry in the color map. // Multiple threads can all write the same color here data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index)); - debug!("try_mark_previous_green({:?}) - END - successfully marked as green", dep_node); + debug!("successfully marked {dep_node:?} as green"); Some(dep_node_index) } @@ -780,9 +755,9 @@ impl<K: DepKind> DepGraph<K> { /// This may be called concurrently on multiple threads for the same dep node. #[cold] #[inline(never)] - fn emit_side_effects<Ctxt: QueryContext<DepKind = K>>( + fn emit_side_effects<Qcx: QueryContext<DepKind = K>>( &self, - tcx: Ctxt, + qcx: Qcx, data: &DepGraphData<K>, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects, @@ -794,9 +769,9 @@ impl<K: DepKind> DepGraph<K> { // must process side effects // Promote the previous diagnostics to the current session. - tcx.store_side_effects(dep_node_index, side_effects.clone()); + qcx.store_side_effects(dep_node_index, side_effects.clone()); - let handle = tcx.dep_context().sess().diagnostic(); + let handle = qcx.dep_context().sess().diagnostic(); for mut diagnostic in side_effects.diagnostics { handle.emit_diagnostic(&mut diagnostic); @@ -824,7 +799,7 @@ impl<K: DepKind> DepGraph<K> { // // This method will only load queries that will end up in the disk cache. // Other queries will not be executed. - pub fn exec_cache_promotions<Ctxt: DepContext<DepKind = K>>(&self, tcx: Ctxt) { + pub fn exec_cache_promotions<Tcx: DepContext<DepKind = K>>(&self, tcx: Tcx) { let _prof_timer = tcx.profiler().generic_activity("incr_comp_query_cache_promotion"); let data = self.data.as_ref().unwrap(); diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index da2075fd5aa..e370c6990a4 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -52,9 +52,8 @@ pub trait DepContext: Copy { } /// Try to force a dep node to execute and see if it's green. + #[instrument(skip(self), level = "debug")] fn try_force_from_dep_node(self, dep_node: DepNode<Self::DepKind>) -> bool { - debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); - let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.force_from_dep_node { f(self, dep_node); diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 0a1cffa3b33..f40e174b7e7 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -11,59 +11,57 @@ use rustc_data_structures::fingerprint::Fingerprint; use std::fmt::Debug; use std::hash::Hash; -pub trait QueryConfig { +pub trait QueryConfig<Qcx: QueryContext> { const NAME: &'static str; type Key: Eq + Hash + Clone + Debug; type Value; type Stored: Clone; + + type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>; + + // Don't use this method to access query results, instead use the methods on TyCtxt + fn query_state<'a>(tcx: Qcx) -> &'a QueryState<Self::Key> + where + Qcx: 'a; + + // Don't use this method to access query results, instead use the methods on TyCtxt + fn query_cache<'a>(tcx: Qcx) -> &'a Self::Cache + where + Qcx: 'a; + + // Don't use this method to compute query results, instead use the methods on TyCtxt + fn make_vtable(tcx: Qcx, key: &Self::Key) -> QueryVTable<Qcx, Self::Key, Self::Value>; + + fn cache_on_disk(tcx: Qcx::DepContext, key: &Self::Key) -> bool; + + // Don't use this method to compute query results, instead use the methods on TyCtxt + fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Stored; } #[derive(Copy, Clone)] -pub struct QueryVTable<CTX: QueryContext, K, V> { +pub struct QueryVTable<Qcx: QueryContext, K, V> { pub anon: bool, - pub dep_kind: CTX::DepKind, + pub dep_kind: Qcx::DepKind, pub eval_always: bool, pub depth_limit: bool, - pub compute: fn(CTX::DepContext, K) -> V, + pub compute: fn(Qcx::DepContext, K) -> V, pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>, pub handle_cycle_error: HandleCycleError, // NOTE: this is also `None` if `cache_on_disk()` returns false, not just if it's unsupported by the query - pub try_load_from_disk: Option<fn(CTX, SerializedDepNodeIndex) -> Option<V>>, + pub try_load_from_disk: Option<fn(Qcx, SerializedDepNodeIndex) -> Option<V>>, } -impl<CTX: QueryContext, K, V> QueryVTable<CTX, K, V> { - pub(crate) fn to_dep_node(&self, tcx: CTX::DepContext, key: &K) -> DepNode<CTX::DepKind> +impl<Qcx: QueryContext, K, V> QueryVTable<Qcx, K, V> { + pub(crate) fn to_dep_node(&self, tcx: Qcx::DepContext, key: &K) -> DepNode<Qcx::DepKind> where - K: crate::dep_graph::DepNodeParams<CTX::DepContext>, + K: crate::dep_graph::DepNodeParams<Qcx::DepContext>, { DepNode::construct(tcx, self.dep_kind, key) } - pub(crate) fn compute(&self, tcx: CTX::DepContext, key: K) -> V { + pub(crate) fn compute(&self, tcx: Qcx::DepContext, key: K) -> V { (self.compute)(tcx, key) } } - -pub trait QueryDescription<CTX: QueryContext>: QueryConfig { - type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>; - - // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(tcx: CTX) -> &'a QueryState<Self::Key> - where - CTX: 'a; - - // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_cache<'a>(tcx: CTX) -> &'a Self::Cache - where - CTX: 'a; - - // Don't use this method to compute query results, instead use the methods on TyCtxt - fn make_vtable(tcx: CTX, key: &Self::Key) -> QueryVTable<CTX, Self::Key, Self::Value>; - - fn cache_on_disk(tcx: CTX::DepContext, key: &Self::Key) -> bool; - - // Don't use this method to compute query results, instead use the methods on TyCtxt - fn execute_query(tcx: CTX::DepContext, k: Self::Key) -> Self::Stored; -} diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index ed65393f57e..49bbcf57804 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -596,8 +596,8 @@ pub(crate) fn report_cycle<'a>( cycle_diag.into_diagnostic(&sess.parse_sess.span_diagnostic) } -pub fn print_query_stack<CTX: QueryContext>( - tcx: CTX, +pub fn print_query_stack<Qcx: QueryContext>( + qcx: Qcx, mut current_query: Option<QueryJobId>, handler: &Handler, num_frames: Option<usize>, @@ -606,7 +606,7 @@ pub fn print_query_stack<CTX: QueryContext>( // a panic hook, which means that the global `Handler` may be in a weird // state if it was responsible for triggering the panic. let mut i = 0; - let query_map = tcx.try_collect_active_jobs(); + let query_map = qcx.try_collect_active_jobs(); while let Some(query) = current_query { if Some(i) == num_frames { diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 118703fc0d4..94adef41e68 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -12,7 +12,7 @@ pub use self::caches::{ }; mod config; -pub use self::config::{QueryConfig, QueryDescription, QueryVTable}; +pub use self::config::{QueryConfig, QueryVTable}; use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; use rustc_data_structures::sync::Lock; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 15b89daa6db..f8d93a27d1c 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -4,7 +4,7 @@ use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams}; use crate::query::caches::QueryCache; -use crate::query::config::{QueryDescription, QueryVTable}; +use crate::query::config::QueryVTable; use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo}; use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame}; use crate::values::Value; @@ -27,6 +27,8 @@ use std::mem; use std::ptr; use thin_vec::ThinVec; +use super::QueryConfig; + pub struct QueryState<K> { #[cfg(parallel_compiler)] active: Sharded<FxHashMap<K, QueryResult>>, @@ -60,10 +62,10 @@ where } } - pub fn try_collect_active_jobs<CTX: Copy>( + pub fn try_collect_active_jobs<Qcx: Copy>( &self, - tcx: CTX, - make_query: fn(CTX, K) -> QueryStackFrame, + qcx: Qcx, + make_query: fn(Qcx, K) -> QueryStackFrame, jobs: &mut QueryMap, ) -> Option<()> { #[cfg(parallel_compiler)] @@ -74,7 +76,7 @@ where for shard in shards.iter() { for (k, v) in shard.iter() { if let QueryResult::Started(ref job) = *v { - let query = make_query(tcx, k.clone()); + let query = make_query(qcx, k.clone()); jobs.insert(job.id, QueryJobInfo { query, job: job.clone() }); } } @@ -88,7 +90,7 @@ where // really hurt much.) for (k, v) in self.active.try_lock()?.iter() { if let QueryResult::Started(ref job) = *v { - let query = make_query(tcx, k.clone()); + let query = make_query(qcx, k.clone()); jobs.insert(job.id, QueryJobInfo { query, job: job.clone() }); } } @@ -117,31 +119,31 @@ where #[cold] #[inline(never)] -fn mk_cycle<CTX, V, R>( - tcx: CTX, +fn mk_cycle<Qcx, V, R>( + qcx: Qcx, cycle_error: CycleError, handler: HandleCycleError, cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>, ) -> R where - CTX: QueryContext, - V: std::fmt::Debug + Value<CTX::DepContext>, + Qcx: QueryContext, + V: std::fmt::Debug + Value<Qcx::DepContext>, R: Clone, { - let error = report_cycle(tcx.dep_context().sess(), &cycle_error); - let value = handle_cycle_error(*tcx.dep_context(), &cycle_error, error, handler); + let error = report_cycle(qcx.dep_context().sess(), &cycle_error); + let value = handle_cycle_error(*qcx.dep_context(), &cycle_error, error, handler); cache.store_nocache(value) } -fn handle_cycle_error<CTX, V>( - tcx: CTX, +fn handle_cycle_error<Tcx, V>( + tcx: Tcx, cycle_error: &CycleError, mut error: DiagnosticBuilder<'_, ErrorGuaranteed>, handler: HandleCycleError, ) -> V where - CTX: DepContext, - V: Value<CTX>, + Tcx: DepContext, + V: Value<Tcx>, { use HandleCycleError::*; match handler { @@ -174,14 +176,14 @@ where /// This function is inlined because that results in a noticeable speed-up /// for some compile-time benchmarks. #[inline(always)] - fn try_start<'b, CTX>( - tcx: &'b CTX, + fn try_start<'b, Qcx>( + qcx: &'b Qcx, state: &'b QueryState<K>, span: Span, key: K, ) -> TryGetJob<'b, K> where - CTX: QueryContext, + Qcx: QueryContext, { #[cfg(parallel_compiler)] let mut state_lock = state.active.get_shard_by_value(&key).lock(); @@ -191,8 +193,8 @@ where match lock.entry(key) { Entry::Vacant(entry) => { - let id = tcx.next_job_id(); - let job = tcx.current_query_job(); + let id = qcx.next_job_id(); + let job = qcx.current_query_job(); let job = QueryJob::new(id, span, job); let key = entry.key().clone(); @@ -211,8 +213,8 @@ where // If we are single-threaded we know that we have cycle error, // so we just return the error. return TryGetJob::Cycle(id.find_cycle_in_stack( - tcx.try_collect_active_jobs().unwrap(), - &tcx.current_query_job(), + qcx.try_collect_active_jobs().unwrap(), + &qcx.current_query_job(), span, )); } @@ -221,7 +223,7 @@ where // For parallel queries, we'll block and wait until the query running // in another thread has completed. Record how long we wait in the // self-profiler. - let query_blocked_prof_timer = tcx.dep_context().profiler().query_blocked(); + let query_blocked_prof_timer = qcx.dep_context().profiler().query_blocked(); // Get the latch out let latch = job.latch(); @@ -230,7 +232,7 @@ where // With parallel queries we might just have to wait on some other // thread. - let result = latch.wait_on(tcx.current_query_job(), span); + let result = latch.wait_on(qcx.current_query_job(), span); match result { Ok(()) => TryGetJob::JobCompleted(query_blocked_prof_timer), @@ -333,8 +335,8 @@ where /// which will be used if the query is not in the cache and we need /// to compute it. #[inline] -pub fn try_get_cached<'a, CTX, C, R, OnHit>( - tcx: CTX, +pub fn try_get_cached<'a, Tcx, C, R, OnHit>( + tcx: Tcx, cache: &'a C, key: &C::Key, // `on_hit` can be called while holding a lock to the query cache @@ -342,7 +344,7 @@ pub fn try_get_cached<'a, CTX, C, R, OnHit>( ) -> Result<R, ()> where C: QueryCache, - CTX: DepContext, + Tcx: DepContext, OnHit: FnOnce(&C::Stored) -> R, { cache.lookup(&key, |value, index| { @@ -354,29 +356,29 @@ where }) } -fn try_execute_query<CTX, C>( - tcx: CTX, +fn try_execute_query<Qcx, C>( + qcx: Qcx, state: &QueryState<C::Key>, cache: &C, span: Span, key: C::Key, - dep_node: Option<DepNode<CTX::DepKind>>, - query: &QueryVTable<CTX, C::Key, C::Value>, + dep_node: Option<DepNode<Qcx::DepKind>>, + query: &QueryVTable<Qcx, C::Key, C::Value>, ) -> (C::Stored, Option<DepNodeIndex>) where C: QueryCache, - C::Key: Clone + DepNodeParams<CTX::DepContext>, - C::Value: Value<CTX::DepContext>, - CTX: QueryContext, + C::Key: Clone + DepNodeParams<Qcx::DepContext>, + C::Value: Value<Qcx::DepContext>, + Qcx: QueryContext, { - match JobOwner::<'_, C::Key>::try_start(&tcx, state, span, key.clone()) { + match JobOwner::<'_, C::Key>::try_start(&qcx, state, span, key.clone()) { TryGetJob::NotYetStarted(job) => { - let (result, dep_node_index) = execute_job(tcx, key, dep_node, query, job.id); + let (result, dep_node_index) = execute_job(qcx, key, dep_node, query, job.id); let result = job.complete(cache, result, dep_node_index); (result, Some(dep_node_index)) } TryGetJob::Cycle(error) => { - let result = mk_cycle(tcx, error, query.handle_cycle_error, cache); + let result = mk_cycle(qcx, error, query.handle_cycle_error, cache); (result, None) } #[cfg(parallel_compiler)] @@ -385,8 +387,8 @@ where .lookup(&key, |value, index| (value.clone(), index)) .unwrap_or_else(|_| panic!("value must be in cache after waiting")); - if std::intrinsics::unlikely(tcx.dep_context().profiler().enabled()) { - tcx.dep_context().profiler().query_cache_hit(index.into()); + if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) { + qcx.dep_context().profiler().query_cache_hit(index.into()); } query_blocked_prof_timer.finish_with_query_invocation_id(index.into()); @@ -395,25 +397,25 @@ where } } -fn execute_job<CTX, K, V>( - tcx: CTX, +fn execute_job<Qcx, K, V>( + qcx: Qcx, key: K, - mut dep_node_opt: Option<DepNode<CTX::DepKind>>, - query: &QueryVTable<CTX, K, V>, + mut dep_node_opt: Option<DepNode<Qcx::DepKind>>, + query: &QueryVTable<Qcx, K, V>, job_id: QueryJobId, ) -> (V, DepNodeIndex) where - K: Clone + DepNodeParams<CTX::DepContext>, + K: Clone + DepNodeParams<Qcx::DepContext>, V: Debug, - CTX: QueryContext, + Qcx: QueryContext, { - let dep_graph = tcx.dep_context().dep_graph(); + let dep_graph = qcx.dep_context().dep_graph(); // Fast path for when incr. comp. is off. if !dep_graph.is_fully_enabled() { - let prof_timer = tcx.dep_context().profiler().query_provider(); - let result = tcx.start_query(job_id, query.depth_limit, None, || { - query.compute(*tcx.dep_context(), key) + let prof_timer = qcx.dep_context().profiler().query_provider(); + let result = qcx.start_query(job_id, query.depth_limit, None, || { + query.compute(*qcx.dep_context(), key) }); let dep_node_index = dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -423,33 +425,33 @@ where if !query.anon && !query.eval_always { // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.get_or_insert_with(|| query.to_dep_node(*tcx.dep_context(), &key)); + dep_node_opt.get_or_insert_with(|| query.to_dep_node(*qcx.dep_context(), &key)); // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. - if let Some(ret) = tcx.start_query(job_id, false, None, || { - try_load_from_disk_and_cache_in_memory(tcx, &key, &dep_node, query) + if let Some(ret) = qcx.start_query(job_id, false, None, || { + try_load_from_disk_and_cache_in_memory(qcx, &key, &dep_node, query) }) { return ret; } } - let prof_timer = tcx.dep_context().profiler().query_provider(); + let prof_timer = qcx.dep_context().profiler().query_provider(); let diagnostics = Lock::new(ThinVec::new()); let (result, dep_node_index) = - tcx.start_query(job_id, query.depth_limit, Some(&diagnostics), || { + qcx.start_query(job_id, query.depth_limit, Some(&diagnostics), || { if query.anon { - return dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || { - query.compute(*tcx.dep_context(), key) + return dep_graph.with_anon_task(*qcx.dep_context(), query.dep_kind, || { + query.compute(*qcx.dep_context(), key) }); } // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.unwrap_or_else(|| query.to_dep_node(*tcx.dep_context(), &key)); + dep_node_opt.unwrap_or_else(|| query.to_dep_node(*qcx.dep_context(), &key)); - dep_graph.with_task(dep_node, *tcx.dep_context(), key, query.compute, query.hash_result) + dep_graph.with_task(dep_node, *qcx.dep_context(), key, query.compute, query.hash_result) }); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -459,55 +461,55 @@ where if std::intrinsics::unlikely(!side_effects.is_empty()) { if query.anon { - tcx.store_side_effects_for_anon_node(dep_node_index, side_effects); + qcx.store_side_effects_for_anon_node(dep_node_index, side_effects); } else { - tcx.store_side_effects(dep_node_index, side_effects); + qcx.store_side_effects(dep_node_index, side_effects); } } (result, dep_node_index) } -fn try_load_from_disk_and_cache_in_memory<CTX, K, V>( - tcx: CTX, +fn try_load_from_disk_and_cache_in_memory<Qcx, K, V>( + qcx: Qcx, key: &K, - dep_node: &DepNode<CTX::DepKind>, - query: &QueryVTable<CTX, K, V>, + dep_node: &DepNode<Qcx::DepKind>, + query: &QueryVTable<Qcx, K, V>, ) -> Option<(V, DepNodeIndex)> where K: Clone, - CTX: QueryContext, + Qcx: QueryContext, V: Debug, { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. - let dep_graph = tcx.dep_context().dep_graph(); - let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(tcx, &dep_node)?; + let dep_graph = qcx.dep_context().dep_graph(); + let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(qcx, &dep_node)?; debug_assert!(dep_graph.is_green(dep_node)); // First we try to load the result from the on-disk cache. // Some things are never cached on disk. if let Some(try_load_from_disk) = query.try_load_from_disk { - let prof_timer = tcx.dep_context().profiler().incr_cache_loading(); + let prof_timer = qcx.dep_context().profiler().incr_cache_loading(); // The call to `with_query_deserialization` enforces that no new `DepNodes` // are created during deserialization. See the docs of that method for more // details. let result = - dep_graph.with_query_deserialization(|| try_load_from_disk(tcx, prev_dep_node_index)); + dep_graph.with_query_deserialization(|| try_load_from_disk(qcx, prev_dep_node_index)); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); if let Some(result) = result { if std::intrinsics::unlikely( - tcx.dep_context().sess().opts.unstable_opts.query_dep_graph, + qcx.dep_context().sess().opts.unstable_opts.query_dep_graph, ) { dep_graph.mark_debug_loaded_from_disk(*dep_node) } - let prev_fingerprint = tcx + let prev_fingerprint = qcx .dep_context() .dep_graph() .prev_fingerprint_of(dep_node) @@ -521,9 +523,9 @@ where // give us some coverage of potential bugs though. let try_verify = prev_fingerprint.as_value().1 % 32 == 0; if std::intrinsics::unlikely( - try_verify || tcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich, + try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich, ) { - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query); } return Some((result, dep_node_index)); @@ -532,7 +534,7 @@ where // We always expect to find a cached result for things that // can be forced from `DepNode`. debug_assert!( - !tcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), + !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), "missing on-disk cache entry for {:?}", dep_node ); @@ -540,10 +542,10 @@ where // We could not load a result from the on-disk cache, so // recompute. - let prof_timer = tcx.dep_context().profiler().query_provider(); + let prof_timer = qcx.dep_context().profiler().query_provider(); // The dep-graph for this computation is already in-place. - let result = dep_graph.with_ignore(|| query.compute(*tcx.dep_context(), key.clone())); + let result = dep_graph.with_ignore(|| query.compute(*qcx.dep_context(), key.clone())); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -556,34 +558,38 @@ where // // See issue #82920 for an example of a miscompilation that would get turned into // an ICE by this check - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query); Some((result, dep_node_index)) } -fn incremental_verify_ich<CTX, K, V: Debug>( - tcx: CTX::DepContext, +#[instrument(skip(qcx, result, query), level = "debug")] +fn incremental_verify_ich<Qcx, K, V: Debug>( + qcx: Qcx::DepContext, result: &V, - dep_node: &DepNode<CTX::DepKind>, - query: &QueryVTable<CTX, K, V>, + dep_node: &DepNode<Qcx::DepKind>, + query: &QueryVTable<Qcx, K, V>, ) where - CTX: QueryContext, + Qcx: QueryContext, { assert!( - tcx.dep_graph().is_green(dep_node), + qcx.dep_graph().is_green(dep_node), "fingerprint for green query instance not loaded from cache: {:?}", dep_node, ); - debug!("BEGIN verify_ich({:?})", dep_node); let new_hash = query.hash_result.map_or(Fingerprint::ZERO, |f| { - tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) + qcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) }); - let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node); - debug!("END verify_ich({:?})", dep_node); + + let old_hash = qcx.dep_graph().prev_fingerprint_of(dep_node); if Some(new_hash) != old_hash { - incremental_verify_ich_cold(tcx.sess(), DebugArg::from(&dep_node), DebugArg::from(&result)); + incremental_verify_ich_failed( + qcx.sess(), + DebugArg::from(&dep_node), + DebugArg::from(&result), + ); } } @@ -629,13 +635,7 @@ impl std::fmt::Debug for DebugArg<'_> { // different implementations for LLVM to chew on (and filling up the final // binary, too). #[cold] -fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: DebugArg<'_>) { - let run_cmd = if let Some(crate_name) = &sess.opts.crate_name { - format!("`cargo clean -p {}` or `cargo clean`", crate_name) - } else { - "`cargo clean`".to_string() - }; - +fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result: DebugArg<'_>) { // When we emit an error message and panic, we try to debug-print the `DepNode` // and query result. Unfortunately, this can cause us to run additional queries, // which may result in another fingerprint mismatch while we're in the middle @@ -651,6 +651,12 @@ fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: D if old_in_panic { sess.emit_err(crate::error::Reentrant); } else { + let run_cmd = if let Some(crate_name) = &sess.opts.crate_name { + format!("`cargo clean -p {}` or `cargo clean`", crate_name) + } else { + "`cargo clean`".to_string() + }; + sess.emit_err(crate::error::IncrementCompilation { run_cmd, dep_node: format!("{:?}", dep_node), @@ -670,14 +676,14 @@ fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: D /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run<CTX, K, V>( - tcx: CTX, +fn ensure_must_run<Qcx, K, V>( + qcx: Qcx, key: &K, - query: &QueryVTable<CTX, K, V>, -) -> (bool, Option<DepNode<CTX::DepKind>>) + query: &QueryVTable<Qcx, K, V>, +) -> (bool, Option<DepNode<Qcx::DepKind>>) where - K: crate::dep_graph::DepNodeParams<CTX::DepContext>, - CTX: QueryContext, + K: crate::dep_graph::DepNodeParams<Qcx::DepContext>, + Qcx: QueryContext, { if query.eval_always { return (true, None); @@ -686,10 +692,10 @@ where // Ensuring an anonymous query makes no sense assert!(!query.anon); - let dep_node = query.to_dep_node(*tcx.dep_context(), key); + let dep_node = query.to_dep_node(*qcx.dep_context(), key); - let dep_graph = tcx.dep_context().dep_graph(); - match dep_graph.try_mark_green(tcx, &dep_node) { + let dep_graph = qcx.dep_context().dep_graph(); + match dep_graph.try_mark_green(qcx, &dep_node) { None => { // A None return from `try_mark_green` means that this is either // a new dep node or that the dep node has already been marked red. @@ -701,7 +707,7 @@ where } Some((_, dep_node_index)) => { dep_graph.read_index(dep_node_index); - tcx.dep_context().profiler().query_cache_hit(dep_node_index.into()); + qcx.dep_context().profiler().query_cache_hit(dep_node_index.into()); (false, None) } } @@ -713,16 +719,16 @@ pub enum QueryMode { Ensure, } -pub fn get_query<Q, CTX>(tcx: CTX, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Stored> +pub fn get_query<Q, Qcx>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Stored> where - Q: QueryDescription<CTX>, - Q::Key: DepNodeParams<CTX::DepContext>, - Q::Value: Value<CTX::DepContext>, - CTX: QueryContext, + Q: QueryConfig<Qcx>, + Q::Key: DepNodeParams<Qcx::DepContext>, + Q::Value: Value<Qcx::DepContext>, + Qcx: QueryContext, { - let query = Q::make_vtable(tcx, &key); + let query = Q::make_vtable(qcx, &key); let dep_node = if let QueryMode::Ensure = mode { - let (must_run, dep_node) = ensure_must_run(tcx, &key, &query); + let (must_run, dep_node) = ensure_must_run(qcx, &key, &query); if !must_run { return None; } @@ -732,33 +738,33 @@ where }; let (result, dep_node_index) = try_execute_query( - tcx, - Q::query_state(tcx), - Q::query_cache(tcx), + qcx, + Q::query_state(qcx), + Q::query_cache(qcx), span, key, dep_node, &query, ); if let Some(dep_node_index) = dep_node_index { - tcx.dep_context().dep_graph().read_index(dep_node_index) + qcx.dep_context().dep_graph().read_index(dep_node_index) } Some(result) } -pub fn force_query<Q, CTX>(tcx: CTX, key: Q::Key, dep_node: DepNode<CTX::DepKind>) +pub fn force_query<Q, Qcx>(qcx: Qcx, key: Q::Key, dep_node: DepNode<Qcx::DepKind>) where - Q: QueryDescription<CTX>, - Q::Key: DepNodeParams<CTX::DepContext>, - Q::Value: Value<CTX::DepContext>, - CTX: QueryContext, + Q: QueryConfig<Qcx>, + Q::Key: DepNodeParams<Qcx::DepContext>, + Q::Value: Value<Qcx::DepContext>, + Qcx: QueryContext, { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. - let cache = Q::query_cache(tcx); + let cache = Q::query_cache(qcx); let cached = cache.lookup(&key, |_, index| { - if std::intrinsics::unlikely(tcx.dep_context().profiler().enabled()) { - tcx.dep_context().profiler().query_cache_hit(index.into()); + if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) { + qcx.dep_context().profiler().query_cache_hit(index.into()); } }); @@ -767,9 +773,9 @@ where Err(()) => {} } - let query = Q::make_vtable(tcx, &key); - let state = Q::query_state(tcx); + let query = Q::make_vtable(qcx, &key); + let state = Q::query_state(qcx); debug_assert!(!query.anon); - try_execute_query(tcx, state, cache, DUMMY_SP, key, Some(dep_node), &query); + try_execute_query(qcx, state, cache, DUMMY_SP, key, Some(dep_node), &query); } diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs index 67fbf14e612..214656abed4 100644 --- a/compiler/rustc_query_system/src/values.rs +++ b/compiler/rustc_query_system/src/values.rs @@ -1,12 +1,12 @@ use crate::dep_graph::DepContext; use crate::query::QueryInfo; -pub trait Value<CTX: DepContext>: Sized { - fn from_cycle_error(tcx: CTX, cycle: &[QueryInfo]) -> Self; +pub trait Value<Tcx: DepContext>: Sized { + fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo]) -> Self; } -impl<CTX: DepContext, T> Value<CTX> for T { - default fn from_cycle_error(tcx: CTX, _: &[QueryInfo]) -> T { +impl<Tcx: DepContext, T> Value<Tcx> for T { + default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo]) -> T { tcx.sess().abort_if_errors(); // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's // non-trivial to define it earlier. diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7961e3f1194..a12918b2979 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -241,10 +241,12 @@ impl<'a> Resolver<'a> { )); err.span_label(span, format!("`{}` re{} here", name, new_participle)); - err.span_label( - self.session.source_map().guess_head_span(old_binding.span), - format!("previous {} of the {} `{}` here", old_noun, old_kind, name), - ); + if !old_binding.span.is_dummy() && old_binding.span != span { + err.span_label( + self.session.source_map().guess_head_span(old_binding.span), + format!("previous {} of the {} `{}` here", old_noun, old_kind, name), + ); + } // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 17ce854cb43..fa6d34be0cc 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -1,16 +1,38 @@ -use crate::{ImportKind, NameBindingKind, Resolver}; +use crate::{ImportKind, NameBinding, NameBindingKind, Resolver, ResolverTree}; use rustc_ast::ast; use rustc_ast::visit; use rustc_ast::visit::Visitor; use rustc_ast::Crate; use rustc_ast::EnumDef; +use rustc_data_structures::intern::Interned; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_middle::middle::privacy::Level; -use rustc_middle::ty::{DefIdTree, Visibility}; +use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; +use rustc_middle::ty::Visibility; + +type ImportId<'a> = Interned<'a, NameBinding<'a>>; + +#[derive(Clone, Copy)] +enum ParentId<'a> { + Def(LocalDefId), + Import(ImportId<'a>), +} + +impl ParentId<'_> { + fn level(self) -> Level { + match self { + ParentId::Def(_) => Level::Direct, + ParentId::Import(_) => Level::Reexported, + } + } +} pub struct EffectiveVisibilitiesVisitor<'r, 'a> { r: &'r mut Resolver<'a>, + /// While walking import chains we need to track effective visibilities per-binding, and def id + /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple + /// bindings can correspond to a single def id in imports. So we keep a separate table. + import_effective_visibilities: EffectiveVisibilities<ImportId<'a>>, changed: bool, } @@ -19,21 +41,57 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> { /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we /// need access to a TyCtxt for that. pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) { - let mut visitor = EffectiveVisibilitiesVisitor { r, changed: false }; + let mut visitor = EffectiveVisibilitiesVisitor { + r, + import_effective_visibilities: Default::default(), + changed: false, + }; - visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, Level::Direct); + visitor.update(CRATE_DEF_ID, CRATE_DEF_ID); visitor.set_bindings_effective_visibilities(CRATE_DEF_ID); while visitor.changed { - visitor.reset(); + visitor.changed = false; visit::walk_crate(&mut visitor, krate); } + // Update visibilities for import def ids. These are not used during the + // `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based + // information, but are used by later passes. Effective visibility of an import def id + // is the maximum value among visibilities of bindings corresponding to that def id. + for (binding, eff_vis) in visitor.import_effective_visibilities.iter() { + let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; + if let Some(node_id) = import.id() { + let mut update = |node_id| { + r.effective_visibilities.update_eff_vis( + r.local_def_id(node_id), + eff_vis, + ResolverTree(&r.definitions, &r.crate_loader), + ) + }; + update(node_id); + if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind { + // In theory all the single import IDs have individual visibilities and + // effective visibilities, but in practice these IDs go straigth to HIR + // where all their few uses assume that their (effective) visibility + // applies to the whole syntactic `use` item. So they all get the same + // value which is the maximum of all bindings. Maybe HIR for imports + // shouldn't use three IDs at all. + if id1 != ast::DUMMY_NODE_ID { + update(id1); + } + if id2 != ast::DUMMY_NODE_ID { + update(id2); + } + } + } + } + info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities); } - fn reset(&mut self) { - self.changed = false; + fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId { + self.r.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local() } /// Update effective visibilities of bindings in the given module, @@ -48,92 +106,83 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> { // Set the given effective visibility level to `Level::Direct` and // sets the rest of the `use` chain to `Level::Reexported` until // we hit the actual exported item. + let mut parent_id = ParentId::Def(module_id); + while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind { + let binding_id = ImportId::new_unchecked(binding); + self.update_import(binding_id, parent_id); - // FIXME: tag and is_public() condition should be removed, but assertions occur. - let tag = if binding.is_import() { Level::Reexported } else { Level::Direct }; - if binding.vis.is_public() { - let mut prev_parent_id = module_id; - let mut level = Level::Direct; - while let NameBindingKind::Import { binding: nested_binding, import, .. } = - binding.kind - { - let mut update = |node_id| { - self.update( - self.r.local_def_id(node_id), - binding.vis.expect_local(), - prev_parent_id, - level, - ) - }; - match import.kind { - ImportKind::Single { id, additional_ids, .. } => { - // In theory all the import IDs have individual visibilities and - // effective visibilities, but in practice these IDs go straigth to - // HIR where all their few uses assume that their (effective) - // visibility applies to the whole syntactic `use` item. So we - // update them all to the maximum value among the potential - // individual effective visibilities. Maybe HIR for imports - // shouldn't use three IDs at all. - update(id); - update(additional_ids.0); - update(additional_ids.1); - prev_parent_id = self.r.local_def_id(id); - } - ImportKind::Glob { id, .. } | ImportKind::ExternCrate { id, .. } => { - update(id); - prev_parent_id = self.r.local_def_id(id); - } - ImportKind::MacroUse => { - // In theory we should reset the parent id to something private - // here, but `macro_use` imports always refer to external items, - // so it doesn't matter and we can just do nothing. - } - ImportKind::MacroExport => { - // In theory we should reset the parent id to something public - // here, but it has the same effect as leaving the previous parent, - // so we can just do nothing. - } - } - - level = Level::Reexported; - binding = nested_binding; - } + parent_id = ParentId::Import(binding_id); + binding = nested_binding; } if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) { - self.update(def_id, binding.vis.expect_local(), module_id, tag); + self.update_def(def_id, binding.vis.expect_local(), parent_id); } } } } - fn update( - &mut self, - def_id: LocalDefId, + fn effective_vis(&self, parent_id: ParentId<'a>) -> Option<EffectiveVisibility> { + match parent_id { + ParentId::Def(def_id) => self.r.effective_visibilities.effective_vis(def_id), + ParentId::Import(binding) => self.import_effective_visibilities.effective_vis(binding), + } + .copied() + } + + /// The update is guaranteed to not change the table and we can skip it. + fn is_noop_update( + &self, + parent_id: ParentId<'a>, nominal_vis: Visibility, - parent_id: LocalDefId, - tag: Level, - ) { - let module_id = self - .r - .get_nearest_non_block_module(def_id.to_def_id()) - .nearest_parent_mod() - .expect_local(); - if nominal_vis == Visibility::Restricted(module_id) - || self.r.visibilities[&parent_id] == Visibility::Restricted(module_id) - { + default_vis: Visibility, + ) -> bool { + nominal_vis == default_vis + || match parent_id { + ParentId::Def(def_id) => self.r.visibilities[&def_id], + ParentId::Import(binding) => binding.vis.expect_local(), + } == default_vis + } + + fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) { + let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; + let nominal_vis = binding.vis.expect_local(); + let default_vis = Visibility::Restricted( + import + .id() + .map(|id| self.nearest_normal_mod(self.r.local_def_id(id))) + .unwrap_or(CRATE_DEF_ID), + ); + if self.is_noop_update(parent_id, nominal_vis, default_vis) { return; } - let mut effective_visibilities = std::mem::take(&mut self.r.effective_visibilities); - self.changed |= effective_visibilities.update( + self.changed |= self.import_effective_visibilities.update( + binding, + nominal_vis, + default_vis, + self.effective_vis(parent_id), + parent_id.level(), + ResolverTree(&self.r.definitions, &self.r.crate_loader), + ); + } + + fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) { + let default_vis = Visibility::Restricted(self.nearest_normal_mod(def_id)); + if self.is_noop_update(parent_id, nominal_vis, default_vis) { + return; + } + self.changed |= self.r.effective_visibilities.update( def_id, nominal_vis, - || Visibility::Restricted(module_id), - parent_id, - tag, - &*self.r, + if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis }, + self.effective_vis(parent_id), + parent_id.level(), + ResolverTree(&self.r.definitions, &self.r.crate_loader), ); - self.r.effective_visibilities = effective_visibilities; + } + + fn update(&mut self, def_id: LocalDefId, parent_id: LocalDefId) { + self.update_def(def_id, self.r.visibilities[&def_id], ParentId::Def(parent_id)); } } @@ -151,12 +200,6 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> { "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage" ), - // Foreign modules inherit level from parents. - ast::ItemKind::ForeignMod(..) => { - let parent_id = self.r.local_parent(def_id); - self.update(def_id, Visibility::Public, parent_id, Level::Direct); - } - ast::ItemKind::Mod(..) => { self.set_bindings_effective_visibilities(def_id); visit::walk_item(self, item); @@ -167,18 +210,14 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> { for variant in variants { let variant_def_id = self.r.local_def_id(variant.id); for field in variant.data.fields() { - let field_def_id = self.r.local_def_id(field.id); - let vis = self.r.visibilities[&field_def_id]; - self.update(field_def_id, vis, variant_def_id, Level::Direct); + self.update(self.r.local_def_id(field.id), variant_def_id); } } } ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => { for field in def.fields() { - let field_def_id = self.r.local_def_id(field.id); - let vis = self.r.visibilities[&field_def_id]; - self.update(field_def_id, vis, def_id, Level::Direct); + self.update(self.r.local_def_id(field.id), def_id); } } @@ -194,6 +233,7 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> { | ast::ItemKind::TyAlias(..) | ast::ItemKind::TraitAlias(..) | ast::ItemKind::MacroDef(..) + | ast::ItemKind::ForeignMod(..) | ast::ItemKind::Fn(..) => return, } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index bdb852548b8..4c899a5ff2d 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -473,7 +473,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { { // In the case of a new import line, throw a diagnostic message // for the previous line. - self.throw_unresolved_import_error(errors, None); + self.throw_unresolved_import_error(errors); errors = vec![]; } if seen_spans.insert(err.span) { @@ -505,29 +505,21 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } if !errors.is_empty() { - self.throw_unresolved_import_error(errors, None); + self.throw_unresolved_import_error(errors); } } - fn throw_unresolved_import_error( - &self, - errors: Vec<(String, UnresolvedImportError)>, - span: Option<MultiSpan>, - ) { + fn throw_unresolved_import_error(&self, errors: Vec<(String, UnresolvedImportError)>) { + if errors.is_empty() { + return; + } + /// Upper limit on the number of `span_label` messages. const MAX_LABEL_COUNT: usize = 10; - let (span, msg) = if errors.is_empty() { - (span.unwrap(), "unresolved import".to_string()) - } else { - let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect()); - - let paths = errors.iter().map(|(path, _)| format!("`{}`", path)).collect::<Vec<_>>(); - - let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),); - - (span, msg) - }; + let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect()); + let paths = errors.iter().map(|(path, _)| format!("`{}`", path)).collect::<Vec<_>>(); + let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),); let mut diag = struct_span_err!(self.r.session, span, E0432, "{}", &msg); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6d2ee25df32..ede67813883 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -527,6 +527,7 @@ struct DiagnosticMetadata<'ast> { /// Used to detect possible new binding written without `let` and to provide structured suggestion. in_assignment: Option<&'ast Expr>, + is_assign_rhs: bool, /// If we are currently in a trait object definition. Used to point at the bounds when /// encountering a struct or enum. @@ -3963,10 +3964,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.resolve_expr(elem, Some(expr)); self.visit_expr(idx); } - ExprKind::Assign(..) => { - let old = self.diagnostic_metadata.in_assignment.replace(expr); - visit::walk_expr(self, expr); - self.diagnostic_metadata.in_assignment = old; + ExprKind::Assign(ref lhs, ref rhs, _) => { + if !self.diagnostic_metadata.is_assign_rhs { + self.diagnostic_metadata.in_assignment = Some(expr); + } + self.visit_expr(lhs); + self.diagnostic_metadata.is_assign_rhs = true; + self.diagnostic_metadata.in_assignment = None; + self.visit_expr(rhs); + self.diagnostic_metadata.is_assign_rhs = false; } _ => { visit::walk_expr(self, expr); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 103187b00d1..95eff92ef5e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -219,26 +219,26 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let (mod_prefix, mod_str, suggestion) = if path.len() == 1 { debug!(?self.diagnostic_metadata.current_impl_items); debug!(?self.diagnostic_metadata.current_function); - let suggestion = if let Some(items) = self.diagnostic_metadata.current_impl_items + let suggestion = if self.current_trait_ref.is_none() && let Some((fn_kind, _)) = self.diagnostic_metadata.current_function - && self.current_trait_ref.is_none() && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt() + && let Some(items) = self.diagnostic_metadata.current_impl_items && let Some(item) = items.iter().find(|i| { - if let AssocItemKind::Fn(fn_) = &i.kind - && !fn_.sig.decl.has_self() - && i.ident.name == item_str.name + if let AssocItemKind::Fn(_) = &i.kind && i.ident.name == item_str.name { debug!(?item_str.name); - debug!(?fn_.sig.decl.inputs); return true } false }) + && let AssocItemKind::Fn(fn_) = &item.kind { + debug!(?fn_); + let self_sugg = if fn_.sig.decl.has_self() { "self." } else { "Self::" }; Some(( - item_span, + item_span.shrink_to_lo(), "consider using the associated function", - format!("Self::{}", item.ident) + self_sugg.to_string() )) } else { None @@ -322,7 +322,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } self.suggest_bare_struct_literal(&mut err); - self.suggest_pattern_match_with_let(&mut err, source, span); + + if self.suggest_pattern_match_with_let(&mut err, source, span) { + // Fallback label. + err.span_label(base_error.span, &base_error.fallback_label); + return (err, Vec::new()); + } self.suggest_self_or_self_ref(&mut err, path, span); self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error); @@ -341,7 +346,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if !self.type_ascription_suggestion(&mut err, base_error.span) { let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); + + // if we have suggested using pattern matching, then don't add needless suggestions + // for typos. fallback |= self.suggest_typo(&mut err, source, path, span, &base_error); + if fallback { // Fallback label. err.span_label(base_error.span, &base_error.fallback_label); @@ -387,11 +396,13 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } fn suggest_self_or_self_ref(&mut self, err: &mut Diagnostic, path: &[Segment], span: Span) { - let is_assoc_fn = self.self_type_is_available(); + if !self.self_type_is_available() { + return; + } let Some(path_last_segment) = path.last() else { return }; let item_str = path_last_segment.ident; // Emit help message for fake-self from other languages (e.g., `this` in Javascript). - if ["this", "my"].contains(&item_str.as_str()) && is_assoc_fn { + if ["this", "my"].contains(&item_str.as_str()) { err.span_suggestion_short( span, "you might have meant to use `self` here instead", @@ -428,7 +439,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn try_lookup_name_relaxed( &mut self, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], span: Span, @@ -442,7 +453,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _)); let path_str = Segment::names_to_string(path); let ident_span = path.last().map_or(span, |ident| ident.ident.span); - let mut candidates = self .r .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected) @@ -488,7 +498,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { .contains(span) { // Already reported this issue on the lhs of the type ascription. - err.delay_as_bug(); + err.downgrade_to_delayed_bug(); return (true, candidates); } } @@ -607,7 +617,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn suggest_trait_and_bounds( &mut self, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + err: &mut Diagnostic, source: PathSource<'_>, res: Option<Res>, span: Span, @@ -682,7 +692,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn suggest_typo( &mut self, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], span: Span, @@ -741,7 +751,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn err_code_special_cases( &mut self, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], span: Span, @@ -797,14 +807,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.code(rustc_errors::error_code!(E0411)); err.span_label(span, "`Self` is only available in impls, traits, and type definitions"); if let Some(item_kind) = self.diagnostic_metadata.current_item { - err.span_label( - item_kind.ident.span, - format!( - "`Self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), - ); + if !item_kind.ident.span.is_dummy() { + err.span_label( + item_kind.ident.span, + format!( + "`Self` not allowed in {} {}", + item_kind.kind.article(), + item_kind.kind.descr() + ), + ); + } } true } @@ -937,7 +949,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err: &mut Diagnostic, source: PathSource<'_>, span: Span, - ) { + ) -> bool { if let PathSource::Expr(_) = source && let Some(Expr { span: expr_span, @@ -954,8 +966,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { "let ", Applicability::MaybeIncorrect, ); + return true; } } + false } fn get_single_associated_item( @@ -1531,7 +1545,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { _ => None, } } - // Fields are generally expected in the same contexts as locals. if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) { if let Some(node_id) = @@ -1799,29 +1812,22 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { false } - fn let_binding_suggestion(&self, err: &mut Diagnostic, ident_span: Span) -> bool { - // try to give a suggestion for this pattern: `name = 1`, which is common in other languages - let mut added_suggestion = false; - if let Some(Expr { kind: ExprKind::Assign(lhs, _rhs, _), .. }) = self.diagnostic_metadata.in_assignment && + // try to give a suggestion for this pattern: `name = blah`, which is common in other languages + // suggest `let name = blah` to introduce a new binding + fn let_binding_suggestion(&mut self, err: &mut Diagnostic, ident_span: Span) -> bool { + if let Some(Expr { kind: ExprKind::Assign(lhs, .. ), .. }) = self.diagnostic_metadata.in_assignment && let ast::ExprKind::Path(None, _) = lhs.kind { - let sm = self.r.session.source_map(); - let line_span = sm.span_extend_to_line(ident_span); - let ident_name = sm.span_to_snippet(ident_span).unwrap(); - // HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros - if sm - .span_to_snippet(line_span) - .map_or(false, |s| s.trim().starts_with(&ident_name)) - { + if !ident_span.from_expansion() { err.span_suggestion_verbose( ident_span.shrink_to_lo(), "you might have meant to introduce a new binding", "let ".to_string(), Applicability::MaybeIncorrect, ); - added_suggestion = true; + return true; } } - added_suggestion + false } fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> { @@ -1930,7 +1936,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_suggestions( span, &msg, - suggestable_variants.into_iter(), + suggestable_variants, Applicability::MaybeIncorrect, ); } @@ -1984,7 +1990,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_suggestions( span, msg, - suggestable_variants.into_iter(), + suggestable_variants, Applicability::MaybeIncorrect, ); } @@ -2014,7 +2020,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_suggestions( span, msg, - suggestable_variants_with_placeholders.into_iter(), + suggestable_variants_with_placeholders, Applicability::HasPlaceholders, ); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ee1c97d5ad2..a1ff477c6fe 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1106,17 +1106,30 @@ impl<'a> AsMut<Resolver<'a>> for Resolver<'a> { } } -impl<'a, 'b> DefIdTree for &'a Resolver<'b> { +/// A minimal subset of resolver that can implemenent `DefIdTree`, sometimes +/// required to satisfy borrow checker by avoiding borrowing the whole resolver. +#[derive(Clone, Copy)] +struct ResolverTree<'a, 'b>(&'a Definitions, &'a CrateLoader<'b>); + +impl DefIdTree for ResolverTree<'_, '_> { #[inline] fn opt_parent(self, id: DefId) -> Option<DefId> { + let ResolverTree(definitions, crate_loader) = self; match id.as_local() { - Some(id) => self.definitions.def_key(id).parent, - None => self.cstore().def_key(id).parent, + Some(id) => definitions.def_key(id).parent, + None => crate_loader.cstore().def_key(id).parent, } .map(|index| DefId { index, ..id }) } } +impl<'a, 'b> DefIdTree for &'a Resolver<'b> { + #[inline] + fn opt_parent(self, id: DefId) -> Option<DefId> { + ResolverTree(&self.definitions, &self.crate_loader).opt_parent(id) + } +} + impl Resolver<'_> { fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> { self.node_id_to_def_id.get(&node).copied() diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 9526296f951..8c7972f8eeb 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -356,7 +356,7 @@ impl<'a> ResolverExpand for Resolver<'a> { has_derive_copy: false, }); let parent_scope = self.invocation_parent_scopes[&expn_id]; - for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() { + for (i, (path, _, opt_ext, _)) in entry.resolutions.iter_mut().enumerate() { if opt_ext.is_none() { *opt_ext = Some( match self.resolve_macro_path( diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml index 3b0b3144f2c..db0ef73544f 100644 --- a/compiler/rustc_serialize/Cargo.toml +++ b/compiler/rustc_serialize/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] indexmap = "1.9.1" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.8" +thin-vec = "0.2.9" [dev-dependencies] rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 6b1eaa4d399..a052f293341 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -17,3 +17,10 @@ rustc_span = { path = "../rustc_span" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_ast = { path = "../rustc_ast" } rustc_lint_defs = { path = "../rustc_lint_defs" } +smallvec = "1.8.1" + +[target.'cfg(unix)'.dependencies] +libc = "0.2" + +[target.'cfg(windows)'.dependencies] +winapi = { version = "0.3", features = ["libloaderapi"] } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index b8ad18c64dc..be084adb7b7 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -548,6 +548,7 @@ pub enum PrintRequest { NativeStaticLibs, StackProtectorStrategies, LinkArgs, + SplitDebuginfo, } pub enum Input { @@ -1806,6 +1807,7 @@ fn collect_print_requests( ("stack-protector-strategies", PrintRequest::StackProtectorStrategies), ("target-spec-json", PrintRequest::TargetSpec), ("link-args", PrintRequest::LinkArgs), + ("split-debuginfo", PrintRequest::SplitDebuginfo), ]; prints.extend(matches.opt_strs("print").into_iter().map(|req| { @@ -2447,7 +2449,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let sysroot = match &sysroot_opt { Some(s) => s, None => { - tmp_buf = crate::filesearch::get_or_default_sysroot(); + tmp_buf = crate::filesearch::get_or_default_sysroot().expect("Failed finding sysroot"); &tmp_buf } }; diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index e8edb38f503..1b66773be6f 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -1,5 +1,6 @@ //! A module for searching for libraries +use smallvec::{smallvec, SmallVec}; use std::env; use std::fs; use std::iter::FromIterator; @@ -62,9 +63,99 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")]) } +#[cfg(unix)] +fn current_dll_path() -> Result<PathBuf, String> { + use std::ffi::{CStr, OsStr}; + use std::os::unix::prelude::*; + + unsafe { + let addr = current_dll_path as usize as *mut _; + let mut info = std::mem::zeroed(); + if libc::dladdr(addr, &mut info) == 0 { + return Err("dladdr failed".into()); + } + if info.dli_fname.is_null() { + return Err("dladdr returned null pointer".into()); + } + let bytes = CStr::from_ptr(info.dli_fname).to_bytes(); + let os = OsStr::from_bytes(bytes); + Ok(PathBuf::from(os)) + } +} + +#[cfg(windows)] +fn current_dll_path() -> Result<PathBuf, String> { + use std::ffi::OsString; + use std::io; + use std::os::windows::prelude::*; + use std::ptr; + + use winapi::um::libloaderapi::{ + GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + }; + + unsafe { + let mut module = ptr::null_mut(); + let r = GetModuleHandleExW( + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + current_dll_path as usize as *mut _, + &mut module, + ); + if r == 0 { + return Err(format!("GetModuleHandleExW failed: {}", io::Error::last_os_error())); + } + let mut space = Vec::with_capacity(1024); + let r = GetModuleFileNameW(module, space.as_mut_ptr(), space.capacity() as u32); + if r == 0 { + return Err(format!("GetModuleFileNameW failed: {}", io::Error::last_os_error())); + } + let r = r as usize; + if r >= space.capacity() { + return Err(format!("our buffer was too small? {}", io::Error::last_os_error())); + } + space.set_len(r); + let os = OsString::from_wide(&space); + Ok(PathBuf::from(os)) + } +} + +pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> { + let target = crate::config::host_triple(); + let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = + smallvec![get_or_default_sysroot().expect("Failed finding sysroot")]; + let path = current_dll_path().and_then(|s| Ok(s.canonicalize().map_err(|e| e.to_string())?)); + if let Ok(dll) = path { + // use `parent` twice to chop off the file name and then also the + // directory containing the dll which should be either `lib` or `bin`. + if let Some(path) = dll.parent().and_then(|p| p.parent()) { + // The original `path` pointed at the `rustc_driver` crate's dll. + // Now that dll should only be in one of two locations. The first is + // in the compiler's libdir, for example `$sysroot/lib/*.dll`. The + // other is the target's libdir, for example + // `$sysroot/lib/rustlib/$target/lib/*.dll`. + // + // We don't know which, so let's assume that if our `path` above + // ends in `$target` we *could* be in the target libdir, and always + // assume that we may be in the main libdir. + sysroot_candidates.push(path.to_owned()); + + if path.ends_with(target) { + sysroot_candidates.extend( + path.parent() // chop off `$target` + .and_then(|p| p.parent()) // chop off `rustlib` + .and_then(|p| p.parent()) // chop off `lib` + .map(|s| s.to_owned()), + ); + } + } + } + + return sysroot_candidates; +} + /// This function checks if sysroot is found using env::args().next(), and if it -/// is not found, uses env::current_exe() to imply sysroot. -pub fn get_or_default_sysroot() -> PathBuf { +/// is not found, finds sysroot from current rustc_driver dll. +pub fn get_or_default_sysroot() -> Result<PathBuf, String> { // Follow symlinks. If the resolved path is relative, make it absolute. fn canonicalize(path: PathBuf) -> PathBuf { let path = fs::canonicalize(&path).unwrap_or(path); @@ -74,17 +165,32 @@ pub fn get_or_default_sysroot() -> PathBuf { fix_windows_verbatim_for_gcc(&path) } - // Use env::current_exe() to get the path of the executable following - // symlinks/canonicalizing components. - fn from_current_exe() -> PathBuf { - match env::current_exe() { - Ok(exe) => { - let mut p = canonicalize(exe); - p.pop(); - p.pop(); - p - } - Err(e) => panic!("failed to get current_exe: {e}"), + fn default_from_rustc_driver_dll() -> Result<PathBuf, String> { + let dll = current_dll_path().and_then(|s| Ok(canonicalize(s)))?; + + // `dll` will be in one of the following two: + // - compiler's libdir: $sysroot/lib/*.dll + // - target's libdir: $sysroot/lib/rustlib/$target/lib/*.dll + // + // use `parent` twice to chop off the file name and then also the + // directory containing the dll + let dir = dll.parent().and_then(|p| p.parent()).ok_or(format!( + "Could not move 2 levels upper using `parent()` on {}", + dll.display() + ))?; + + // if `dir` points target's dir, move up to the sysroot + if dir.ends_with(crate::config::host_triple()) { + dir.parent() // chop off `$target` + .and_then(|p| p.parent()) // chop off `rustlib` + .and_then(|p| p.parent()) // chop off `lib` + .map(|s| s.to_owned()) + .ok_or(format!( + "Could not move 3 levels upper using `parent()` on {}", + dir.display() + )) + } else { + Ok(dir.to_owned()) } } @@ -118,7 +224,5 @@ pub fn get_or_default_sysroot() -> PathBuf { } } - // Check if sysroot is found using env::args().next(), and if is not found, - // use env::current_exe() to imply sysroot. - from_env_args_next().unwrap_or_else(from_current_exe) + Ok(from_env_args_next().unwrap_or(default_from_rustc_driver_dll()?)) } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ec0a5b9d0d8..10352198357 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1309,7 +1309,7 @@ pub fn build_session( let sysroot = match &sopts.maybe_sysroot { Some(sysroot) => sysroot.clone(), - None => filesearch::get_or_default_sysroot(), + None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"), }; let target_cfg = config::build_target_config(&sopts, target_override, &sysroot); diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index f9566eeee94..7ea028b12ef 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -753,6 +753,50 @@ impl SourceMap { } } + /// Given a 'Span', tries to tell if the next character is '>' + /// and the previous charactoer is '<' after skipping white space + /// return true if wrapped by '<>' + pub fn span_wrapped_by_angle_bracket(&self, span: Span) -> bool { + self.span_to_source(span, |src, start_index, end_index| { + if src.get(start_index..end_index).is_none() { + return Ok(false); + } + // test the right side to match '>' after skipping white space + let end_src = &src[end_index..]; + let mut i = 0; + while let Some(cc) = end_src.chars().nth(i) { + if cc == ' ' { + i = i + 1; + } else if cc == '>' { + // found > in the right; + break; + } else { + // failed to find '>' return false immediately + return Ok(false); + } + } + // test the left side to match '<' after skipping white space + i = start_index; + let start_src = &src[0..start_index]; + while let Some(cc) = start_src.chars().nth(i) { + if cc == ' ' { + if i == 0 { + return Ok(false); + } + i = i - 1; + } else if cc == '<' { + // found < in the left + break; + } else { + // failed to find '<' return false immediately + return Ok(false); + } + } + return Ok(true); + }) + .map_or(false, |is_accessible| is_accessible) + } + /// Given a `Span`, tries to get a shorter span ending just after the first occurrence of `char` /// `c`. pub fn span_through_char(&self, sp: Span, c: char) -> Span { @@ -855,7 +899,8 @@ impl SourceMap { /// Returns a new span representing the next character after the end-point of this span. /// Special cases: /// - if span is a dummy one, returns the same span - /// - if next_point reached the end of source, return span with lo = hi + /// - if next_point reached the end of source, return a span exceeding the end of source, + /// which means sm.span_to_snippet(next_point) will get `Err` /// - respect multi-byte characters pub fn next_point(&self, sp: Span) -> Span { if sp.is_dummy() { @@ -864,9 +909,6 @@ impl SourceMap { let start_of_next_point = sp.hi().0; let width = self.find_width_of_character_at_span(sp, true); - if width == 0 { - return Span::new(sp.hi(), sp.hi(), sp.ctxt(), None); - } // If the width is 1, then the next span should only contain the next char besides current ending. // However, in the case of a multibyte character, where the width != 1, the next span should // span multiple bytes to include the whole character. @@ -938,7 +980,7 @@ impl SourceMap { // Ensure indexes are also not malformed. if start_index > end_index || end_index > source_len - 1 { debug!("find_width_of_character_at_span: source indexes are malformed"); - return 0; + return 1; } let src = local_begin.sf.external_src.borrow(); diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 1fd81018fa0..3cab59e8dbe 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -511,16 +511,17 @@ fn test_next_point() { assert_eq!(span.lo().0, 4); assert_eq!(span.hi().0, 5); - // A non-empty span at the last byte should advance to create an empty - // span pointing at the end of the file. + // Reaching to the end of file, return a span that will get error with `span_to_snippet` let span = Span::with_root_ctxt(BytePos(4), BytePos(5)); let span = sm.next_point(span); assert_eq!(span.lo().0, 5); - assert_eq!(span.hi().0, 5); + assert_eq!(span.hi().0, 6); + assert!(sm.span_to_snippet(span).is_err()); - // Empty span pointing just past the last byte. + // Reaching to the end of file, return a span that will get error with `span_to_snippet` let span = Span::with_root_ctxt(BytePos(5), BytePos(5)); let span = sm.next_point(span); assert_eq!(span.lo().0, 5); - assert_eq!(span.hi().0, 5); + assert_eq!(span.hi().0, 6); + assert!(sm.span_to_snippet(span).is_err()); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index cccc4897ecc..b48db73618b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -584,6 +584,7 @@ symbols! { custom_attribute, custom_derive, custom_inner_attributes, + custom_mir, custom_test_frameworks, d, d32, @@ -619,6 +620,7 @@ symbols! { deref_mut, deref_target, derive, + derive_const, derive_default_enum, destruct, destructuring_assignment, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index ecfe6861e84..e540e2f2a21 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -218,7 +218,7 @@ impl<'tcx> SymbolMangler<'tcx> { let lifetimes = regions .into_iter() .map(|br| match br { - ty::BrAnon(i) => i, + ty::BrAnon(i, _) => i, _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value), }) .max() @@ -335,7 +335,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { // Late-bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => { + ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i, _), .. }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + i; @@ -654,8 +654,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { .builtin_deref(true) .expect("tried to dereference on non-ptr type") .ty; - let dereferenced_const = - self.tcx.mk_const(ty::ConstS { kind: ct.kind(), ty: pointee_ty }); + let dereferenced_const = self.tcx.mk_const(ct.kind(), pointee_ty); self = dereferenced_const.print(self)?; } } diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/abi/call/loongarch.rs new file mode 100644 index 00000000000..d29b479de5d --- /dev/null +++ b/compiler/rustc_target/src/abi/call/loongarch.rs @@ -0,0 +1,342 @@ +use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; +use crate::spec::HasTargetSpec; + +#[derive(Copy, Clone)] +enum RegPassKind { + Float(Reg), + Integer(Reg), + Unknown, +} + +#[derive(Copy, Clone)] +enum FloatConv { + FloatPair(Reg, Reg), + Float(Reg), + MixedPair(Reg, Reg), +} + +#[derive(Copy, Clone)] +struct CannotUseFpConv; + +fn is_loongarch_aggregate<'a, Ty>(arg: &ArgAbi<'a, Ty>) -> bool { + match arg.layout.abi { + Abi::Vector { .. } => true, + _ => arg.layout.is_aggregate(), + } +} + +fn should_use_fp_conv_helper<'a, Ty, C>( + cx: &C, + arg_layout: &TyAndLayout<'a, Ty>, + xlen: u64, + flen: u64, + field1_kind: &mut RegPassKind, + field2_kind: &mut RegPassKind, +) -> Result<(), CannotUseFpConv> +where + Ty: TyAbiInterface<'a, C> + Copy, +{ + match arg_layout.abi { + Abi::Scalar(scalar) => match scalar.primitive() { + abi::Int(..) | abi::Pointer => { + if arg_layout.size.bits() > xlen { + return Err(CannotUseFpConv); + } + match (*field1_kind, *field2_kind) { + (RegPassKind::Unknown, _) => { + *field1_kind = RegPassKind::Integer(Reg { + kind: RegKind::Integer, + size: arg_layout.size, + }); + } + (RegPassKind::Float(_), RegPassKind::Unknown) => { + *field2_kind = RegPassKind::Integer(Reg { + kind: RegKind::Integer, + size: arg_layout.size, + }); + } + _ => return Err(CannotUseFpConv), + } + } + abi::F32 | abi::F64 => { + if arg_layout.size.bits() > flen { + return Err(CannotUseFpConv); + } + match (*field1_kind, *field2_kind) { + (RegPassKind::Unknown, _) => { + *field1_kind = + RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); + } + (_, RegPassKind::Unknown) => { + *field2_kind = + RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); + } + _ => return Err(CannotUseFpConv), + } + } + }, + Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv), + Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields { + FieldsShape::Primitive => { + unreachable!("aggregates can't have `FieldsShape::Primitive`") + } + FieldsShape::Union(_) => { + if !arg_layout.is_zst() { + return Err(CannotUseFpConv); + } + } + FieldsShape::Array { count, .. } => { + for _ in 0..count { + let elem_layout = arg_layout.field(cx, 0); + should_use_fp_conv_helper( + cx, + &elem_layout, + xlen, + flen, + field1_kind, + field2_kind, + )?; + } + } + FieldsShape::Arbitrary { .. } => { + match arg_layout.variants { + abi::Variants::Multiple { .. } => return Err(CannotUseFpConv), + abi::Variants::Single { .. } => (), + } + for i in arg_layout.fields.index_by_increasing_offset() { + let field = arg_layout.field(cx, i); + should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?; + } + } + }, + } + Ok(()) +} + +fn should_use_fp_conv<'a, Ty, C>( + cx: &C, + arg: &TyAndLayout<'a, Ty>, + xlen: u64, + flen: u64, +) -> Option<FloatConv> +where + Ty: TyAbiInterface<'a, C> + Copy, +{ + let mut field1_kind = RegPassKind::Unknown; + let mut field2_kind = RegPassKind::Unknown; + if should_use_fp_conv_helper(cx, arg, xlen, flen, &mut field1_kind, &mut field2_kind).is_err() { + return None; + } + match (field1_kind, field2_kind) { + (RegPassKind::Integer(l), RegPassKind::Float(r)) => Some(FloatConv::MixedPair(l, r)), + (RegPassKind::Float(l), RegPassKind::Integer(r)) => Some(FloatConv::MixedPair(l, r)), + (RegPassKind::Float(l), RegPassKind::Float(r)) => Some(FloatConv::FloatPair(l, r)), + (RegPassKind::Float(f), RegPassKind::Unknown) => Some(FloatConv::Float(f)), + _ => None, + } +} + +fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u64) -> bool +where + Ty: TyAbiInterface<'a, C> + Copy, +{ + if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) { + match conv { + FloatConv::Float(f) => { + arg.cast_to(f); + } + FloatConv::FloatPair(l, r) => { + arg.cast_to(CastTarget::pair(l, r)); + } + FloatConv::MixedPair(l, r) => { + arg.cast_to(CastTarget::pair(l, r)); + } + } + return false; + } + + let total = arg.layout.size; + + // "Scalars wider than 2✕XLEN are passed by reference and are replaced in + // the argument list with the address." + // "Aggregates larger than 2✕XLEN bits are passed by reference and are + // replaced in the argument list with the address, as are C++ aggregates + // with nontrivial copy constructors, destructors, or vtables." + if total.bits() > 2 * xlen { + // We rely on the LLVM backend lowering code to lower passing a scalar larger than 2*XLEN. + if is_loongarch_aggregate(arg) { + arg.make_indirect(); + } + return true; + } + + let xlen_reg = match xlen { + 32 => Reg::i32(), + 64 => Reg::i64(), + _ => unreachable!("Unsupported XLEN: {}", xlen), + }; + if is_loongarch_aggregate(arg) { + if total.bits() <= xlen { + arg.cast_to(xlen_reg); + } else { + arg.cast_to(Uniform { unit: xlen_reg, total: Size::from_bits(xlen * 2) }); + } + return false; + } + + // "When passed in registers, scalars narrower than XLEN bits are widened + // according to the sign of their type up to 32 bits, then sign-extended to + // XLEN bits." + extend_integer_width(arg, xlen); + false +} + +fn classify_arg<'a, Ty, C>( + cx: &C, + arg: &mut ArgAbi<'a, Ty>, + xlen: u64, + flen: u64, + is_vararg: bool, + avail_gprs: &mut u64, + avail_fprs: &mut u64, +) where + Ty: TyAbiInterface<'a, C> + Copy, +{ + if !is_vararg { + match should_use_fp_conv(cx, &arg.layout, xlen, flen) { + Some(FloatConv::Float(f)) if *avail_fprs >= 1 => { + *avail_fprs -= 1; + arg.cast_to(f); + return; + } + Some(FloatConv::FloatPair(l, r)) if *avail_fprs >= 2 => { + *avail_fprs -= 2; + arg.cast_to(CastTarget::pair(l, r)); + return; + } + Some(FloatConv::MixedPair(l, r)) if *avail_fprs >= 1 && *avail_gprs >= 1 => { + *avail_gprs -= 1; + *avail_fprs -= 1; + arg.cast_to(CastTarget::pair(l, r)); + return; + } + _ => (), + } + } + + let total = arg.layout.size; + let align = arg.layout.align.abi.bits(); + + // "Scalars wider than 2✕XLEN are passed by reference and are replaced in + // the argument list with the address." + // "Aggregates larger than 2✕XLEN bits are passed by reference and are + // replaced in the argument list with the address, as are C++ aggregates + // with nontrivial copy constructors, destructors, or vtables." + if total.bits() > 2 * xlen { + // We rely on the LLVM backend lowering code to lower passing a scalar larger than 2*XLEN. + if is_loongarch_aggregate(arg) { + arg.make_indirect(); + } + if *avail_gprs >= 1 { + *avail_gprs -= 1; + } + return; + } + + let double_xlen_reg = match xlen { + 32 => Reg::i64(), + 64 => Reg::i128(), + _ => unreachable!("Unsupported XLEN: {}", xlen), + }; + + let xlen_reg = match xlen { + 32 => Reg::i32(), + 64 => Reg::i64(), + _ => unreachable!("Unsupported XLEN: {}", xlen), + }; + + if total.bits() > xlen { + let align_regs = align > xlen; + if is_loongarch_aggregate(arg) { + arg.cast_to(Uniform { + unit: if align_regs { double_xlen_reg } else { xlen_reg }, + total: Size::from_bits(xlen * 2), + }); + } + if align_regs && is_vararg { + *avail_gprs -= *avail_gprs % 2; + } + if *avail_gprs >= 2 { + *avail_gprs -= 2; + } else { + *avail_gprs = 0; + } + return; + } else if is_loongarch_aggregate(arg) { + arg.cast_to(xlen_reg); + if *avail_gprs >= 1 { + *avail_gprs -= 1; + } + return; + } + + // "When passed in registers, scalars narrower than XLEN bits are widened + // according to the sign of their type up to 32 bits, then sign-extended to + // XLEN bits." + if *avail_gprs >= 1 { + extend_integer_width(arg, xlen); + *avail_gprs -= 1; + } +} + +fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { + if let Abi::Scalar(scalar) = arg.layout.abi { + if let abi::Int(i, _) = scalar.primitive() { + // 32-bit integers are always sign-extended + if i.size().bits() == 32 && xlen > 32 { + if let PassMode::Direct(ref mut attrs) = arg.mode { + attrs.ext(ArgExtension::Sext); + return; + } + } + } + } + + arg.extend_integer_width_to(xlen); +} + +pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout + HasTargetSpec, +{ + let xlen = cx.data_layout().pointer_size.bits(); + let flen = match &cx.target_spec().llvm_abiname[..] { + "ilp32f" | "lp64f" => 32, + "ilp32d" | "lp64d" => 64, + _ => 0, + }; + + let mut avail_gprs = 8; + let mut avail_fprs = 8; + + if !fn_abi.ret.is_ignore() && classify_ret(cx, &mut fn_abi.ret, xlen, flen) { + avail_gprs -= 1; + } + + for (i, arg) in fn_abi.args.iter_mut().enumerate() { + if arg.is_ignore() { + continue; + } + classify_arg( + cx, + arg, + xlen, + flen, + i >= fn_abi.fixed_count as usize, + &mut avail_gprs, + &mut avail_fprs, + ); + } +} diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 9e5f0e4d158..c5a6f9893b6 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -10,6 +10,7 @@ mod arm; mod avr; mod bpf; mod hexagon; +mod loongarch; mod m68k; mod mips; mod mips64; @@ -696,6 +697,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "amdgpu" => amdgpu::compute_abi_info(cx, self), "arm" => arm::compute_abi_info(cx, self), "avr" => avr::compute_abi_info(self), + "loongarch64" => loongarch::compute_abi_info(cx, self), "m68k" => m68k::compute_abi_info(self), "mips" => mips::compute_abi_info(cx, self), "mips64" => mips64::compute_abi_info(cx, self), diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 6d919a4c2ad..0f6bbc32317 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -1,26 +1,25 @@ +use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = "arm64"; - let mut base = super::apple_base::opts("macos", arch, ""); + let arch = Arch::Arm64; + let mut base = opts("macos", arch); base.cpu = "apple-a14".into(); base.max_atomic_width = Some(128); // FIXME: The leak sanitizer currently fails the tests, see #88132. base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD; - base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); - - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - let llvm_target = super::apple_base::macos_llvm_target(arch); + base.link_env_remove.to_mut().extend(macos_link_env_remove()); Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + llvm_target: macos_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), frame_pointer: FramePointer::NonLeaf, diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs index beb9042390b..b5f9eb1259d 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs @@ -1,19 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_llvm_target, opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the target to pick the right - // MACH-O commands, so we do too. - let arch = "arm64"; - let llvm_target = super::apple_base::ios_llvm_target(arch); - + let arch = Arch::Arm64; Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // IPHONEOS_DEPLOYMENT_TARGET. + // This is required for the target to pick the right + // MACH-O commands, so we do too. + llvm_target: ios_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), @@ -30,7 +28,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..opts("ios", Arch::Arm64) + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs index 2d2671549cf..0009972cf42 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs @@ -1,17 +1,18 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { let llvm_target = "arm64-apple-ios14.0-macabi"; - let mut base = opts("ios", Arch::Arm64_macabi); + let arch = Arch::Arm64_macabi; + let mut base = opts("ios", arch); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]); Target { llvm_target: llvm_target.into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs index b4e135f66e9..3374755e2dd 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs @@ -1,21 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::Arm64_sim); - - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the simulator target to pick the right - // MACH-O commands, so we do too. - let arch = "arm64"; - let llvm_target = super::apple_base::ios_sim_llvm_target(arch); - + let arch = Arch::Arm64_sim; Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // IPHONEOS_DEPLOYMENT_TARGET. + // This is required for the simulator target to pick the right + // MACH-O commands, so we do too. + llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), @@ -32,7 +28,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs index 2e31d16dc76..bb7c39ff26b 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs @@ -1,18 +1,19 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { + let arch = Arch::Arm64; Target { llvm_target: "arm64-apple-tvos".into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), forces_embed_bitcode: true, frame_pointer: FramePointer::NonLeaf, - ..opts("tvos", Arch::Arm64) + ..opts("tvos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs index 3059f42140b..e4af4127c22 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs @@ -1,21 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("watchos", Arch::Arm64_sim); - - // Clang automatically chooses a more specific target based on - // WATCHOS_DEPLOYMENT_TARGET. - // This is required for the simulator target to pick the right - // MACH-O commands, so we do too. - let arch = "arm64"; - let llvm_target = super::apple_base::watchos_sim_llvm_target(arch); - + let arch = Arch::Arm64_sim; Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // WATCHOS_DEPLOYMENT_TARGET. + // This is required for the simulator target to pick the right + // MACH-O commands, so we do too. + llvm_target: watchos_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), @@ -32,7 +28,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("watchos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs new file mode 100644 index 00000000000..916b6137b65 --- /dev/null +++ b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs @@ -0,0 +1,28 @@ +use super::nto_qnx_base; +use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "aarch64-unknown-unknown".into(), + pointer_width: 64, + // from: https://llvm.org/docs/LangRef.html#data-layout + // e = little endian + // m:e = ELF mangling: Private symbols get a .L prefix + // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 + // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 + // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 + // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 + // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. + // S128 = 128 bits are the natural alignment of the stack in bits. + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), + arch: "aarch64".into(), + options: TargetOptions { + max_atomic_width: Some(128), + pre_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-Vgcc_ntoaarch64le_cxx"], + ), + ..nto_qnx_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 40bc59ca145..23c826cb1bd 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -3,7 +3,88 @@ use std::{borrow::Cow, env}; use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs}; use crate::spec::{LinkerFlavor, Lld, SplitDebuginfo, StaticCow, TargetOptions}; -fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs { +#[cfg(test)] +#[path = "apple/tests.rs"] +mod tests; + +use Arch::*; +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub enum Arch { + Armv7, + Armv7k, + Armv7s, + Arm64, + Arm64_32, + I386, + I686, + X86_64, + X86_64_sim, + X86_64_macabi, + Arm64_macabi, + Arm64_sim, +} + +impl Arch { + pub fn target_name(self) -> &'static str { + match self { + Armv7 => "armv7", + Armv7k => "armv7k", + Armv7s => "armv7s", + Arm64 | Arm64_macabi | Arm64_sim => "arm64", + Arm64_32 => "arm64_32", + I386 => "i386", + I686 => "i686", + X86_64 | X86_64_sim | X86_64_macabi => "x86_64", + } + } + + pub fn target_arch(self) -> Cow<'static, str> { + Cow::Borrowed(match self { + Armv7 | Armv7k | Armv7s => "arm", + Arm64 | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64", + I386 | I686 => "x86", + X86_64 | X86_64_sim | X86_64_macabi => "x86_64", + }) + } + + fn target_abi(self) -> &'static str { + match self { + Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 => "", + X86_64_macabi | Arm64_macabi => "macabi", + // x86_64-apple-ios is a simulator target, even though it isn't + // declared that way in the target like the other ones... + Arm64_sim | X86_64_sim => "sim", + } + } + + fn target_cpu(self) -> &'static str { + match self { + Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher + Armv7k => "cortex-a8", + Armv7s => "cortex-a9", + Arm64 => "apple-a7", + Arm64_32 => "apple-s4", + I386 | I686 => "yonah", + X86_64 | X86_64_sim => "core2", + X86_64_macabi => "core2", + Arm64_macabi => "apple-a12", + Arm64_sim => "apple-a12", + } + } + + fn link_env_remove(self) -> StaticCow<[StaticCow<str>]> { + match self { + Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim + | Arm64_sim => { + cvs!["MACOSX_DEPLOYMENT_TARGET"] + } + X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], + } + } +} + +fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs { let platform_name: StaticCow<str> = match abi { "sim" => format!("{}-simulator", os).into(), "macabi" => "mac-catalyst".into(), @@ -19,6 +100,8 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin } .into(); + let arch = arch.target_name(); + let mut args = TargetOptions::link_args( LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch, "-platform_version"], @@ -35,24 +118,29 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin args } -pub fn opts(os: &'static str, arch: &'static str, abi: &'static str) -> TargetOptions { - // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 +pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { + // Static TLS is only available in macOS 10.7+. If you try to compile for 10.6 // either the linker will complain if it is used or the binary will end up // segfaulting at runtime when run on 10.6. Rust by default supports macOS // 10.7+, but there is a standard environment variable, // MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older // versions of macOS. For example compiling on 10.10 with // MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate - // warnings about the usage of ELF TLS. + // warnings about the usage of static TLS. // - // Here we detect what version is being requested, defaulting to 10.7. ELF + // Here we detect what version is being requested, defaulting to 10.7. Static // TLS is flagged as enabled if it looks to be supported. The architecture // only matters for default deployment target which is 11.0 for ARM64 and // 10.7 for everything else. - let has_thread_local = macos_deployment_target("x86_64") >= (10, 7); + let has_thread_local = os == "macos" && macos_deployment_target(Arch::X86_64) >= (10, 7); + + let abi = arch.target_abi(); TargetOptions { + abi: abi.into(), os: os.into(), + cpu: arch.target_cpu().into(), + link_env_remove: arch.link_env_remove(), vendor: "apple".into(), linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No), // macOS has -dead_strip, which doesn't rely on function_sections @@ -103,23 +191,24 @@ fn deployment_target(var_name: &str) -> Option<(u32, u32)> { .and_then(|(a, b)| a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok()) } -fn macos_default_deployment_target(arch: &str) -> (u32, u32) { - if arch == "arm64" { (11, 0) } else { (10, 7) } +fn macos_default_deployment_target(arch: Arch) -> (u32, u32) { + // Note: Arm64_sim is not included since macOS has no simulator. + if matches!(arch, Arm64 | Arm64_macabi) { (11, 0) } else { (10, 7) } } -fn macos_deployment_target(arch: &str) -> (u32, u32) { +fn macos_deployment_target(arch: Arch) -> (u32, u32) { deployment_target("MACOSX_DEPLOYMENT_TARGET") .unwrap_or_else(|| macos_default_deployment_target(arch)) } -fn macos_lld_platform_version(arch: &str) -> String { +fn macos_lld_platform_version(arch: Arch) -> String { let (major, minor) = macos_deployment_target(arch); format!("{}.{}", major, minor) } -pub fn macos_llvm_target(arch: &str) -> String { +pub fn macos_llvm_target(arch: Arch) -> String { let (major, minor) = macos_deployment_target(arch); - format!("{}-apple-macosx{}.{}.0", arch, major, minor) + format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor) } pub fn macos_link_env_remove() -> Vec<StaticCow<str>> { @@ -142,7 +231,7 @@ fn ios_deployment_target() -> (u32, u32) { deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0)) } -pub fn ios_llvm_target(arch: &str) -> String { +pub fn ios_llvm_target(arch: Arch) -> String { // Modern iOS tooling extracts information about deployment target // from LC_BUILD_VERSION. This load command will only be emitted when // we build with a version specific `llvm_target`, with the version @@ -150,7 +239,7 @@ pub fn ios_llvm_target(arch: &str) -> String { // to pick it up (since std and core are still built with the fallback // of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION). let (major, minor) = ios_deployment_target(); - format!("{}-apple-ios{}.{}.0", arch, major, minor) + format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor) } fn ios_lld_platform_version() -> String { @@ -158,9 +247,9 @@ fn ios_lld_platform_version() -> String { format!("{}.{}", major, minor) } -pub fn ios_sim_llvm_target(arch: &str) -> String { +pub fn ios_sim_llvm_target(arch: Arch) -> String { let (major, minor) = ios_deployment_target(); - format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor) + format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor) } fn tvos_deployment_target() -> (u32, u32) { @@ -181,7 +270,7 @@ fn watchos_lld_platform_version() -> String { format!("{}.{}", major, minor) } -pub fn watchos_sim_llvm_target(arch: &str) -> String { +pub fn watchos_sim_llvm_target(arch: Arch) -> String { let (major, minor) = watchos_deployment_target(); - format!("{}-apple-watchos{}.{}.0-simulator", arch, major, minor) + format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor) } diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs deleted file mode 100644 index 148031b1569..00000000000 --- a/compiler/rustc_target/src/spec/apple_sdk_base.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::spec::{cvs, TargetOptions}; -use std::borrow::Cow; - -#[cfg(test)] -#[path = "apple/tests.rs"] -mod tests; - -use Arch::*; -#[allow(non_camel_case_types)] -#[derive(Copy, Clone)] -pub enum Arch { - Armv7, - Armv7k, - Armv7s, - Arm64, - Arm64_32, - I386, - #[allow(dead_code)] // Some targets don't use this enum... - X86_64, - X86_64_sim, - X86_64_macabi, - Arm64_macabi, - Arm64_sim, -} - -fn target_arch_name(arch: Arch) -> &'static str { - match arch { - Armv7 => "armv7", - Armv7k => "armv7k", - Armv7s => "armv7s", - Arm64 | Arm64_macabi | Arm64_sim => "arm64", - Arm64_32 => "arm64_32", - I386 => "i386", - X86_64 | X86_64_sim | X86_64_macabi => "x86_64", - } -} - -fn target_abi(arch: Arch) -> &'static str { - match arch { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "", - X86_64_macabi | Arm64_macabi => "macabi", - // x86_64-apple-ios is a simulator target, even though it isn't - // declared that way in the target like the other ones... - Arm64_sim | X86_64_sim => "sim", - } -} - -fn target_cpu(arch: Arch) -> &'static str { - match arch { - Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher - Armv7k => "cortex-a8", - Armv7s => "cortex-a9", - Arm64 => "apple-a7", - Arm64_32 => "apple-s4", - I386 => "yonah", - X86_64 | X86_64_sim => "core2", - X86_64_macabi => "core2", - Arm64_macabi => "apple-a12", - Arm64_sim => "apple-a12", - } -} - -fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> { - match arch { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 | X86_64_sim | Arm64_sim => { - cvs!["MACOSX_DEPLOYMENT_TARGET"] - } - X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], - } -} - -pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { - let abi = target_abi(arch); - TargetOptions { - abi: abi.into(), - cpu: target_cpu(arch).into(), - link_env_remove: link_env_remove(arch), - has_thread_local: false, - ..super::apple_base::opts(os, target_arch_name(arch), abi) - } -} diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs index cb7f5f2a583..2cf2cbc7510 100644 --- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs index 57fd74a36b6..3259c854791 100644 --- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs @@ -1,18 +1,21 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let llvm_target = super::apple_base::ios_llvm_target("armv7"); - + let arch = Arch::Armv7; Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // IPHONEOS_DEPLOYMENT_TARGET. + // This is required for the target to pick the right + // MACH-O commands, so we do too. + llvm_target: ios_llvm_target(arch).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(), - arch: "arm".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+v7,+vfp3,+neon".into(), max_atomic_width: Some(64), - ..opts("ios", Arch::Armv7) + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs index af5d1c2ff45..45ead8d65ab 100644 --- a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs @@ -1,13 +1,13 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = opts("watchos", Arch::Armv7k); + let arch = Arch::Armv7k; Target { llvm_target: "armv7k-apple-watchos".into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(), - arch: "arm".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), @@ -22,7 +22,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("watchos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs index cc17265b2b8..be4bc675844 100644 --- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs @@ -1,16 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { + let arch = Arch::Armv7s; Target { llvm_target: "armv7s-apple-ios".into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(), - arch: "arm".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), - ..opts("ios", Arch::Armv7s) + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs index b85214a9c6b..5819981612e 100644 --- a/compiler/rustc_target/src/spec/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs @@ -1,21 +1,23 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::I386); - let llvm_target = super::apple_base::ios_sim_llvm_target("i386"); - + let arch = Arch::I386; Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // IPHONEOS_DEPLOYMENT_TARGET. + // This is required for the target to pick the right + // MACH-O commands, so we do too. + llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ f64:32:64-f80:128-n8:16:32-S128" .into(), - arch: "x86".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..base + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index 15607c12ea9..8b968af5ecc 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -1,28 +1,28 @@ +use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - // ld64 only understand i386 and not i686 - let mut base = super::apple_base::opts("macos", "i386", ""); - base.cpu = "yonah".into(); + // ld64 only understands i386 and not i686 + let arch = Arch::I386; + let mut base = opts("macos", arch); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); - base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); + base.link_env_remove.to_mut().extend(macos_link_env_remove()); base.stack_probes = StackProbeType::X86; base.frame_pointer = FramePointer::Always; - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - let arch = "i686"; - let llvm_target = super::apple_base::macos_llvm_target(&arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + // + // While ld64 doesn't understand i686, LLVM does. + llvm_target: macos_llvm_target(Arch::I686).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ f64:32:64-f80:128-n8:16:32-S128" .into(), - arch: "x86".into(), + arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs deleted file mode 100644 index f41533a9548..00000000000 --- a/compiler/rustc_target/src/spec/linux_kernel_base.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::spec::TargetOptions; -use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType}; - -pub fn opts() -> TargetOptions { - TargetOptions { - env: "gnu".into(), - disable_redzone: true, - panic_strategy: PanicStrategy::Abort, - stack_probes: StackProbeType::X86, - frame_pointer: FramePointer::Always, - position_independent_executables: true, - needs_plt: true, - relro_level: RelroLevel::Full, - relocation_model: RelocModel::Static, - - ..Default::default() - } -} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 72b088d663b..e809f646860 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -59,7 +59,6 @@ pub mod crt_objects; mod android_base; mod apple_base; -mod apple_sdk_base; mod avr_gnu_base; mod bpf_base; mod dragonfly_base; @@ -71,11 +70,11 @@ mod illumos_base; mod l4re_base; mod linux_base; mod linux_gnu_base; -mod linux_kernel_base; mod linux_musl_base; mod linux_uclibc_base; mod msvc_base; mod netbsd_base; +mod nto_qnx_base; mod openbsd_base; mod redox_base; mod solaris_base; @@ -1003,7 +1002,7 @@ macro_rules! supported_targets { $( #[test] // `#[test]` fn $module() { - tests_impl::test_target(super::$module::target(), $triple); + tests_impl::test_target(super::$module::target()); } )+ } @@ -1071,8 +1070,6 @@ supported_targets! { ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi), ("aarch64-linux-android", aarch64_linux_android), - ("x86_64-unknown-none-linuxkernel", x86_64_unknown_none_linuxkernel), - ("aarch64-unknown-freebsd", aarch64_unknown_freebsd), ("armv6-unknown-freebsd", armv6_unknown_freebsd), ("armv7-unknown-freebsd", armv7_unknown_freebsd), @@ -1246,6 +1243,9 @@ supported_targets! { ("x86_64-unknown-none", x86_64_unknown_none), ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl), + + ("aarch64-unknown-nto-qnx7.1.0", aarch64_unknown_nto_qnx_710), + ("x86_64-pc-nto-qnx7.1.0", x86_64_pc_nto_qnx710), } /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]> @@ -1915,6 +1915,7 @@ impl Target { Abi::Stdcall { unwind } } Abi::System { unwind } => Abi::C { unwind }, + Abi::EfiApi if self.arch == "arm" => Abi::Aapcs { unwind: false }, Abi::EfiApi if self.arch == "x86_64" => Abi::Win64 { unwind: false }, Abi::EfiApi => Abi::C { unwind: false }, @@ -1941,8 +1942,10 @@ impl Target { | PlatformIntrinsic | Unadjusted | Cdecl { .. } - | EfiApi | RustCold => true, + EfiApi => { + ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..]) + } X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]), Aapcs { .. } => "arm" == self.arch, CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]), diff --git a/compiler/rustc_target/src/spec/nto_qnx_base.rs b/compiler/rustc_target/src/spec/nto_qnx_base.rs new file mode 100644 index 00000000000..6fb581ef5ce --- /dev/null +++ b/compiler/rustc_target/src/spec/nto_qnx_base.rs @@ -0,0 +1,19 @@ +use crate::spec::{cvs, RelroLevel, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { + crt_static_respected: true, + dynamic_linking: true, + env: "nto71".into(), + executables: true, + families: cvs!["unix"], + has_rpath: true, + has_thread_local: false, + linker: Some("qcc".into()), + os: "nto".into(), + position_independent_executables: true, + static_position_independent_executables: true, + relro_level: RelroLevel::Full, + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs index 0539eca6c1f..8281bac10f8 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-freebsd".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs index 7d1bf228c37..90dccb28063 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-linux-gnu".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs index f04f8a48bc8..1a56c78e685 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-linux-musl".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs index 67806d578c8..409b0b26961 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{RelocModel, Target, TargetOptions}; pub fn target() -> Target { Target { - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), llvm_target: "riscv64".into(), pointer_width: 64, arch: "riscv64".into(), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs index cd10f3afaac..ade9d77624b 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-openbsd".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs index f371e09bed7..87aba9171b4 100644 --- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{RelocModel, Target, TargetOptions}; pub fn target() -> Target { Target { - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), llvm_target: "riscv64".into(), pointer_width: 64, arch: "riscv64".into(), diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index 172da0ed5df..e0ecf8037c3 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -2,15 +2,15 @@ use super::super::*; use std::assert_matches::assert_matches; // Test target self-consistency and JSON encoding/decoding roundtrip. -pub(super) fn test_target(mut target: Target, triple: &str) { +pub(super) fn test_target(mut target: Target) { let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j); target.update_to_cli(); - target.check_consistency(triple); + target.check_consistency(); assert_eq!(recycled_target, Ok(target)); } impl Target { - fn check_consistency(&self, triple: &str) { + fn check_consistency(&self) { assert_eq!(self.is_like_osx, self.vendor == "apple"); assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos"); assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi"); @@ -129,8 +129,7 @@ impl Target { if self.dynamic_linking && !(self.is_like_wasm && self.os != "emscripten") { assert_eq!(self.relocation_model, RelocModel::Pic); } - // PIEs are supported but not enabled by default with linuxkernel target. - if self.position_independent_executables && !triple.ends_with("-linuxkernel") { + if self.position_independent_executables { assert_eq!(self.relocation_model, RelocModel::Pic); } // The UEFI targets do not support dynamic linking but still require PIC (#101377). diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs index 58210c75a3d..cada28652f9 100644 --- a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs @@ -1,4 +1,5 @@ -use crate::spec::{cvs, Cc, LinkerFlavor, Lld, TargetOptions}; +use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions}; +use std::borrow::Cow; pub fn opts() -> TargetOptions { // We cannot use `-nodefaultlibs` because compiler-rt has to be passed @@ -36,7 +37,10 @@ pub fn opts() -> TargetOptions { eh_frame_header: false, no_default_libraries: false, has_thread_local: true, - + // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to + // output DWO, despite using DWARF, doesn't use ELF.. + debuginfo_kind: DebuginfoKind::Pdb, + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index 087be1b957b..c053031612c 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -1,29 +1,27 @@ +use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let arch = "x86_64"; - let mut base = super::apple_base::opts("macos", arch, ""); - base.cpu = "core2".into(); - base.max_atomic_width = Some(128); // core2 support cmpxchg16b + let arch = Arch::X86_64; + let mut base = opts("macos", arch); + base.max_atomic_width = Some(128); // core2 supports cmpxchg16b base.frame_pointer = FramePointer::Always; base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); - base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); + base.link_env_remove.to_mut().extend(macos_link_env_remove()); base.stack_probes = StackProbeType::X86; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - let llvm_target = super::apple_base::macos_llvm_target(&arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + llvm_target: macos_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: arch.into(), + arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs index db23f01c233..fbd3ebd4d04 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs @@ -1,20 +1,18 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::X86_64_sim); - let llvm_target = super::apple_base::ios_sim_llvm_target("x86_64"); - + let arch = Arch::X86_64_sim; Target { - llvm_target: llvm_target.into(), + llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..base + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs index 13259205ac0..0f3f8519963 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs @@ -1,10 +1,11 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let llvm_target = "x86_64-apple-ios13.0-macabi"; - let mut base = opts("ios", Arch::X86_64_macabi); + let arch = Arch::X86_64_macabi; + let mut base = opts("ios", arch); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]); Target { @@ -12,7 +13,7 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs index c1fd8e1c8b9..550ce0b9ce5 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs @@ -1,17 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("tvos", Arch::X86_64_sim); + let arch = Arch::X86_64_sim; Target { llvm_target: "x86_64-apple-tvos".into(), pointer_width: 64, data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..base + ..opts("tvos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs index 550566b2aa7..75ce02cba1d 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs @@ -1,18 +1,14 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("watchos", Arch::X86_64_sim); - - let arch = "x86_64"; - let llvm_target = super::apple_base::watchos_sim_llvm_target(arch); - + let arch = Arch::X86_64_sim; Target { - llvm_target: llvm_target.into(), + llvm_target: watchos_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, @@ -28,7 +24,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("watchos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs new file mode 100644 index 00000000000..e9b3acee2e7 --- /dev/null +++ b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs @@ -0,0 +1,21 @@ +use super::nto_qnx_base; +use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "x86_64-pc-unknown".into(), + pointer_width: 64, + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + .into(), + arch: "x86_64".into(), + options: TargetOptions { + cpu: "x86-64".into(), + max_atomic_width: Some(64), + pre_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-Vgcc_ntox86_64_cxx"], + ), + ..nto_qnx_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs deleted file mode 100644 index ebd9636ff51..00000000000 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs +++ /dev/null @@ -1,28 +0,0 @@ -// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for -// generic Linux kernel options. - -use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, Target}; - -pub fn target() -> Target { - let mut base = super::linux_kernel_base::opts(); - base.cpu = "x86-64".into(); - base.max_atomic_width = Some(64); - base.features = - "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float".into(); - base.code_model = Some(CodeModel::Kernel); - base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); - - Target { - // FIXME: Some dispute, the linux-on-clang folks think this should use - // "Linux". We disagree because running *on* Linux is nothing like - // running *as" linux, and historically the "os" component as has always - // been used to mean the "on" part. - llvm_target: "x86_64-unknown-none-elf".into(), - pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), - arch: "x86_64".into(), - - options: base, - } -} diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 61cfeec4bbb..54c738d8389 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -1,6 +1,6 @@ use crate::errors::AutoDerefReachedRecursionLimit; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{self, TraitEngine}; +use crate::traits::{self, TraitEngine, TraitEngineExt}; use rustc_hir as hir; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt}; @@ -27,7 +27,6 @@ pub struct Autoderef<'a, 'tcx> { // Meta infos: infcx: &'a InferCtxt<'tcx>, span: Span, - overloaded_span: Span, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, @@ -99,12 +98,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { body_id: hir::HirId, span: Span, base_ty: Ty<'tcx>, - overloaded_span: Span, ) -> Autoderef<'a, 'tcx> { Autoderef { infcx, span, - overloaded_span, body_id, param_env, state: AutoderefSnapshot { @@ -142,7 +139,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { return None; } - let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot(); + let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx); let normalized_ty = fulfillcx.normalize_projection_type( &self.infcx, self.param_env, @@ -193,10 +190,6 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { self.span } - pub fn overloaded_span(&self) -> Span { - self.overloaded_span - } - pub fn reached_recursion_limit(&self) -> bool { self.state.reached_recursion_limit } diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 96ac4e9c129..0f2e22604dc 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -93,6 +93,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// Normalizes associated types in `value`, potentially returning /// new obligations that must further be processed. + #[instrument(level = "debug", skip(self, cause, param_env), ret)] fn partially_normalize_associated_types_in<T>( &self, cause: ObligationCause<'tcx>, @@ -102,17 +103,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { where T: TypeFoldable<'tcx>, { - debug!("partially_normalize_associated_types_in(value={:?})", value); let mut selcx = traits::SelectionContext::new(self); let traits::Normalized { value, obligations } = traits::normalize(&mut selcx, param_env, cause, value); - debug!( - "partially_normalize_associated_types_in: result={:?} predicates={:?}", - value, obligations - ); InferOk { value, obligations } } + #[instrument(level = "debug", skip(self), ret)] fn type_implements_trait( &self, trait_def_id: DefId, @@ -120,11 +117,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { params: SubstsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> traits::EvaluationResult { - debug!( - "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}", - trait_def_id, ty, params, param_env - ); - let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) }; diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 5d52aa07523..2dce18e2d3c 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -10,7 +10,6 @@ //! //! This API is completely unstable and subject to change. -#![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index ed34ab95ad6..188f8bb7e2a 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{PolyTraitRef, Region, RegionVid}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use std::collections::hash_map::Entry; use std::collections::VecDeque; @@ -27,8 +27,8 @@ pub enum RegionTarget<'tcx> { #[derive(Default, Debug, Clone)] pub struct RegionDeps<'tcx> { - larger: FxHashSet<RegionTarget<'tcx>>, - smaller: FxHashSet<RegionTarget<'tcx>>, + larger: FxIndexSet<RegionTarget<'tcx>>, + smaller: FxIndexSet<RegionTarget<'tcx>>, } pub enum AutoTraitResult<A> { @@ -266,7 +266,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { })); let computed_preds = param_env.caller_bounds().iter(); - let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds().iter().collect(); + let mut user_computed_preds: FxIndexSet<_> = user_env.caller_bounds().iter().collect(); let mut new_env = param_env; let dummy_cause = ObligationCause::dummy(); @@ -389,7 +389,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { /// not just one specific lifetime (e.g., `'static`). fn add_user_pred( &self, - user_computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>, + user_computed_preds: &mut FxIndexSet<ty::Predicate<'tcx>>, new_pred: ty::Predicate<'tcx>, ) { let mut should_add_new = true; @@ -585,7 +585,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { &self, ty: Ty<'_>, nested: impl Iterator<Item = Obligation<'tcx, ty::Predicate<'tcx>>>, - computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>, + computed_preds: &mut FxIndexSet<ty::Predicate<'tcx>>, fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>, predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>, select: &mut SelectionContext<'_, 'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index 81e1d64493e..8f9d5eaac9d 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -14,15 +14,22 @@ pub struct FulfillmentContext<'tcx> { obligations: FxIndexSet<PredicateObligation<'tcx>>, relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>, + + usable_in_snapshot: bool, } impl FulfillmentContext<'_> { - pub(crate) fn new() -> Self { + pub(super) fn new() -> Self { FulfillmentContext { obligations: FxIndexSet::default(), relationships: FxHashMap::default(), + usable_in_snapshot: false, } } + + pub(crate) fn new_in_snapshot() -> Self { + FulfillmentContext { usable_in_snapshot: true, ..Self::new() } + } } impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { @@ -41,7 +48,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { infcx: &InferCtxt<'tcx>, obligation: PredicateObligation<'tcx>, ) { - assert!(!infcx.is_in_snapshot()); + if !self.usable_in_snapshot { + assert!(!infcx.is_in_snapshot()); + } let obligation = infcx.resolve_vars_if_possible(obligation); super::relationships::update(self, infcx, &obligation); @@ -72,7 +81,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { } fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> { - assert!(!infcx.is_in_snapshot()); + if !self.usable_in_snapshot { + assert!(!infcx.is_in_snapshot()); + } let mut errors = Vec::new(); let mut next_round = FxIndexSet::default(); diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 21516c93efb..ae29c9f5617 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use super::TraitEngine; use super::{ChalkFulfillmentContext, FulfillmentContext}; use crate::infer::InferCtxtExt; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{ @@ -38,7 +38,7 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box<Self> { if tcx.sess.opts.unstable_opts.chalk { - Box::new(ChalkFulfillmentContext::new()) + Box::new(ChalkFulfillmentContext::new_in_snapshot()) } else { Box::new(FulfillmentContext::new_in_snapshot()) } @@ -119,13 +119,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { expected: T, actual: T, ) -> Result<(), TypeError<'tcx>> { - match self.infcx.at(cause, param_env).eq(expected, actual) { - Ok(InferOk { obligations, value: () }) => { - self.register_obligations(obligations); - Ok(()) - } - Err(e) => Err(e), - } + self.infcx + .at(cause, param_env) + .eq(expected, actual) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } pub fn sup<T: ToTrace<'tcx>>( @@ -144,6 +141,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { } } + pub fn select_where_possible(&self) -> Vec<FulfillmentError<'tcx>> { + self.engine.borrow_mut().select_where_possible(self.infcx) + } + pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> { self.engine.borrow_mut().select_all_or_error(self.infcx) } @@ -153,10 +154,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, span: Span, def_id: LocalDefId, - ) -> FxHashSet<Ty<'tcx>> { + ) -> FxIndexSet<Ty<'tcx>> { let tcx = self.infcx.tcx; let assumed_wf_types = tcx.assumed_wf_types(def_id); - let mut implied_bounds = FxHashSet::default(); + let mut implied_bounds = FxIndexSet::default(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let cause = ObligationCause::misc(span, hir_id); for ty in assumed_wf_types { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs new file mode 100644 index 00000000000..58da54afb75 --- /dev/null +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -0,0 +1,52 @@ +use rustc_hir::def_id::DefId; +use rustc_infer::infer::InferCtxt; +use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation}; +use rustc_span::DUMMY_SP; + +use crate::traits::ObligationCtxt; + +pub fn recompute_applicable_impls<'tcx>( + infcx: &InferCtxt<'tcx>, + obligation: &TraitObligation<'tcx>, +) -> Vec<DefId> { + let tcx = infcx.tcx; + let param_env = obligation.param_env; + let dummy_cause = ObligationCause::dummy(); + let impl_may_apply = |impl_def_id| { + let ocx = ObligationCtxt::new_in_snapshot(infcx); + let placeholder_obligation = + infcx.replace_bound_vars_with_placeholders(obligation.predicate); + let obligation_trait_ref = + ocx.normalize(dummy_cause.clone(), param_env, placeholder_obligation.trait_ref); + + let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); + let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs); + let impl_trait_ref = ocx.normalize(ObligationCause::dummy(), param_env, impl_trait_ref); + + if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) { + return false; + } + + let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs); + ocx.register_obligations( + impl_predicates + .predicates + .iter() + .map(|&predicate| Obligation::new(dummy_cause.clone(), param_env, predicate)), + ); + + ocx.select_where_possible().is_empty() + }; + + let mut impls = Vec::new(); + tcx.for_each_relevant_impl( + obligation.predicate.def_id(), + obligation.predicate.skip_binder().trait_ref.self_ty(), + |impl_def_id| { + if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) { + impls.push(impl_def_id) + } + }, + ); + impls +} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index dacce5cd2f6..98c13ffdafb 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1,17 +1,22 @@ +mod ambiguity; pub mod on_unimplemented; pub mod suggestions; use super::{ - FulfillmentContext, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, - Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective, - OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation, + FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, ObligationCause, + ObligationCauseCode, OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, }; - use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_data_structures::fx::FxHashMap; +use crate::traits::engine::TraitEngineExt as _; +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +use crate::traits::query::normalize::AtExt as _; +use crate::traits::specialize::to_pretty_impl_header; +use on_unimplemented::OnUnimplementedNote; +use on_unimplemented::TypeErrCtxtExt as _; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, Style, @@ -40,11 +45,6 @@ use rustc_span::{ExpnKind, Span, DUMMY_SP}; use std::fmt; use std::iter; use std::ops::ControlFlow; - -use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::query::normalize::AtExt as _; -use crate::traits::specialize::to_pretty_impl_header; -use on_unimplemented::TypeErrCtxtExt as _; use suggestions::TypeErrCtxtExt as _; pub use rustc_infer::traits::error_reporting::*; @@ -101,7 +101,6 @@ pub trait TypeErrCtxtExt<'tcx> { &self, errors: &[FulfillmentError<'tcx>], body_id: Option<hir::BodyId>, - fallback_has_occurred: bool, ) -> ErrorGuaranteed; fn report_overflow_error<T>( @@ -124,7 +123,6 @@ pub trait TypeErrCtxtExt<'tcx> { obligation: PredicateObligation<'tcx>, root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, - fallback_has_occurred: bool, ); } @@ -355,7 +353,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { }) .to_predicate(self.tcx), ); - let mut fulfill_cx = FulfillmentContext::new_in_snapshot(); + let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx); fulfill_cx.register_predicate_obligation(self, obligation); if fulfill_cx.select_all_or_error(self).is_empty() { return Ok(( @@ -375,7 +373,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, errors: &[FulfillmentError<'tcx>], body_id: Option<hir::BodyId>, - fallback_has_occurred: bool, ) -> ErrorGuaranteed { #[derive(Debug)] struct ErrorDescriptor<'tcx> { @@ -383,7 +380,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { index: Option<usize>, // None if this is an old error } - let mut error_map: FxHashMap<_, Vec<_>> = self + let mut error_map: FxIndexMap<_, Vec<_>> = self .reported_trait_errors .borrow() .iter() @@ -452,7 +449,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { for (error, suppressed) in iter::zip(errors, is_suppressed) { if !suppressed { - self.report_fulfillment_error(error, body_id, fallback_has_occurred); + self.report_fulfillment_error(error, body_id); } } @@ -534,22 +531,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { mut obligation: PredicateObligation<'tcx>, root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, - fallback_has_occurred: bool, ) { self.set_tainted_by_errors(); let tcx = self.tcx; let mut span = obligation.cause.span; let mut err = match *error { - SelectionError::Ambiguous(ref impls) => { - let mut err = self.tcx.sess.struct_span_err( - obligation.cause.span, - &format!("multiple applicable `impl`s for `{}`", obligation.predicate), - ); - self.annotate_source_of_ambiguity(&mut err, impls, obligation.predicate); - err.emit(); - return; - } SelectionError::Unimplemented => { // If this obligation was generated as a result of well-formedness checking, see if we // can get a better error message by performing HIR-based well-formedness checking. @@ -700,6 +687,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() { + match obligation.cause.code().peel_derives() { + ObligationCauseCode::RustCall => { + err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument"); + } + ObligationCauseCode::BindingObligation(def_id, _) + | ObligationCauseCode::ItemObligation(def_id) + if ty::ClosureKind::from_def_id(tcx, *def_id).is_some() => + { + err.code(rustc_errors::error_code!(E0059)); + err.set_primary_message(format!( + "type parameter to bare `{}` trait must be a tuple", + tcx.def_path_str(*def_id) + )); + } + _ => {} + } + } + if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait() && predicate_is_const { @@ -848,12 +854,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } - let is_fn_trait = [ - self.tcx.lang_items().fn_trait(), - self.tcx.lang_items().fn_mut_trait(), - self.tcx.lang_items().fn_once_trait(), - ] - .contains(&Some(trait_ref.def_id())); + let is_fn_trait = + ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some(); let is_target_feature_fn = if let ty::FnDef(def_id, _) = *trait_ref.skip_binder().self_ty().kind() { @@ -1000,7 +1002,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // variable that used to fallback to `()` now falling back to `!`. Issue a // note informing about the change in behaviour. if trait_predicate.skip_binder().self_ty().is_never() - && fallback_has_occurred + && self.fallback_has_occurred { let predicate = trait_predicate.map_bound(|mut trait_pred| { trait_pred.trait_ref.substs = self.tcx.mk_substs_trait( @@ -1366,7 +1368,6 @@ trait InferCtxtPrivExt<'tcx> { &self, error: &FulfillmentError<'tcx>, body_id: Option<hir::BodyId>, - fallback_has_occurred: bool, ); fn report_projection_error( @@ -1516,7 +1517,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, error: &FulfillmentError<'tcx>, body_id: Option<hir::BodyId>, - fallback_has_occurred: bool, ) { match error.code { FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { @@ -1524,7 +1524,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { error.obligation.clone(), &error.root_obligation, selection_error, - fallback_has_occurred, ); } FulfillmentErrorCode::CodeProjectionError(ref e) => { @@ -2138,12 +2137,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { crate::traits::TraitQueryMode::Standard, ); match selcx.select_from_obligation(&obligation) { - Err(SelectionError::Ambiguous(impls)) if impls.len() > 1 => { - self.annotate_source_of_ambiguity(&mut err, &impls, predicate); + Ok(None) => { + let impls = ambiguity::recompute_applicable_impls(self.infcx, &obligation); + let has_non_region_infer = + trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer()); + // It doesn't make sense to talk about applicable impls if there are more + // than a handful of them. + if impls.len() > 1 && impls.len() < 5 && has_non_region_infer { + self.annotate_source_of_ambiguity(&mut err, &impls, predicate); + } else { + if self.is_tainted_by_errors() { + err.delay_as_bug(); + return; + } + err.note(&format!("cannot satisfy `{}`", predicate)); + } } _ => { if self.is_tainted_by_errors() { - err.cancel(); + err.delay_as_bug(); return; } err.note(&format!("cannot satisfy `{}`", predicate)); @@ -2435,7 +2447,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } } - let msg = format!("multiple `impl`s satisfying `{}` found", predicate); let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect(); crate_names.sort(); crate_names.dedup(); @@ -2456,13 +2467,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.downgrade_to_delayed_bug(); return; } - let post = if post.len() > 4 { - format!( - ":\n{}\nand {} more", - post.iter().map(|p| format!("- {}", p)).take(4).collect::<Vec<_>>().join("\n"), - post.len() - 4, - ) - } else if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) { + + let msg = format!("multiple `impl`s satisfying `{}` found", predicate); + let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) { format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),) } else if post.len() == 1 { format!(": `{}`", post[0]) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 5eef54c6330..82f0440b307 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -1,14 +1,22 @@ -use super::{ - ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation, -}; +use super::{ObligationCauseCode, PredicateObligation}; use crate::infer::error_reporting::TypeErrCtxt; +use rustc_ast::{MetaItem, NestedMetaItem}; +use rustc_attr as attr; +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::{struct_span_err, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::SubstsRef; -use rustc_middle::ty::{self, GenericParamDefKind}; -use rustc_span::symbol::sym; +use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; +use rustc_parse_format::{ParseMode, Parser, Piece, Position}; +use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::{Span, DUMMY_SP}; use std::iter; +use crate::errors::{ + EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented, +}; + use super::InferCtxtPrivExt; pub trait TypeErrCtxtExt<'tcx> { @@ -276,3 +284,383 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } } + +#[derive(Clone, Debug)] +pub struct OnUnimplementedFormatString(Symbol); + +#[derive(Debug)] +pub struct OnUnimplementedDirective { + pub condition: Option<MetaItem>, + pub subcommands: Vec<OnUnimplementedDirective>, + pub message: Option<OnUnimplementedFormatString>, + pub label: Option<OnUnimplementedFormatString>, + pub note: Option<OnUnimplementedFormatString>, + pub parent_label: Option<OnUnimplementedFormatString>, + pub append_const_msg: Option<Option<Symbol>>, +} + +/// For the `#[rustc_on_unimplemented]` attribute +#[derive(Default)] +pub struct OnUnimplementedNote { + pub message: Option<String>, + pub label: Option<String>, + pub note: Option<String>, + pub parent_label: Option<String>, + /// Append a message for `~const Trait` errors. `None` means not requested and + /// should fallback to a generic message, `Some(None)` suggests using the default + /// appended message, `Some(Some(s))` suggests use the `s` message instead of the + /// default one.. + pub append_const_msg: Option<Option<Symbol>>, +} + +impl<'tcx> OnUnimplementedDirective { + fn parse( + tcx: TyCtxt<'tcx>, + item_def_id: DefId, + items: &[NestedMetaItem], + span: Span, + is_root: bool, + ) -> Result<Self, ErrorGuaranteed> { + let mut errored = None; + let mut item_iter = items.iter(); + + let parse_value = |value_str| { + OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span).map(Some) + }; + + let condition = if is_root { + None + } else { + let cond = item_iter + .next() + .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))? + .meta_item() + .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?; + attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| { + if let Some(value) = cfg.value && let Err(guar) = parse_value(value) { + errored = Some(guar); + } + true + }); + Some(cond.clone()) + }; + + let mut message = None; + let mut label = None; + let mut note = None; + let mut parent_label = None; + let mut subcommands = vec![]; + let mut append_const_msg = None; + + for item in item_iter { + if item.has_name(sym::message) && message.is_none() { + if let Some(message_) = item.value_str() { + message = parse_value(message_)?; + continue; + } + } else if item.has_name(sym::label) && label.is_none() { + if let Some(label_) = item.value_str() { + label = parse_value(label_)?; + continue; + } + } else if item.has_name(sym::note) && note.is_none() { + if let Some(note_) = item.value_str() { + note = parse_value(note_)?; + continue; + } + } else if item.has_name(sym::parent_label) && parent_label.is_none() { + if let Some(parent_label_) = item.value_str() { + parent_label = parse_value(parent_label_)?; + continue; + } + } else if item.has_name(sym::on) + && is_root + && message.is_none() + && label.is_none() + && note.is_none() + { + if let Some(items) = item.meta_item_list() { + match Self::parse(tcx, item_def_id, &items, item.span(), false) { + Ok(subcommand) => subcommands.push(subcommand), + Err(reported) => errored = Some(reported), + }; + continue; + } + } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() { + if let Some(msg) = item.value_str() { + append_const_msg = Some(Some(msg)); + continue; + } else if item.is_word() { + append_const_msg = Some(None); + continue; + } + } + + // nothing found + tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() }); + } + + if let Some(reported) = errored { + Err(reported) + } else { + Ok(OnUnimplementedDirective { + condition, + subcommands, + message, + label, + note, + parent_label, + append_const_msg, + }) + } + } + + pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, ErrorGuaranteed> { + let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) else { + return Ok(None); + }; + + let result = if let Some(items) = attr.meta_item_list() { + Self::parse(tcx, item_def_id, &items, attr.span, true).map(Some) + } else if let Some(value) = attr.value_str() { + Ok(Some(OnUnimplementedDirective { + condition: None, + message: None, + subcommands: vec![], + label: Some(OnUnimplementedFormatString::try_parse( + tcx, + item_def_id, + value, + attr.span, + )?), + note: None, + parent_label: None, + append_const_msg: None, + })) + } else { + let reported = + tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str"); + return Err(reported); + }; + debug!("of_item({:?}) = {:?}", item_def_id, result); + result + } + + pub fn evaluate( + &self, + tcx: TyCtxt<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + options: &[(Symbol, Option<String>)], + ) -> OnUnimplementedNote { + let mut message = None; + let mut label = None; + let mut note = None; + let mut parent_label = None; + let mut append_const_msg = None; + info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); + + let options_map: FxHashMap<Symbol, String> = + options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); + + for command in self.subcommands.iter().chain(Some(self)).rev() { + if let Some(ref condition) = command.condition && !attr::eval_condition( + condition, + &tcx.sess.parse_sess, + Some(tcx.features()), + &mut |cfg| { + let value = cfg.value.map(|v| { + OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map) + }); + + options.contains(&(cfg.name, value)) + }, + ) { + debug!("evaluate: skipping {:?} due to condition", command); + continue; + } + debug!("evaluate: {:?} succeeded", command); + if let Some(ref message_) = command.message { + message = Some(message_.clone()); + } + + if let Some(ref label_) = command.label { + label = Some(label_.clone()); + } + + if let Some(ref note_) = command.note { + note = Some(note_.clone()); + } + + if let Some(ref parent_label_) = command.parent_label { + parent_label = Some(parent_label_.clone()); + } + + append_const_msg = command.append_const_msg; + } + + OnUnimplementedNote { + label: label.map(|l| l.format(tcx, trait_ref, &options_map)), + message: message.map(|m| m.format(tcx, trait_ref, &options_map)), + note: note.map(|n| n.format(tcx, trait_ref, &options_map)), + parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)), + append_const_msg, + } + } +} + +impl<'tcx> OnUnimplementedFormatString { + fn try_parse( + tcx: TyCtxt<'tcx>, + item_def_id: DefId, + from: Symbol, + err_sp: Span, + ) -> Result<Self, ErrorGuaranteed> { + let result = OnUnimplementedFormatString(from); + result.verify(tcx, item_def_id, err_sp)?; + Ok(result) + } + + fn verify( + &self, + tcx: TyCtxt<'tcx>, + item_def_id: DefId, + span: Span, + ) -> Result<(), ErrorGuaranteed> { + let trait_def_id = if tcx.is_trait(item_def_id) { + item_def_id + } else { + tcx.trait_id_of_impl(item_def_id) + .expect("expected `on_unimplemented` to correspond to a trait") + }; + let trait_name = tcx.item_name(trait_def_id); + let generics = tcx.generics_of(item_def_id); + let s = self.0.as_str(); + let parser = Parser::new(s, None, None, false, ParseMode::Format); + let mut result = Ok(()); + for token in parser { + match token { + Piece::String(_) => (), // Normal string, no need to check it + Piece::NextArgument(a) => match a.position { + Position::ArgumentNamed(s) => { + match Symbol::intern(s) { + // `{Self}` is allowed + kw::SelfUpper => (), + // `{ThisTraitsName}` is allowed + s if s == trait_name => (), + // `{from_method}` is allowed + sym::from_method => (), + // `{from_desugaring}` is allowed + sym::from_desugaring => (), + // `{ItemContext}` is allowed + sym::ItemContext => (), + // `{integral}` and `{integer}` and `{float}` are allowed + sym::integral | sym::integer_ | sym::float => (), + // So is `{A}` if A is a type parameter + s => match generics.params.iter().find(|param| param.name == s) { + Some(_) => (), + None => { + let reported = struct_span_err!( + tcx.sess, + span, + E0230, + "there is no parameter `{}` on {}", + s, + if trait_def_id == item_def_id { + format!("trait `{}`", trait_name) + } else { + "impl".to_string() + } + ) + .emit(); + result = Err(reported); + } + }, + } + } + // `{:1}` and `{}` are not to be used + Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => { + let reported = struct_span_err!( + tcx.sess, + span, + E0231, + "only named substitution parameters are allowed" + ) + .emit(); + result = Err(reported); + } + }, + } + } + + result + } + + pub fn format( + &self, + tcx: TyCtxt<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + options: &FxHashMap<Symbol, String>, + ) -> String { + let name = tcx.item_name(trait_ref.def_id); + let trait_str = tcx.def_path_str(trait_ref.def_id); + let generics = tcx.generics_of(trait_ref.def_id); + let generic_map = generics + .params + .iter() + .filter_map(|param| { + let value = match param.kind { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + trait_ref.substs[param.index as usize].to_string() + } + GenericParamDefKind::Lifetime => return None, + }; + let name = param.name; + Some((name, value)) + }) + .collect::<FxHashMap<Symbol, String>>(); + let empty_string = String::new(); + + let s = self.0.as_str(); + let parser = Parser::new(s, None, None, false, ParseMode::Format); + let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string); + parser + .map(|p| match p { + Piece::String(s) => s, + Piece::NextArgument(a) => match a.position { + Position::ArgumentNamed(s) => { + let s = Symbol::intern(s); + match generic_map.get(&s) { + Some(val) => val, + None if s == name => &trait_str, + None => { + if let Some(val) = options.get(&s) { + val + } else if s == sym::from_desugaring || s == sym::from_method { + // don't break messages using these two arguments incorrectly + &empty_string + } else if s == sym::ItemContext { + &item_context + } else if s == sym::integral { + "{integral}" + } else if s == sym::integer_ { + "{integer}" + } else if s == sym::float { + "{float}" + } else { + bug!( + "broken on_unimplemented {:?} for {:?}: \ + no argument matching {:?}", + self.0, + trait_ref, + s + ) + } + } + } + } + _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0), + }, + }) + .collect() + } +} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index d7606d88803..22e7d3ea5dd 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -714,7 +714,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligation.cause.body_id, span, base_ty, - span, ); if let Some(steps) = autoderef.find_map(|(ty, steps)| { // Re-add the `&` @@ -1117,7 +1116,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.span_suggestions( span.shrink_to_lo(), "consider borrowing here", - ["&".to_string(), "&mut ".to_string()].into_iter(), + ["&".to_string(), "&mut ".to_string()], Applicability::MaybeIncorrect, ); } else { @@ -2407,7 +2406,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::CheckAssociatedTypeBounds { .. } | ObligationCauseCode::LetElse | ObligationCauseCode::BinOp { .. } - | ObligationCauseCode::AscribeUserTypeProvePredicate(..) => {} + | ObligationCauseCode::AscribeUserTypeProvePredicate(..) + | ObligationCauseCode::RustCall => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); } @@ -2445,12 +2445,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { (Ok(l), Ok(r)) => l.line == r.line, _ => true, }; - if !ident.span.overlaps(span) && !same_line { + if !ident.span.is_dummy() && !ident.span.overlaps(span) && !same_line { multispan.push_span_label(ident.span, "required by a bound in this"); } } let descr = format!("required by a bound in `{}`", item_name); - if span != DUMMY_SP { + if !span.is_dummy() { let msg = format!("required by this bound in `{}`", item_name); multispan.push_span_label(span, msg); err.span_note(multispan, &descr); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index a417e1440b9..b486c07f354 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -85,7 +85,7 @@ static_assert_size!(PendingPredicateObligation<'_>, 72); impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. - pub fn new() -> FulfillmentContext<'tcx> { + pub(super) fn new() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), relationships: FxHashMap::default(), @@ -93,7 +93,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { } } - pub fn new_in_snapshot() -> FulfillmentContext<'tcx> { + pub(super) fn new_in_snapshot() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), relationships: FxHashMap::default(), diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index be603c609cb..b6ded4ce5a3 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -70,7 +70,7 @@ pub fn can_type_implement_copy<'tcx>( } } Err(errors) => { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } }; } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 9ee6e0a2bf3..10e48610e3a 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -12,7 +12,6 @@ pub mod error_reporting; mod fulfill; pub mod misc; mod object_safety; -mod on_unimplemented; pub mod outlives_bounds; mod project; pub mod query; @@ -58,7 +57,6 @@ pub use self::object_safety::astconv_object_safety_violations; pub use self::object_safety::is_vtable_safe_method; pub use self::object_safety::MethodViolationCode; pub use self::object_safety::ObjectSafetyViolation; -pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; pub use self::project::{normalize, normalize_projection_type, normalize_to}; pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; @@ -117,14 +115,12 @@ pub enum TraitQueryMode { } /// Creates predicate obligations from the generic bounds. +#[instrument(level = "debug", skip(cause, param_env))] pub fn predicates_for_generics<'tcx>( cause: impl Fn(usize, Span) -> ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, generic_bounds: ty::InstantiatedPredicates<'tcx>, ) -> impl Iterator<Item = PredicateObligation<'tcx>> { - let generic_bounds = generic_bounds; - debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); - std::iter::zip(generic_bounds.predicates, generic_bounds.spans).enumerate().map( move |(idx, (predicate, span))| Obligation { cause: cause(idx, span), @@ -140,6 +136,7 @@ pub fn predicates_for_generics<'tcx>( /// `bound` or is not known to meet bound (note that this is /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). +#[instrument(level = "debug", skip(infcx, param_env, span), ret)] pub fn type_known_to_meet_bound_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -147,12 +144,6 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( def_id: DefId, span: Span, ) -> bool { - debug!( - "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})", - ty, - infcx.tcx.def_path_str(def_id) - ); - let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }); let obligation = Obligation { @@ -163,12 +154,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( }; let result = infcx.predicate_must_hold_modulo_regions(&obligation); - debug!( - "type_known_to_meet_ty={:?} bound={} => {:?}", - ty, - infcx.tcx.def_path_str(def_id), - result - ); + debug!(?result); if result && ty.has_non_region_infer() { // Because of inference "guessing", selection can sometimes claim @@ -190,21 +176,9 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( // *definitively* show that it implements `Copy`. Otherwise, // assume it is move; linear is always ok. match &errors[..] { - [] => { - debug!( - "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success", - ty, - infcx.tcx.def_path_str(def_id) - ); - true - } + [] => true, errors => { - debug!( - ?ty, - bound = %infcx.tcx.def_path_str(def_id), - ?errors, - "type_known_to_meet_bound_modulo_regions" - ); + debug!(?errors); false } } @@ -238,7 +212,7 @@ fn do_normalize_predicates<'tcx>( let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) { Ok(predicates) => predicates, Err(errors) => { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } }; @@ -924,25 +898,13 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( def_id: unsize_trait_did, substs: tcx.mk_substs_trait(source, &[target.into()]), }; - let obligation = Obligation::new( - ObligationCause::dummy(), - ty::ParamEnv::reveal_all(), - ty::Binder::dummy(ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: ty::ImplPolarity::Positive, - }), - ); - - let infcx = tcx.infer_ctxt().build(); - let mut selcx = SelectionContext::new(&infcx); - let implsrc = selcx.select(&obligation).unwrap(); - let Some(ImplSource::TraitUpcasting(implsrc_traitcasting)) = implsrc else { - bug!(); - }; - - implsrc_traitcasting.vtable_vptr_slot + match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) { + Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => { + implsrc_traitcasting.vtable_vptr_slot + } + otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"), + } } pub fn provide(providers: &mut ty::query::Providers) { diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs deleted file mode 100644 index 4a4f34b7680..00000000000 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ /dev/null @@ -1,392 +0,0 @@ -use rustc_ast::{MetaItem, NestedMetaItem}; -use rustc_attr as attr; -use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{struct_span_err, ErrorGuaranteed}; -use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; -use rustc_parse_format::{ParseMode, Parser, Piece, Position}; -use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{Span, DUMMY_SP}; - -use crate::errors::{ - EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented, -}; - -#[derive(Clone, Debug)] -pub struct OnUnimplementedFormatString(Symbol); - -#[derive(Debug)] -pub struct OnUnimplementedDirective { - pub condition: Option<MetaItem>, - pub subcommands: Vec<OnUnimplementedDirective>, - pub message: Option<OnUnimplementedFormatString>, - pub label: Option<OnUnimplementedFormatString>, - pub note: Option<OnUnimplementedFormatString>, - pub parent_label: Option<OnUnimplementedFormatString>, - pub append_const_msg: Option<Option<Symbol>>, -} - -#[derive(Default)] -pub struct OnUnimplementedNote { - pub message: Option<String>, - pub label: Option<String>, - pub note: Option<String>, - pub parent_label: Option<String>, - /// Append a message for `~const Trait` errors. `None` means not requested and - /// should fallback to a generic message, `Some(None)` suggests using the default - /// appended message, `Some(Some(s))` suggests use the `s` message instead of the - /// default one.. - pub append_const_msg: Option<Option<Symbol>>, -} - -impl<'tcx> OnUnimplementedDirective { - fn parse( - tcx: TyCtxt<'tcx>, - item_def_id: DefId, - items: &[NestedMetaItem], - span: Span, - is_root: bool, - ) -> Result<Self, ErrorGuaranteed> { - let mut errored = None; - let mut item_iter = items.iter(); - - let parse_value = |value_str| { - OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span).map(Some) - }; - - let condition = if is_root { - None - } else { - let cond = item_iter - .next() - .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))? - .meta_item() - .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?; - attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| { - if let Some(value) = cfg.value && let Err(guar) = parse_value(value) { - errored = Some(guar); - } - true - }); - Some(cond.clone()) - }; - - let mut message = None; - let mut label = None; - let mut note = None; - let mut parent_label = None; - let mut subcommands = vec![]; - let mut append_const_msg = None; - - for item in item_iter { - if item.has_name(sym::message) && message.is_none() { - if let Some(message_) = item.value_str() { - message = parse_value(message_)?; - continue; - } - } else if item.has_name(sym::label) && label.is_none() { - if let Some(label_) = item.value_str() { - label = parse_value(label_)?; - continue; - } - } else if item.has_name(sym::note) && note.is_none() { - if let Some(note_) = item.value_str() { - note = parse_value(note_)?; - continue; - } - } else if item.has_name(sym::parent_label) && parent_label.is_none() { - if let Some(parent_label_) = item.value_str() { - parent_label = parse_value(parent_label_)?; - continue; - } - } else if item.has_name(sym::on) - && is_root - && message.is_none() - && label.is_none() - && note.is_none() - { - if let Some(items) = item.meta_item_list() { - match Self::parse(tcx, item_def_id, &items, item.span(), false) { - Ok(subcommand) => subcommands.push(subcommand), - Err(reported) => errored = Some(reported), - }; - continue; - } - } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() { - if let Some(msg) = item.value_str() { - append_const_msg = Some(Some(msg)); - continue; - } else if item.is_word() { - append_const_msg = Some(None); - continue; - } - } - - // nothing found - tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() }); - } - - if let Some(reported) = errored { - Err(reported) - } else { - Ok(OnUnimplementedDirective { - condition, - subcommands, - message, - label, - note, - parent_label, - append_const_msg, - }) - } - } - - pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, ErrorGuaranteed> { - let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) else { - return Ok(None); - }; - - let result = if let Some(items) = attr.meta_item_list() { - Self::parse(tcx, item_def_id, &items, attr.span, true).map(Some) - } else if let Some(value) = attr.value_str() { - Ok(Some(OnUnimplementedDirective { - condition: None, - message: None, - subcommands: vec![], - label: Some(OnUnimplementedFormatString::try_parse( - tcx, - item_def_id, - value, - attr.span, - )?), - note: None, - parent_label: None, - append_const_msg: None, - })) - } else { - let reported = - tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str"); - return Err(reported); - }; - debug!("of_item({:?}) = {:?}", item_def_id, result); - result - } - - pub fn evaluate( - &self, - tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - options: &[(Symbol, Option<String>)], - ) -> OnUnimplementedNote { - let mut message = None; - let mut label = None; - let mut note = None; - let mut parent_label = None; - let mut append_const_msg = None; - info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); - - let options_map: FxHashMap<Symbol, String> = - options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); - - for command in self.subcommands.iter().chain(Some(self)).rev() { - if let Some(ref condition) = command.condition && !attr::eval_condition( - condition, - &tcx.sess.parse_sess, - Some(tcx.features()), - &mut |cfg| { - let value = cfg.value.map(|v| { - OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map) - }); - - options.contains(&(cfg.name, value)) - }, - ) { - debug!("evaluate: skipping {:?} due to condition", command); - continue; - } - debug!("evaluate: {:?} succeeded", command); - if let Some(ref message_) = command.message { - message = Some(message_.clone()); - } - - if let Some(ref label_) = command.label { - label = Some(label_.clone()); - } - - if let Some(ref note_) = command.note { - note = Some(note_.clone()); - } - - if let Some(ref parent_label_) = command.parent_label { - parent_label = Some(parent_label_.clone()); - } - - append_const_msg = command.append_const_msg; - } - - OnUnimplementedNote { - label: label.map(|l| l.format(tcx, trait_ref, &options_map)), - message: message.map(|m| m.format(tcx, trait_ref, &options_map)), - note: note.map(|n| n.format(tcx, trait_ref, &options_map)), - parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)), - append_const_msg, - } - } -} - -impl<'tcx> OnUnimplementedFormatString { - fn try_parse( - tcx: TyCtxt<'tcx>, - item_def_id: DefId, - from: Symbol, - err_sp: Span, - ) -> Result<Self, ErrorGuaranteed> { - let result = OnUnimplementedFormatString(from); - result.verify(tcx, item_def_id, err_sp)?; - Ok(result) - } - - fn verify( - &self, - tcx: TyCtxt<'tcx>, - item_def_id: DefId, - span: Span, - ) -> Result<(), ErrorGuaranteed> { - let trait_def_id = if tcx.is_trait(item_def_id) { - item_def_id - } else { - tcx.trait_id_of_impl(item_def_id) - .expect("expected `on_unimplemented` to correspond to a trait") - }; - let trait_name = tcx.item_name(trait_def_id); - let generics = tcx.generics_of(item_def_id); - let s = self.0.as_str(); - let parser = Parser::new(s, None, None, false, ParseMode::Format); - let mut result = Ok(()); - for token in parser { - match token { - Piece::String(_) => (), // Normal string, no need to check it - Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => { - match Symbol::intern(s) { - // `{Self}` is allowed - kw::SelfUpper => (), - // `{ThisTraitsName}` is allowed - s if s == trait_name => (), - // `{from_method}` is allowed - sym::from_method => (), - // `{from_desugaring}` is allowed - sym::from_desugaring => (), - // `{ItemContext}` is allowed - sym::ItemContext => (), - // `{integral}` and `{integer}` and `{float}` are allowed - sym::integral | sym::integer_ | sym::float => (), - // So is `{A}` if A is a type parameter - s => match generics.params.iter().find(|param| param.name == s) { - Some(_) => (), - None => { - let reported = struct_span_err!( - tcx.sess, - span, - E0230, - "there is no parameter `{}` on {}", - s, - if trait_def_id == item_def_id { - format!("trait `{}`", trait_name) - } else { - "impl".to_string() - } - ) - .emit(); - result = Err(reported); - } - }, - } - } - // `{:1}` and `{}` are not to be used - Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => { - let reported = struct_span_err!( - tcx.sess, - span, - E0231, - "only named substitution parameters are allowed" - ) - .emit(); - result = Err(reported); - } - }, - } - } - - result - } - - pub fn format( - &self, - tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - options: &FxHashMap<Symbol, String>, - ) -> String { - let name = tcx.item_name(trait_ref.def_id); - let trait_str = tcx.def_path_str(trait_ref.def_id); - let generics = tcx.generics_of(trait_ref.def_id); - let generic_map = generics - .params - .iter() - .filter_map(|param| { - let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { - trait_ref.substs[param.index as usize].to_string() - } - GenericParamDefKind::Lifetime => return None, - }; - let name = param.name; - Some((name, value)) - }) - .collect::<FxHashMap<Symbol, String>>(); - let empty_string = String::new(); - - let s = self.0.as_str(); - let parser = Parser::new(s, None, None, false, ParseMode::Format); - let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string); - parser - .map(|p| match p { - Piece::String(s) => s, - Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => { - let s = Symbol::intern(s); - match generic_map.get(&s) { - Some(val) => val, - None if s == name => &trait_str, - None => { - if let Some(val) = options.get(&s) { - val - } else if s == sym::from_desugaring || s == sym::from_method { - // don't break messages using these two arguments incorrectly - &empty_string - } else if s == sym::ItemContext { - &item_context - } else if s == sym::integral { - "{integral}" - } else if s == sym::integer_ { - "{integer}" - } else if s == sym::float { - "{float}" - } else { - bug!( - "broken on_unimplemented {:?} for {:?}: \ - no argument matching {:?}", - self.0, - trait_ref, - s - ) - } - } - } - } - _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0), - }, - }) - .collect() - } -} diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 108dae092cf..e1092a788e3 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -1,8 +1,8 @@ use crate::infer::InferCtxt; use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput}; use crate::traits::query::NoSolution; -use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt}; -use rustc_data_structures::fx::FxHashSet; +use crate::traits::ObligationCause; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::HirId; use rustc_middle::ty::{self, ParamEnv, Ty}; @@ -22,7 +22,7 @@ pub trait InferCtxtExt<'a, 'tcx> { &'a self, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, - tys: FxHashSet<Ty<'tcx>>, + tys: FxIndexSet<Ty<'tcx>>, ) -> Bounds<'a, 'tcx>; } @@ -74,20 +74,20 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { debug!(?constraints); // Instantiation may have produced new inference variables and constraints on those // variables. Process these constraints. - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.tcx); let cause = ObligationCause::misc(span, body_id); - for &constraint in &constraints.outlives { - let obligation = self.query_outlives_constraint_to_obligation( - constraint, - cause.clone(), - param_env, - ); - fulfill_cx.register_predicate_obligation(self, obligation); - } + let errors = super::fully_solve_obligations( + self, + constraints.outlives.iter().map(|constraint| { + self.query_outlives_constraint_to_obligation( + *constraint, + cause.clone(), + param_env, + ) + }), + ); if !constraints.member_constraints.is_empty() { span_bug!(span, "{:#?}", constraints.member_constraints); } - let errors = fulfill_cx.select_all_or_error(self); if !errors.is_empty() { self.tcx.sess.delay_span_bug( span, @@ -103,7 +103,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { &'a self, param_env: ParamEnv<'tcx>, body_id: HirId, - tys: FxHashSet<Ty<'tcx>>, + tys: FxIndexSet<Ty<'tcx>>, ) -> Bounds<'a, 'tcx> { tys.into_iter() .map(move |ty| { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c8276854016..572f82117cc 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -647,7 +647,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { #[instrument(skip(self), level = "debug")] fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> { let tcx = self.selcx.tcx(); - if tcx.lazy_normalization() { + if tcx.lazy_normalization() || !needs_normalization(&constant, self.param_env.reveal()) { constant } else { let constant = constant.super_fold_with(self); @@ -831,9 +831,7 @@ impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { let universe = self.universe_for(debruijn); let p = ty::PlaceholderConst { universe, name: bound_const }; self.mapped_consts.insert(p, bound_const); - self.infcx - .tcx - .mk_const(ty::ConstS { kind: ty::ConstKind::Placeholder(p), ty: ct.ty() }) + self.infcx.tcx.mk_const(ty::ConstKind::Placeholder(p), ct.ty()) } _ => ct.super_fold_with(self), } @@ -968,10 +966,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { let db = ty::DebruijnIndex::from_usize( self.universe_indices.len() - index + self.current_index.as_usize() - 1, ); - self.tcx().mk_const(ty::ConstS { - kind: ty::ConstKind::Bound(db, *replace_var), - ty: ct.ty(), - }) + self.tcx().mk_const(ty::ConstKind::Bound(db, *replace_var), ct.ty()) } None => ct, } @@ -2173,7 +2168,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id); let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id); let kind = ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs)); - ty.map_bound(|ty| tcx.mk_const(ty::ConstS { ty, kind }).into()) + ty.map_bound(|ty| tcx.mk_const(kind, ty).into()) } else { ty.map_bound(|ty| ty.into()) }; @@ -2192,7 +2187,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( // Verify that the trait item and its implementation have compatible substs lists fn check_substs_compatible<'tcx>( tcx: TyCtxt<'tcx>, - assoc_ty: &ty::AssocItem, + assoc_item: &ty::AssocItem, substs: ty::SubstsRef<'tcx>, ) -> bool { fn check_substs_compatible_inner<'tcx>( @@ -2224,7 +2219,10 @@ fn check_substs_compatible<'tcx>( true } - check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice()) + let generics = tcx.generics_of(assoc_item.def_id); + // Chop off any additional substs (RPITIT) substs + let substs = &substs[0..generics.count().min(substs.len())]; + check_substs_compatible_inner(tcx, generics, substs) } fn confirm_impl_trait_in_trait_candidate<'tcx>( @@ -2253,11 +2251,27 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( }; } - let impl_fn_def_id = leaf_def.item.def_id; // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque}, // since `data.substs` are the impl substs. let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs); + let impl_fn_substs = translate_substs( + selcx.infcx(), + obligation.param_env, + data.impl_def_id, + impl_fn_substs, + leaf_def.defining_node, + ); + + if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) { + let err = tcx.ty_error_with_message( + obligation.cause.span, + "impl method and trait method have different parameters", + ); + return Progress { term: err.into(), obligations }; + } + + let impl_fn_def_id = leaf_def.item.def_id; let cause = ObligationCause::new( obligation.cause.span, diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 715f5be8e2f..a7932b332c9 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -353,6 +353,10 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { &mut self, constant: ty::Const<'tcx>, ) -> Result<ty::Const<'tcx>, Self::Error> { + if !needs_normalization(&constant, self.param_env.reveal()) { + return Ok(constant); + } + let constant = constant.try_super_fold_with(self)?; debug!(?constant, ?self.param_env); Ok(crate::traits::project::with_replaced_escaping_bound_vars( diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 4c5bc333961..3671a0d87df 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -20,7 +20,7 @@ use crate::traits; use crate::traits::coherence::Conflict; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{util, SelectionResult}; -use crate::traits::{Ambiguous, ErrorReporting, Overflow, Unimplemented}; +use crate::traits::{ErrorReporting, Overflow, Unimplemented}; use super::BuiltinImplConditions; use super::IntercrateAmbiguityCause; @@ -200,15 +200,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // and report ambiguity. if i > 1 { debug!("multiple matches, ambig"); - return Err(Ambiguous( - candidates - .into_iter() - .filter_map(|c| match c.candidate { - SelectionCandidate::ImplCandidate(def_id) => Some(def_id), - _ => None, - }) - .collect(), - )); + return Ok(None); } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ed22058c646..28b4bae7cbe 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -555,13 +555,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { GenericParamDefKind::Const { .. } => { let bound_var = ty::BoundVariableKind::Const; bound_vars.push(bound_var); - tcx.mk_const(ty::ConstS { - ty: tcx.type_of(param.def_id), - kind: ty::ConstKind::Bound( + tcx.mk_const( + ty::ConstKind::Bound( ty::INNERMOST, ty::BoundVar::from_usize(bound_vars.len() - 1), ), - }) + tcx.type_of(param.def_id), + ) .into() } }); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9ebff489201..a12f67125bb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2,6 +2,12 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection +// FIXME: The `map` field in ProvisionalEvaluationCache should be changed to +// a `FxIndexMap` to avoid query instability, but right now it causes a perf regression. This would be +// fixed or at least lightened by the addition of the `drain_filter` method to `FxIndexMap` +// Relevant: https://github.com/rust-lang/rust/pull/103723 and https://github.com/bluss/indexmap/issues/242 +#![allow(rustc::potential_query_instability)] + use self::EvaluationResult::*; use self::SelectionCandidate::*; @@ -24,7 +30,8 @@ use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectionCacheKeyExt; use crate::traits::ProjectionCacheKey; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; @@ -294,9 +301,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { assert!(self.query_mode == TraitQueryMode::Canonical); return Err(SelectionError::Overflow(OverflowError::Canonical)); } - Err(SelectionError::Ambiguous(_)) => { - return Ok(None); - } Err(e) => { return Err(e); } @@ -931,7 +935,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.candidate_from_obligation(stack) { Ok(Some(c)) => self.evaluate_candidate(stack, &c), - Err(SelectionError::Ambiguous(_)) => Ok(EvaluatedToAmbig), Ok(None) => Ok(EvaluatedToAmbig), Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical), Err(ErrorReporting) => Err(OverflowError::ErrorReporting), @@ -956,7 +959,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool { let result = match predicate.kind().skip_binder() { - ty::PredicateKind::Trait(ref data) => self.tcx().trait_is_auto(data.def_id()), + ty::PredicateKind::Trait(ref data) => self.tcx().trait_is_coinductive(data.def_id()), ty::PredicateKind::WellFormed(_) => true, _ => false, }; @@ -1132,12 +1135,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// filter_impls filters constant trait obligations and candidates that have a positive impl /// for a negative goal and a negative impl for a positive goal - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, candidates))] fn filter_impls( &mut self, candidates: Vec<SelectionCandidate<'tcx>>, obligation: &TraitObligation<'tcx>, ) -> Vec<SelectionCandidate<'tcx>> { + trace!("{candidates:#?}"); let tcx = self.tcx(); let mut result = Vec::with_capacity(candidates.len()); @@ -1177,6 +1181,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + trace!("{result:#?}"); result } @@ -1973,6 +1978,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32] /// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32] /// ``` + #[instrument(level = "debug", skip(self), ret)] fn constituent_types_for_ty( &self, t: ty::Binder<'tcx, Ty<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index c891658582a..231a18f86ea 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -10,13 +10,15 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html pub mod specialization_graph; +use rustc_infer::traits::{TraitEngine, TraitEngineExt as _}; use specialization_graph::GraphExt; use crate::errors::NegativePositiveConflict; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use crate::traits::engine::TraitEngineExt as _; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause}; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{struct_span_err, DiagnosticBuilder, EmissionGuarantee}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::{self, ImplSubject, TyCtxt}; @@ -200,36 +202,32 @@ fn fulfill_implication<'tcx>( return Err(()); }; + // Needs to be `in_snapshot` because this function is used to rebase + // substitutions, which may happen inside of a select within a probe. + let mut engine = <dyn TraitEngine<'tcx>>::new_in_snapshot(infcx.tcx); // attempt to prove all of the predicates for impl2 given those for impl1 // (which are packed up in penv) + engine.register_predicate_obligations(infcx, obligations.chain(more_obligations)); - infcx.save_and_restore_in_snapshot_flag(|infcx| { - let errors = traits::fully_solve_obligations(&infcx, obligations.chain(more_obligations)); - match &errors[..] { - [] => { - debug!( - "fulfill_implication: an impl for {:?} specializes {:?}", - source_trait, target_trait - ); + let errors = engine.select_all_or_error(infcx); + if !errors.is_empty() { + // no dice! + debug!( + "fulfill_implication: for impls on {:?} and {:?}, \ + could not fulfill: {:?} given {:?}", + source_trait, + target_trait, + errors, + param_env.caller_bounds() + ); + return Err(()); + } - // Now resolve the *substitution* we built for the target earlier, replacing - // the inference variables inside with whatever we got from fulfillment. - Ok(infcx.resolve_vars_if_possible(target_substs)) - } - errors => { - // no dice! - debug!( - "fulfill_implication: for impls on {:?} and {:?}, \ - could not fulfill: {:?} given {:?}", - source_trait, - target_trait, - errors, - param_env.caller_bounds() - ); - Err(()) - } - } - }) + debug!("fulfill_implication: an impl for {:?} specializes {:?}", source_trait, target_trait); + + // Now resolve the *substitution* we built for the target earlier, replacing + // the inference variables inside with whatever we got from fulfillment. + Ok(infcx.resolve_vars_if_possible(target_substs)) } // Query provider for `specialization_graph_of`. @@ -435,7 +433,7 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti // FIXME: Currently only handles ?Sized. // Needs to support ?Move and ?DynSized when they are implemented. - let mut types_without_default_bounds = FxHashSet::default(); + let mut types_without_default_bounds = FxIndexSet::default(); let sized_trait = tcx.lang_items().sized_trait(); if !substs.is_empty() { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 8908fe230b0..fc0a9f69003 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -547,7 +547,7 @@ impl<'tcx> WfPredicates<'tcx> { } ty::FnDef(did, substs) => { - let obligations = self.nominal_obligations(did, substs); + let obligations = self.nominal_obligations_without_const(did, substs); self.out.extend(obligations); } diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 0de28b82661..07f92299f72 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -728,16 +728,16 @@ fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx ty::GenericParamDefKind::Lifetime => { let br = ty::BoundRegion { var: ty::BoundVar::from_usize(substs.len()), - kind: ty::BrAnon(substs.len() as u32), + kind: ty::BrAnon(substs.len() as u32, None), }; tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() } ty::GenericParamDefKind::Const { .. } => tcx - .mk_const(ty::ConstS { - kind: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), - ty: tcx.type_of(param.def_id), - }) + .mk_const( + ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), + tcx.type_of(param.def_id), + ) .into(), }) } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 45d5ea93d54..b64d53e60de 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -498,13 +498,13 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t ty::DebruijnIndex::from_u32(var.debruijn.depth()), ty::BoundRegion { var: ty::BoundVar::from_usize(var.index), - kind: ty::BrAnon(var.index as u32), + kind: ty::BrAnon(var.index as u32, None), }, ), chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(), chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder { universe: ty::UniverseIndex::from_usize(p.ui.counter), - name: ty::BoundRegionKind::BrAnon(p.idx as u32), + name: ty::BoundRegionKind::BrAnon(p.idx as u32, None), }), chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static, chalk_ir::LifetimeData::Empty(_) => { @@ -546,7 +546,7 @@ impl<'tcx> LowerInto<'tcx, ty::Const<'tcx>> for &chalk_ir::Const<RustInterner<'t chalk_ir::ConstValue::Placeholder(_p) => unimplemented!(), chalk_ir::ConstValue::Concrete(c) => ty::ConstKind::Value(c.interned), }; - interner.tcx.mk_const(ty::ConstS { ty, kind }) + interner.tcx.mk_const(kind, ty) } } @@ -933,7 +933,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { } } - ty::BoundRegionKind::BrAnon(var) => match self.parameters.entry(var) { + ty::BoundRegionKind::BrAnon(var, _) => match self.parameters.entry(var) { Entry::Vacant(entry) => { entry.insert(chalk_ir::VariableKind::Lifetime); } @@ -991,13 +991,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> { ty::ReLateBound(index, br) if index == self.binder_index => match br.kind { ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) { Some(idx) => { - let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) }; + let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) }; return self.tcx.mk_region(ty::ReLateBound(index, new_br)); } None => panic!("Missing `BrNamed`."), }, ty::BrEnv => unimplemented!(), - ty::BrAnon(_) => {} + ty::BrAnon(..) => {} }, _ => (), }; @@ -1072,14 +1072,16 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { Some(idx) => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(*idx), - kind: ty::BrAnon(*idx), + kind: ty::BrAnon(*idx, None), }; self.tcx.mk_region(ty::ReLateBound(self.binder_index, br)) } None => { let idx = self.named_regions.len() as u32; - let br = - ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(idx), + kind: ty::BrAnon(idx, None), + }; self.named_regions.insert(_re.def_id, idx); self.tcx.mk_region(ty::ReLateBound(self.binder_index, br)) } @@ -1156,7 +1158,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector { fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> { match *r { ty::RePlaceholder(p) if p.universe == self.universe_index => { - if let ty::BoundRegionKind::BrAnon(anon) = p.name { + if let ty::BoundRegionKind::BrAnon(anon, _) = p.name { self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon); } } diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index d5a8ca5ea78..7b4ad9fea13 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -2,20 +2,18 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::ty::query::Providers; use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; +use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives; use rustc_trait_selection::traits::query::dropck_outlives::{ DropckConstraint, DropckOutlivesResult, }; use rustc_trait_selection::traits::query::normalize::AtExt; use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution}; -use rustc_trait_selection::traits::{ - Normalized, ObligationCause, TraitEngine, TraitEngineExt as _, -}; +use rustc_trait_selection::traits::{Normalized, ObligationCause}; pub(crate) fn provide(p: &mut Providers) { *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p }; @@ -27,120 +25,109 @@ fn dropck_outlives<'tcx>( ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution> { debug!("dropck_outlives(goal={:#?})", canonical_goal); - let (ref infcx, goal, canonical_inference_vars) = - tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal); - let tcx = infcx.tcx; - let ParamEnvAnd { param_env, value: for_ty } = goal; - - let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] }; - - // A stack of types left to process. Each round, we pop - // something from the stack and invoke - // `dtorck_constraint_for_ty`. This may produce new types that - // have to be pushed on the stack. This continues until we have explored - // all the reachable types from the type `for_ty`. - // - // Example: Imagine that we have the following code: - // - // ```rust - // struct A { - // value: B, - // children: Vec<A>, - // } - // - // struct B { - // value: u32 - // } - // - // fn f() { - // let a: A = ...; - // .. - // } // here, `a` is dropped - // ``` - // - // at the point where `a` is dropped, we need to figure out - // which types inside of `a` contain region data that may be - // accessed by any destructors in `a`. We begin by pushing `A` - // onto the stack, as that is the type of `a`. We will then - // invoke `dtorck_constraint_for_ty` which will expand `A` - // into the types of its fields `(B, Vec<A>)`. These will get - // pushed onto the stack. Eventually, expanding `Vec<A>` will - // lead to us trying to push `A` a second time -- to prevent - // infinite recursion, we notice that `A` was already pushed - // once and stop. - let mut ty_stack = vec![(for_ty, 0)]; - - // Set used to detect infinite recursion. - let mut ty_set = FxHashSet::default(); - - let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); - - let cause = ObligationCause::dummy(); - let mut constraints = DropckConstraint::empty(); - while let Some((ty, depth)) = ty_stack.pop() { - debug!( - "{} kinds, {} overflows, {} ty_stack", - result.kinds.len(), - result.overflows.len(), - ty_stack.len() - ); - dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?; - - // "outlives" represent types/regions that may be touched - // by a destructor. - result.kinds.append(&mut constraints.outlives); - result.overflows.append(&mut constraints.overflows); - - // If we have even one overflow, we should stop trying to evaluate further -- - // chances are, the subsequent overflows for this evaluation won't provide useful - // information and will just decrease the speed at which we can emit these errors - // (since we'll be printing for just that much longer for the often enormous types - // that result here). - if !result.overflows.is_empty() { - break; - } + tcx.infer_ctxt().enter_canonical_trait_query(&canonical_goal, |ocx, goal| { + let tcx = ocx.infcx.tcx; + let ParamEnvAnd { param_env, value: for_ty } = goal; + + let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] }; + + // A stack of types left to process. Each round, we pop + // something from the stack and invoke + // `dtorck_constraint_for_ty`. This may produce new types that + // have to be pushed on the stack. This continues until we have explored + // all the reachable types from the type `for_ty`. + // + // Example: Imagine that we have the following code: + // + // ```rust + // struct A { + // value: B, + // children: Vec<A>, + // } + // + // struct B { + // value: u32 + // } + // + // fn f() { + // let a: A = ...; + // .. + // } // here, `a` is dropped + // ``` + // + // at the point where `a` is dropped, we need to figure out + // which types inside of `a` contain region data that may be + // accessed by any destructors in `a`. We begin by pushing `A` + // onto the stack, as that is the type of `a`. We will then + // invoke `dtorck_constraint_for_ty` which will expand `A` + // into the types of its fields `(B, Vec<A>)`. These will get + // pushed onto the stack. Eventually, expanding `Vec<A>` will + // lead to us trying to push `A` a second time -- to prevent + // infinite recursion, we notice that `A` was already pushed + // once and stop. + let mut ty_stack = vec![(for_ty, 0)]; + + // Set used to detect infinite recursion. + let mut ty_set = FxHashSet::default(); + + let cause = ObligationCause::dummy(); + let mut constraints = DropckConstraint::empty(); + while let Some((ty, depth)) = ty_stack.pop() { + debug!( + "{} kinds, {} overflows, {} ty_stack", + result.kinds.len(), + result.overflows.len(), + ty_stack.len() + ); + dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?; + + // "outlives" represent types/regions that may be touched + // by a destructor. + result.kinds.append(&mut constraints.outlives); + result.overflows.append(&mut constraints.overflows); + + // If we have even one overflow, we should stop trying to evaluate further -- + // chances are, the subsequent overflows for this evaluation won't provide useful + // information and will just decrease the speed at which we can emit these errors + // (since we'll be printing for just that much longer for the often enormous types + // that result here). + if !result.overflows.is_empty() { + break; + } - // dtorck types are "types that will get dropped but which - // do not themselves define a destructor", more or less. We have - // to push them onto the stack to be expanded. - for ty in constraints.dtorck_types.drain(..) { - match infcx.at(&cause, param_env).normalize(ty) { - Ok(Normalized { value: ty, obligations }) => { - fulfill_cx.register_predicate_obligations(infcx, obligations); - - debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); - - match ty.kind() { - // All parameters live for the duration of the - // function. - ty::Param(..) => {} - - // A projection that we couldn't resolve - it - // might have a destructor. - ty::Projection(..) | ty::Opaque(..) => { - result.kinds.push(ty.into()); - } + // dtorck types are "types that will get dropped but which + // do not themselves define a destructor", more or less. We have + // to push them onto the stack to be expanded. + for ty in constraints.dtorck_types.drain(..) { + let Normalized { value: ty, obligations } = + ocx.infcx.at(&cause, param_env).normalize(ty)?; + ocx.register_obligations(obligations); + + debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); + + match ty.kind() { + // All parameters live for the duration of the + // function. + ty::Param(..) => {} + + // A projection that we couldn't resolve - it + // might have a destructor. + ty::Projection(..) | ty::Opaque(..) => { + result.kinds.push(ty.into()); + } - _ => { - if ty_set.insert(ty) { - ty_stack.push((ty, depth + 1)); - } + _ => { + if ty_set.insert(ty) { + ty_stack.push((ty, depth + 1)); } } } - - // We don't actually expect to fail to normalize. - // That implies a WF error somewhere else. - Err(NoSolution) => { - return Err(NoSolution); - } } } - } - - debug!("dropck_outlives: result = {:#?}", result); - infcx.make_canonicalized_query_response(canonical_inference_vars, result, &mut *fulfill_cx) + debug!("dropck_outlives: result = {:#?}", result); + Ok(result) + }) } /// Returns a set of constraints that needs to be satisfied in diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 2bc6bc1fc23..30e20ba6f58 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -436,8 +436,8 @@ pub(crate) mod rustc { // finally: padding let padding_span = trace_span!("adding trailing padding").entered(); - let padding_needed = layout_summary.total_size - variant_layout.size(); - if padding_needed > 0 { + if layout_summary.total_size > variant_layout.size() { + let padding_needed = layout_summary.total_size - variant_layout.size(); tree = tree.then(Self::padding(padding_needed)); }; drop(padding_span); diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index f7cc94e5314..384d03106b1 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -122,7 +122,7 @@ mod rustc { let c = c.eval(tcx, param_env); - if let Some(err) = c.error_reported() { + if let Err(err) = c.error_reported() { return Some(Self { alignment: true, lifetimes: true, diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index e057bb66825..cb41c4f94e2 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -33,7 +33,7 @@ pub(crate) fn destructure_const<'tcx>( // construct the consts for the elements of the array/slice let field_consts = branches .iter() - .map(|b| tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty })) + .map(|b| tcx.mk_const(ty::ConstKind::Value(*b), *inner_ty)) .collect::<Vec<_>>(); debug!(?field_consts); @@ -52,10 +52,7 @@ pub(crate) fn destructure_const<'tcx>( for (field, field_valtree) in iter::zip(fields, branches) { let field_ty = field.ty(tcx, substs); - let field_const = tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Value(*field_valtree), - ty: field_ty, - }); + let field_const = tcx.mk_const(ty::ConstKind::Value(*field_valtree), field_ty); field_consts.push(field_const); } debug!(?field_consts); @@ -65,10 +62,7 @@ pub(crate) fn destructure_const<'tcx>( ty::Tuple(elem_tys) => { let fields = iter::zip(*elem_tys, branches) .map(|(elem_ty, elem_valtree)| { - tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Value(*elem_valtree), - ty: elem_ty, - }) + tcx.mk_const(ty::ConstKind::Value(*elem_valtree), elem_ty) }) .collect::<Vec<_>>(); @@ -241,7 +235,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { neg, }) { Ok(c) => c, - Err(LitToConstError::Reported) => self.tcx.const_error(node.ty), + Err(LitToConstError::Reported(guar)) => { + self.tcx.const_error_with_guaranteed(node.ty, guar) + } Err(LitToConstError::TypeError) => { bug!("encountered type error in lit_to_const") } @@ -261,17 +257,13 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let uneval = ty::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs); - let constant = self - .tcx - .mk_const(ty::ConstS { kind: ty::ConstKind::Unevaluated(uneval), ty: node.ty }); + let constant = self.tcx.mk_const(ty::ConstKind::Unevaluated(uneval), node.ty); self.nodes.push(Node::Leaf(constant)) } ExprKind::ConstParam { param, .. } => { - let const_param = self - .tcx - .mk_const(ty::ConstS { kind: ty::ConstKind::Param(*param), ty: node.ty }); + let const_param = self.tcx.mk_const(ty::ConstKind::Param(*param), node.ty); self.nodes.push(Node::Leaf(const_param)) } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 3eebb4ace47..99d3bda6ebf 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -413,7 +413,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> { /// Check if a function is async. fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { let node = tcx.hir().get_by_def_id(def_id.expect_local()); - if let Some(fn_kind) = node.fn_kind() { fn_kind.asyncness() } else { hir::IsAsync::NotAsync } + node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness) } /// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead. diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 7fbe78aa523..7c3eb4efbc9 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -45,7 +45,7 @@ pub trait Interner { type BoundTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type PlaceholderType: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type InferTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; - type DelaySpanBugEmitted: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; + type ErrorGuaranteed: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; type AllocId: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index a4fb1480fa4..02cbb2e858f 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -217,7 +217,7 @@ pub enum TyKind<I: Interner> { /// A placeholder for a type which could not be computed; this is /// propagated to avoid useless error messages. - Error(I::DelaySpanBugEmitted), + Error(I::ErrorGuaranteed), } impl<I: Interner> TyKind<I> { @@ -626,7 +626,7 @@ impl<I: Interner> fmt::Debug for TyKind<I> { // This is manually implemented because a derive would require `I: Encodable` impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I> where - I::DelaySpanBugEmitted: Encodable<E>, + I::ErrorGuaranteed: Encodable<E>, I::AdtDef: Encodable<E>, I::SubstsRef: Encodable<E>, I::DefId: Encodable<E>, @@ -645,7 +645,6 @@ where I::BoundTy: Encodable<E>, I::PlaceholderType: Encodable<E>, I::InferTy: Encodable<E>, - I::DelaySpanBugEmitted: Encodable<E>, I::PredicateKind: Encodable<E>, I::AllocId: Encodable<E>, { @@ -744,7 +743,7 @@ where // This is manually implemented because a derive would require `I: Decodable` impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for TyKind<I> where - I::DelaySpanBugEmitted: Decodable<D>, + I::ErrorGuaranteed: Decodable<D>, I::AdtDef: Decodable<D>, I::SubstsRef: Decodable<D>, I::DefId: Decodable<D>, @@ -763,7 +762,6 @@ where I::BoundTy: Decodable<D>, I::PlaceholderType: Decodable<D>, I::InferTy: Decodable<D>, - I::DelaySpanBugEmitted: Decodable<D>, I::PredicateKind: Decodable<D>, I::AllocId: Decodable<D>, { @@ -829,7 +827,7 @@ where I::ParamTy: HashStable<CTX>, I::PlaceholderType: HashStable<CTX>, I::InferTy: HashStable<CTX>, - I::DelaySpanBugEmitted: HashStable<CTX>, + I::ErrorGuaranteed: HashStable<CTX>, { #[inline] fn hash_stable( diff --git a/config.toml.example b/config.toml.example index 2373fb2ec4f..c94a27b12a3 100644 --- a/config.toml.example +++ b/config.toml.example @@ -87,9 +87,10 @@ changelog-seen = 2 # this flag will indicate that this version check should not be done. #version-check = true -# Link libstdc++ statically into the rustc_llvm instead of relying on a -# dynamic version to be available. -#static-libstdcpp = true +# When true, link libstdc++ statically into the rustc_llvm. +# This is useful if you don't want to use the dynamic version of that +# library provided by LLVM. +#static-libstdcpp = false # Whether to use Ninja to build LLVM. This runs much faster than make. #ninja = true diff --git a/library/alloc/src/alloc/tests.rs b/library/alloc/src/alloc/tests.rs index b2f0194599b..1a5938fd34c 100644 --- a/library/alloc/src/alloc/tests.rs +++ b/library/alloc/src/alloc/tests.rs @@ -22,7 +22,6 @@ fn allocate_zeroed() { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn alloc_owned_small(b: &mut Bencher) { b.iter(|| { let _: Box<_> = Box::new(10); diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index b7e7d5a38a5..66f4c19e0f9 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -158,6 +158,8 @@ use core::hash::{Hash, Hasher}; #[cfg(not(no_global_oom_handling))] use core::iter::FromIterator; use core::iter::{FusedIterator, Iterator}; +#[cfg(not(bootstrap))] +use core::marker::Tuple; use core::marker::{Destruct, Unpin, Unsize}; use core::mem; use core::ops::{ @@ -1979,6 +1981,7 @@ impl<I: ExactSizeIterator + ?Sized, A: Allocator> ExactSizeIterator for Box<I, A #[stable(feature = "fused", since = "1.26.0")] impl<I: FusedIterator + ?Sized, A: Allocator> FusedIterator for Box<I, A> {} +#[cfg(bootstrap)] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl<Args, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> { type Output = <F as FnOnce<Args>>::Output; @@ -1988,6 +1991,17 @@ impl<Args, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> { } } +#[cfg(not(bootstrap))] +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl<Args: Tuple, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> { + type Output = <F as FnOnce<Args>>::Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + <F as FnOnce<Args>>::call_once(*self, args) + } +} + +#[cfg(bootstrap)] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl<Args, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { @@ -1995,6 +2009,15 @@ impl<Args, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> { } } +#[cfg(not(bootstrap))] +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl<Args: Tuple, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + <F as FnMut<Args>>::call_mut(self, args) + } +} + +#[cfg(bootstrap)] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl<Args, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> { extern "rust-call" fn call(&self, args: Args) -> Self::Output { @@ -2002,6 +2025,14 @@ impl<Args, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> { } } +#[cfg(not(bootstrap))] +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl<Args: Tuple, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> { + extern "rust-call" fn call(&self, args: Args) -> Self::Output { + <F as Fn<Args>>::call(self, args) + } +} + #[unstable(feature = "coerce_unsized", issue = "27732")] impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {} diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs index aadb0dc9c40..64bce0ff8c0 100644 --- a/library/alloc/src/collections/btree/node/tests.rs +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -94,6 +94,7 @@ fn test_partial_eq() { #[test] #[cfg(target_arch = "x86_64")] +#[cfg_attr(miri, ignore)] // We'd like to run Miri with layout randomization fn test_sizes() { assert_eq!(core::mem::size_of::<LeafNode<(), ()>>(), 16); assert_eq!(core::mem::size_of::<LeafNode<i64, i64>>(), 16 + CAPACITY * 2 * 8); diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 161a375736c..3e0b0f73550 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -139,7 +139,7 @@ impl Display for TryReserveError { " because the computed capacity exceeded the collection's maximum" } TryReserveErrorKind::AllocError { .. } => { - " because the memory allocator returned a error" + " because the memory allocator returned an error" } }; fmt.write_str(reason) diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index 1f2daef213c..6e0f83020f9 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -3,7 +3,6 @@ use core::iter::TrustedLen; use super::*; #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_push_back_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); b.iter(|| { @@ -16,7 +15,6 @@ fn bench_push_back_100(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_push_front_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); b.iter(|| { @@ -29,12 +27,15 @@ fn bench_push_front_100(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_pop_back_100(b: &mut test::Bencher) { - let mut deq = VecDeque::<i32>::with_capacity(101); + let size = 100; + let mut deq = VecDeque::<i32>::with_capacity(size + 1); + // We'll mess with private state to pretend like `deq` is filled. + // Make sure the buffer is initialized so that we don't read uninit memory. + unsafe { deq.ptr().write_bytes(0u8, size + 1) }; b.iter(|| { - deq.head = 100; + deq.head = size; deq.tail = 0; while !deq.is_empty() { test::black_box(deq.pop_back()); @@ -43,9 +44,9 @@ fn bench_pop_back_100(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_retain_whole_10000(b: &mut test::Bencher) { - let v = (1..100000).collect::<VecDeque<u32>>(); + let size = if cfg!(miri) { 1000 } else { 100000 }; + let v = (1..size).collect::<VecDeque<u32>>(); b.iter(|| { let mut v = v.clone(); @@ -54,9 +55,9 @@ fn bench_retain_whole_10000(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_retain_odd_10000(b: &mut test::Bencher) { - let v = (1..100000).collect::<VecDeque<u32>>(); + let size = if cfg!(miri) { 1000 } else { 100000 }; + let v = (1..size).collect::<VecDeque<u32>>(); b.iter(|| { let mut v = v.clone(); @@ -65,23 +66,26 @@ fn bench_retain_odd_10000(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_retain_half_10000(b: &mut test::Bencher) { - let v = (1..100000).collect::<VecDeque<u32>>(); + let size = if cfg!(miri) { 1000 } else { 100000 }; + let v = (1..size).collect::<VecDeque<u32>>(); b.iter(|| { let mut v = v.clone(); - v.retain(|x| *x > 50000) + v.retain(|x| *x > size / 2) }) } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_pop_front_100(b: &mut test::Bencher) { - let mut deq = VecDeque::<i32>::with_capacity(101); + let size = 100; + let mut deq = VecDeque::<i32>::with_capacity(size + 1); + // We'll mess with private state to pretend like `deq` is filled. + // Make sure the buffer is initialized so that we don't read uninit memory. + unsafe { deq.ptr().write_bytes(0u8, size + 1) }; b.iter(|| { - deq.head = 100; + deq.head = size; deq.tail = 0; while !deq.is_empty() { test::black_box(deq.pop_front()); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index ce36b116f13..008926666c1 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -150,6 +150,7 @@ #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] +#![cfg_attr(not(bootstrap), feature(tuple_trait))] #![feature(unchecked_math)] #![feature(unicode_internals)] #![feature(unsize)] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index bbbdc3aa2a2..766006939fa 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2588,7 +2588,7 @@ impl<T: Clone, A: Allocator> ExtendFromWithinSpec for Vec<T, A> { let (this, spare, len) = unsafe { self.split_at_spare_mut_with_len() }; // SAFETY: - // - caller guaratees that src is a valid index + // - caller guarantees that src is a valid index let to_clone = unsafe { this.get_unchecked(src) }; iter::zip(to_clone, spare) @@ -2607,7 +2607,7 @@ impl<T: Copy, A: Allocator> ExtendFromWithinSpec for Vec<T, A> { let (init, spare) = self.split_at_spare_mut(); // SAFETY: - // - caller guaratees that `src` is a valid index + // - caller guarantees that `src` is a valid index let source = unsafe { init.get_unchecked(src) }; // SAFETY: @@ -2780,7 +2780,7 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> { /// assert_eq!(v_iter.next(), None); /// ``` #[inline] - fn into_iter(self) -> IntoIter<T, A> { + fn into_iter(self) -> Self::IntoIter { unsafe { let mut me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); @@ -2808,7 +2808,7 @@ impl<'a, T, A: Allocator> IntoIterator for &'a Vec<T, A> { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; - fn into_iter(self) -> slice::Iter<'a, T> { + fn into_iter(self) -> Self::IntoIter { self.iter() } } @@ -2818,7 +2818,7 @@ impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec<T, A> { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; - fn into_iter(self) -> slice::IterMut<'a, T> { + fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs index 38887f29af1..9193c79bee8 100644 --- a/library/core/benches/iter.rs +++ b/library/core/benches/iter.rs @@ -1,3 +1,4 @@ +use core::borrow::Borrow; use core::iter::*; use core::mem; use core::num::Wrapping; @@ -403,13 +404,31 @@ fn bench_trusted_random_access_adapters(b: &mut Bencher) { /// Exercises the iter::Copied specialization for slice::Iter #[bench] -fn bench_copied_array_chunks(b: &mut Bencher) { +fn bench_copied_chunks(b: &mut Bencher) { + let v = vec![1u8; 1024]; + + b.iter(|| { + let mut iter = black_box(&v).iter().copied(); + let mut acc = Wrapping(0); + // This uses a while-let loop to side-step the TRA specialization in ArrayChunks + while let Ok(chunk) = iter.next_chunk::<{ mem::size_of::<u64>() }>() { + let d = u64::from_ne_bytes(chunk); + acc += Wrapping(d.rotate_left(7).wrapping_add(1)); + } + acc + }) +} + +/// Exercises the TrustedRandomAccess specialization in ArrayChunks +#[bench] +fn bench_trusted_random_access_chunks(b: &mut Bencher) { let v = vec![1u8; 1024]; b.iter(|| { black_box(&v) .iter() - .copied() + // this shows that we're not relying on the slice::Iter specialization in Copied + .map(|b| *b.borrow()) .array_chunks::<{ mem::size_of::<u64>() }>() .map(|ary| { let d = u64::from_ne_bytes(ary); diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index 1e462e3fc3f..f1244d93285 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -1,10 +1,10 @@ // wasm32 does not support benches (no time). #![cfg(not(target_arch = "wasm32"))] #![feature(flt2dec)] -#![feature(int_log)] #![feature(test)] #![feature(trusted_random_access)] #![feature(iter_array_chunks)] +#![feature(iter_next_chunk)] extern crate test; diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 920e559cc4a..f50d9a8e1bd 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -7,8 +7,8 @@ use crate::cmp; use crate::error::Error; use crate::fmt; -use crate::mem::{self, ValidAlign}; -use crate::ptr::NonNull; +use crate::mem; +use crate::ptr::{Alignment, NonNull}; // While this function is used in one place and its implementation // could be inlined, the previous attempts to do so made rustc @@ -46,7 +46,7 @@ pub struct Layout { // // (However, we do not analogously require `align >= sizeof(void*)`, // even though that is *also* a requirement of `posix_memalign`.) - align: ValidAlign, + align: Alignment, } impl Layout { @@ -71,11 +71,11 @@ impl Layout { } // SAFETY: just checked that align is a power of two. - Layout::from_size_valid_align(size, unsafe { ValidAlign::new_unchecked(align) }) + Layout::from_size_alignment(size, unsafe { Alignment::new_unchecked(align) }) } #[inline(always)] - const fn max_size_for_align(align: ValidAlign) -> usize { + const fn max_size_for_align(align: Alignment) -> usize { // (power-of-two implies align != 0.) // Rounded up size is: @@ -95,7 +95,7 @@ impl Layout { /// Internal helper constructor to skip revalidating alignment validity. #[inline] - const fn from_size_valid_align(size: usize, align: ValidAlign) -> Result<Self, LayoutError> { + const fn from_size_alignment(size: usize, align: Alignment) -> Result<Self, LayoutError> { if size > Self::max_size_for_align(align) { return Err(LayoutError); } @@ -117,7 +117,7 @@ impl Layout { #[rustc_allow_const_fn_unstable(ptr_alignment_type)] pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { // SAFETY: the caller is required to uphold the preconditions. - unsafe { Layout { size, align: ValidAlign::new_unchecked(align) } } + unsafe { Layout { size, align: Alignment::new_unchecked(align) } } } /// The minimum size in bytes for a memory block of this layout. @@ -321,7 +321,7 @@ impl Layout { let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. - Layout::from_size_valid_align(alloc_size, self.align).map(|layout| (layout, padded_size)) + Layout::from_size_alignment(alloc_size, self.align).map(|layout| (layout, padded_size)) } /// Creates a layout describing the record for `self` followed by @@ -379,7 +379,7 @@ impl Layout { let new_size = offset.checked_add(next.size()).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. - let layout = Layout::from_size_valid_align(new_size, new_align)?; + let layout = Layout::from_size_alignment(new_size, new_align)?; Ok((layout, offset)) } @@ -400,7 +400,7 @@ impl Layout { pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> { let size = self.size().checked_mul(n).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. - Layout::from_size_valid_align(size, self.align) + Layout::from_size_alignment(size, self.align) } /// Creates a layout describing the record for `self` followed by @@ -414,7 +414,7 @@ impl Layout { pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> { let new_size = self.size().checked_add(next.size()).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. - Layout::from_size_valid_align(new_size, self.align) + Layout::from_size_alignment(new_size, self.align) } /// Creates a layout describing the record for a `[T; n]`. @@ -425,10 +425,10 @@ impl Layout { #[inline] pub fn array<T>(n: usize) -> Result<Self, LayoutError> { // Reduce the amount of code we need to monomorphize per `T`. - return inner(mem::size_of::<T>(), ValidAlign::of::<T>(), n); + return inner(mem::size_of::<T>(), Alignment::of::<T>(), n); #[inline] - fn inner(element_size: usize, align: ValidAlign, n: usize) -> Result<Layout, LayoutError> { + fn inner(element_size: usize, align: Alignment, n: usize) -> Result<Layout, LayoutError> { // We need to check two things about the size: // - That the total size won't overflow a `usize`, and // - That the total size still fits in an `isize`. @@ -443,7 +443,7 @@ impl Layout { // SAFETY: We just checked above that the `array_size` will not // exceed `isize::MAX` even when rounded up to the alignment. - // And `ValidAlign` guarantees it's a power of two. + // And `Alignment` guarantees it's a power of two. unsafe { Ok(Layout::from_size_align_unchecked(array_size, align.as_usize())) } } } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index eae0e1c7618..2090756d7a3 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -865,24 +865,6 @@ where return Ok(Try::from_output(unsafe { mem::zeroed() })); } - struct Guard<'a, T, const N: usize> { - array_mut: &'a mut [MaybeUninit<T>; N], - initialized: usize, - } - - impl<T, const N: usize> Drop for Guard<'_, T, N> { - fn drop(&mut self) { - debug_assert!(self.initialized <= N); - - // SAFETY: this slice will contain only initialized objects. - unsafe { - crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( - &mut self.array_mut.get_unchecked_mut(..self.initialized), - )); - } - } - } - let mut array = MaybeUninit::uninit_array::<N>(); let mut guard = Guard { array_mut: &mut array, initialized: 0 }; @@ -896,13 +878,11 @@ where ControlFlow::Continue(elem) => elem, }; - // SAFETY: `guard.initialized` starts at 0, is increased by one in the - // loop and the loop is aborted once it reaches N (which is - // `array.len()`). + // SAFETY: `guard.initialized` starts at 0, which means push can be called + // at most N times, which this loop does. unsafe { - guard.array_mut.get_unchecked_mut(guard.initialized).write(item); + guard.push_unchecked(item); } - guard.initialized += 1; } None => { let alive = 0..guard.initialized; @@ -920,6 +900,55 @@ where Ok(Try::from_output(output)) } +/// Panic guard for incremental initialization of arrays. +/// +/// Disarm the guard with `mem::forget` once the array has been initialized. +/// +/// # Safety +/// +/// All write accesses to this structure are unsafe and must maintain a correct +/// count of `initialized` elements. +/// +/// To minimize indirection fields are still pub but callers should at least use +/// `push_unchecked` to signal that something unsafe is going on. +pub(crate) struct Guard<'a, T, const N: usize> { + /// The array to be initialized. + pub array_mut: &'a mut [MaybeUninit<T>; N], + /// The number of items that have been initialized so far. + pub initialized: usize, +} + +impl<T, const N: usize> Guard<'_, T, N> { + /// Adds an item to the array and updates the initialized item counter. + /// + /// # Safety + /// + /// No more than N elements must be initialized. + #[inline] + pub unsafe fn push_unchecked(&mut self, item: T) { + // SAFETY: If `initialized` was correct before and the caller does not + // invoke this method more than N times then writes will be in-bounds + // and slots will not be initialized more than once. + unsafe { + self.array_mut.get_unchecked_mut(self.initialized).write(item); + self.initialized = self.initialized.unchecked_add(1); + } + } +} + +impl<T, const N: usize> Drop for Guard<'_, T, N> { + fn drop(&mut self) { + debug_assert!(self.initialized <= N); + + // SAFETY: this slice will contain only initialized objects. + unsafe { + crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( + &mut self.array_mut.get_unchecked_mut(..self.initialized), + )); + } + } +} + /// Returns the next chunk of `N` items from the iterator or errors with an /// iterator over the remainder. Used for `Iterator::next_chunk`. #[inline] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 7bf32cb0d98..f2975d05457 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1856,7 +1856,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> { /// } /// ``` /// -/// Coverting in the other direction from a `&mut T` +/// Converting in the other direction from a `&mut T` /// to an `&UnsafeCell<T>` is allowed: /// /// ```rust @@ -1936,7 +1936,7 @@ impl<T> UnsafeCell<T> { /// Constructs a new instance of `UnsafeCell` which will wrap the specified /// value. /// - /// All access to the inner value through methods is `unsafe`. + /// All access to the inner value through `&UnsafeCell<T>` requires `unsafe` code. /// /// # Examples /// diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs index 9e9c02093be..151c8e6d898 100644 --- a/library/core/src/const_closure.rs +++ b/library/core/src/const_closure.rs @@ -1,4 +1,6 @@ use crate::marker::Destruct; +#[cfg(not(bootstrap))] +use crate::marker::Tuple; /// Struct representing a closure with mutably borrowed data. /// @@ -44,6 +46,7 @@ impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, macro_rules! impl_fn_mut_tuple { ($($var:ident)*) => { + #[cfg(bootstrap)] #[allow(unused_parens)] impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> @@ -56,6 +59,7 @@ macro_rules! impl_fn_mut_tuple { self.call_mut(args) } } + #[cfg(bootstrap)] #[allow(unused_parens)] impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> @@ -68,6 +72,32 @@ macro_rules! impl_fn_mut_tuple { (self.func)(($($var),*), args) } } + #[cfg(not(bootstrap))] + #[allow(unused_parens)] + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct, + { + type Output = ClosureReturnValue; + + extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { + self.call_mut(args) + } + } + #[cfg(not(bootstrap))] + #[allow(unused_parens)] + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue, + { + extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { + #[allow(non_snake_case)] + let ($($var),*) = &mut self.data; + (self.func)(($($var),*), args) + } + } }; } impl_fn_mut_tuple!(A); diff --git a/library/core/src/error.md b/library/core/src/error.md index 891abebbfd3..78808d489b2 100644 --- a/library/core/src/error.md +++ b/library/core/src/error.md @@ -46,7 +46,7 @@ These functions are equivalent, they either return the inner value if the `Result` is `Ok` or panic if the `Result` is `Err` printing the inner error as the source. The only difference between them is that with `expect` you provide a panic error message to be printed alongside the source, whereas -`unwrap` has a default message indicating only that you unwraped an `Err`. +`unwrap` has a default message indicating only that you unwrapped an `Err`. Of the two, `expect` is generally preferred since its `msg` field allows you to convey your intent and assumptions which makes tracking down the source diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 8923f548adf..15dd9ea7e80 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -13,9 +13,9 @@ use crate::str; /// array of bytes. It can be constructed safely from a <code>&[[u8]]</code> /// slice, or unsafely from a raw `*const c_char`. It can then be /// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or -/// into an owned `CString`. +/// into an owned [`CString`]. /// -/// `&CStr` is to `CString` as <code>&[str]</code> is to `String`: the former +/// `&CStr` is to [`CString`] as <code>&[str]</code> is to [`String`]: the former /// in each pair are borrowed references; the latter are owned /// strings. /// @@ -24,6 +24,9 @@ use crate::str; /// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide /// a safe interface to other consumers. /// +/// [`CString`]: ../../std/ffi/struct.CString.html +/// [`String`]: ../../std/string/struct.String.html +/// /// # Examples /// /// Inspecting a foreign C string: diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index aa13435e680..c755afa39eb 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -86,7 +86,8 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::fmt; -use crate::marker; +use crate::intrinsics::const_eval_select; +use crate::marker::{self, Destruct}; #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] @@ -183,6 +184,7 @@ mod sip; /// [impl]: ../../std/primitive.str.html#impl-Hash-for-str #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Hash"] +#[const_trait] pub trait Hash { /// Feeds this value into the given [`Hasher`]. /// @@ -234,13 +236,25 @@ pub trait Hash { /// [`hash`]: Hash::hash /// [`hash_slice`]: Hash::hash_slice #[stable(feature = "hash_slice", since = "1.3.0")] - fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) + fn hash_slice<H: ~const Hasher>(data: &[Self], state: &mut H) where Self: Sized, { - for piece in data { - piece.hash(state); + //FIXME(const_trait_impl): revert to only a for loop + fn rt<T: Hash, H: Hasher>(data: &[T], state: &mut H) { + for piece in data { + piece.hash(state) + } + } + const fn ct<T: ~const Hash, H: ~const Hasher>(data: &[T], state: &mut H) { + let mut i = 0; + while i < data.len() { + data[i].hash(state); + i += 1; + } } + // SAFETY: same behavior, CT just uses while instead of for + unsafe { const_eval_select((data, state), ct, rt) }; } } @@ -313,6 +327,7 @@ pub use macros::Hash; /// [`write_u8`]: Hasher::write_u8 /// [`write_u32`]: Hasher::write_u32 #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait Hasher { /// Returns the hash value for the values written so far. /// @@ -558,7 +573,8 @@ pub trait Hasher { } #[stable(feature = "indirect_hasher_impl", since = "1.22.0")] -impl<H: Hasher + ?Sized> Hasher for &mut H { +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] +impl<H: ~const Hasher + ?Sized> const Hasher for &mut H { fn finish(&self) -> u64 { (**self).finish() } @@ -638,6 +654,7 @@ impl<H: Hasher + ?Sized> Hasher for &mut H { /// [`build_hasher`]: BuildHasher::build_hasher /// [`HashMap`]: ../../std/collections/struct.HashMap.html #[stable(since = "1.7.0", feature = "build_hasher")] +#[const_trait] pub trait BuildHasher { /// Type of the hasher that will be created. #[stable(since = "1.7.0", feature = "build_hasher")] @@ -698,9 +715,10 @@ pub trait BuildHasher { /// ); /// ``` #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")] - fn hash_one<T: Hash>(&self, x: T) -> u64 + fn hash_one<T: ~const Hash + ~const Destruct>(&self, x: T) -> u64 where Self: Sized, + Self::Hasher: ~const Hasher + ~const Destruct, { let mut hasher = self.build_hasher(); x.hash(&mut hasher); @@ -764,7 +782,8 @@ impl<H> fmt::Debug for BuildHasherDefault<H> { } #[stable(since = "1.7.0", feature = "build_hasher")] -impl<H: Default + Hasher> BuildHasher for BuildHasherDefault<H> { +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] +impl<H: ~const Default + Hasher> const BuildHasher for BuildHasherDefault<H> { type Hasher = H; fn build_hasher(&self) -> H { @@ -806,14 +825,15 @@ mod impls { macro_rules! impl_write { ($(($ty:ident, $meth:ident),)*) => {$( #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for $ty { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl const Hash for $ty { #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { + fn hash<H: ~const Hasher>(&self, state: &mut H) { state.$meth(*self) } #[inline] - fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) { + fn hash_slice<H: ~const Hasher>(data: &[$ty], state: &mut H) { let newlen = data.len() * mem::size_of::<$ty>(); let ptr = data.as_ptr() as *const u8; // SAFETY: `ptr` is valid and aligned, as this macro is only used @@ -842,33 +862,37 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for bool { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl const Hash for bool { #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { + fn hash<H: ~const Hasher>(&self, state: &mut H) { state.write_u8(*self as u8) } } #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for char { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl const Hash for char { #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { + fn hash<H: ~const Hasher>(&self, state: &mut H) { state.write_u32(*self as u32) } } #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for str { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl const Hash for str { #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { + fn hash<H: ~const Hasher>(&self, state: &mut H) { state.write_str(self); } } #[stable(feature = "never_hash", since = "1.29.0")] - impl Hash for ! { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl const Hash for ! { #[inline] - fn hash<H: Hasher>(&self, _: &mut H) { + fn hash<H: ~const Hasher>(&self, _: &mut H) { *self } } @@ -876,9 +900,10 @@ mod impls { macro_rules! impl_hash_tuple { () => ( #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for () { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl const Hash for () { #[inline] - fn hash<H: Hasher>(&self, _state: &mut H) {} + fn hash<H: ~const Hasher>(&self, _state: &mut H) {} } ); @@ -886,10 +911,11 @@ mod impls { maybe_tuple_doc! { $($name)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl<$($name: ~const Hash),+> const Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case)] #[inline] - fn hash<S: Hasher>(&self, state: &mut S) { + fn hash<S: ~const Hasher>(&self, state: &mut S) { let ($(ref $name,)+) = *self; $($name.hash(state);)+ } @@ -932,24 +958,27 @@ mod impls { impl_hash_tuple! { T B C D E F G H I J K L } #[stable(feature = "rust1", since = "1.0.0")] - impl<T: Hash> Hash for [T] { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl<T: ~const Hash> const Hash for [T] { #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { + fn hash<H: ~const Hasher>(&self, state: &mut H) { state.write_length_prefix(self.len()); Hash::hash_slice(self, state) } } #[stable(feature = "rust1", since = "1.0.0")] - impl<T: ?Sized + Hash> Hash for &T { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl<T: ?Sized + ~const Hash> const Hash for &T { #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { + fn hash<H: ~const Hasher>(&self, state: &mut H) { (**self).hash(state); } } #[stable(feature = "rust1", since = "1.0.0")] - impl<T: ?Sized + Hash> Hash for &mut T { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + impl<T: ?Sized + ~const Hash> const Hash for &mut T { #[inline] fn hash<H: Hasher>(&self, state: &mut H) { (**self).hash(state); diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 81bf1dfdf45..7f8287bf56f 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -118,7 +118,7 @@ macro_rules! load_int_le { /// Safety: this performs unchecked indexing of `buf` at `start..start+len`, so /// that must be in-bounds. #[inline] -unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { +const unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { debug_assert!(len < 8); let mut i = 0; // current byte index (from LSB) in the output u64 let mut out = 0; @@ -138,7 +138,8 @@ unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8); i += 1; } - debug_assert_eq!(i, len); + //FIXME(fee1-dead): use debug_assert_eq + debug_assert!(i == len); out } @@ -150,8 +151,9 @@ impl SipHasher { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] - pub fn new() -> SipHasher { + pub const fn new() -> SipHasher { SipHasher::new_with_keys(0, 0) } @@ -162,8 +164,9 @@ impl SipHasher { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] - pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { + pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher { SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) }) } } @@ -176,7 +179,8 @@ impl SipHasher13 { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] - pub fn new() -> SipHasher13 { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + pub const fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) } @@ -187,14 +191,15 @@ impl SipHasher13 { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] - pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) } } } impl<S: Sip> Hasher<S> { #[inline] - fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> { + const fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> { let mut state = Hasher { k0: key0, k1: key1, @@ -209,7 +214,7 @@ impl<S: Sip> Hasher<S> { } #[inline] - fn reset(&mut self) { + const fn reset(&mut self) { self.length = 0; self.state.v0 = self.k0 ^ 0x736f6d6570736575; self.state.v1 = self.k1 ^ 0x646f72616e646f6d; @@ -220,7 +225,8 @@ impl<S: Sip> Hasher<S> { } #[stable(feature = "rust1", since = "1.0.0")] -impl super::Hasher for SipHasher { +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] +impl const super::Hasher for SipHasher { #[inline] fn write(&mut self, msg: &[u8]) { self.0.hasher.write(msg) @@ -238,7 +244,8 @@ impl super::Hasher for SipHasher { } #[unstable(feature = "hashmap_internals", issue = "none")] -impl super::Hasher for SipHasher13 { +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] +impl const super::Hasher for SipHasher13 { #[inline] fn write(&mut self, msg: &[u8]) { self.hasher.write(msg) @@ -255,7 +262,7 @@ impl super::Hasher for SipHasher13 { } } -impl<S: Sip> super::Hasher for Hasher<S> { +impl<S: ~const Sip> const super::Hasher for Hasher<S> { // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined // for this type. We could add them, copy the `short_write` implementation // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*` @@ -335,7 +342,7 @@ impl<S: Sip> super::Hasher for Hasher<S> { } } -impl<S: Sip> Clone for Hasher<S> { +impl<S: Sip> const Clone for Hasher<S> { #[inline] fn clone(&self) -> Hasher<S> { Hasher { @@ -359,6 +366,7 @@ impl<S: Sip> Default for Hasher<S> { } #[doc(hidden)] +#[const_trait] trait Sip { fn c_rounds(_: &mut State); fn d_rounds(_: &mut State); @@ -367,7 +375,7 @@ trait Sip { #[derive(Debug, Clone, Default)] struct Sip13Rounds; -impl Sip for Sip13Rounds { +impl const Sip for Sip13Rounds { #[inline] fn c_rounds(state: &mut State) { compress!(state); @@ -384,7 +392,7 @@ impl Sip for Sip13Rounds { #[derive(Debug, Clone, Default)] struct Sip24Rounds; -impl Sip for Sip24Rounds { +impl const Sip for Sip24Rounds { #[inline] fn c_rounds(state: &mut State) { compress!(state); diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 1dc79afe83f..cec603dcb10 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -55,8 +55,13 @@ #![allow(missing_docs)] use crate::marker::DiscriminantKind; +#[cfg(not(bootstrap))] +use crate::marker::Tuple; use crate::mem; +#[cfg(not(bootstrap))] +pub mod mir; + // These imports are used for simplifying intra-doc links #[allow(unused_imports)] #[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))] @@ -2169,11 +2174,75 @@ extern "rust-intrinsic" { /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, /// which violates the principle that a `const fn` must behave the same at /// compile-time and at run-time. The unsafe code in crate B is fine. + #[cfg(bootstrap)] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] pub fn const_eval_select<ARG, F, G, RET>(arg: ARG, called_in_const: F, called_at_rt: G) -> RET where G: FnOnce<ARG, Output = RET>, F: FnOnce<ARG, Output = RET>; + + /// Selects which function to call depending on the context. + /// + /// If this function is evaluated at compile-time, then a call to this + /// intrinsic will be replaced with a call to `called_in_const`. It gets + /// replaced with a call to `called_at_rt` otherwise. + /// + /// # Type Requirements + /// + /// The two functions must be both function items. They cannot be function + /// pointers or closures. The first function must be a `const fn`. + /// + /// `arg` will be the tupled arguments that will be passed to either one of + /// the two functions, therefore, both functions must accept the same type of + /// arguments. Both functions must return RET. + /// + /// # Safety + /// + /// The two functions must behave observably equivalent. Safe code in other + /// crates may assume that calling a `const fn` at compile-time and at run-time + /// produces the same result. A function that produces a different result when + /// evaluated at run-time, or has any other observable side-effects, is + /// *unsound*. + /// + /// Here is an example of how this could cause a problem: + /// ```no_run + /// #![feature(const_eval_select)] + /// #![feature(core_intrinsics)] + /// use std::hint::unreachable_unchecked; + /// use std::intrinsics::const_eval_select; + /// + /// // Crate A + /// pub const fn inconsistent() -> i32 { + /// fn runtime() -> i32 { 1 } + /// const fn compiletime() -> i32 { 2 } + /// + /// unsafe { + // // ⚠ This code violates the required equivalence of `compiletime` + /// // and `runtime`. + /// const_eval_select((), compiletime, runtime) + /// } + /// } + /// + /// // Crate B + /// const X: i32 = inconsistent(); + /// let x = inconsistent(); + /// if x != X { unsafe { unreachable_unchecked(); }} + /// ``` + /// + /// This code causes Undefined Behavior when being run, since the + /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, + /// which violates the principle that a `const fn` must behave the same at + /// compile-time and at run-time. The unsafe code in crate B is fine. + #[cfg(not(bootstrap))] + #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] + pub fn const_eval_select<ARG: Tuple, F, G, RET>( + arg: ARG, + called_in_const: F, + called_at_rt: G, + ) -> RET + where + G: FnOnce<ARG, Output = RET>, + F: FnOnce<ARG, Output = RET>; } // Some functions are defined here because they accidentally got made diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs new file mode 100644 index 00000000000..1bacdc39148 --- /dev/null +++ b/library/core/src/intrinsics/mir.rs @@ -0,0 +1,123 @@ +//! Rustc internal tooling for hand-writing MIR. +//! +//! If for some reasons you are not writing rustc tests and have found yourself considering using +//! this feature, turn back. This is *exceptionally* unstable. There is no attempt at all to make +//! anything work besides those things which the rustc test suite happened to need. If you make a +//! typo you'll probably ICE. Really, this is not the solution to your problems. Consider instead +//! supporting the [stable MIR project group](https://github.com/rust-lang/project-stable-mir). +//! +//! The documentation for this module describes how to use this feature. If you are interested in +//! hacking on the implementation, most of that documentation lives at +//! `rustc_mir_building/src/build/custom/mod.rs`. +//! +//! Typical usage will look like this: +//! +//! ```rust +//! #![feature(core_intrinsics, custom_mir)] +//! +//! extern crate core; +//! use core::intrinsics::mir::*; +//! +//! #[custom_mir(dialect = "built")] +//! pub fn simple(x: i32) -> i32 { +//! mir!( +//! let temp1: i32; +//! let temp2: _; +//! +//! { +//! temp1 = x; +//! Goto(exit) +//! } +//! +//! exit = { +//! temp2 = Move(temp1); +//! RET = temp2; +//! Return() +//! } +//! ) +//! } +//! ``` +//! +//! Hopefully most of this is fairly self-explanatory. Expanding on some notable details: +//! +//! - The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This +//! attribute only works on functions - there is no way to insert custom MIR into the middle of +//! another function. +//! - The `dialect` and `phase` parameters indicate which version of MIR you are inserting here. +//! This will normally be the phase that corresponds to the thing you are trying to test. The +//! phase can be omitted for dialects that have just one. +//! - You should define your function signature like you normally would. Externally, this function +//! can be called like any other function. +//! - Type inference works - you don't have to spell out the type of all of your locals. +//! +//! For now, all statements and terminators are parsed from nested invocations of the special +//! functions provided in this module. We additionally want to (but do not yet) support more +//! "normal" Rust syntax in places where it makes sense. Also, most kinds of instructions are not +//! supported yet. +//! + +#![unstable( + feature = "custom_mir", + reason = "MIR is an implementation detail and extremely unstable", + issue = "none" +)] +#![allow(unused_variables, non_snake_case, missing_debug_implementations)] + +/// Type representing basic blocks. +/// +/// All terminators will have this type as a return type. It helps achieve some type safety. +pub struct BasicBlock; + +macro_rules! define { + ($name:literal, $($sig:tt)*) => { + #[rustc_diagnostic_item = $name] + pub $($sig)* { panic!() } + } +} + +define!("mir_return", fn Return() -> BasicBlock); +define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); +define!("mir_retag", fn Retag<T>(place: T)); +define!("mir_retag_raw", fn RetagRaw<T>(place: T)); +define!("mir_move", fn Move<T>(place: T) -> T); + +/// Convenience macro for generating custom MIR. +/// +/// See the module documentation for syntax details. This macro is not magic - it only transforms +/// your MIR into something that is easier to parse in the compiler. +#[rustc_macro_transparency = "transparent"] +pub macro mir { + ( + $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)* + + $entry_block:block + + $( + $block_name:ident = $block:block + )* + ) => {{ + // First, we declare all basic blocks. + $( + let $block_name: ::core::intrinsics::mir::BasicBlock; + )* + + { + // Now all locals + #[allow(non_snake_case)] + let RET; + $( + let $local_decl $(: $local_decl_ty)? ; + )* + + { + // Finally, the contents of the basic blocks + $entry_block; + $( + $block; + )* + + RET + } + } + }} +} diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index d4fb886101f..5e4211058aa 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -1,6 +1,8 @@ use crate::array; -use crate::iter::{ByRefSized, FusedIterator, Iterator}; -use crate::ops::{ControlFlow, Try}; +use crate::const_closure::ConstFnMutClosure; +use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce}; +use crate::mem::{self, MaybeUninit}; +use crate::ops::{ControlFlow, NeverShortCircuit, Try}; /// An iterator over `N` elements of the iterator at a time. /// @@ -82,7 +84,13 @@ where } } - impl_fold_via_try_fold! { fold -> try_fold } + fn fold<B, F>(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + <Self as SpecFold>::fold(self, init, f) + } } #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] @@ -168,3 +176,64 @@ where self.iter.len() < N } } + +trait SpecFold: Iterator { + fn fold<B, F>(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B; +} + +impl<I, const N: usize> SpecFold for ArrayChunks<I, N> +where + I: Iterator, +{ + #[inline] + default fn fold<B, F>(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let fold = ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp); + self.try_fold(init, fold).0 + } +} + +impl<I, const N: usize> SpecFold for ArrayChunks<I, N> +where + I: Iterator + TrustedRandomAccessNoCoerce, +{ + #[inline] + fn fold<B, F>(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + let inner_len = self.iter.size(); + let mut i = 0; + // Use a while loop because (0..len).step_by(N) doesn't optimize well. + while inner_len - i >= N { + let mut chunk = MaybeUninit::uninit_array(); + let mut guard = array::Guard { array_mut: &mut chunk, initialized: 0 }; + while guard.initialized < N { + // SAFETY: The method consumes the iterator and the loop condition ensures that + // all accesses are in bounds and only happen once. + unsafe { + let idx = i + guard.initialized; + guard.push_unchecked(self.iter.__iterator_get_unchecked(idx)); + } + } + mem::forget(guard); + // SAFETY: The loop above initialized all elements + let chunk = unsafe { MaybeUninit::array_assume_init(chunk) }; + accum = f(accum, chunk); + i += N; + } + + // unlike try_fold this method does not need to take care of the remainder + // since `self` will be dropped + + accum + } +} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 659409557c9..5dc7427bee0 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -112,6 +112,7 @@ #![feature(const_float_bits_conv)] #![feature(const_float_classify)] #![feature(const_fmt_arguments_new)] +#![feature(const_hash)] #![feature(const_heap)] #![feature(const_convert)] #![feature(const_index_range_slice_index)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 2850d84acc3..32bdc26bc51 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1464,6 +1464,19 @@ pub(crate) mod builtin { /* compiler built-in */ } + /// Attribute macro used to apply derive macros for implementing traits + /// in a const context. + /// + /// See [the reference] for more info. + /// + /// [the reference]: ../../../reference/attributes/derive.html + #[unstable(feature = "derive_const", issue = "none")] + #[rustc_builtin_macro] + #[cfg(not(bootstrap))] + pub macro derive_const($item:item) { + /* compiler built-in */ + } + /// Attribute macro applied to a function to turn it into a unit test. /// /// See [the reference] for more info. diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 2e1a667097c..956a69eda8a 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -21,11 +21,6 @@ mod maybe_uninit; #[stable(feature = "maybe_uninit", since = "1.36.0")] pub use maybe_uninit::MaybeUninit; -// FIXME: This is left here for now to avoid complications around pending reverts. -// Once <https://github.com/rust-lang/rust/issues/101899> is fully resolved, -// this should be removed and the references in `alloc::Layout` updated. -pub(crate) use ptr::Alignment as ValidAlign; - mod transmutability; #[unstable(feature = "transmutability", issue = "99571")] pub use transmutability::{Assume, BikeshedIntrinsicFrom}; diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index a6deb3f65ec..582c8524cf0 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -107,6 +107,9 @@ macro_rules! int_impl { /// Returns the number of leading zeros in the binary representation of `self`. /// + /// Depending on what you're doing with the value, you might also be interested in the + /// [`ilog2`] function which returns a consistent number, even if the type widens. + /// /// # Examples /// /// Basic usage: @@ -116,6 +119,7 @@ macro_rules! int_impl { /// /// assert_eq!(n.leading_zeros(), 0); /// ``` + #[doc = concat!("[`ilog2`]: ", stringify!($SelfT), "::ilog2")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ @@ -2275,15 +2279,16 @@ macro_rules! int_impl { /// # Panics /// /// This function will panic if `self` is less than or equal to zero, - /// or if `base` is less then 2. + /// or if `base` is less than 2. /// /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2302,10 +2307,11 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2323,10 +2329,11 @@ macro_rules! int_impl { /// # Example /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2347,10 +2354,10 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2383,10 +2390,10 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2407,10 +2414,10 @@ macro_rules! int_impl { /// # Example /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 6b6f3417f8a..5b7521220ac 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -460,14 +460,14 @@ macro_rules! nonzero_unsigned_operations { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("# use std::num::", stringify!($Ty), ";")] /// #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -485,14 +485,14 @@ macro_rules! nonzero_unsigned_operations { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("# use std::num::", stringify!($Ty), ";")] /// #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 93f65c5c7aa..d3ba79a2e64 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -109,6 +109,9 @@ macro_rules! uint_impl { /// Returns the number of leading zeros in the binary representation of `self`. /// + /// Depending on what you're doing with the value, you might also be interested in the + /// [`ilog2`] function which returns a consistent number, even if the type widens. + /// /// # Examples /// /// Basic usage: @@ -118,6 +121,7 @@ macro_rules! uint_impl { /// /// assert_eq!(n.leading_zeros(), 2); /// ``` + #[doc = concat!("[`ilog2`]: ", stringify!($SelfT), "::ilog2")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ @@ -692,15 +696,16 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `self` is zero, or if `base` is less then 2. + /// This function will panic if `self` is zero, or if `base` is less than 2. /// /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -719,10 +724,11 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -740,10 +746,11 @@ macro_rules! uint_impl { /// # Example /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -764,10 +771,10 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -800,10 +807,10 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -822,10 +829,10 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 2e0a752c815..11b43b621c7 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -1,3 +1,6 @@ +#[cfg(not(bootstrap))] +use crate::marker::Tuple; + /// The version of the call operator that takes an immutable receiver. /// /// Instances of `Fn` can be called repeatedly without mutating state. @@ -51,6 +54,7 @@ /// let double = |x| x * 2; /// assert_eq!(call_with_one(double), 2); /// ``` +#[cfg(bootstrap)] #[lang = "fn"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Fn"] @@ -71,13 +75,93 @@ )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), const_trait)] pub trait Fn<Args>: FnMut<Args> { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] extern "rust-call" fn call(&self, args: Args) -> Self::Output; } +/// The version of the call operator that takes an immutable receiver. +/// +/// Instances of `Fn` can be called repeatedly without mutating state. +/// +/// *This trait (`Fn`) is not to be confused with [function pointers] +/// (`fn`).* +/// +/// `Fn` is implemented automatically by closures which only take immutable +/// references to captured variables or don't capture anything at all, as well +/// as (safe) [function pointers] (with some caveats, see their documentation +/// for more details). Additionally, for any type `F` that implements `Fn`, `&F` +/// implements `Fn`, too. +/// +/// Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any +/// instance of `Fn` can be used as a parameter where a [`FnMut`] or [`FnOnce`] +/// is expected. +/// +/// Use `Fn` as a bound when you want to accept a parameter of function-like +/// type and need to call it repeatedly and without mutating state (e.g., when +/// calling it concurrently). If you do not need such strict requirements, use +/// [`FnMut`] or [`FnOnce`] as bounds. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// some more information on this topic. +/// +/// Also of note is the special syntax for `Fn` traits (e.g. +/// `Fn(usize, bool) -> usize`). Those interested in the technical details of +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. +/// +/// [book]: ../../book/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Calling a closure +/// +/// ``` +/// let square = |x| x * x; +/// assert_eq!(square(5), 25); +/// ``` +/// +/// ## Using a `Fn` parameter +/// +/// ``` +/// fn call_with_one<F>(func: F) -> usize +/// where F: Fn(usize) -> usize { +/// func(1) +/// } +/// +/// let double = |x| x * 2; +/// assert_eq!(call_with_one(double), 2); +/// ``` +#[cfg(not(bootstrap))] +#[lang = "fn"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Fn"] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{Fn}<{Args}>` closure, found `{Self}`", + label = "expected an `Fn<{Args}>` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +#[const_trait] +pub trait Fn<Args: Tuple>: FnMut<Args> { + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + /// The version of the call operator that takes a mutable receiver. /// /// Instances of `FnMut` can be called repeatedly and may mutate state. @@ -139,6 +223,7 @@ pub trait Fn<Args>: FnMut<Args> { /// /// assert_eq!(x, 5); /// ``` +#[cfg(bootstrap)] #[lang = "fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "FnMut"] @@ -159,13 +244,101 @@ pub trait Fn<Args>: FnMut<Args> { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), const_trait)] pub trait FnMut<Args>: FnOnce<Args> { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } +/// The version of the call operator that takes a mutable receiver. +/// +/// Instances of `FnMut` can be called repeatedly and may mutate state. +/// +/// `FnMut` is implemented automatically by closures which take mutable +/// references to captured variables, as well as all types that implement +/// [`Fn`], e.g., (safe) [function pointers] (since `FnMut` is a supertrait of +/// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F` +/// implements `FnMut`, too. +/// +/// Since [`FnOnce`] is a supertrait of `FnMut`, any instance of `FnMut` can be +/// used where a [`FnOnce`] is expected, and since [`Fn`] is a subtrait of +/// `FnMut`, any instance of [`Fn`] can be used where `FnMut` is expected. +/// +/// Use `FnMut` as a bound when you want to accept a parameter of function-like +/// type and need to call it repeatedly, while allowing it to mutate state. +/// If you don't want the parameter to mutate state, use [`Fn`] as a +/// bound; if you don't need to call it repeatedly, use [`FnOnce`]. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// some more information on this topic. +/// +/// Also of note is the special syntax for `Fn` traits (e.g. +/// `Fn(usize, bool) -> usize`). Those interested in the technical details of +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. +/// +/// [book]: ../../book/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Calling a mutably capturing closure +/// +/// ``` +/// let mut x = 5; +/// { +/// let mut square_x = || x *= x; +/// square_x(); +/// } +/// assert_eq!(x, 25); +/// ``` +/// +/// ## Using a `FnMut` parameter +/// +/// ``` +/// fn do_twice<F>(mut func: F) +/// where F: FnMut() +/// { +/// func(); +/// func(); +/// } +/// +/// let mut x: usize = 1; +/// { +/// let add_two_to_x = || x += 2; +/// do_twice(add_two_to_x); +/// } +/// +/// assert_eq!(x, 5); +/// ``` +#[cfg(not(bootstrap))] +#[lang = "fn_mut"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnMut"] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`", + label = "expected an `FnMut<{Args}>` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +#[const_trait] +pub trait FnMut<Args: Tuple>: FnOnce<Args> { + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + /// The version of the call operator that takes a by-value receiver. /// /// Instances of `FnOnce` can be called, but might not be callable multiple @@ -219,6 +392,7 @@ pub trait FnMut<Args>: FnOnce<Args> { /// /// // `consume_and_return_x` can no longer be invoked at this point /// ``` +#[cfg(bootstrap)] #[lang = "fn_once"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "FnOnce"] @@ -239,7 +413,6 @@ pub trait FnMut<Args>: FnOnce<Args> { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), const_trait)] pub trait FnOnce<Args> { /// The returned type after the call operator is used. #[lang = "fn_once_output"] @@ -251,6 +424,93 @@ pub trait FnOnce<Args> { extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } +/// The version of the call operator that takes a by-value receiver. +/// +/// Instances of `FnOnce` can be called, but might not be callable multiple +/// times. Because of this, if the only thing known about a type is that it +/// implements `FnOnce`, it can only be called once. +/// +/// `FnOnce` is implemented automatically by closures that might consume captured +/// variables, as well as all types that implement [`FnMut`], e.g., (safe) +/// [function pointers] (since `FnOnce` is a supertrait of [`FnMut`]). +/// +/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of +/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected. +/// +/// Use `FnOnce` as a bound when you want to accept a parameter of function-like +/// type and only need to call it once. If you need to call the parameter +/// repeatedly, use [`FnMut`] as a bound; if you also need it to not mutate +/// state, use [`Fn`]. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// some more information on this topic. +/// +/// Also of note is the special syntax for `Fn` traits (e.g. +/// `Fn(usize, bool) -> usize`). Those interested in the technical details of +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. +/// +/// [book]: ../../book/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Using a `FnOnce` parameter +/// +/// ``` +/// fn consume_with_relish<F>(func: F) +/// where F: FnOnce() -> String +/// { +/// // `func` consumes its captured variables, so it cannot be run more +/// // than once. +/// println!("Consumed: {}", func()); +/// +/// println!("Delicious!"); +/// +/// // Attempting to invoke `func()` again will throw a `use of moved +/// // value` error for `func`. +/// } +/// +/// let x = String::from("x"); +/// let consume_and_return_x = move || x; +/// consume_with_relish(consume_and_return_x); +/// +/// // `consume_and_return_x` can no longer be invoked at this point +/// ``` +#[cfg(not(bootstrap))] +#[lang = "fn_once"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnOnce"] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`", + label = "expected an `FnOnce<{Args}>` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +#[const_trait] +pub trait FnOnce<Args: Tuple> { + /// The returned type after the call operator is used. + #[lang = "fn_once_output"] + #[stable(feature = "fn_once_output", since = "1.12.0")] + type Output; + + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +#[cfg(bootstrap)] mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] @@ -310,3 +570,66 @@ mod impls { } } } + +#[cfg(not(bootstrap))] +mod impls { + use crate::marker::Tuple; + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl<A: Tuple, F: ?Sized> const Fn<A> for &F + where + F: ~const Fn<A>, + { + extern "rust-call" fn call(&self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl<A: Tuple, F: ?Sized> const FnMut<A> for &F + where + F: ~const Fn<A>, + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F + where + F: ~const Fn<A>, + { + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F + where + F: ~const FnMut<A>, + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F + where + F: ~const FnMut<A>, + { + type Output = F::Output; + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call_mut(args) + } + } +} diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index ccef35b4532..f0258640e2a 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1059,7 +1059,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {} /// 8 | let x: Pin<&mut Foo> = { /// | - borrow later stored here /// 9 | let x: Pin<&mut Foo> = pin!(Foo { /* … */ }); -/// | ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use +/// | ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use /// 10 | x /// 11 | }; // <- Foo is dropped /// | - temporary value is freed at the end of this statement diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 804a179bdb3..d3d255a802d 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -81,6 +81,10 @@ pub use crate::macros::builtin::alloc_error_handler; #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case}; +#[unstable(feature = "derive_const", issue = "none")] +#[cfg(not(bootstrap))] +pub use crate::macros::builtin::derive_const; + #[unstable( feature = "cfg_accessible", issue = "64797", diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 5a083227bb0..926d2ae5113 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -568,6 +568,31 @@ impl<T: ?Sized> *const T { /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// ## Examples + /// + /// ``` + /// #![feature(ptr_mask, strict_provenance)] + /// let v = 17_u32; + /// let ptr: *const u32 = &v; + /// + /// // `u32` is 4 bytes aligned, + /// // which means that lower 2 bits are always 0. + /// let tag_mask = 0b11; + /// let ptr_mask = !tag_mask; + /// + /// // We can store something in these lower bits + /// let tagged_ptr = ptr.map_addr(|a| a | 0b10); + /// + /// // Get the "tag" back + /// let tag = tagged_ptr.addr() & tag_mask; + /// assert_eq!(tag, 0b10); + /// + /// // Note that `tagged_ptr` is unaligned, it's UB to read from it. + /// // To get original pointer `mask` can be used: + /// let masked_ptr = tagged_ptr.mask(ptr_mask); + /// assert_eq!(unsafe { *masked_ptr }, 17); + /// ``` #[unstable(feature = "ptr_mask", issue = "98290")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline(always)] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6764002bcd4..f71696e9ca0 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -588,6 +588,34 @@ impl<T: ?Sized> *mut T { /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// ## Examples + /// + /// ``` + /// #![feature(ptr_mask, strict_provenance)] + /// let mut v = 17_u32; + /// let ptr: *mut u32 = &mut v; + /// + /// // `u32` is 4 bytes aligned, + /// // which means that lower 2 bits are always 0. + /// let tag_mask = 0b11; + /// let ptr_mask = !tag_mask; + /// + /// // We can store something in these lower bits + /// let tagged_ptr = ptr.map_addr(|a| a | 0b10); + /// + /// // Get the "tag" back + /// let tag = tagged_ptr.addr() & tag_mask; + /// assert_eq!(tag, 0b10); + /// + /// // Note that `tagged_ptr` is unaligned, it's UB to read from/write to it. + /// // To get original pointer `mask` can be used: + /// let masked_ptr = tagged_ptr.mask(ptr_mask); + /// assert_eq!(unsafe { *masked_ptr }, 17); + /// + /// unsafe { *masked_ptr = 0 }; + /// assert_eq!(v, 0); + /// ``` #[unstable(feature = "ptr_mask", issue = "98290")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline(always)] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 4f1bb17344b..0f58bc643d9 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3524,8 +3524,8 @@ impl<T> [T] { } } - /// Transmute the slice to a slice of another type, ensuring alignment of the types is - /// maintained. + /// Transmute the mutable slice to a mutable slice of another type, ensuring alignment of the + /// types is maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest @@ -3667,7 +3667,8 @@ impl<T> [T] { unsafe { self.align_to() } } - /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix. + /// Split a mutable slice into a mutable prefix, a middle of aligned SIMD types, + /// and a mutable suffix. /// /// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak /// postconditions as that method. You're only assured that diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index fc91fe468cc..28275798f75 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -22,7 +22,8 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialEq),+> PartialEq for ($($T,)+) + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl<$($T: ~const PartialEq),+> const PartialEq for ($($T,)+) where last_type!($($T,)+): ?Sized { @@ -40,7 +41,7 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Eq),+> Eq for ($($T,)+) + impl<$($T: Eq),+> Eq for ($($T,)+) where last_type!($($T,)+): ?Sized {} @@ -49,7 +50,8 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl<$($T: ~const PartialOrd + ~const PartialEq),+> const PartialOrd for ($($T,)+) where last_type!($($T,)+): ?Sized { @@ -79,7 +81,8 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Ord),+> Ord for ($($T,)+) + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl<$($T: ~const Ord),+> const Ord for ($($T,)+) where last_type!($($T,)+): ?Sized { diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index f7934d062a3..267245f05dc 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -9,16 +9,19 @@ struct MyHasher { hash: u64, } -impl Default for MyHasher { +impl const Default for MyHasher { fn default() -> MyHasher { MyHasher { hash: 0 } } } -impl Hasher for MyHasher { +impl const Hasher for MyHasher { fn write(&mut self, buf: &[u8]) { - for byte in buf { - self.hash += *byte as u64; + // FIXME(const_trait_impl): change to for loop + let mut i = 0; + while i < buf.len() { + self.hash += buf[i] as u64; + i += 1; } } fn write_str(&mut self, s: &str) { @@ -32,12 +35,25 @@ impl Hasher for MyHasher { #[test] fn test_writer_hasher() { - fn hash<T: Hash>(t: &T) -> u64 { + const fn hash<T: ~const Hash>(t: &T) -> u64 { let mut s = MyHasher { hash: 0 }; t.hash(&mut s); s.finish() } + const { + // FIXME(fee1-dead): assert_eq + assert!(hash(&()) == 0); + assert!(hash(&5_u8) == 5); + assert!(hash(&5_u16) == 5); + assert!(hash(&5_u32) == 5); + + assert!(hash(&'a') == 97); + + let s: &str = "a"; + assert!(hash(&s) == 97 + 0xFF); + }; + assert_eq!(hash(&()), 0); assert_eq!(hash(&5_u8), 5); @@ -97,7 +113,7 @@ struct CustomHasher { output: u64, } -impl Hasher for CustomHasher { +impl const Hasher for CustomHasher { fn finish(&self) -> u64 { self.output } @@ -109,27 +125,29 @@ impl Hasher for CustomHasher { } } -impl Default for CustomHasher { +impl const Default for CustomHasher { fn default() -> CustomHasher { CustomHasher { output: 0 } } } -impl Hash for Custom { - fn hash<H: Hasher>(&self, state: &mut H) { +impl const Hash for Custom { + fn hash<H: ~const Hasher>(&self, state: &mut H) { state.write_u64(self.hash); } } #[test] fn test_custom_state() { - fn hash<T: Hash>(t: &T) -> u64 { + const fn hash<T: ~const Hash>(t: &T) -> u64 { let mut c = CustomHasher { output: 0 }; t.hash(&mut c); c.finish() } assert_eq!(hash(&Custom { hash: 5 }), 5); + + const { assert!(hash(&Custom { hash: 6 }) == 6) }; } // FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten. diff --git a/library/core/tests/hash/sip.rs b/library/core/tests/hash/sip.rs index 877d0841830..3abf6efcfa9 100644 --- a/library/core/tests/hash/sip.rs +++ b/library/core/tests/hash/sip.rs @@ -8,7 +8,6 @@ use core::{mem, slice}; struct Bytes<'a>(&'a [u8]); impl<'a> Hash for Bytes<'a> { - #[allow(unused_must_use)] fn hash<H: Hasher>(&self, state: &mut H) { let Bytes(v) = *self; state.write(v); @@ -25,6 +24,20 @@ fn hash<T: Hash>(x: &T) -> u64 { } #[test] +const fn test_const_sip() { + let val1 = 0x45; + let val2 = 0xfeed; + + const fn const_hash<T: ~const Hash>(x: &T) -> u64 { + let mut st = SipHasher::new(); + x.hash(&mut st); + st.finish() + } + + assert!(const_hash(&(val1)) != const_hash(&(val2))); +} + +#[test] #[allow(unused_must_use)] fn test_siphash_1_3() { let vecs: [[u8; 8]; 64] = [ diff --git a/library/core/tests/iter/adapters/array_chunks.rs b/library/core/tests/iter/adapters/array_chunks.rs index 4e9d89e1e58..ef4a7e53bdd 100644 --- a/library/core/tests/iter/adapters/array_chunks.rs +++ b/library/core/tests/iter/adapters/array_chunks.rs @@ -139,7 +139,8 @@ fn test_iterator_array_chunks_fold() { let result = (0..10).map(|_| CountDrop::new(&count)).array_chunks::<3>().fold(0, |acc, _item| acc + 1); assert_eq!(result, 3); - assert_eq!(count.get(), 10); + // fold impls may or may not process the remainder + assert!(count.get() <= 10 && count.get() >= 9); } #[test] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index eda176d9fcb..61d31b34487 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -11,6 +11,7 @@ #![feature(const_caller_location)] #![feature(const_cell_into_inner)] #![feature(const_convert)] +#![feature(const_hash)] #![feature(const_heap)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init_read)] @@ -64,7 +65,6 @@ #![feature(try_trait_v2)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] -#![feature(int_log)] #![feature(iter_advance_by)] #![feature(iter_array_chunks)] #![feature(iter_collect_into)] diff --git a/library/panic_abort/Cargo.toml b/library/panic_abort/Cargo.toml index 46183d1ad00..e6ea2b1849b 100644 --- a/library/panic_abort/Cargo.toml +++ b/library/panic_abort/Cargo.toml @@ -13,7 +13,7 @@ doc = false [dependencies] alloc = { path = "../alloc" } -cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } +cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } core = { path = "../core" } libc = { version = "0.2", default-features = false } compiler_builtins = "0.1.0" diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index d720cc7bcbd..85386976d63 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -17,4 +17,4 @@ core = { path = "../core" } libc = { version = "0.2", default-features = false } unwind = { path = "../unwind" } compiler_builtins = "0.1.0" -cfg-if = "0.1.8" +cfg-if = "1.0" diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index bc10b12ec2a..daa6976c301 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -23,11 +23,11 @@ hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] } # Dependencies of the `backtrace` crate -addr2line = { version = "0.16.0", optional = true, default-features = false } +addr2line = { version = "0.17.0", optional = true, default-features = false } rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] } -miniz_oxide = { version = "0.4.0", optional = true, default-features = false } +miniz_oxide = { version = "0.5.0", optional = true, default-features = false } [dependencies.object] -version = "0.26.1" +version = "0.29.0" optional = true default-features = false features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 708edc5de47..df490358827 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -3161,14 +3161,16 @@ impl DefaultHasher { #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] #[inline] #[allow(deprecated)] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] - pub fn new() -> DefaultHasher { + pub const fn new() -> DefaultHasher { DefaultHasher(SipHasher13::new_with_keys(0, 0)) } } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Default for DefaultHasher { +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] +impl const Default for DefaultHasher { /// Creates a new `DefaultHasher` using [`new`]. /// See its documentation for more. /// @@ -3180,7 +3182,8 @@ impl Default for DefaultHasher { } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Hasher for DefaultHasher { +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] +impl const Hasher for DefaultHasher { // The underlying `SipHasher13` doesn't override the other // `write_*` methods, so it's ok not to forward them here. diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 3dd5b12507f..4127c4056f2 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -77,9 +77,11 @@ impl f32 { /// ``` /// let f = 3.3_f32; /// let g = -3.3_f32; + /// let h = -3.7_f32; /// /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); + /// assert_eq!(h.round(), -4.0); /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] @@ -275,7 +277,7 @@ impl f32 { /// This result is not an element of the function's codomain, but it is the /// closest floating point number in the real numbers and thus fulfills the /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)` - /// approximatively. + /// approximately. /// /// # Examples /// diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 31351a87978..cc64258da60 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -77,9 +77,11 @@ impl f64 { /// ``` /// let f = 3.3_f64; /// let g = -3.3_f64; + /// let h = -3.7_f64; /// /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); + /// assert_eq!(h.round(), -4.0); /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] @@ -275,7 +277,7 @@ impl f64 { /// This result is not an element of the function's codomain, but it is the /// closest floating point number in the real numbers and thus fulfills the /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)` - /// approximatively. + /// approximately. /// /// # Examples /// diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 385585dada8..9334c833bb6 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -352,6 +352,7 @@ // // Only for const-ness: #![feature(const_collections_with_hasher)] +#![feature(const_hash)] #![feature(const_io_structs)] #![feature(const_ip)] #![feature(const_ipv4)] diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 36d9e8921ef..d5ac16e6b94 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -65,6 +65,10 @@ pub use core::prelude::v1::alloc_error_handler; #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case}; +#[unstable(feature = "derive_const", issue = "none")] +#[cfg(not(bootstrap))] +pub use core::prelude::v1::derive_const; + // Do not `doc(no_inline)` either. #[unstable( feature = "cfg_accessible", diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index eb1e7135a6e..76a1b4a2a86 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -3,7 +3,7 @@ mod tests; use crate::fmt; use crate::sync::{mutex, poison, LockResult, MutexGuard, PoisonError}; -use crate::sys_common::condvar as sys; +use crate::sys::locks as sys; use crate::time::{Duration, Instant}; /// A type indicating whether a timed wait on a condition variable returned diff --git a/library/std/src/sync/mpsc/mpsc_queue.rs b/library/std/src/sync/mpsc/mpsc_queue.rs index cdd64a5def5..7322512e3b4 100644 --- a/library/std/src/sync/mpsc/mpsc_queue.rs +++ b/library/std/src/sync/mpsc/mpsc_queue.rs @@ -8,8 +8,15 @@ //! method, and see the method for more information about it. Due to this //! caveat, this queue might not be appropriate for all use-cases. -// https://www.1024cores.net/home/lock-free-algorithms -// /queues/non-intrusive-mpsc-node-based-queue +// The original implementation is based off: +// https://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue +// +// Note that back when the code was imported, it was licensed under the BSD-2-Clause license: +// http://web.archive.org/web/20110411011612/https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue +// +// The original author of the code agreed to relicense it under `MIT OR Apache-2.0` in 2017, so as +// of today the license of this file is the same as the rest of the codebase: +// https://github.com/rust-lang/rust/pull/42149 #[cfg(all(test, not(target_os = "emscripten")))] mod tests; diff --git a/library/std/src/sync/mpsc/spsc_queue.rs b/library/std/src/sync/mpsc/spsc_queue.rs index 7e745eb31de..61f91313ea9 100644 --- a/library/std/src/sync/mpsc/spsc_queue.rs +++ b/library/std/src/sync/mpsc/spsc_queue.rs @@ -4,7 +4,15 @@ //! concurrently between two threads. This data structure is safe to use and //! enforces the semantics that there is one pusher and one popper. +// The original implementation is based off: // https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue +// +// Note that back when the code was imported, it was licensed under the BSD-2-Clause license: +// http://web.archive.org/web/20110411011612/https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue +// +// The original author of the code agreed to relicense it under `MIT OR Apache-2.0` in 2017, so as +// of today the license of this file is the same as the rest of the codebase: +// https://github.com/rust-lang/rust/pull/42149 #[cfg(all(test, not(target_os = "emscripten")))] mod tests; diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index de851c8fbbe..065045f4420 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -5,7 +5,7 @@ use crate::cell::UnsafeCell; use crate::fmt; use crate::ops::{Deref, DerefMut}; use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; -use crate::sys_common::mutex as sys; +use crate::sys::locks as sys; /// A mutual exclusion primitive useful for protecting shared data /// @@ -163,7 +163,7 @@ use crate::sys_common::mutex as sys; #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Mutex")] pub struct Mutex<T: ?Sized> { - inner: sys::MovableMutex, + inner: sys::Mutex, poison: poison::Flag, data: UnsafeCell<T>, } @@ -217,11 +217,7 @@ impl<T> Mutex<T> { #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] #[inline] pub const fn new(t: T) -> Mutex<T> { - Mutex { - inner: sys::MovableMutex::new(), - poison: poison::Flag::new(), - data: UnsafeCell::new(t), - } + Mutex { inner: sys::Mutex::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t) } } } @@ -264,7 +260,7 @@ impl<T: ?Sized> Mutex<T> { #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> { unsafe { - self.inner.raw_lock(); + self.inner.lock(); MutexGuard::new(self) } } @@ -526,7 +522,7 @@ impl<T: ?Sized> Drop for MutexGuard<'_, T> { fn drop(&mut self) { unsafe { self.lock.poison.done(&self.poison); - self.lock.inner.raw_unlock(); + self.lock.inner.unlock(); } } } @@ -545,7 +541,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> { } } -pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::MovableMutex { +pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { &guard.lock.inner } diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 8b387760768..7c409cb3e97 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -6,7 +6,7 @@ use crate::fmt; use crate::ops::{Deref, DerefMut}; use crate::ptr::NonNull; use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; -use crate::sys_common::rwlock as sys; +use crate::sys::locks as sys; /// A reader-writer lock /// @@ -78,7 +78,7 @@ use crate::sys_common::rwlock as sys; #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "RwLock")] pub struct RwLock<T: ?Sized> { - inner: sys::MovableRwLock, + inner: sys::RwLock, poison: poison::Flag, data: UnsafeCell<T>, } @@ -109,7 +109,7 @@ pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { // `NonNull` is also covariant over `T`, just like we would have with `&T`. `NonNull` // is preferable over `const* T` to allow for niche optimization. data: NonNull<T>, - inner_lock: &'a sys::MovableRwLock, + inner_lock: &'a sys::RwLock, } #[stable(feature = "rust1", since = "1.0.0")] @@ -158,11 +158,7 @@ impl<T> RwLock<T> { #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] #[inline] pub const fn new(t: T) -> RwLock<T> { - RwLock { - inner: sys::MovableRwLock::new(), - poison: poison::Flag::new(), - data: UnsafeCell::new(t), - } + RwLock { inner: sys::RwLock::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t) } } } diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index e6534df8938..6811fadb018 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -51,9 +51,9 @@ pub mod locks { mod futex_condvar; mod futex_mutex; mod futex_rwlock; - pub(crate) use futex_condvar::MovableCondvar; - pub(crate) use futex_mutex::{MovableMutex, Mutex}; - pub(crate) use futex_rwlock::{MovableRwLock, RwLock}; + pub(crate) use futex_condvar::Condvar; + pub(crate) use futex_mutex::Mutex; + pub(crate) use futex_rwlock::RwLock; } use crate::io::ErrorKind; diff --git a/library/std/src/sys/itron/condvar.rs b/library/std/src/sys/itron/condvar.rs index 008cd8fb1e3..f70aa434e48 100644 --- a/library/std/src/sys/itron/condvar.rs +++ b/library/std/src/sys/itron/condvar.rs @@ -12,18 +12,13 @@ pub struct Condvar { unsafe impl Send for Condvar {} unsafe impl Sync for Condvar {} -pub type MovableCondvar = Condvar; - impl Condvar { #[inline] pub const fn new() -> Condvar { Condvar { waiters: SpinMutex::new(waiter_queue::WaiterQueue::new()) } } - #[inline] - pub unsafe fn init(&mut self) {} - - pub unsafe fn notify_one(&self) { + pub fn notify_one(&self) { self.waiters.with_locked(|waiters| { if let Some(task) = waiters.pop_front() { // Unpark the task @@ -39,7 +34,7 @@ impl Condvar { }); } - pub unsafe fn notify_all(&self) { + pub fn notify_all(&self) { self.waiters.with_locked(|waiters| { while let Some(task) = waiters.pop_front() { // Unpark the task diff --git a/library/std/src/sys/itron/mutex.rs b/library/std/src/sys/itron/mutex.rs index 085662e6d44..f2eed8e771c 100644 --- a/library/std/src/sys/itron/mutex.rs +++ b/library/std/src/sys/itron/mutex.rs @@ -11,8 +11,6 @@ pub struct Mutex { mtx: SpinIdOnceCell<()>, } -pub type MovableMutex = Mutex; - /// Create a mutex object. This function never panics. fn new_mtx() -> Result<abi::ID, ItronError> { ItronError::err_if_negative(unsafe { @@ -39,7 +37,7 @@ impl Mutex { } } - pub unsafe fn lock(&self) { + pub fn lock(&self) { let mtx = self.raw(); expect_success(unsafe { abi::loc_mtx(mtx) }, &"loc_mtx"); } @@ -49,7 +47,7 @@ impl Mutex { expect_success_aborting(unsafe { abi::unl_mtx(mtx) }, &"unl_mtx"); } - pub unsafe fn try_lock(&self) -> bool { + pub fn try_lock(&self) -> bool { let mtx = self.raw(); match unsafe { abi::ploc_mtx(mtx) } { abi::E_TMOUT => false, diff --git a/library/std/src/sys/sgx/condvar.rs b/library/std/src/sys/sgx/condvar.rs index 36534e0eff3..aa1174664ae 100644 --- a/library/std/src/sys/sgx/condvar.rs +++ b/library/std/src/sys/sgx/condvar.rs @@ -4,42 +4,43 @@ use crate::time::Duration; use super::waitqueue::{SpinMutex, WaitQueue, WaitVariable}; +/// FIXME: `UnsafeList` is not movable. +struct AllocatedCondvar(SpinMutex<WaitVariable<()>>); + pub struct Condvar { - inner: SpinMutex<WaitVariable<()>>, + inner: LazyBox<AllocatedCondvar>, } -pub(crate) type MovableCondvar = LazyBox<Condvar>; - -impl LazyInit for Condvar { +impl LazyInit for AllocatedCondvar { fn init() -> Box<Self> { - Box::new(Self::new()) + Box::new(AllocatedCondvar(SpinMutex::new(WaitVariable::new(())))) } } impl Condvar { pub const fn new() -> Condvar { - Condvar { inner: SpinMutex::new(WaitVariable::new(())) } + Condvar { inner: LazyBox::new() } } #[inline] - pub unsafe fn notify_one(&self) { - let _ = WaitQueue::notify_one(self.inner.lock()); + pub fn notify_one(&self) { + let _ = WaitQueue::notify_one(self.inner.0.lock()); } #[inline] - pub unsafe fn notify_all(&self) { - let _ = WaitQueue::notify_all(self.inner.lock()); + pub fn notify_all(&self) { + let _ = WaitQueue::notify_all(self.inner.0.lock()); } pub unsafe fn wait(&self, mutex: &Mutex) { - let guard = self.inner.lock(); + let guard = self.inner.0.lock(); WaitQueue::wait(guard, || unsafe { mutex.unlock() }); - unsafe { mutex.lock() } + mutex.lock() } pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { - let success = WaitQueue::wait_timeout(&self.inner, dur, || unsafe { mutex.unlock() }); - unsafe { mutex.lock() }; + let success = WaitQueue::wait_timeout(&self.inner.0, dur, || unsafe { mutex.unlock() }); + mutex.lock(); success } } diff --git a/library/std/src/sys/sgx/mutex.rs b/library/std/src/sys/sgx/mutex.rs index aa747d56b0d..0dbf020ebe0 100644 --- a/library/std/src/sys/sgx/mutex.rs +++ b/library/std/src/sys/sgx/mutex.rs @@ -1,28 +1,28 @@ use super::waitqueue::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable}; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; +/// FIXME: `UnsafeList` is not movable. +struct AllocatedMutex(SpinMutex<WaitVariable<bool>>); + pub struct Mutex { - inner: SpinMutex<WaitVariable<bool>>, + inner: LazyBox<AllocatedMutex>, } -// not movable: see UnsafeList implementation -pub(crate) type MovableMutex = LazyBox<Mutex>; - -impl LazyInit for Mutex { +impl LazyInit for AllocatedMutex { fn init() -> Box<Self> { - Box::new(Self::new()) + Box::new(AllocatedMutex(SpinMutex::new(WaitVariable::new(false)))) } } // Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28 impl Mutex { pub const fn new() -> Mutex { - Mutex { inner: SpinMutex::new(WaitVariable::new(false)) } + Mutex { inner: LazyBox::new() } } #[inline] - pub unsafe fn lock(&self) { - let mut guard = self.inner.lock(); + pub fn lock(&self) { + let mut guard = self.inner.0.lock(); if *guard.lock_var() { // Another thread has the lock, wait WaitQueue::wait(guard, || {}) @@ -35,7 +35,7 @@ impl Mutex { #[inline] pub unsafe fn unlock(&self) { - let guard = self.inner.lock(); + let guard = self.inner.0.lock(); if let Err(mut guard) = WaitQueue::notify_one(guard) { // No other waiters, unlock *guard.lock_var_mut() = false; @@ -45,8 +45,8 @@ impl Mutex { } #[inline] - pub unsafe fn try_lock(&self) -> bool { - let mut guard = try_lock_or_false!(self.inner); + pub fn try_lock(&self) -> bool { + let mut guard = try_lock_or_false!(self.inner.0); if *guard.lock_var() { // Another thread has the lock false diff --git a/library/std/src/sys/sgx/rwlock.rs b/library/std/src/sys/sgx/rwlock.rs index a97fb9ab026..d89de18ca5f 100644 --- a/library/std/src/sys/sgx/rwlock.rs +++ b/library/std/src/sys/sgx/rwlock.rs @@ -7,42 +7,45 @@ use crate::sys_common::lazy_box::{LazyBox, LazyInit}; use super::waitqueue::{ try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable, }; -use crate::mem; +use crate::alloc::Layout; -pub struct RwLock { +struct AllocatedRwLock { readers: SpinMutex<WaitVariable<Option<NonZeroUsize>>>, writer: SpinMutex<WaitVariable<bool>>, } -pub(crate) type MovableRwLock = LazyBox<RwLock>; +pub struct RwLock { + inner: LazyBox<AllocatedRwLock>, +} -impl LazyInit for RwLock { +impl LazyInit for AllocatedRwLock { fn init() -> Box<Self> { - Box::new(Self::new()) + Box::new(AllocatedRwLock { + readers: SpinMutex::new(WaitVariable::new(None)), + writer: SpinMutex::new(WaitVariable::new(false)), + }) } } -// Check at compile time that RwLock size matches C definition (see test_c_rwlock_initializer below) -// -// # Safety -// Never called, as it is a compile time check. -#[allow(dead_code)] -unsafe fn rw_lock_size_assert(r: RwLock) { - unsafe { mem::transmute::<RwLock, [u8; 144]>(r) }; -} +// Check at compile time that RwLock's size and alignment matches the C definition +// in libunwind (see also `test_c_rwlock_initializer` in `tests`). +const _: () = { + let rust = Layout::new::<RwLock>(); + let c = Layout::new::<*mut ()>(); + assert!(rust.size() == c.size()); + assert!(rust.align() == c.align()); +}; impl RwLock { pub const fn new() -> RwLock { - RwLock { - readers: SpinMutex::new(WaitVariable::new(None)), - writer: SpinMutex::new(WaitVariable::new(false)), - } + RwLock { inner: LazyBox::new() } } #[inline] - pub unsafe fn read(&self) { - let mut rguard = self.readers.lock(); - let wguard = self.writer.lock(); + pub fn read(&self) { + let lock = &*self.inner; + let mut rguard = lock.readers.lock(); + let wguard = lock.writer.lock(); if *wguard.lock_var() || !wguard.queue_empty() { // Another thread has or is waiting for the write lock, wait drop(wguard); @@ -57,8 +60,9 @@ impl RwLock { #[inline] pub unsafe fn try_read(&self) -> bool { - let mut rguard = try_lock_or_false!(self.readers); - let wguard = try_lock_or_false!(self.writer); + let lock = &*self.inner; + let mut rguard = try_lock_or_false!(lock.readers); + let wguard = try_lock_or_false!(lock.writer); if *wguard.lock_var() || !wguard.queue_empty() { // Another thread has or is waiting for the write lock false @@ -71,9 +75,10 @@ impl RwLock { } #[inline] - pub unsafe fn write(&self) { - let rguard = self.readers.lock(); - let mut wguard = self.writer.lock(); + pub fn write(&self) { + let lock = &*self.inner; + let rguard = lock.readers.lock(); + let mut wguard = lock.writer.lock(); if *wguard.lock_var() || rguard.lock_var().is_some() { // Another thread has the lock, wait drop(rguard); @@ -86,9 +91,10 @@ impl RwLock { } #[inline] - pub unsafe fn try_write(&self) -> bool { - let rguard = try_lock_or_false!(self.readers); - let mut wguard = try_lock_or_false!(self.writer); + pub fn try_write(&self) -> bool { + let lock = &*self.inner; + let rguard = try_lock_or_false!(lock.readers); + let mut wguard = try_lock_or_false!(lock.writer); if *wguard.lock_var() || rguard.lock_var().is_some() { // Another thread has the lock false @@ -122,8 +128,9 @@ impl RwLock { #[inline] pub unsafe fn read_unlock(&self) { - let rguard = self.readers.lock(); - let wguard = self.writer.lock(); + let lock = &*self.inner; + let rguard = lock.readers.lock(); + let wguard = lock.writer.lock(); unsafe { self.__read_unlock(rguard, wguard) }; } @@ -158,8 +165,9 @@ impl RwLock { #[inline] pub unsafe fn write_unlock(&self) { - let rguard = self.readers.lock(); - let wguard = self.writer.lock(); + let lock = &*self.inner; + let rguard = lock.readers.lock(); + let wguard = lock.writer.lock(); unsafe { self.__write_unlock(rguard, wguard) }; } @@ -167,8 +175,9 @@ impl RwLock { #[inline] #[cfg_attr(test, allow(dead_code))] unsafe fn unlock(&self) { - let rguard = self.readers.lock(); - let wguard = self.writer.lock(); + let lock = &*self.inner; + let rguard = lock.readers.lock(); + let wguard = lock.writer.lock(); if *wguard.lock_var() == true { unsafe { self.__write_unlock(rguard, wguard) }; } else { @@ -201,6 +210,7 @@ pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RwLock) -> i32 { unsafe { (*p).write() }; return 0; } + #[cfg(not(test))] #[no_mangle] pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RwLock) -> i32 { diff --git a/library/std/src/sys/sgx/rwlock/tests.rs b/library/std/src/sys/sgx/rwlock/tests.rs index 4799961154a..5fd6670afd4 100644 --- a/library/std/src/sys/sgx/rwlock/tests.rs +++ b/library/std/src/sys/sgx/rwlock/tests.rs @@ -1,22 +1,12 @@ use super::*; +use crate::ptr; // Verify that the byte pattern libunwind uses to initialize an RwLock is // equivalent to the value of RwLock::new(). If the value changes, // `src/UnwindRustSgx.h` in libunwind needs to be changed too. #[test] fn test_c_rwlock_initializer() { - #[rustfmt::skip] - const C_RWLOCK_INIT: &[u8] = &[ - /* 0x00 */ 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* 0x10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* 0x20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* 0x30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* 0x40 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* 0x50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* 0x60 */ 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* 0x70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* 0x80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - ]; + const C_RWLOCK_INIT: *mut () = ptr::null_mut(); // For the test to work, we need the padding/unused bytes in RwLock to be // initialized as 0. In practice, this is the case with statics. @@ -26,6 +16,6 @@ fn test_c_rwlock_initializer() { // If the assertion fails, that not necessarily an issue with the value // of C_RWLOCK_INIT. It might just be an issue with the way padding // bytes are initialized in the test code. - assert_eq!(&crate::mem::transmute_copy::<_, [u8; 144]>(&RUST_RWLOCK_INIT), C_RWLOCK_INIT); + assert_eq!(crate::mem::transmute_copy::<_, *mut ()>(&RUST_RWLOCK_INIT), C_RWLOCK_INIT); }; } diff --git a/library/std/src/sys/solid/rwlock.rs b/library/std/src/sys/solid/rwlock.rs index 0a770cf03f2..ecb4eb83b9b 100644 --- a/library/std/src/sys/solid/rwlock.rs +++ b/library/std/src/sys/solid/rwlock.rs @@ -12,8 +12,6 @@ pub struct RwLock { rwl: SpinIdOnceCell<()>, } -pub type MovableRwLock = RwLock; - // Safety: `num_readers` is protected by `mtx_num_readers` unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} @@ -37,13 +35,13 @@ impl RwLock { } #[inline] - pub unsafe fn read(&self) { + pub fn read(&self) { let rwl = self.raw(); expect_success(unsafe { abi::rwl_loc_rdl(rwl) }, &"rwl_loc_rdl"); } #[inline] - pub unsafe fn try_read(&self) -> bool { + pub fn try_read(&self) -> bool { let rwl = self.raw(); match unsafe { abi::rwl_ploc_rdl(rwl) } { abi::E_TMOUT => false, @@ -55,13 +53,13 @@ impl RwLock { } #[inline] - pub unsafe fn write(&self) { + pub fn write(&self) { let rwl = self.raw(); expect_success(unsafe { abi::rwl_loc_wrl(rwl) }, &"rwl_loc_wrl"); } #[inline] - pub unsafe fn try_write(&self) -> bool { + pub fn try_write(&self) -> bool { let rwl = self.raw(); match unsafe { abi::rwl_ploc_wrl(rwl) } { abi::E_TMOUT => false, diff --git a/library/std/src/sys/unix/locks/fuchsia_mutex.rs b/library/std/src/sys/unix/locks/fuchsia_mutex.rs index 117611ce43f..5d89e5a13fd 100644 --- a/library/std/src/sys/unix/locks/fuchsia_mutex.rs +++ b/library/std/src/sys/unix/locks/fuchsia_mutex.rs @@ -53,8 +53,6 @@ const CONTESTED_BIT: u32 = 1; // This can never be a valid `zx_handle_t`. const UNLOCKED: u32 = 0; -pub type MovableMutex = Mutex; - pub struct Mutex { futex: AtomicU32, } @@ -86,23 +84,27 @@ impl Mutex { } #[inline] - pub unsafe fn try_lock(&self) -> bool { - let thread_self = zx_thread_self(); + pub fn try_lock(&self) -> bool { + let thread_self = unsafe { zx_thread_self() }; self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed).is_ok() } #[inline] - pub unsafe fn lock(&self) { - let thread_self = zx_thread_self(); + pub fn lock(&self) { + let thread_self = unsafe { zx_thread_self() }; if let Err(state) = self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed) { - self.lock_contested(state, thread_self); + unsafe { + self.lock_contested(state, thread_self); + } } } + /// # Safety + /// `thread_self` must be the handle for the current thread. #[cold] - fn lock_contested(&self, mut state: u32, thread_self: zx_handle_t) { + unsafe fn lock_contested(&self, mut state: u32, thread_self: zx_handle_t) { let owned_state = mark_contested(to_state(thread_self)); loop { // Mark the mutex as contested if it is not already. diff --git a/library/std/src/sys/unix/locks/futex_condvar.rs b/library/std/src/sys/unix/locks/futex_condvar.rs index c0576c17880..4bd65dd25c2 100644 --- a/library/std/src/sys/unix/locks/futex_condvar.rs +++ b/library/std/src/sys/unix/locks/futex_condvar.rs @@ -3,8 +3,6 @@ use crate::sync::atomic::{AtomicU32, Ordering::Relaxed}; use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; use crate::time::Duration; -pub type MovableCondvar = Condvar; - pub struct Condvar { // The value of this atomic is simply incremented on every notification. // This is used by `.wait()` to not miss any notifications after @@ -21,12 +19,12 @@ impl Condvar { // All the memory orderings here are `Relaxed`, // because synchronization is done by unlocking and locking the mutex. - pub unsafe fn notify_one(&self) { + pub fn notify_one(&self) { self.futex.fetch_add(1, Relaxed); futex_wake(&self.futex); } - pub unsafe fn notify_all(&self) { + pub fn notify_all(&self) { self.futex.fetch_add(1, Relaxed); futex_wake_all(&self.futex); } diff --git a/library/std/src/sys/unix/locks/futex_mutex.rs b/library/std/src/sys/unix/locks/futex_mutex.rs index 33b13dad4d6..c01229586c3 100644 --- a/library/std/src/sys/unix/locks/futex_mutex.rs +++ b/library/std/src/sys/unix/locks/futex_mutex.rs @@ -4,8 +4,6 @@ use crate::sync::atomic::{ }; use crate::sys::futex::{futex_wait, futex_wake}; -pub type MovableMutex = Mutex; - pub struct Mutex { /// 0: unlocked /// 1: locked, no other threads waiting @@ -20,12 +18,12 @@ impl Mutex { } #[inline] - pub unsafe fn try_lock(&self) -> bool { + pub fn try_lock(&self) -> bool { self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_ok() } #[inline] - pub unsafe fn lock(&self) { + pub fn lock(&self) { if self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_err() { self.lock_contended(); } diff --git a/library/std/src/sys/unix/locks/futex_rwlock.rs b/library/std/src/sys/unix/locks/futex_rwlock.rs index 0cc92244eca..aa0de900238 100644 --- a/library/std/src/sys/unix/locks/futex_rwlock.rs +++ b/library/std/src/sys/unix/locks/futex_rwlock.rs @@ -4,8 +4,6 @@ use crate::sync::atomic::{ }; use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; -pub type MovableRwLock = RwLock; - pub struct RwLock { // The state consists of a 30-bit reader counter, a 'readers waiting' flag, and a 'writers waiting' flag. // Bits 0..30: @@ -70,14 +68,14 @@ impl RwLock { } #[inline] - pub unsafe fn try_read(&self) -> bool { + pub fn try_read(&self) -> bool { self.state .fetch_update(Acquire, Relaxed, |s| is_read_lockable(s).then(|| s + READ_LOCKED)) .is_ok() } #[inline] - pub unsafe fn read(&self) { + pub fn read(&self) { let state = self.state.load(Relaxed); if !is_read_lockable(state) || self @@ -144,14 +142,14 @@ impl RwLock { } #[inline] - pub unsafe fn try_write(&self) -> bool { + pub fn try_write(&self) -> bool { self.state .fetch_update(Acquire, Relaxed, |s| is_unlocked(s).then(|| s + WRITE_LOCKED)) .is_ok() } #[inline] - pub unsafe fn write(&self) { + pub fn write(&self) { if self.state.compare_exchange_weak(0, WRITE_LOCKED, Acquire, Relaxed).is_err() { self.write_contended(); } diff --git a/library/std/src/sys/unix/locks/mod.rs b/library/std/src/sys/unix/locks/mod.rs index 9bb314b7010..b2e0e49ad73 100644 --- a/library/std/src/sys/unix/locks/mod.rs +++ b/library/std/src/sys/unix/locks/mod.rs @@ -10,22 +10,22 @@ cfg_if::cfg_if! { mod futex_mutex; mod futex_rwlock; mod futex_condvar; - pub(crate) use futex_mutex::{Mutex, MovableMutex}; - pub(crate) use futex_rwlock::MovableRwLock; - pub(crate) use futex_condvar::MovableCondvar; + pub(crate) use futex_mutex::Mutex; + pub(crate) use futex_rwlock::RwLock; + pub(crate) use futex_condvar::Condvar; } else if #[cfg(target_os = "fuchsia")] { mod fuchsia_mutex; mod futex_rwlock; mod futex_condvar; - pub(crate) use fuchsia_mutex::{Mutex, MovableMutex}; - pub(crate) use futex_rwlock::MovableRwLock; - pub(crate) use futex_condvar::MovableCondvar; + pub(crate) use fuchsia_mutex::Mutex; + pub(crate) use futex_rwlock::RwLock; + pub(crate) use futex_condvar::Condvar; } else { mod pthread_mutex; mod pthread_rwlock; mod pthread_condvar; - pub(crate) use pthread_mutex::{Mutex, MovableMutex}; - pub(crate) use pthread_rwlock::MovableRwLock; - pub(crate) use pthread_condvar::MovableCondvar; + pub(crate) use pthread_mutex::Mutex; + pub(crate) use pthread_rwlock::RwLock; + pub(crate) use pthread_condvar::Condvar; } } diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs index 4741c0c6736..1ddb09905db 100644 --- a/library/std/src/sys/unix/locks/pthread_condvar.rs +++ b/library/std/src/sys/unix/locks/pthread_condvar.rs @@ -1,17 +1,17 @@ use crate::cell::UnsafeCell; +use crate::ptr; +use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed}; use crate::sys::locks::{pthread_mutex, Mutex}; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; use crate::time::Duration; +struct AllocatedCondvar(UnsafeCell<libc::pthread_cond_t>); + pub struct Condvar { - inner: UnsafeCell<libc::pthread_cond_t>, + inner: LazyBox<AllocatedCondvar>, + mutex: AtomicPtr<libc::pthread_mutex_t>, } -pub(crate) type MovableCondvar = LazyBox<Condvar>; - -unsafe impl Send for Condvar {} -unsafe impl Sync for Condvar {} - const TIMESPEC_MAX: libc::timespec = libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 }; @@ -19,81 +19,104 @@ fn saturating_cast_to_time_t(value: u64) -> libc::time_t { if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t } } -impl LazyInit for Condvar { +#[inline] +fn raw(c: &Condvar) -> *mut libc::pthread_cond_t { + c.inner.0.get() +} + +unsafe impl Send for AllocatedCondvar {} +unsafe impl Sync for AllocatedCondvar {} + +impl LazyInit for AllocatedCondvar { fn init() -> Box<Self> { - let mut condvar = Box::new(Self::new()); - unsafe { condvar.init() }; + let condvar = Box::new(AllocatedCondvar(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER))); + + cfg_if::cfg_if! { + if #[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "watchos", + target_os = "l4re", + target_os = "android", + target_os = "redox" + ))] { + // `pthread_condattr_setclock` is unfortunately not supported on these platforms. + } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] { + // NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet + // So on that platform, init() should always be called + // Moreover, that platform does not have pthread_condattr_setclock support, + // hence that initialization should be skipped as well + // + // Similar story for the 3DS (horizon). + let r = unsafe { libc::pthread_cond_init(condvar.0.get(), crate::ptr::null()) }; + assert_eq!(r, 0); + } else { + use crate::mem::MaybeUninit; + let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit(); + let r = unsafe { libc::pthread_condattr_init(attr.as_mut_ptr()) }; + assert_eq!(r, 0); + let r = unsafe { libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC) }; + assert_eq!(r, 0); + let r = unsafe { libc::pthread_cond_init(condvar.0.get(), attr.as_ptr()) }; + assert_eq!(r, 0); + let r = unsafe { libc::pthread_condattr_destroy(attr.as_mut_ptr()) }; + assert_eq!(r, 0); + } + } + condvar } } -impl Condvar { - pub const fn new() -> Condvar { - // Might be moved and address is changing it is better to avoid - // initialization of potentially opaque OS data before it landed - Condvar { inner: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER) } +impl Drop for AllocatedCondvar { + #[inline] + fn drop(&mut self) { + let r = unsafe { libc::pthread_cond_destroy(self.0.get()) }; + if cfg!(target_os = "dragonfly") { + // On DragonFly pthread_cond_destroy() returns EINVAL if called on + // a condvar that was just initialized with + // libc::PTHREAD_COND_INITIALIZER. Once it is used or + // pthread_cond_init() is called, this behaviour no longer occurs. + debug_assert!(r == 0 || r == libc::EINVAL); + } else { + debug_assert_eq!(r, 0); + } } +} - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "l4re", - target_os = "android", - target_os = "redox" - ))] - unsafe fn init(&mut self) {} - - // NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet - // So on that platform, init() should always be called - // Moreover, that platform does not have pthread_condattr_setclock support, - // hence that initialization should be skipped as well - // - // Similar story for the 3DS (horizon). - #[cfg(any(target_os = "espidf", target_os = "horizon"))] - unsafe fn init(&mut self) { - let r = libc::pthread_cond_init(self.inner.get(), crate::ptr::null()); - assert_eq!(r, 0); +impl Condvar { + pub const fn new() -> Condvar { + Condvar { inner: LazyBox::new(), mutex: AtomicPtr::new(ptr::null_mut()) } } - #[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "l4re", - target_os = "android", - target_os = "redox", - target_os = "espidf", - target_os = "horizon" - )))] - unsafe fn init(&mut self) { - use crate::mem::MaybeUninit; - let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit(); - let r = libc::pthread_condattr_init(attr.as_mut_ptr()); - assert_eq!(r, 0); - let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC); - assert_eq!(r, 0); - let r = libc::pthread_cond_init(self.inner.get(), attr.as_ptr()); - assert_eq!(r, 0); - let r = libc::pthread_condattr_destroy(attr.as_mut_ptr()); - assert_eq!(r, 0); + #[inline] + fn verify(&self, mutex: *mut libc::pthread_mutex_t) { + // Relaxed is okay here because we never read through `self.addr`, and only use it to + // compare addresses. + match self.mutex.compare_exchange(ptr::null_mut(), mutex, Relaxed, Relaxed) { + Ok(_) => {} // Stored the address + Err(n) if n == mutex => {} // Lost a race to store the same address + _ => panic!("attempted to use a condition variable with two mutexes"), + } } #[inline] - pub unsafe fn notify_one(&self) { - let r = libc::pthread_cond_signal(self.inner.get()); + pub fn notify_one(&self) { + let r = unsafe { libc::pthread_cond_signal(raw(self)) }; debug_assert_eq!(r, 0); } #[inline] - pub unsafe fn notify_all(&self) { - let r = libc::pthread_cond_broadcast(self.inner.get()); + pub fn notify_all(&self) { + let r = unsafe { libc::pthread_cond_broadcast(raw(self)) }; debug_assert_eq!(r, 0); } #[inline] pub unsafe fn wait(&self, mutex: &Mutex) { - let r = libc::pthread_cond_wait(self.inner.get(), pthread_mutex::raw(mutex)); + let mutex = pthread_mutex::raw(mutex); + self.verify(mutex); + let r = libc::pthread_cond_wait(raw(self), mutex); debug_assert_eq!(r, 0); } @@ -112,6 +135,9 @@ impl Condvar { pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { use crate::mem; + let mutex = pthread_mutex::raw(mutex); + self.verify(mutex); + let mut now: libc::timespec = mem::zeroed(); let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now); assert_eq!(r, 0); @@ -127,7 +153,7 @@ impl Condvar { let timeout = sec.map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec as _ }).unwrap_or(TIMESPEC_MAX); - let r = libc::pthread_cond_timedwait(self.inner.get(), pthread_mutex::raw(mutex), &timeout); + let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout); assert!(r == libc::ETIMEDOUT || r == 0); r == 0 } @@ -144,9 +170,11 @@ impl Condvar { target_os = "horizon" ))] pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool { - use crate::ptr; use crate::time::Instant; + let mutex = pthread_mutex::raw(mutex); + self.verify(mutex); + // 1000 years let max_dur = Duration::from_secs(1000 * 365 * 86400); @@ -187,36 +215,11 @@ impl Condvar { .unwrap_or(TIMESPEC_MAX); // And wait! - let r = libc::pthread_cond_timedwait(self.inner.get(), pthread_mutex::raw(mutex), &timeout); + let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout); debug_assert!(r == libc::ETIMEDOUT || r == 0); // ETIMEDOUT is not a totally reliable method of determining timeout due // to clock shifts, so do the check ourselves stable_now.elapsed() < dur } - - #[inline] - #[cfg(not(target_os = "dragonfly"))] - unsafe fn destroy(&mut self) { - let r = libc::pthread_cond_destroy(self.inner.get()); - debug_assert_eq!(r, 0); - } - - #[inline] - #[cfg(target_os = "dragonfly")] - unsafe fn destroy(&mut self) { - let r = libc::pthread_cond_destroy(self.inner.get()); - // On DragonFly pthread_cond_destroy() returns EINVAL if called on - // a condvar that was just initialized with - // libc::PTHREAD_COND_INITIALIZER. Once it is used or - // pthread_cond_init() is called, this behaviour no longer occurs. - debug_assert!(r == 0 || r == libc::EINVAL); - } -} - -impl Drop for Condvar { - #[inline] - fn drop(&mut self) { - unsafe { self.destroy() }; - } } diff --git a/library/std/src/sys/unix/locks/pthread_mutex.rs b/library/std/src/sys/unix/locks/pthread_mutex.rs index 5964935ddb5..8a78bc1fd73 100644 --- a/library/std/src/sys/unix/locks/pthread_mutex.rs +++ b/library/std/src/sys/unix/locks/pthread_mutex.rs @@ -3,56 +3,24 @@ use crate::mem::{forget, MaybeUninit}; use crate::sys::cvt_nz; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; +struct AllocatedMutex(UnsafeCell<libc::pthread_mutex_t>); + pub struct Mutex { - inner: UnsafeCell<libc::pthread_mutex_t>, + inner: LazyBox<AllocatedMutex>, } -pub(crate) type MovableMutex = LazyBox<Mutex>; - #[inline] pub unsafe fn raw(m: &Mutex) -> *mut libc::pthread_mutex_t { - m.inner.get() + m.inner.0.get() } -unsafe impl Send for Mutex {} -unsafe impl Sync for Mutex {} +unsafe impl Send for AllocatedMutex {} +unsafe impl Sync for AllocatedMutex {} -impl LazyInit for Mutex { +impl LazyInit for AllocatedMutex { fn init() -> Box<Self> { - let mut mutex = Box::new(Self::new()); - unsafe { mutex.init() }; - mutex - } - - fn destroy(mutex: Box<Self>) { - // We're not allowed to pthread_mutex_destroy a locked mutex, - // so check first if it's unlocked. - if unsafe { mutex.try_lock() } { - unsafe { mutex.unlock() }; - drop(mutex); - } else { - // The mutex is locked. This happens if a MutexGuard is leaked. - // In this case, we just leak the Mutex too. - forget(mutex); - } - } - - fn cancel_init(_: Box<Self>) { - // In this case, we can just drop it without any checks, - // since it cannot have been locked yet. - } -} + let mutex = Box::new(AllocatedMutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER))); -impl Mutex { - pub const fn new() -> Mutex { - // Might be moved to a different address, so it is better to avoid - // initialization of potentially opaque OS data before it landed. - // Be very careful using this newly constructed `Mutex`, reentrant - // locking is undefined behavior until `init` is called! - Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) } - } - #[inline] - unsafe fn init(&mut self) { // Issue #33770 // // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have @@ -77,49 +45,77 @@ impl Mutex { // references, we instead create the mutex with type // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to // re-lock it from the same thread, thus avoiding undefined behavior. - let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit(); - cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap(); - let attr = PthreadMutexAttr(&mut attr); - cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL)) + unsafe { + let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit(); + cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap(); + let attr = PthreadMutexAttr(&mut attr); + cvt_nz(libc::pthread_mutexattr_settype( + attr.0.as_mut_ptr(), + libc::PTHREAD_MUTEX_NORMAL, + )) .unwrap(); - cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap(); + cvt_nz(libc::pthread_mutex_init(mutex.0.get(), attr.0.as_ptr())).unwrap(); + } + + mutex } - #[inline] - pub unsafe fn lock(&self) { - let r = libc::pthread_mutex_lock(self.inner.get()); - debug_assert_eq!(r, 0); + + fn destroy(mutex: Box<Self>) { + // We're not allowed to pthread_mutex_destroy a locked mutex, + // so check first if it's unlocked. + if unsafe { libc::pthread_mutex_trylock(mutex.0.get()) == 0 } { + unsafe { libc::pthread_mutex_unlock(mutex.0.get()) }; + drop(mutex); + } else { + // The mutex is locked. This happens if a MutexGuard is leaked. + // In this case, we just leak the Mutex too. + forget(mutex); + } } + + fn cancel_init(_: Box<Self>) { + // In this case, we can just drop it without any checks, + // since it cannot have been locked yet. + } +} + +impl Drop for AllocatedMutex { #[inline] - pub unsafe fn unlock(&self) { - let r = libc::pthread_mutex_unlock(self.inner.get()); - debug_assert_eq!(r, 0); + fn drop(&mut self) { + let r = unsafe { libc::pthread_mutex_destroy(self.0.get()) }; + if cfg!(target_os = "dragonfly") { + // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a + // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. + // Once it is used (locked/unlocked) or pthread_mutex_init() is called, + // this behaviour no longer occurs. + debug_assert!(r == 0 || r == libc::EINVAL); + } else { + debug_assert_eq!(r, 0); + } } +} + +impl Mutex { #[inline] - pub unsafe fn try_lock(&self) -> bool { - libc::pthread_mutex_trylock(self.inner.get()) == 0 + pub const fn new() -> Mutex { + Mutex { inner: LazyBox::new() } } + #[inline] - #[cfg(not(target_os = "dragonfly"))] - unsafe fn destroy(&mut self) { - let r = libc::pthread_mutex_destroy(self.inner.get()); + pub unsafe fn lock(&self) { + let r = libc::pthread_mutex_lock(raw(self)); debug_assert_eq!(r, 0); } + #[inline] - #[cfg(target_os = "dragonfly")] - unsafe fn destroy(&mut self) { - let r = libc::pthread_mutex_destroy(self.inner.get()); - // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a - // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. - // Once it is used (locked/unlocked) or pthread_mutex_init() is called, - // this behaviour no longer occurs. - debug_assert!(r == 0 || r == libc::EINVAL); + pub unsafe fn unlock(&self) { + let r = libc::pthread_mutex_unlock(raw(self)); + debug_assert_eq!(r, 0); } -} -impl Drop for Mutex { #[inline] - fn drop(&mut self) { - unsafe { self.destroy() }; + pub unsafe fn try_lock(&self) -> bool { + libc::pthread_mutex_trylock(raw(self)) == 0 } } diff --git a/library/std/src/sys/unix/locks/pthread_rwlock.rs b/library/std/src/sys/unix/locks/pthread_rwlock.rs index adfe2a88338..04662be9d82 100644 --- a/library/std/src/sys/unix/locks/pthread_rwlock.rs +++ b/library/std/src/sys/unix/locks/pthread_rwlock.rs @@ -3,20 +3,26 @@ use crate::mem::forget; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; -pub struct RwLock { +struct AllocatedRwLock { inner: UnsafeCell<libc::pthread_rwlock_t>, write_locked: UnsafeCell<bool>, // guarded by the `inner` RwLock num_readers: AtomicUsize, } -pub(crate) type MovableRwLock = LazyBox<RwLock>; +unsafe impl Send for AllocatedRwLock {} +unsafe impl Sync for AllocatedRwLock {} -unsafe impl Send for RwLock {} -unsafe impl Sync for RwLock {} +pub struct RwLock { + inner: LazyBox<AllocatedRwLock>, +} -impl LazyInit for RwLock { +impl LazyInit for AllocatedRwLock { fn init() -> Box<Self> { - Box::new(Self::new()) + Box::new(AllocatedRwLock { + inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER), + write_locked: UnsafeCell::new(false), + num_readers: AtomicUsize::new(0), + }) } fn destroy(mut rwlock: Box<Self>) { @@ -35,17 +41,39 @@ impl LazyInit for RwLock { } } +impl AllocatedRwLock { + #[inline] + unsafe fn raw_unlock(&self) { + let r = libc::pthread_rwlock_unlock(self.inner.get()); + debug_assert_eq!(r, 0); + } +} + +impl Drop for AllocatedRwLock { + fn drop(&mut self) { + let r = unsafe { libc::pthread_rwlock_destroy(self.inner.get()) }; + // On DragonFly pthread_rwlock_destroy() returns EINVAL if called on a + // rwlock that was just initialized with + // libc::PTHREAD_RWLOCK_INITIALIZER. Once it is used (locked/unlocked) + // or pthread_rwlock_init() is called, this behaviour no longer occurs. + if cfg!(target_os = "dragonfly") { + debug_assert!(r == 0 || r == libc::EINVAL); + } else { + debug_assert_eq!(r, 0); + } + } +} + impl RwLock { + #[inline] pub const fn new() -> RwLock { - RwLock { - inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER), - write_locked: UnsafeCell::new(false), - num_readers: AtomicUsize::new(0), - } + RwLock { inner: LazyBox::new() } } + #[inline] - pub unsafe fn read(&self) { - let r = libc::pthread_rwlock_rdlock(self.inner.get()); + pub fn read(&self) { + let lock = &*self.inner; + let r = unsafe { libc::pthread_rwlock_rdlock(lock.inner.get()) }; // According to POSIX, when a thread tries to acquire this read lock // while it already holds the write lock @@ -62,51 +90,61 @@ impl RwLock { // got the write lock more than once, or got a read and a write lock. if r == libc::EAGAIN { panic!("rwlock maximum reader count exceeded"); - } else if r == libc::EDEADLK || (r == 0 && *self.write_locked.get()) { + } else if r == libc::EDEADLK || (r == 0 && unsafe { *lock.write_locked.get() }) { // Above, we make sure to only access `write_locked` when `r == 0` to avoid // data races. if r == 0 { // `pthread_rwlock_rdlock` succeeded when it should not have. - self.raw_unlock(); + unsafe { + lock.raw_unlock(); + } } panic!("rwlock read lock would result in deadlock"); } else { // POSIX does not make guarantees about all the errors that may be returned. // See issue #94705 for more details. assert_eq!(r, 0, "unexpected error during rwlock read lock: {:?}", r); - self.num_readers.fetch_add(1, Ordering::Relaxed); + lock.num_readers.fetch_add(1, Ordering::Relaxed); } } + #[inline] - pub unsafe fn try_read(&self) -> bool { - let r = libc::pthread_rwlock_tryrdlock(self.inner.get()); + pub fn try_read(&self) -> bool { + let lock = &*self.inner; + let r = unsafe { libc::pthread_rwlock_tryrdlock(lock.inner.get()) }; if r == 0 { - if *self.write_locked.get() { + if unsafe { *lock.write_locked.get() } { // `pthread_rwlock_tryrdlock` succeeded when it should not have. - self.raw_unlock(); + unsafe { + lock.raw_unlock(); + } false } else { - self.num_readers.fetch_add(1, Ordering::Relaxed); + lock.num_readers.fetch_add(1, Ordering::Relaxed); true } } else { false } } + #[inline] - pub unsafe fn write(&self) { - let r = libc::pthread_rwlock_wrlock(self.inner.get()); + pub fn write(&self) { + let lock = &*self.inner; + let r = unsafe { libc::pthread_rwlock_wrlock(lock.inner.get()) }; // See comments above for why we check for EDEADLK and write_locked. For the same reason, // we also need to check that there are no readers (tracked in `num_readers`). if r == libc::EDEADLK - || (r == 0 && *self.write_locked.get()) - || self.num_readers.load(Ordering::Relaxed) != 0 + || (r == 0 && unsafe { *lock.write_locked.get() }) + || lock.num_readers.load(Ordering::Relaxed) != 0 { // Above, we make sure to only access `write_locked` when `r == 0` to avoid // data races. if r == 0 { // `pthread_rwlock_wrlock` succeeded when it should not have. - self.raw_unlock(); + unsafe { + lock.raw_unlock(); + } } panic!("rwlock write lock would result in deadlock"); } else { @@ -114,60 +152,44 @@ impl RwLock { // return EDEADLK or 0. We rely on that. debug_assert_eq!(r, 0); } - *self.write_locked.get() = true; + + unsafe { + *lock.write_locked.get() = true; + } } + #[inline] pub unsafe fn try_write(&self) -> bool { - let r = libc::pthread_rwlock_trywrlock(self.inner.get()); + let lock = &*self.inner; + let r = libc::pthread_rwlock_trywrlock(lock.inner.get()); if r == 0 { - if *self.write_locked.get() || self.num_readers.load(Ordering::Relaxed) != 0 { + if *lock.write_locked.get() || lock.num_readers.load(Ordering::Relaxed) != 0 { // `pthread_rwlock_trywrlock` succeeded when it should not have. - self.raw_unlock(); + lock.raw_unlock(); false } else { - *self.write_locked.get() = true; + *lock.write_locked.get() = true; true } } else { false } } - #[inline] - unsafe fn raw_unlock(&self) { - let r = libc::pthread_rwlock_unlock(self.inner.get()); - debug_assert_eq!(r, 0); - } + #[inline] pub unsafe fn read_unlock(&self) { - debug_assert!(!*self.write_locked.get()); - self.num_readers.fetch_sub(1, Ordering::Relaxed); - self.raw_unlock(); - } - #[inline] - pub unsafe fn write_unlock(&self) { - debug_assert_eq!(self.num_readers.load(Ordering::Relaxed), 0); - debug_assert!(*self.write_locked.get()); - *self.write_locked.get() = false; - self.raw_unlock(); + let lock = &*self.inner; + debug_assert!(!*lock.write_locked.get()); + lock.num_readers.fetch_sub(1, Ordering::Relaxed); + lock.raw_unlock(); } - #[inline] - unsafe fn destroy(&mut self) { - let r = libc::pthread_rwlock_destroy(self.inner.get()); - // On DragonFly pthread_rwlock_destroy() returns EINVAL if called on a - // rwlock that was just initialized with - // libc::PTHREAD_RWLOCK_INITIALIZER. Once it is used (locked/unlocked) - // or pthread_rwlock_init() is called, this behaviour no longer occurs. - if cfg!(target_os = "dragonfly") { - debug_assert!(r == 0 || r == libc::EINVAL); - } else { - debug_assert_eq!(r, 0); - } - } -} -impl Drop for RwLock { #[inline] - fn drop(&mut self) { - unsafe { self.destroy() }; + pub unsafe fn write_unlock(&self) { + let lock = &*self.inner; + debug_assert_eq!(lock.num_readers.load(Ordering::Relaxed), 0); + debug_assert!(*lock.write_locked.get()); + *lock.write_locked.get() = false; + lock.raw_unlock(); } } diff --git a/library/std/src/sys/unsupported/locks/condvar.rs b/library/std/src/sys/unsupported/locks/condvar.rs index 527a26a12bc..3f0943b50ee 100644 --- a/library/std/src/sys/unsupported/locks/condvar.rs +++ b/library/std/src/sys/unsupported/locks/condvar.rs @@ -3,8 +3,6 @@ use crate::time::Duration; pub struct Condvar {} -pub type MovableCondvar = Condvar; - impl Condvar { #[inline] #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] @@ -13,10 +11,10 @@ impl Condvar { } #[inline] - pub unsafe fn notify_one(&self) {} + pub fn notify_one(&self) {} #[inline] - pub unsafe fn notify_all(&self) {} + pub fn notify_all(&self) {} pub unsafe fn wait(&self, _mutex: &Mutex) { panic!("condvar wait not supported") diff --git a/library/std/src/sys/unsupported/locks/mod.rs b/library/std/src/sys/unsupported/locks/mod.rs index 602a2d6231a..0e0f9eccb21 100644 --- a/library/std/src/sys/unsupported/locks/mod.rs +++ b/library/std/src/sys/unsupported/locks/mod.rs @@ -1,6 +1,6 @@ mod condvar; mod mutex; mod rwlock; -pub use condvar::{Condvar, MovableCondvar}; -pub use mutex::{MovableMutex, Mutex}; -pub use rwlock::MovableRwLock; +pub use condvar::Condvar; +pub use mutex::Mutex; +pub use rwlock::RwLock; diff --git a/library/std/src/sys/unsupported/locks/mutex.rs b/library/std/src/sys/unsupported/locks/mutex.rs index 87ea475c6e3..4a13c55fb8b 100644 --- a/library/std/src/sys/unsupported/locks/mutex.rs +++ b/library/std/src/sys/unsupported/locks/mutex.rs @@ -5,8 +5,6 @@ pub struct Mutex { locked: Cell<bool>, } -pub type MovableMutex = Mutex; - unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} // no threads on this platform @@ -18,7 +16,7 @@ impl Mutex { } #[inline] - pub unsafe fn lock(&self) { + pub fn lock(&self) { assert_eq!(self.locked.replace(true), false, "cannot recursively acquire mutex"); } @@ -28,7 +26,7 @@ impl Mutex { } #[inline] - pub unsafe fn try_lock(&self) -> bool { + pub fn try_lock(&self) -> bool { self.locked.replace(true) == false } } diff --git a/library/std/src/sys/unsupported/locks/rwlock.rs b/library/std/src/sys/unsupported/locks/rwlock.rs index 5292691b955..789ef9b29e5 100644 --- a/library/std/src/sys/unsupported/locks/rwlock.rs +++ b/library/std/src/sys/unsupported/locks/rwlock.rs @@ -5,8 +5,6 @@ pub struct RwLock { mode: Cell<isize>, } -pub type MovableRwLock = RwLock; - unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} // no threads on this platform @@ -18,7 +16,7 @@ impl RwLock { } #[inline] - pub unsafe fn read(&self) { + pub fn read(&self) { let m = self.mode.get(); if m >= 0 { self.mode.set(m + 1); @@ -28,7 +26,7 @@ impl RwLock { } #[inline] - pub unsafe fn try_read(&self) -> bool { + pub fn try_read(&self) -> bool { let m = self.mode.get(); if m >= 0 { self.mode.set(m + 1); @@ -39,14 +37,14 @@ impl RwLock { } #[inline] - pub unsafe fn write(&self) { + pub fn write(&self) { if self.mode.replace(-1) != 0 { rtabort!("rwlock locked for reading") } } #[inline] - pub unsafe fn try_write(&self) -> bool { + pub fn try_write(&self) -> bool { if self.mode.get() == 0 { self.mode.set(-1); true diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs index 93838390bee..d68c3e5f1df 100644 --- a/library/std/src/sys/wasm/mod.rs +++ b/library/std/src/sys/wasm/mod.rs @@ -55,9 +55,9 @@ cfg_if::cfg_if! { mod futex_condvar; mod futex_mutex; mod futex_rwlock; - pub(crate) use futex_condvar::{Condvar, MovableCondvar}; - pub(crate) use futex_mutex::{Mutex, MovableMutex}; - pub(crate) use futex_rwlock::MovableRwLock; + pub(crate) use futex_condvar::Condvar; + pub(crate) use futex_mutex::Mutex; + pub(crate) use futex_rwlock::RwLock; } #[path = "atomics/futex.rs"] pub mod futex; diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index fc2dc42833d..81461de4f72 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -363,7 +363,7 @@ impl IO_STATUS_BLOCK { pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn( dwErrorCode: DWORD, - dwNumberOfBytesTransfered: DWORD, + dwNumberOfBytesTransferred: DWORD, lpOverlapped: *mut OVERLAPPED, ); diff --git a/library/std/src/sys/windows/locks/condvar.rs b/library/std/src/sys/windows/locks/condvar.rs index be9a2abbe35..66fafa2c00b 100644 --- a/library/std/src/sys/windows/locks/condvar.rs +++ b/library/std/src/sys/windows/locks/condvar.rs @@ -8,8 +8,6 @@ pub struct Condvar { inner: UnsafeCell<c::CONDITION_VARIABLE>, } -pub type MovableCondvar = Condvar; - unsafe impl Send for Condvar {} unsafe impl Sync for Condvar {} @@ -41,12 +39,12 @@ impl Condvar { } #[inline] - pub unsafe fn notify_one(&self) { - c::WakeConditionVariable(self.inner.get()) + pub fn notify_one(&self) { + unsafe { c::WakeConditionVariable(self.inner.get()) } } #[inline] - pub unsafe fn notify_all(&self) { - c::WakeAllConditionVariable(self.inner.get()) + pub fn notify_all(&self) { + unsafe { c::WakeAllConditionVariable(self.inner.get()) } } } diff --git a/library/std/src/sys/windows/locks/mod.rs b/library/std/src/sys/windows/locks/mod.rs index 602a2d6231a..0e0f9eccb21 100644 --- a/library/std/src/sys/windows/locks/mod.rs +++ b/library/std/src/sys/windows/locks/mod.rs @@ -1,6 +1,6 @@ mod condvar; mod mutex; mod rwlock; -pub use condvar::{Condvar, MovableCondvar}; -pub use mutex::{MovableMutex, Mutex}; -pub use rwlock::MovableRwLock; +pub use condvar::Condvar; +pub use mutex::Mutex; +pub use rwlock::RwLock; diff --git a/library/std/src/sys/windows/locks/mutex.rs b/library/std/src/sys/windows/locks/mutex.rs index 91207f5f466..ef2f84082cd 100644 --- a/library/std/src/sys/windows/locks/mutex.rs +++ b/library/std/src/sys/windows/locks/mutex.rs @@ -21,9 +21,6 @@ pub struct Mutex { srwlock: UnsafeCell<c::SRWLOCK>, } -// Windows SRW Locks are movable (while not borrowed). -pub type MovableMutex = Mutex; - unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} @@ -39,13 +36,15 @@ impl Mutex { } #[inline] - pub unsafe fn lock(&self) { - c::AcquireSRWLockExclusive(raw(self)); + pub fn lock(&self) { + unsafe { + c::AcquireSRWLockExclusive(raw(self)); + } } #[inline] - pub unsafe fn try_lock(&self) -> bool { - c::TryAcquireSRWLockExclusive(raw(self)) != 0 + pub fn try_lock(&self) -> bool { + unsafe { c::TryAcquireSRWLockExclusive(raw(self)) != 0 } } #[inline] diff --git a/library/std/src/sys/windows/locks/rwlock.rs b/library/std/src/sys/windows/locks/rwlock.rs index fa5ffe5749f..e69415baac4 100644 --- a/library/std/src/sys/windows/locks/rwlock.rs +++ b/library/std/src/sys/windows/locks/rwlock.rs @@ -5,8 +5,6 @@ pub struct RwLock { inner: UnsafeCell<c::SRWLOCK>, } -pub type MovableRwLock = RwLock; - unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} @@ -16,20 +14,20 @@ impl RwLock { RwLock { inner: UnsafeCell::new(c::SRWLOCK_INIT) } } #[inline] - pub unsafe fn read(&self) { - c::AcquireSRWLockShared(self.inner.get()) + pub fn read(&self) { + unsafe { c::AcquireSRWLockShared(self.inner.get()) } } #[inline] - pub unsafe fn try_read(&self) -> bool { - c::TryAcquireSRWLockShared(self.inner.get()) != 0 + pub fn try_read(&self) -> bool { + unsafe { c::TryAcquireSRWLockShared(self.inner.get()) != 0 } } #[inline] - pub unsafe fn write(&self) { - c::AcquireSRWLockExclusive(self.inner.get()) + pub fn write(&self) { + unsafe { c::AcquireSRWLockExclusive(self.inner.get()) } } #[inline] - pub unsafe fn try_write(&self) -> bool { - c::TryAcquireSRWLockExclusive(self.inner.get()) != 0 + pub fn try_write(&self) -> bool { + unsafe { c::TryAcquireSRWLockExclusive(self.inner.get()) != 0 } } #[inline] pub unsafe fn read_unlock(&self) { diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index 013c776c476..9f26acc4520 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs @@ -324,17 +324,18 @@ impl AnonPipe { let mut async_result: Option<AsyncResult> = None; struct AsyncResult { error: u32, - transfered: u32, + transferred: u32, } // STEP 3: The callback. unsafe extern "system" fn callback( dwErrorCode: u32, - dwNumberOfBytesTransfered: u32, + dwNumberOfBytesTransferred: u32, lpOverlapped: *mut c::OVERLAPPED, ) { // Set `async_result` using a pointer smuggled through `hEvent`. - let result = AsyncResult { error: dwErrorCode, transfered: dwNumberOfBytesTransfered }; + let result = + AsyncResult { error: dwErrorCode, transferred: dwNumberOfBytesTransferred }; *(*lpOverlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result); } @@ -365,7 +366,7 @@ impl AnonPipe { // STEP 4: Return the result. // `async_result` is always `Some` at this point match result.error { - c::ERROR_SUCCESS => Ok(result.transfered as usize), + c::ERROR_SUCCESS => Ok(result.transferred as usize), error => Err(io::Error::from_raw_os_error(error as _)), } } diff --git a/library/std/src/sys_common/condvar.rs b/library/std/src/sys_common/condvar.rs deleted file mode 100644 index 8bc5b24115d..00000000000 --- a/library/std/src/sys_common/condvar.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::sys::locks as imp; -use crate::sys_common::mutex::MovableMutex; -use crate::time::Duration; - -mod check; - -type CondvarCheck = <imp::MovableMutex as check::CondvarCheck>::Check; - -/// An OS-based condition variable. -pub struct Condvar { - inner: imp::MovableCondvar, - check: CondvarCheck, -} - -impl Condvar { - /// Creates a new condition variable for use. - #[inline] - #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] - pub const fn new() -> Self { - Self { inner: imp::MovableCondvar::new(), check: CondvarCheck::new() } - } - - /// Signals one waiter on this condition variable to wake up. - #[inline] - pub fn notify_one(&self) { - unsafe { self.inner.notify_one() }; - } - - /// Awakens all current waiters on this condition variable. - #[inline] - pub fn notify_all(&self) { - unsafe { self.inner.notify_all() }; - } - - /// Waits for a signal on the specified mutex. - /// - /// Behavior is undefined if the mutex is not locked by the current thread. - /// - /// May panic if used with more than one mutex. - #[inline] - pub unsafe fn wait(&self, mutex: &MovableMutex) { - self.check.verify(mutex); - self.inner.wait(mutex.raw()) - } - - /// Waits for a signal on the specified mutex with a timeout duration - /// specified by `dur` (a relative time into the future). - /// - /// Behavior is undefined if the mutex is not locked by the current thread. - /// - /// May panic if used with more than one mutex. - #[inline] - pub unsafe fn wait_timeout(&self, mutex: &MovableMutex, dur: Duration) -> bool { - self.check.verify(mutex); - self.inner.wait_timeout(mutex.raw(), dur) - } -} diff --git a/library/std/src/sys_common/condvar/check.rs b/library/std/src/sys_common/condvar/check.rs deleted file mode 100644 index 4ac9e62bf86..00000000000 --- a/library/std/src/sys_common/condvar/check.rs +++ /dev/null @@ -1,58 +0,0 @@ -use crate::ptr; -use crate::sync::atomic::{AtomicPtr, Ordering}; -use crate::sys::locks as imp; -use crate::sys_common::lazy_box::{LazyBox, LazyInit}; -use crate::sys_common::mutex::MovableMutex; - -pub trait CondvarCheck { - type Check; -} - -/// For boxed mutexes, a `Condvar` will check it's only ever used with the same -/// mutex, based on its (stable) address. -impl<T: LazyInit> CondvarCheck for LazyBox<T> { - type Check = SameMutexCheck; -} - -pub struct SameMutexCheck { - addr: AtomicPtr<()>, -} - -#[allow(dead_code)] -impl SameMutexCheck { - pub const fn new() -> Self { - Self { addr: AtomicPtr::new(ptr::null_mut()) } - } - pub fn verify(&self, mutex: &MovableMutex) { - let addr = mutex.raw() as *const imp::Mutex as *const () as *mut _; - // Relaxed is okay here because we never read through `self.addr`, and only use it to - // compare addresses. - match self.addr.compare_exchange( - ptr::null_mut(), - addr, - Ordering::Relaxed, - Ordering::Relaxed, - ) { - Ok(_) => {} // Stored the address - Err(n) if n == addr => {} // Lost a race to store the same address - _ => panic!("attempted to use a condition variable with two mutexes"), - } - } -} - -/// Unboxed mutexes may move, so `Condvar` can not require its address to stay -/// constant. -impl CondvarCheck for imp::Mutex { - type Check = NoCheck; -} - -pub struct NoCheck; - -#[allow(dead_code)] -impl NoCheck { - #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] - pub const fn new() -> Self { - Self - } - pub fn verify(&self, _: &MovableMutex) {} -} diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 8c19f9332dc..069b13e9d85 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -21,16 +21,13 @@ mod tests; pub mod backtrace; -pub mod condvar; pub mod fs; pub mod io; pub mod lazy_box; pub mod memchr; -pub mod mutex; pub mod once; pub mod process; pub mod remutex; -pub mod rwlock; pub mod thread; pub mod thread_info; pub mod thread_local_dtor; diff --git a/library/std/src/sys_common/mutex.rs b/library/std/src/sys_common/mutex.rs deleted file mode 100644 index 98046f20f89..00000000000 --- a/library/std/src/sys_common/mutex.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::sys::locks as imp; - -/// An OS-based mutual exclusion lock. -/// -/// This mutex cleans up its resources in its `Drop` implementation, may safely -/// be moved (when not borrowed), and does not cause UB when used reentrantly. -/// -/// This mutex does not implement poisoning. -/// -/// This is either a wrapper around `LazyBox<imp::Mutex>` or `imp::Mutex`, -/// depending on the platform. It is boxed on platforms where `imp::Mutex` may -/// not be moved. -pub struct MovableMutex(imp::MovableMutex); - -unsafe impl Sync for MovableMutex {} - -impl MovableMutex { - /// Creates a new mutex. - #[inline] - #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] - pub const fn new() -> Self { - Self(imp::MovableMutex::new()) - } - - pub(super) fn raw(&self) -> &imp::Mutex { - &self.0 - } - - /// Locks the mutex blocking the current thread until it is available. - #[inline] - pub fn raw_lock(&self) { - unsafe { self.0.lock() } - } - - /// Attempts to lock the mutex without blocking, returning whether it was - /// successfully acquired or not. - #[inline] - pub fn try_lock(&self) -> bool { - unsafe { self.0.try_lock() } - } - - /// Unlocks the mutex. - /// - /// Behavior is undefined if the current thread does not actually hold the - /// mutex. - #[inline] - pub unsafe fn raw_unlock(&self) { - self.0.unlock() - } -} diff --git a/library/std/src/sys_common/remutex.rs b/library/std/src/sys_common/remutex.rs index b448ae3a997..4c054da6471 100644 --- a/library/std/src/sys_common/remutex.rs +++ b/library/std/src/sys_common/remutex.rs @@ -1,11 +1,11 @@ #[cfg(all(test, not(target_os = "emscripten")))] mod tests; -use super::mutex as sys; use crate::cell::UnsafeCell; use crate::ops::Deref; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; +use crate::sys::locks as sys; /// A re-entrant mutual exclusion /// @@ -39,7 +39,7 @@ use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; /// synchronization is left to the mutex, making relaxed memory ordering for /// the `owner` field fine in all cases. pub struct ReentrantMutex<T> { - mutex: sys::MovableMutex, + mutex: sys::Mutex, owner: AtomicUsize, lock_count: UnsafeCell<u32>, data: T, @@ -74,7 +74,7 @@ impl<T> ReentrantMutex<T> { /// Creates a new reentrant mutex in an unlocked state. pub const fn new(t: T) -> ReentrantMutex<T> { ReentrantMutex { - mutex: sys::MovableMutex::new(), + mutex: sys::Mutex::new(), owner: AtomicUsize::new(0), lock_count: UnsafeCell::new(0), data: t, @@ -100,7 +100,7 @@ impl<T> ReentrantMutex<T> { if self.owner.load(Relaxed) == this_thread { self.increment_lock_count(); } else { - self.mutex.raw_lock(); + self.mutex.lock(); self.owner.store(this_thread, Relaxed); debug_assert_eq!(*self.lock_count.get(), 0); *self.lock_count.get() = 1; @@ -162,7 +162,7 @@ impl<T> Drop for ReentrantMutexGuard<'_, T> { *self.lock.lock_count.get() -= 1; if *self.lock.lock_count.get() == 0 { self.lock.owner.store(0, Relaxed); - self.lock.mutex.raw_unlock(); + self.lock.mutex.unlock(); } } } diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs deleted file mode 100644 index 042981dac60..00000000000 --- a/library/std/src/sys_common/rwlock.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::sys::locks as imp; - -/// An OS-based reader-writer lock. -/// -/// This rwlock cleans up its resources in its `Drop` implementation and may -/// safely be moved (when not borrowed). -/// -/// This rwlock does not implement poisoning. -/// -/// This is either a wrapper around `LazyBox<imp::RwLock>` or `imp::RwLock`, -/// depending on the platform. It is boxed on platforms where `imp::RwLock` may -/// not be moved. -pub struct MovableRwLock(imp::MovableRwLock); - -impl MovableRwLock { - /// Creates a new reader-writer lock for use. - #[inline] - #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] - pub const fn new() -> Self { - Self(imp::MovableRwLock::new()) - } - - /// Acquires shared access to the underlying lock, blocking the current - /// thread to do so. - #[inline] - pub fn read(&self) { - unsafe { self.0.read() } - } - - /// Attempts to acquire shared access to this lock, returning whether it - /// succeeded or not. - /// - /// This function does not block the current thread. - #[inline] - pub fn try_read(&self) -> bool { - unsafe { self.0.try_read() } - } - - /// Acquires write access to the underlying lock, blocking the current thread - /// to do so. - #[inline] - pub fn write(&self) { - unsafe { self.0.write() } - } - - /// Attempts to acquire exclusive access to this lock, returning whether it - /// succeeded or not. - /// - /// This function does not block the current thread. - #[inline] - pub fn try_write(&self) -> bool { - unsafe { self.0.try_write() } - } - - /// Unlocks previously acquired shared access to this lock. - /// - /// Behavior is undefined if the current thread does not have shared access. - #[inline] - pub unsafe fn read_unlock(&self) { - self.0.read_unlock() - } - - /// Unlocks previously acquired exclusive access to this lock. - /// - /// Behavior is undefined if the current thread does not currently have - /// exclusive access. - #[inline] - pub unsafe fn write_unlock(&self) { - self.0.write_unlock() - } -} diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index f16d94bbc81..27320e8dbc5 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -40,7 +40,7 @@ pub mod test { cli::{parse_opts, TestOpts}, filter_tests, helpers::metrics::{Metric, MetricMap}, - options::{Concurrent, Options, RunIgnored, RunStrategy, ShouldPanic}, + options::{Options, RunIgnored, RunStrategy, ShouldPanic}, run_test, test_main, test_main_static, test_result::{TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk}, time::{TestExecTime, TestTimeOptions}, @@ -85,7 +85,7 @@ use event::{CompletedTest, TestEvent}; use helpers::concurrency::get_concurrency; use helpers::exit_code::get_exit_code; use helpers::shuffle::{get_shuffle_seed, shuffle_tests}; -use options::{Concurrent, RunStrategy}; +use options::RunStrategy; use test_result::*; use time::TestExecTime; @@ -267,6 +267,19 @@ where join_handle: Option<thread::JoinHandle<()>>, } + impl RunningTest { + fn join(self, completed_test: &mut CompletedTest) { + if let Some(join_handle) = self.join_handle { + if let Err(_) = join_handle.join() { + if let TrOk = completed_test.result { + completed_test.result = + TrFailedMsg("panicked after reporting success".to_string()); + } + } + } + } + } + // Use a deterministic hasher type TestMap = HashMap<TestId, RunningTest, BuildHasherDefault<collections::hash_map::DefaultHasher>>; @@ -366,10 +379,10 @@ where let (id, test) = remaining.pop_front().unwrap(); let event = TestEvent::TeWait(test.desc.clone()); notify_about_test_event(event)?; - let join_handle = - run_test(opts, !opts.run_tests, id, test, run_strategy, tx.clone(), Concurrent::No); - assert!(join_handle.is_none()); - let completed_test = rx.recv().unwrap(); + let join_handle = run_test(opts, !opts.run_tests, id, test, run_strategy, tx.clone()); + // Wait for the test to complete. + let mut completed_test = rx.recv().unwrap(); + RunningTest { join_handle }.join(&mut completed_test); let event = TestEvent::TeResult(completed_test); notify_about_test_event(event)?; @@ -383,15 +396,8 @@ where let event = TestEvent::TeWait(desc.clone()); notify_about_test_event(event)?; //here no pad - let join_handle = run_test( - opts, - !opts.run_tests, - id, - test, - run_strategy, - tx.clone(), - Concurrent::Yes, - ); + let join_handle = + run_test(opts, !opts.run_tests, id, test, run_strategy, tx.clone()); running_tests.insert(id, RunningTest { join_handle }); timeout_queue.push_back(TimeoutEntry { id, desc, timeout }); pending += 1; @@ -423,14 +429,7 @@ where let mut completed_test = res.unwrap(); let running_test = running_tests.remove(&completed_test.id).unwrap(); - if let Some(join_handle) = running_test.join_handle { - if let Err(_) = join_handle.join() { - if let TrOk = completed_test.result { - completed_test.result = - TrFailedMsg("panicked after reporting success".to_string()); - } - } - } + running_test.join(&mut completed_test); let event = TestEvent::TeResult(completed_test); notify_about_test_event(event)?; @@ -443,8 +442,10 @@ where for (id, b) in filtered.benchs { let event = TestEvent::TeWait(b.desc.clone()); notify_about_test_event(event)?; - run_test(opts, false, id, b, run_strategy, tx.clone(), Concurrent::No); - let completed_test = rx.recv().unwrap(); + let join_handle = run_test(opts, false, id, b, run_strategy, tx.clone()); + // Wait for the test to complete. + let mut completed_test = rx.recv().unwrap(); + RunningTest { join_handle }.join(&mut completed_test); let event = TestEvent::TeResult(completed_test); notify_about_test_event(event)?; @@ -520,7 +521,6 @@ pub fn run_test( test: TestDescAndFn, strategy: RunStrategy, monitor_ch: Sender<CompletedTest>, - concurrency: Concurrent, ) -> Option<thread::JoinHandle<()>> { let TestDescAndFn { desc, testfn } = test; @@ -538,7 +538,6 @@ pub fn run_test( struct TestRunOpts { pub strategy: RunStrategy, pub nocapture: bool, - pub concurrency: Concurrent, pub time: Option<time::TestTimeOptions>, } @@ -549,7 +548,6 @@ pub fn run_test( testfn: Box<dyn FnOnce() -> Result<(), String> + Send>, opts: TestRunOpts, ) -> Option<thread::JoinHandle<()>> { - let concurrency = opts.concurrency; let name = desc.name.clone(); let runtest = move || match opts.strategy { @@ -576,7 +574,7 @@ pub fn run_test( // the test synchronously, regardless of the concurrency // level. let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm"); - if concurrency == Concurrent::Yes && supports_threads { + if supports_threads { let cfg = thread::Builder::new().name(name.as_slice().to_owned()); let mut runtest = Arc::new(Mutex::new(Some(runtest))); let runtest2 = runtest.clone(); @@ -597,7 +595,7 @@ pub fn run_test( } let test_run_opts = - TestRunOpts { strategy, nocapture: opts.nocapture, concurrency, time: opts.time_options }; + TestRunOpts { strategy, nocapture: opts.nocapture, time: opts.time_options }; match testfn { DynBenchFn(benchfn) => { diff --git a/library/test/src/options.rs b/library/test/src/options.rs index baf36b5f1d8..75ec0b616e1 100644 --- a/library/test/src/options.rs +++ b/library/test/src/options.rs @@ -1,12 +1,5 @@ //! Enums denoting options for test execution. -/// Whether to execute tests concurrently or not -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum Concurrent { - Yes, - No, -} - /// Number of times to run a benchmarked function #[derive(Clone, PartialEq, Eq)] pub enum BenchMode { diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index b54be64efcf..7b2e6707f9d 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -102,7 +102,7 @@ pub fn do_not_run_ignored_tests() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx); let result = rx.recv().unwrap().result; assert_ne!(result, TrOk); } @@ -125,7 +125,7 @@ pub fn ignored_tests_result_in_ignored() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx); let result = rx.recv().unwrap().result; assert_eq!(result, TrIgnored); } @@ -150,7 +150,7 @@ fn test_should_panic() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx); let result = rx.recv().unwrap().result; assert_eq!(result, TrOk); } @@ -175,7 +175,7 @@ fn test_should_panic_good_message() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx); let result = rx.recv().unwrap().result; assert_eq!(result, TrOk); } @@ -205,7 +205,7 @@ fn test_should_panic_bad_message() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx); let result = rx.recv().unwrap().result; assert_eq!(result, TrFailedMsg(failed_msg.to_string())); } @@ -239,7 +239,7 @@ fn test_should_panic_non_string_message_type() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx); let result = rx.recv().unwrap().result; assert_eq!(result, TrFailedMsg(failed_msg)); } @@ -267,15 +267,7 @@ fn test_should_panic_but_succeeds() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test( - &TestOpts::new(), - false, - TestId(0), - desc, - RunStrategy::InProcess, - tx, - Concurrent::No, - ); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx); let result = rx.recv().unwrap().result; assert_eq!( result, @@ -306,7 +298,7 @@ fn report_time_test_template(report_time: bool) -> Option<TestExecTime> { let test_opts = TestOpts { time_options, ..TestOpts::new() }; let (tx, rx) = channel(); - run_test(&test_opts, false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&test_opts, false, TestId(0), desc, RunStrategy::InProcess, tx); let exec_time = rx.recv().unwrap().exec_time; exec_time } @@ -345,7 +337,7 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { let test_opts = TestOpts { time_options: Some(time_options), ..TestOpts::new() }; let (tx, rx) = channel(); - run_test(&test_opts, false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&test_opts, false, TestId(0), desc, RunStrategy::InProcess, tx); let result = rx.recv().unwrap().result; result diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index 69fce8d7795..32c4a7eb5c1 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -17,7 +17,7 @@ doc = false core = { path = "../core" } libc = { version = "0.2.79", features = ['rustc-dep-of-std'], default-features = false } compiler_builtins = "0.1.0" -cfg-if = "0.1.8" +cfg-if = "1.0" [build-dependencies] cc = "1.0.69" diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 46fe50cb945..32c0ef3e116 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -15,7 +15,6 @@ cfg_if::cfg_if! { target_os = "espidf", ))] { // These "unix" family members do not have unwinder. - // Note this also matches x86_64-unknown-none-linuxkernel. } else if #[cfg(any( unix, windows, diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index baecca44cd9..e1a108cea95 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -224,13 +224,13 @@ dependencies = [ [[package]] name = "fd-lock" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517" +checksum = "0c93a581058d957dc4176875aad04f82f81613e6611d64aa1a9c755bdfb16711" dependencies = [ "cfg-if", "rustix", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -528,7 +528,7 @@ dependencies = [ "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -721,44 +721,101 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] [[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + +[[package]] name = "xattr" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 95e71173773..f74738437ea 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -36,7 +36,7 @@ test = false [dependencies] cmake = "0.1.38" -fd-lock = "3.0.6" +fd-lock = "3.0.7" filetime = "0.2" getopts = "0.2.19" cc = "1.0.69" diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index 9b4861ccd95..be69f819c64 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -35,7 +35,7 @@ fn main() { // NOTE: Since `./configure` generates a `config.toml`, distro maintainers will see the // changelog warning, not the `x.py setup` message. - let suggest_setup = !config.config.exists() && !matches!(config.cmd, Subcommand::Setup { .. }); + let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. }); if suggest_setup { println!("warning: you have not made a `config.toml`"); println!( diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6de37463633..6fd36393507 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -755,6 +755,7 @@ impl<'a> Builder<'a> { run::BuildManifest, run::BumpStage0, run::ReplaceVersionPlaceholder, + run::Miri, ), // These commands either don't use paths, or they're special-cased in Build::build() Kind::Clean | Kind::Format | Kind::Setup => vec![], @@ -818,7 +819,7 @@ impl<'a> Builder<'a> { Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]), Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]), Subcommand::Install { ref paths } => (Kind::Install, &paths[..]), - Subcommand::Run { ref paths } => (Kind::Run, &paths[..]), + Subcommand::Run { ref paths, .. } => (Kind::Run, &paths[..]), Subcommand::Format { .. } => (Kind::Format, &[][..]), Subcommand::Clean { .. } | Subcommand::Setup { .. } => { panic!() @@ -2207,6 +2208,24 @@ impl<'a> Builder<'a> { false } + + pub(crate) fn maybe_open_in_browser<S: Step>(&self, path: impl AsRef<Path>) { + if self.was_invoked_explicitly::<S>(Kind::Doc) { + self.open_in_browser(path); + } + } + + pub(crate) fn open_in_browser(&self, path: impl AsRef<Path>) { + if self.config.dry_run || !self.config.cmd.open() { + return; + } + + let path = path.as_ref(); + self.info(&format!("Opening doc {}", path.display())); + if let Err(err) = opener::open(path) { + self.info(&format!("{}\n", err)); + } + } } #[cfg(test)] diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 34d5504827c..2afce4fac42 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -80,7 +80,7 @@ pub struct Config { pub keep_stage_std: Vec<u32>, pub src: PathBuf, /// defaults to `config.toml` - pub config: PathBuf, + pub config: Option<PathBuf>, pub jobs: Option<u32>, pub cmd: Subcommand, pub incremental: bool, @@ -781,7 +781,7 @@ impl Config { config.llvm_optimize = true; config.ninja_in_file = true; config.llvm_version_check = true; - config.llvm_static_stdcpp = true; + config.llvm_static_stdcpp = false; config.backtrace = true; config.rust_optimize = true; config.rust_optimize_tests = true; @@ -926,8 +926,10 @@ impl Config { // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, // but not if `config.toml` hasn't been created. let mut toml = if !using_default_path || toml_path.exists() { + config.config = Some(toml_path.clone()); get_toml(&toml_path) } else { + config.config = None; TomlConfig::default() }; @@ -942,7 +944,6 @@ impl Config { } config.changelog_seen = toml.changelog_seen; - config.config = toml_path; let build = toml.build.unwrap_or_default(); @@ -1380,21 +1381,46 @@ impl Config { git } - pub(crate) fn artifact_channel(&self, builder: &Builder<'_>, commit: &str) -> String { - if builder.rust_info.is_managed_git_subrepository() { + /// Bootstrap embeds a version number into the name of shared libraries it uploads in CI. + /// Return the version it would have used for the given commit. + pub(crate) fn artifact_version_part(&self, builder: &Builder<'_>, commit: &str) -> String { + let (channel, version) = if builder.rust_info.is_managed_git_subrepository() { let mut channel = self.git(); channel.arg("show").arg(format!("{}:src/ci/channel", commit)); let channel = output(&mut channel); - channel.trim().to_owned() - } else if let Ok(channel) = fs::read_to_string(builder.src.join("src/ci/channel")) { - channel.trim().to_owned() + let mut version = self.git(); + version.arg("show").arg(format!("{}:src/version", commit)); + let version = output(&mut version); + (channel.trim().to_owned(), version.trim().to_owned()) } else { - let src = builder.src.display(); - eprintln!("error: failed to determine artifact channel"); - eprintln!( - "help: either use git or ensure that {src}/src/ci/channel contains the name of the channel to use" - ); - panic!(); + let channel = fs::read_to_string(builder.src.join("src/ci/channel")); + let version = fs::read_to_string(builder.src.join("src/version")); + match (channel, version) { + (Ok(channel), Ok(version)) => { + (channel.trim().to_owned(), version.trim().to_owned()) + } + (channel, version) => { + let src = builder.src.display(); + eprintln!("error: failed to determine artifact channel and/or version"); + eprintln!( + "help: consider using a git checkout or ensure these files are readable" + ); + if let Err(channel) = channel { + eprintln!("reading {}/src/ci/channel failed: {:?}", src, channel); + } + if let Err(version) = version { + eprintln!("reading {}/src/version failed: {:?}", src, version); + } + panic!(); + } + } + }; + + match channel.as_str() { + "stable" => version, + "beta" => channel, + "nightly" => channel, + other => unreachable!("{:?} is not recognized as a valid channel", other), } } @@ -1637,7 +1663,7 @@ fn maybe_download_rustfmt(builder: &Builder<'_>) -> Option<PathBuf> { fn download_ci_rustc(builder: &Builder<'_>, commit: &str) { builder.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})")); - let channel = builder.config.artifact_channel(builder, commit); + let version = builder.config.artifact_version_part(builder, commit); let host = builder.config.build.triple; let bin_root = builder.out.join(host).join("ci-rustc"); let rustc_stamp = bin_root.join(".rustc-stamp"); @@ -1646,13 +1672,13 @@ fn download_ci_rustc(builder: &Builder<'_>, commit: &str) { if bin_root.exists() { t!(fs::remove_dir_all(&bin_root)); } - let filename = format!("rust-std-{channel}-{host}.tar.xz"); + let filename = format!("rust-std-{version}-{host}.tar.xz"); let pattern = format!("rust-std-{host}"); download_ci_component(builder, filename, &pattern, commit); - let filename = format!("rustc-{channel}-{host}.tar.xz"); + let filename = format!("rustc-{version}-{host}.tar.xz"); download_ci_component(builder, filename, "rustc", commit); // download-rustc doesn't need its own cargo, it can just use beta's. - let filename = format!("rustc-dev-{channel}-{host}.tar.xz"); + let filename = format!("rustc-dev-{version}-{host}.tar.xz"); download_ci_component(builder, filename, "rustc-dev", commit); builder.fix_bin_or_dylib(&bin_root.join("bin").join("rustc")); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 805633c926c..110a3ee4918 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -19,6 +19,7 @@ use crate::cache::{Interned, INTERNER}; use crate::channel; use crate::compile; use crate::config::TargetSelection; +use crate::doc::DocumentationFormat; use crate::tarball::{GeneratedTarball, OverlayKind, Tarball}; use crate::tool::{self, Tool}; use crate::util::{exe, is_dylib, output, t, timeit}; @@ -97,7 +98,11 @@ impl Step for JsonDocs { /// Builds the `rust-docs-json` installer component. fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> { let host = self.host; - builder.ensure(crate::doc::JsonStd { stage: builder.top_stage, target: host }); + builder.ensure(crate::doc::Std { + stage: builder.top_stage, + target: host, + format: DocumentationFormat::JSON, + }); let dest = "share/doc/rust/json"; diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5d265b9ad0c..280e232ca2d 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -85,18 +85,6 @@ book!( StyleGuide, "src/doc/style-guide", "style-guide"; ); -fn open(builder: &Builder<'_>, path: impl AsRef<Path>) { - if builder.config.dry_run || !builder.config.cmd.open() { - return; - } - - let path = path.as_ref(); - builder.info(&format!("Opening doc {}", path.display())); - if let Err(err) = opener::open(path) { - builder.info(&format!("{}\n", err)); - } -} - // "library/std" -> ["library", "std"] // // Used for deciding whether a particular step is one requested by the user on @@ -240,11 +228,9 @@ impl Step for TheBook { invoke_rustdoc(builder, compiler, &shared_assets, target, path); } - if builder.was_invoked_explicitly::<Self>(Kind::Doc) { - let out = builder.doc_out(target); - let index = out.join("book").join("index.html"); - open(builder, &index); - } + let out = builder.doc_out(target); + let index = out.join("book").join("index.html"); + builder.maybe_open_in_browser::<Self>(index); } } @@ -386,7 +372,7 @@ impl Step for Standalone { // with no particular explicit doc requested (e.g. library/core). if builder.paths.is_empty() || builder.was_invoked_explicitly::<Self>(Kind::Doc) { let index = out.join("index.html"); - open(builder, &index); + builder.open_in_browser(&index); } } } @@ -434,6 +420,7 @@ impl Step for SharedAssets { pub struct Std { pub stage: u32, pub target: TargetSelection, + pub format: DocumentationFormat, } impl Step for Std { @@ -446,7 +433,15 @@ impl Step for Std { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target }); + run.builder.ensure(Std { + stage: run.builder.top_stage, + target: run.target, + format: if run.builder.config.cmd.json() { + DocumentationFormat::JSON + } else { + DocumentationFormat::HTML + }, + }); } /// Compile all standard library documentation. @@ -456,19 +451,26 @@ impl Step for Std { fn run(self, builder: &Builder<'_>) { let stage = self.stage; let target = self.target; - let out = builder.doc_out(target); + let out = match self.format { + DocumentationFormat::HTML => builder.doc_out(target), + DocumentationFormat::JSON => builder.json_doc_out(target), + }; + t!(fs::create_dir_all(&out)); builder.ensure(SharedAssets { target: self.target }); let index_page = builder.src.join("src/doc/index.md").into_os_string(); - let mut extra_args = vec![ - OsStr::new("--markdown-css"), - OsStr::new("rust.css"), - OsStr::new("--markdown-no-toc"), - OsStr::new("--index-page"), - &index_page, - ]; + let mut extra_args = match self.format { + DocumentationFormat::HTML => vec![ + OsStr::new("--markdown-css"), + OsStr::new("rust.css"), + OsStr::new("--markdown-no-toc"), + OsStr::new("--index-page"), + &index_page, + ], + DocumentationFormat::JSON => vec![OsStr::new("--output-format"), OsStr::new("json")], + }; if !builder.config.docs_minification { extra_args.push(OsStr::new("--disable-minification")); @@ -492,59 +494,24 @@ impl Step for Std { }) .collect::<Vec<_>>(); - doc_std( - builder, - DocumentationFormat::HTML, - stage, - target, - &out, - &extra_args, - &requested_crates, - ); + doc_std(builder, self.format, stage, target, &out, &extra_args, &requested_crates); + + // Don't open if the format is json + if let DocumentationFormat::JSON = self.format { + return; + } // Look for library/std, library/core etc in the `x.py doc` arguments and // open the corresponding rendered docs. for requested_crate in requested_crates { if STD_PUBLIC_CRATES.iter().any(|k| *k == requested_crate.as_str()) { let index = out.join(requested_crate).join("index.html"); - open(builder, &index); + builder.open_in_browser(index); } } } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct JsonStd { - pub stage: u32, - pub target: TargetSelection, -} - -impl Step for JsonStd { - type Output = (); - const DEFAULT: bool = false; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = run.builder.config.docs && run.builder.config.cmd.json(); - run.all_krates("test").path("library").default_condition(default) - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target }); - } - - /// Build JSON documentation for the standard library crates. - /// - /// This is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let target = self.target; - let out = builder.json_doc_out(target); - t!(fs::create_dir_all(&out)); - let extra_args = [OsStr::new("--output-format"), OsStr::new("json")]; - doc_std(builder, DocumentationFormat::JSON, stage, target, &out, &extra_args, &[]) - } -} - /// Name of the crates that are visible to consumers of the standard library. /// Documentation for internal crates is handled by the rustc step, so internal crates will show /// up there. @@ -557,7 +524,7 @@ impl Step for JsonStd { const STD_PUBLIC_CRATES: [&str; 5] = ["core", "alloc", "std", "proc_macro", "test"]; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -enum DocumentationFormat { +pub enum DocumentationFormat { HTML, JSON, } @@ -759,7 +726,7 @@ impl Step for Rustc { // Let's open the first crate documentation page: if let Some(krate) = to_open { let index = out.join(krate).join("index.html"); - open(builder, &index); + builder.open_in_browser(index); } } } @@ -1019,10 +986,9 @@ impl Step for RustcBook { name: INTERNER.intern_str("rustc"), src: INTERNER.intern_path(out_base), }); - if builder.was_invoked_explicitly::<Self>(Kind::Doc) { - let out = builder.doc_out(self.target); - let index = out.join("rustc").join("index.html"); - open(builder, &index); - } + + let out = builder.doc_out(self.target); + let index = out.join("rustc").join("index.html"); + builder.maybe_open_in_browser::<Self>(index); } } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index ee341a353ac..2001e29bd2e 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -140,6 +140,7 @@ pub enum Subcommand { }, Run { paths: Vec<PathBuf>, + args: Vec<String>, }, Setup { profile: Profile, @@ -342,6 +343,9 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`", Kind::Format => { opts.optflag("", "check", "check formatting instead of applying."); } + Kind::Run => { + opts.optmulti("", "args", "arguments for the tool", "ARGS"); + } _ => {} }; @@ -613,7 +617,7 @@ Arguments: println!("\nrun requires at least a path!\n"); usage(1, &opts, verbose, &subcommand_help); } - Subcommand::Run { paths } + Subcommand::Run { paths, args: matches.opt_strs("args") } } Kind::Setup => { let profile = if paths.len() > 1 { @@ -721,16 +725,12 @@ impl Subcommand { } pub fn test_args(&self) -> Vec<&str> { - let mut args = vec![]; - match *self { Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => { - args.extend(test_args.iter().flat_map(|s| s.split_whitespace())) + test_args.iter().flat_map(|s| s.split_whitespace()).collect() } - _ => (), + _ => vec![], } - - args } pub fn rustc_args(&self) -> Vec<&str> { @@ -738,7 +738,16 @@ impl Subcommand { Subcommand::Test { ref rustc_args, .. } => { rustc_args.iter().flat_map(|s| s.split_whitespace()).collect() } - _ => Vec::new(), + _ => vec![], + } + } + + pub fn args(&self) -> Vec<&str> { + match *self { + Subcommand::Run { ref args, .. } => { + args.iter().flat_map(|s| s.split_whitespace()).collect() + } + _ => vec![], } } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 2f856c2761c..94a61b727a3 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -269,8 +269,8 @@ fn download_ci_llvm(builder: &Builder<'_>, llvm_sha: &str) { } else { &builder.config.stage0_metadata.config.artifacts_server }; - let channel = builder.config.artifact_channel(builder, llvm_sha); - let filename = format!("rust-dev-{}-{}.tar.xz", channel, builder.build.build.triple); + let version = builder.config.artifact_version_part(builder, llvm_sha); + let filename = format!("rust-dev-{}-{}.tar.xz", version, builder.build.build.triple); let tarball = rustc_cache.join(&filename); if !tarball.exists() { let help_on_error = "error: failed to download llvm from ci diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index 511872903d1..d49b41c5132 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -1,8 +1,12 @@ +use std::process::Command; + use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::config::TargetSelection; use crate::dist::distdir; -use crate::tool::Tool; +use crate::test; +use crate::tool::{self, SourceType, Tool}; use crate::util::output; -use std::process::Command; +use crate::Mode; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct ExpandYamlAnchors; @@ -125,3 +129,63 @@ impl Step for ReplaceVersionPlaceholder { builder.run(&mut cmd); } } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Miri { + stage: u32, + host: TargetSelection, + target: TargetSelection, +} + +impl Step for Miri { + type Output = (); + const ONLY_HOSTS: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/miri") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Miri { + stage: run.builder.top_stage, + host: run.build_triple(), + target: run.target, + }); + } + + fn run(self, builder: &Builder<'_>) { + let stage = self.stage; + let host = self.host; + let target = self.target; + let compiler = builder.compiler(stage, host); + + let miri = builder + .ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + let miri_sysroot = test::Miri::build_miri_sysroot(builder, compiler, &miri, target); + + // # Run miri. + // Running it via `cargo run` as that figures out the right dylib path. + // add_rustc_lib_path does not add the path that contains librustc_driver-<...>.so. + let mut miri = tool::prepare_tool_cargo( + builder, + compiler, + Mode::ToolRustc, + host, + "run", + "src/tools/miri", + SourceType::InTree, + &[], + ); + miri.add_rustc_lib_path(builder, compiler); + // Forward arguments. + miri.arg("--").arg("--target").arg(target.rustc_target_arg()); + miri.args(builder.config.cmd.args()); + + // miri tests need to know about the stage sysroot + miri.env("MIRI_SYSROOT", &miri_sysroot); + + let mut miri = Command::from(miri); + builder.run(&mut miri); + } +} diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index e905517253c..bdfd5fe5c42 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -155,6 +155,14 @@ than building it. continue; } + // Some environments don't want or need these tools, such as when testing Miri. + // FIXME: it would be better to refactor this code to split necessary setup from pure sanity + // checks, and have a regular flag for skipping the latter. Also see + // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>. + if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() { + continue; + } + if !build.config.dry_run { cmd_finder.must_have(build.cc(*target)); if let Some(ar) = build.ar(*target) { @@ -212,6 +220,14 @@ than building it. } } + // Some environments don't want or need these tools, such as when testing Miri. + // FIXME: it would be better to refactor this code to split necessary setup from pure sanity + // checks, and have a regular flag for skipping the latter. Also see + // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>. + if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() { + continue; + } + if need_cmake && target.contains("msvc") { // There are three builds of cmake on windows: MSVC, MinGW, and // Cygwin. The Cygwin build does not have generators for Visual diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index eb7da1bda73..04480277fe0 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -82,7 +82,7 @@ impl fmt::Display for Profile { } pub fn setup(config: &Config, profile: Profile) { - let path = &config.config; + let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml")); if path.exists() { eprintln!( diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e168dd571f6..2b2257b72ae 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -16,6 +16,7 @@ use crate::cache::Interned; use crate::compile; use crate::config::TargetSelection; use crate::dist; +use crate::doc::DocumentationFormat; use crate::flags::Subcommand; use crate::native; use crate::tool::{self, SourceType, Tool}; @@ -464,49 +465,20 @@ pub struct Miri { target: TargetSelection, } -impl Step for Miri { - type Output = (); - const ONLY_HOSTS: bool = false; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/miri") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Miri { - stage: run.builder.top_stage, - host: run.build_triple(), - target: run.target, - }); - } - - /// Runs `cargo test` for miri. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let host = self.host; - let target = self.target; - let compiler = builder.compiler(stage, host); - // We need the stdlib for the *next* stage, as it was built with this compiler that also built Miri. - // Except if we are at stage 2, the bootstrap loop is complete and we can stick with our current stage. - let compiler_std = builder.compiler(if stage < 2 { stage + 1 } else { stage }, host); - - let miri = builder - .ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() }) - .expect("in-tree tool"); - let _cargo_miri = builder - .ensure(tool::CargoMiri { compiler, target: self.host, extra_features: Vec::new() }) - .expect("in-tree tool"); - // The stdlib we need might be at a different stage. And just asking for the - // sysroot does not seem to populate it, so we do that first. - builder.ensure(compile::Std::new(compiler_std, host)); - let sysroot = builder.sysroot(compiler_std); - - // # Run `cargo miri setup` for the given target. +impl Miri { + /// Run `cargo miri setup` for the given target, return where the Miri sysroot was put. + pub fn build_miri_sysroot( + builder: &Builder<'_>, + compiler: Compiler, + miri: &Path, + target: TargetSelection, + ) -> String { + let miri_sysroot = builder.out.join(compiler.host.triple).join("miri-sysrot"); let mut cargo = tool::prepare_tool_cargo( builder, compiler, Mode::ToolRustc, - host, + compiler.host, "run", "src/tools/miri/cargo-miri", SourceType::InTree, @@ -520,6 +492,8 @@ impl Step for Miri { cargo.env("MIRI_LIB_SRC", builder.src.join("library")); // Tell it where to find Miri. cargo.env("MIRI", &miri); + // Tell it where to put the sysroot. + cargo.env("MIRI_SYSROOT", &miri_sysroot); // Debug things. cargo.env("RUST_BACKTRACE", "1"); @@ -534,7 +508,7 @@ impl Step for Miri { cargo.arg("--print-sysroot"); // FIXME: Is there a way in which we can re-use the usual `run` helpers? - let miri_sysroot = if builder.config.dry_run { + if builder.config.dry_run { String::new() } else { builder.verbose(&format!("running: {:?}", cargo)); @@ -547,7 +521,48 @@ impl Step for Miri { let sysroot = stdout.trim_end(); builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {:?}", sysroot)); sysroot.to_owned() - }; + } + } +} + +impl Step for Miri { + type Output = (); + const ONLY_HOSTS: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/miri") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Miri { + stage: run.builder.top_stage, + host: run.build_triple(), + target: run.target, + }); + } + + /// Runs `cargo test` for miri. + fn run(self, builder: &Builder<'_>) { + let stage = self.stage; + let host = self.host; + let target = self.target; + let compiler = builder.compiler(stage, host); + // We need the stdlib for the *next* stage, as it was built with this compiler that also built Miri. + // Except if we are at stage 2, the bootstrap loop is complete and we can stick with our current stage. + let compiler_std = builder.compiler(if stage < 2 { stage + 1 } else { stage }, host); + + let miri = builder + .ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + let _cargo_miri = builder + .ensure(tool::CargoMiri { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + // The stdlib we need might be at a different stage. And just asking for the + // sysroot does not seem to populate it, so we do that first. + builder.ensure(compile::Std::new(compiler_std, host)); + let sysroot = builder.sysroot(compiler_std); + // We also need a Miri sysroot. + let miri_sysroot = Miri::build_miri_sysroot(builder, compiler, &miri, target); // # Run `cargo test`. let mut cargo = tool::prepare_tool_cargo( @@ -565,7 +580,6 @@ impl Step for Miri { // miri tests need to know about the stage sysroot cargo.env("MIRI_SYSROOT", &miri_sysroot); cargo.env("MIRI_HOST_SYSROOT", sysroot); - cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler)); cargo.env("MIRI", &miri); // propagate --bless if builder.config.cmd.bless() { @@ -606,7 +620,6 @@ impl Step for Miri { // Tell `cargo miri` where to find things. cargo.env("MIRI_SYSROOT", &miri_sysroot); cargo.env("MIRI_HOST_SYSROOT", sysroot); - cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler)); cargo.env("MIRI", &miri); // Debug things. cargo.env("RUST_BACKTRACE", "1"); @@ -822,7 +835,11 @@ impl Step for RustdocJSStd { command.arg("--test-file").arg(path); } } - builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage }); + builder.ensure(crate::doc::Std { + target: self.target, + stage: builder.top_stage, + format: DocumentationFormat::HTML, + }); builder.run(&mut command); } else { builder.info("No nodejs found, skipping \"src/test/rustdoc-js-std\" tests"); @@ -1052,6 +1069,9 @@ impl Step for Tidy { if builder.is_verbose() { cmd.arg("--verbose"); } + if builder.config.cmd.bless() { + cmd.arg("--bless"); + } builder.info("tidy check"); try_run(builder, &mut cmd); diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 126c292b38e..e1adabaac9b 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -118,6 +118,9 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi ENV TARGETS=$TARGETS,i686-unknown-freebsd ENV TARGETS=$TARGETS,x86_64-unknown-none +ENV TARGETS=$TARGETS,aarch64-unknown-uefi +ENV TARGETS=$TARGETS,i686-unknown-uefi +ENV TARGETS=$TARGETS,x86_64-unknown-uefi # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 # we need asm in the search path for gcc-8 (for gnux32) but not in the search path of the diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index b75e2f085cd..b0f35bcb9cc 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -16,7 +16,9 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins pkg-config \ xz-utils \ wget \ - patch + patch \ + ovmf \ + qemu-system-x86 RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \ tar -xJ @@ -64,4 +66,9 @@ ENV MUSL_TARGETS=x86_64-unknown-linux-musl \ CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++ ENV MUSL_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $MUSL_TARGETS -ENV SCRIPT $WASM_SCRIPT && $NVPTX_SCRIPT && $MUSL_SCRIPT +COPY host-x86_64/test-various/uefi_qemu_test /uefi_qemu_test +ENV UEFI_TARGETS=x86_64-unknown-uefi +ENV UEFI_SCRIPT python3 /checkout/x.py --stage 2 build --host='' --target $UEFI_TARGETS && \ + python3 -u /uefi_qemu_test/run.py + +ENV SCRIPT $WASM_SCRIPT && $NVPTX_SCRIPT && $MUSL_SCRIPT && $UEFI_SCRIPT diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml new file mode 100644 index 00000000000..fa8e5b3d080 --- /dev/null +++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "uefi_qemu_test" +version = "0.0.0" +edition = "2021" + +[workspace] + +[dependencies] +r-efi = "4.1.0" diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py new file mode 100644 index 00000000000..46793ce3afa --- /dev/null +++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + +import os +import shutil +import subprocess +import sys +import tempfile + +from pathlib import Path + + +def run(*cmd, capture=False, check=True, env=None): + """Print and run a command, optionally capturing the output.""" + cmd = [str(p) for p in cmd] + print(' '.join(cmd)) + return subprocess.run(cmd, + capture_output=capture, + check=check, + env=env, + text=True) + + +def build_and_run(tmp_dir): + host_artifacts = Path('/checkout/obj/build/x86_64-unknown-linux-gnu') + stage0 = host_artifacts / 'stage0/bin' + stage2 = host_artifacts / 'stage2/bin' + + env = dict(os.environ) + env['PATH'] = '{}:{}:{}'.format(stage2, stage0, env['PATH']) + + # Copy the test create into `tmp_dir`. + test_crate = Path(tmp_dir) / 'uefi_qemu_test' + shutil.copytree('/uefi_qemu_test', test_crate) + + # Build the UEFI executable. + target = 'x86_64-unknown-uefi' + run('cargo', + 'build', + '--manifest-path', + test_crate / 'Cargo.toml', + '--target', + target, + env=env) + + # Create a mock EFI System Partition in a subdirectory. + esp = test_crate / 'esp' + boot = esp / 'efi/boot' + os.makedirs(boot, exist_ok=True) + + # Copy the executable into the ESP. + src_exe_path = test_crate / 'target' / target / 'debug/uefi_qemu_test.efi' + shutil.copy(src_exe_path, boot / 'bootx64.efi') + + # Run the executable in QEMU and capture the output. + qemu = 'qemu-system-x86_64' + ovmf_dir = Path('/usr/share/OVMF') + ovmf_code = ovmf_dir / 'OVMF_CODE.fd' + ovmf_vars = ovmf_dir / 'OVMF_VARS.fd' + output = run(qemu, + '-display', + 'none', + '-serial', + 'stdio', + '-drive', + f'if=pflash,format=raw,readonly=on,file={ovmf_code}', + '-drive', + f'if=pflash,format=raw,readonly=on,file={ovmf_vars}', + '-drive', + f'format=raw,file=fat:rw:{esp}', + capture=True, + # Ubuntu 20.04 (which is what the Dockerfile currently + # uses) provides QEMU 4.2.1, which segfaults on + # shutdown under some circumstances. That has been + # fixed in newer versions of QEMU, but for now just + # don't check the exit status. + check=False).stdout + + if 'Hello World!' in output: + print('VM produced expected output') + else: + print('unexpected VM output:') + print('---start---') + print(output) + print('---end---') + sys.exit(1) + + +def main(): + # Create a temporary directory so that we have a writeable + # workspace. + with tempfile.TemporaryDirectory() as tmp_dir: + build_and_run(tmp_dir) + + +if __name__ == "__main__": + main() diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs new file mode 100644 index 00000000000..2ec554c140b --- /dev/null +++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs @@ -0,0 +1,45 @@ +// Code is adapted from this hello world example: +// https://doc.rust-lang.org/nightly/rustc/platform-support/unknown-uefi.html + +#![no_main] +#![no_std] + +use core::{panic, ptr}; +use r_efi::efi::{Char16, Handle, Status, SystemTable, RESET_SHUTDOWN}; + +#[panic_handler] +fn panic_handler(_info: &panic::PanicInfo) -> ! { + loop {} +} + +#[export_name = "efi_main"] +pub extern "C" fn main(_h: Handle, st: *mut SystemTable) -> Status { + let s = [ + 0x0048u16, 0x0065u16, 0x006cu16, 0x006cu16, 0x006fu16, // "Hello" + 0x0020u16, // " " + 0x0057u16, 0x006fu16, 0x0072u16, 0x006cu16, 0x0064u16, // "World" + 0x0021u16, // "!" + 0x000au16, // "\n" + 0x0000u16, // NUL + ]; + + // Print "Hello World!". + let r = unsafe { ((*(*st).con_out).output_string)((*st).con_out, s.as_ptr() as *mut Char16) }; + if r.is_error() { + return r; + } + + // Shut down. + unsafe { + ((*((*st).runtime_services)).reset_system)( + RESET_SHUTDOWN, + Status::SUCCESS, + 0, + ptr::null_mut(), + ); + } + + // This should never be reached because `reset_system` should never + // return, so fail with an error if we get here. + Status::UNSUPPORTED +} 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 cc96715b285..ed0d9e9902b 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.12.7 \ No newline at end of file +0.13.1 \ No newline at end of file diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index d8738455610..7dde6370904 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -27,10 +27,7 @@ python3 "$X_PY" test --stage 2 src/tools/rustfmt python3 "$X_PY" test --stage 2 src/tools/miri # We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc. # Also cover some other targets (on both of these hosts) via cross-testing. -# -# Currently disabled -- we end up pulling in a cross-compile of LLVM (maybe -# just overly eager sanity checks), but in any case this won't work when -# building LLVM as of this comment. -#python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc -#FIXME(https://github.com/rust-lang/rust/issues/103519): macOS testing is currently disabled -# python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin +export BOOTSTRAP_SKIP_TARGET_SANITY=1 # we don't need `cc` for these targets +python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc +python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin +unset BOOTSTRAP_SKIP_TARGET_SANITY diff --git a/src/ci/run.sh b/src/ci/run.sh index 9a247fb60a8..7de06ec35c3 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -123,6 +123,10 @@ else # (And PGO is its own can of worms). if [ "$NO_DOWNLOAD_CI_LLVM" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.download-ci-llvm=if-available" + else + # When building for CI we want to use the static C++ Standard library + # included with LLVM, since a dynamic libstdcpp may not be available. + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.static-libstdcpp" fi fi diff --git a/src/doc/book b/src/doc/book -Subproject aa5ee485bd6bd80d205da7c82fcdd776f92fdd5 +Subproject 3f64052c048c6def93b94a2b514ee88bba91874 diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject 9c73283775466d22208a0b28afcab44db4c0cc1 +Subproject 05532356e7a4dbea2330aabb77611f5179493bb diff --git a/src/doc/reference b/src/doc/reference -Subproject 4ea7c5def38ac81df33a9e48e5637a82a5ac404 +Subproject 9f0cc13ffcd27c1fbe1ab766a9491e15ddcf4d1 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 03491f33375c5a2a1661c7fa4be671fe95ce124 +Subproject 2b15c0abf2bada6e00553814336bc3e2d839909 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject 51a37ad19a15709d0601afbac6581f5aea6a45d +Subproject d0dc6c97a6486f68bac782fff135086eae6d77e diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 86bb2c0d381..2d3b8309461 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -33,6 +33,7 @@ - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) + - [\*-nto-qnx-\*](platform-support/nto-qnx.md) - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index b1854b22a7c..9272b9ac9b2 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -131,24 +131,47 @@ able to get around this problem by setting `-Clinker=lld-link` in RUSTFLAGS ## Toolchain Compatibility -<!-- NOTE: to update the below table, you can use this shell script: - -```sh -rustup toolchain install --profile minimal nightly -MINOR_VERSION=$(rustc +nightly --version | cut -d . -f 2) -LOWER_BOUND=61 - -llvm_version() { - toolchain="$1" - printf "Rust $toolchain | Clang " - rustc +"$toolchain" -Vv | grep LLVM | cut -d ':' -f 2 | tr -d ' ' -} - -for version in `seq $LOWER_BOUND $((MINOR_VERSION - 2))`; do - toolchain=1.$version.0 - rustup toolchain install --no-self-update --profile minimal $toolchain >/dev/null 2>&1 - llvm_version $toolchain -done +<!-- NOTE: to update the below table, you can use this Python script: + +```python +from collections import defaultdict +import subprocess + +def minor_version(version): + return int(version.split('.')[1]) + +INSTALL_TOOLCHAIN = ["rustup", "toolchain", "install", "--profile", "minimal"] +subprocess.run(INSTALL_TOOLCHAIN + ["nightly"]) + +LOWER_BOUND = 65 +NIGHTLY_VERSION = minor_version(subprocess.run( + ["rustc", "+nightly", "--version"], + capture_output=True, + text=True).stdout) + +def llvm_version(toolchain): + version_text = subprocess.run( + ["rustc", "+{}".format(toolchain), "-Vv"], + capture_output=True, + text=True).stdout + return int(version_text.split("LLVM")[1].split(':')[1].split('.')[0]) + +version_map = defaultdict(lambda: []) +for version in range(LOWER_BOUND, NIGHTLY_VERSION - 1): + toolchain = "1.{}.0".format(version) + subprocess.run( + INSTALL_TOOLCHAIN + ["--no-self-update", toolchain], + capture_output=True) + version_map[llvm_version(toolchain)].append(version) + +print("| Rust Version | Clang Version |") +print("|--------------|---------------|") +for clang, rust in sorted(version_map.items()): + if len(rust) > 1: + rust_range = "1.{} - 1.{}".format(rust[0], rust[-1]) + else: + rust_range = "1.{} ".format(rust[0]) + print("| {} | {} |".format(rust_range, clang)) ``` --> @@ -166,32 +189,13 @@ The following table shows known good combinations of toolchain versions. | Rust Version | Clang Version | |--------------|---------------| -| Rust 1.34 | Clang 8 | -| Rust 1.35 | Clang 8 | -| Rust 1.36 | Clang 8 | -| Rust 1.37 | Clang 8 | -| Rust 1.38 | Clang 9 | -| Rust 1.39 | Clang 9 | -| Rust 1.40 | Clang 9 | -| Rust 1.41 | Clang 9 | -| Rust 1.42 | Clang 9 | -| Rust 1.43 | Clang 9 | -| Rust 1.44 | Clang 9 | -| Rust 1.45 | Clang 10 | -| Rust 1.46 | Clang 10 | -| Rust 1.47 | Clang 11 | -| Rust 1.48 | Clang 11 | -| Rust 1.49 | Clang 11 | -| Rust 1.50 | Clang 11 | -| Rust 1.51 | Clang 11 | -| Rust 1.52 | Clang 12 | -| Rust 1.53 | Clang 12 | -| Rust 1.54 | Clang 12 | -| Rust 1.55 | Clang 12 | -| Rust 1.56 | Clang 13 | -| Rust 1.57 | Clang 13 | -| Rust 1.58 | Clang 13 | -| Rust 1.59 | Clang 13 | -| Rust 1.60 | Clang 14 | +| 1.34 - 1.37 | 8 | +| 1.38 - 1.44 | 9 | +| 1.45 - 1.46 | 10 | +| 1.47 - 1.51 | 11 | +| 1.52 - 1.55 | 12 | +| 1.56 - 1.59 | 13 | +| 1.60 - 1.64 | 14 | +| 1.65 | 15 | Note that the compatibility policy for this feature might change in the future. diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 3ae9872cf62..28929acb9b4 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -128,6 +128,7 @@ target | std | notes [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat `aarch64-unknown-none` | * | Bare ARM64, hardfloat +[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | ARM64 UEFI [`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7 Android `arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL `arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat @@ -149,6 +150,7 @@ target | std | notes [`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD `i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL +[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI `mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL `mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL `mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL @@ -181,6 +183,7 @@ target | std | notes `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat `x86_64-unknown-redox` | ✓ | Redox OS +[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI [Fortanix ABI]: https://edp.fortanix.com/ @@ -211,9 +214,9 @@ target | std | host | notes [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3 [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | +[`aarch64-unknown-nto-qnx7.1.0`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore -[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | | ARM64 UEFI `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) `aarch64-unknown-netbsd` | ✓ | ✓ | [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD @@ -252,7 +255,6 @@ target | std | host | notes `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku `i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD -[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | | 32-bit UEFI `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | `i686-wrs-vxworks` | ? | | @@ -302,6 +304,7 @@ target | std | host | notes `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 `x86_64-apple-tvos` | * | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator +[`x86_64-pc-nto-qnx7.1.0`](platform-support/nto-qnx.md) | ? | | x86 64-bit QNX Neutrino 7.1 RTOS | [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support `x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos @@ -309,9 +312,7 @@ target | std | host | notes `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku `x86_64-unknown-hermit` | ✓ | | HermitCore `x86_64-unknown-l4re-uclibc` | ? | | -`x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD -[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | | 64-bit UEFI `x86_64-uwp-windows-gnu` | ✓ | | `x86_64-uwp-windows-msvc` | ✓ | | `x86_64-wrs-vxworks` | ? | | diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md new file mode 100644 index 00000000000..2f6ea94d113 --- /dev/null +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -0,0 +1,118 @@ +# nto-qnx + +**Tier: 3** + +[BlackBerry® QNX®][BlackBerry] Neutrino (nto) Real-time operating system. +The support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit] +and [BlackBerry][BlackBerry]. + +[BlackBerry]: https://blackberry.qnx.com +[Elektrobit]: https://www.elektrobit.com + +## Target maintainers + +- Florian Bartels, `Florian.Bartels@elektrobit.com`, https://github.com/flba-eb +- Tristan Roach, `TRoach@blackberry.com`, https://github.com/gh-tr + +## Requirements + +Currently, only cross-compilation for QNX Neutrino on AArch64 and x86_64 are supported (little endian). +Adding other architectures that are supported by QNX Neutrino is possible. + +The standard library does not yet support QNX Neutrino. Therefore, only `no_std` code can +be compiled. + +`core` and `alloc` (with default allocator) are supported. + +Applications must link against `libc.so` (see example). This is required because applications +always link against the `crt` library and `crt` depends on `libc.so`. + +The correct version of `qcc` must be available by setting the `$PATH` variable (e.g. by sourcing `qnxsdp-env.sh` of the +QNX Neutrino toolchain). + +### Small example application + +```rust,ignore (platform-specific) +#![no_std] +#![no_main] +#![feature(lang_items)] + +// We must always link against libc, even if no external functions are used +// "extern C" - Block can be empty but must be present +#[link(name = "c")] +extern "C" { + pub fn printf(format: *const core::ffi::c_char, ...) -> core::ffi::c_int; +} + +#[no_mangle] +pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize { + const HELLO: &'static str = "Hello World, the answer is %d\n\0"; + unsafe { + printf(HELLO.as_ptr() as *const _, 42); + } + 0 +} + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_panic: &PanicInfo<'_>) -> ! { + loop {} +} + +#[lang = "eh_personality"] +#[no_mangle] +pub extern "C" fn rust_eh_personality() {} +``` + +The QNX Neutrino support of Rust has been tested with QNX Neutrino 7.1. + +There are no further known requirements. + +## Conditional compilation + +For conditional compilation, following QNX Neutrino specific attributes are defined: + +- `target_os` = `"nto"` +- `target_env` = `"nto71"` (for QNX Neutrino 7.1) + +## Building the target + +1. Create a `config.toml` + +Example content: + +```toml +profile = "compiler" +changelog-seen = 2 +``` + +2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets) + +Run the following: + +```bash +env \ + CC_aarch64-unknown-nto-qnx7.1.0="qcc" \ + CFLAGS_aarch64-unknown-nto-qnx7.1.0="-Vgcc_ntoaarch64le_cxx" \ + CXX_aarch64-unknown-nto-qnx7.1.0="qcc" \ + AR_aarch64_unknown_nto_qnx7.1.0="ntoaarch64-ar" \ + CC_x86_64-pc-nto-qnx7.1.0="qcc" \ + CFLAGS_x86_64-pc-nto-qnx7.1.0="-Vgcc_ntox86_64_cxx" \ + CXX_x86_64-pc-nto-qnx7.1.0="qcc" \ + AR_x86_64_pc_nto_qnx7.1.0="ntox86_64-ar" \ + ./x.py build --target aarch64-unknown-nto-qnx7.1.0 --target x86_64-pc-nto-qnx7.1.0 --target x86_64-unknown-linux-gnu rustc library/core library/alloc/ +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you must either build Rust with the target enabled (see "Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +## Testing + +Compiled executables can directly be run on QNX Neutrino. + +## Cross-compilation toolchains and C code + +Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above), to ensure `qcc` is used with proper arguments. To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout. diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index 295dec0f0e4..e2bdf73a929 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -1,6 +1,6 @@ # `*-unknown-uefi` -**Tier: 3** +**Tier: 2** Unified Extensible Firmware Interface (UEFI) targets for application, driver, and core UEFI binaries. @@ -72,28 +72,14 @@ target = ["x86_64-unknown-uefi"] ## Building Rust programs -Rust does not yet ship pre-compiled artifacts for this target. To compile for -this target, you will either need to build Rust with the target enabled (see -"Building rust for UEFI targets" above), or build your own copy of `core` by -using `build-std`, `cargo-buildx`, or similar. - -A native build with the unstable `build-std`-feature can be achieved via: - -```sh -cargo +nightly build \ - -Zbuild-std=core,compiler_builtins \ - -Zbuild-std-features=compiler-builtins-mem \ - --target x86_64-unknown-uefi -``` - -Alternatively, you can install `cargo-xbuild` via -`cargo install --force cargo-xbuild` and build for the UEFI targets via: +Starting with Rust 1.67, precompiled artifacts are provided via +`rustup`. For example, to use `x86_64-unknown-uefi`: ```sh -cargo \ - +nightly \ - xbuild \ - --target x86_64-unknown-uefi +# install cross-compile toolchain +rustup target add x86_64-unknown-uefi +# target flag may be used with any cargo or rustc command +cargo build --target x86_64-unknown-uefi ``` ## Testing @@ -167,18 +153,10 @@ The following code is a valid UEFI application returning immediately upon execution with an exit code of 0. A panic handler is provided. This is executed by rust on panic. For simplicity, we simply end up in an infinite loop. -Note that as of rust-1.31.0, all features used here are stabilized. No unstable -features are required, nor do we rely on nightly compilers. However, if you do -not compile rustc for the UEFI targets, you need a nightly compiler to support -the `-Z build-std` flag. - This example can be compiled as binary crate via `cargo`: ```sh -cargo +nightly build \ - -Zbuild-std=core,compiler_builtins \ - -Zbuild-std-features=compiler-builtins-mem \ - --target x86_64-unknown-uefi +cargo build --target x86_64-unknown-uefi ``` ```rust,ignore (platform-specific,eh-personality-is-unstable) diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index 53d0470fa81..df9131ce84a 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -3,6 +3,7 @@ ## Table of Contents * [General](#general) +* [Adding a new target](#adding-a-new-target) * [Tier 3 target policy](#tier-3-target-policy) * [Tier 2 target policy](#tier-2-target-policy) * [Tier 2 with host tools](#tier-2-with-host-tools) @@ -104,6 +105,30 @@ indicates something entirely optional, and does not indicate guidance or recommendations. This language is based on [IETF RFC 2119](https://tools.ietf.org/html/rfc2119). +## Adding a new target + +New targets typically start as Tier 3 and then can be promoted later. +To propose addition of a new target, open a pull request on [`rust-lang/rust`]: + +- Copy the [Tier 3 target policy](#tier-3-target-policy) to the description + and fill it out, see [example][tier3example]. +- Add a new description for the target in `src/doc/rustc/src/platform-support` + using the [template][platform_template]. +- Add the target to the [SUMMARY.md][summary] (allows wildcards) and + [platform-support.md][platformsupport] (must name all targets verbatim). + Link to the created description page. +- Ensure the pull request is assigned to a member of the [Rust compiler team][rust_compiler_team] by commenting: + ```text + r? compiler-team + ``` + +[tier3example]: https://github.com/rust-lang/rust/pull/94872 +[platform_template]: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/platform-support/TEMPLATE.md +[summary]: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/SUMMARY.md +[platformsupport]: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/platform-support.md +[rust_compiler_team]: https://www.rust-lang.org/governance/teams/compiler +[`rust-lang/rust`]: https://github.com/rust-lang/rust + ## Tier 3 target policy At this tier, the Rust project provides no official support for a target, so we diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 277e57aaf6f..8c16a562e34 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -1,6 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> - <Type Name="str"> + <Type Name="ref$<str$>"> + <AlternativeType Name="ref_mut$<str$>" /> + <AlternativeType Name="ptr_const$<str$>" /> + <AlternativeType Name="ptr_mut$<str$>" /> + <DisplayString>{(char*)data_ptr,[length]s8}</DisplayString> <StringView>(char*)data_ptr,[length]s8</StringView> <Expand> @@ -15,7 +19,11 @@ </Synthetic> </Expand> </Type> - <Type Name="slice$<*>"> + <Type Name="ref$<slice2$<*> >"> + <AlternativeType Name="ref_mut$<slice2$<*> >" /> + <AlternativeType Name="ptr_const$<slice2$<*> >" /> + <AlternativeType Name="ptr_mut$<slice2$<*> >" /> + <DisplayString>{{ len={length} }}</DisplayString> <Expand> <Item Name="[len]" ExcludeView="simple">length</Item> diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index bf6c02b9146..41f4a3767f5 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -85,7 +85,7 @@ </Type> <!-- alloc::rc::Rc<[T]> --> - <Type Name="alloc::rc::Rc<slice$<*> >"> + <Type Name="alloc::rc::Rc<slice2$<*> >"> <DisplayString>{{ len={ptr.pointer.length} }}</DisplayString> <Expand> <Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item> @@ -115,7 +115,7 @@ </Type> <!-- alloc::rc::Weak<[T]> --> - <Type Name="alloc::rc::Weak<slice$<*> >"> + <Type Name="alloc::rc::Weak<slice2$<*> >"> <DisplayString>{{ len={ptr.pointer.length} }}</DisplayString> <Expand> <Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item> @@ -144,7 +144,7 @@ </Type> <!-- alloc::sync::Arc<[T]> --> - <Type Name="alloc::sync::Arc<slice$<*> >"> + <Type Name="alloc::sync::Arc<slice2$<*> >"> <DisplayString>{{ len={ptr.pointer.length} }}</DisplayString> <Expand> <Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item> @@ -173,7 +173,7 @@ </Type> <!-- alloc::sync::Weak<[T]> --> - <Type Name="alloc::sync::Weak<slice$<*> >"> + <Type Name="alloc::sync::Weak<slice2$<*> >"> <DisplayString>{{ len={ptr.pointer.length} }}</DisplayString> <Expand> <Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item> diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 7bc35c7d551..0da69202e67 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -20,7 +20,7 @@ serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } smallvec = "1.8.1" tempfile = "3" -thin-vec = "0.2.8" +thin-vec = "0.2.9" tracing = "0.1" tracing-tree = "0.2.0" diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 00bdbe41ee4..85bd8446640 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -3,6 +3,7 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::{self, Region, RegionVid, TypeFoldable, TypeSuperFoldable}; use rustc_trait_selection::traits::auto_trait::{self, AutoTraitResult}; +use thin_vec::ThinVec; use std::fmt::Debug; @@ -110,7 +111,7 @@ where ); let params = raw_generics.params; - Generics { params, where_predicates: Vec::new() } + Generics { params, where_predicates: ThinVec::new() } } AutoTraitResult::ExplicitImpl => return None, }; @@ -183,7 +184,7 @@ where fn handle_lifetimes<'cx>( regions: &RegionConstraintData<'cx>, names_map: &FxHashMap<Symbol, Lifetime>, - ) -> Vec<WherePredicate> { + ) -> ThinVec<WherePredicate> { // Our goal is to 'flatten' the list of constraints by eliminating // all intermediate RegionVids. At the end, all constraints should // be between Regions (aka region variables). This gives us the information @@ -335,10 +336,7 @@ where match br { // We only care about named late bound regions, as we need to add them // to the 'for<>' section - ty::BrNamed(_, name) => Some(GenericParamDef { - name, - kind: GenericParamDefKind::Lifetime { outlives: vec![] }, - }), + ty::BrNamed(_, name) => Some(GenericParamDef::lifetime(name)), _ => None, } }) @@ -429,7 +427,7 @@ where &mut self, item_def_id: DefId, param_env: ty::ParamEnv<'tcx>, - mut existing_predicates: Vec<WherePredicate>, + mut existing_predicates: ThinVec<WherePredicate>, vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'tcx>>, ) -> Generics { debug!( @@ -663,7 +661,7 @@ where /// both for visual consistency between 'rustdoc' runs, and to /// make writing tests much easier #[inline] - fn sort_where_predicates(&self, predicates: &mut Vec<WherePredicate>) { + fn sort_where_predicates(&self, predicates: &mut [WherePredicate]) { // We should never have identical bounds - and if we do, // they're visually identical as well. Therefore, using // an unstable sort is fine. @@ -710,7 +708,7 @@ where /// approach is probably somewhat slower, but the small number of items /// involved (impls rarely have more than a few bounds) means that it /// shouldn't matter in practice. - fn unstable_debug_sort<T: Debug>(&self, vec: &mut Vec<T>) { + fn unstable_debug_sort<T: Debug>(&self, vec: &mut [T]) { vec.sort_by_cached_key(|x| format!("{:?}", x)) } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index ec93eefb7d1..3fc4aae923a 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -3,7 +3,7 @@ use std::iter::once; use std::sync::Arc; -use thin_vec::ThinVec; +use thin_vec::{thin_vec, ThinVec}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; @@ -19,8 +19,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty, - clean_ty_generics, clean_variant_def, clean_visibility, utils, Attributes, AttributesExt, - ImplKind, ItemId, Type, + clean_ty_generics, clean_variant_def, utils, Attributes, AttributesExt, ImplKind, ItemId, Type, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -244,10 +243,19 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box<clean::Function> { let sig = cx.tcx.fn_sig(did); - let predicates = cx.tcx.predicates_of(did); + let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var { + ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => { + Some(clean::GenericParamDef::lifetime(name)) + } + _ => None, + }); + + let predicates = cx.tcx.explicit_predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, |cx| { // NOTE: generics need to be cleaned before the decl! - let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); + let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); + // FIXME: This does not place parameters in source order (late-bound ones come last) + generics.params.extend(late_bound_regions); let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig); (generics, decl) }); @@ -597,7 +605,7 @@ fn build_module_items( clean::ImportSource { path: clean::Path { res, - segments: vec![clean::PathSegment { + segments: thin_vec![clean::PathSegment { name: prim_ty.as_sym(), args: clean::GenericArgs::AngleBracketed { args: Default::default(), @@ -654,7 +662,7 @@ fn build_macro( match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.sess()) { LoadedMacro::MacroDef(item_def, _) => { if let ast::ItemKind::MacroDef(ref def) = item_def.kind { - let vis = clean_visibility(cx.tcx.visibility(import_def_id.unwrap_or(def_id))); + let vis = cx.tcx.visibility(import_def_id.unwrap_or(def_id)); clean::MacroItem(clean::Macro { source: utils::display_macro_source(cx, name, def, def_id, vis), }) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ad4ad4104e1..56a873e3e82 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -12,7 +12,7 @@ pub(crate) mod utils; use rustc_ast as ast; use rustc_attr as attr; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -182,10 +182,9 @@ fn clean_poly_trait_ref_with_bindings<'tcx>( .collect_referenced_late_bound_regions(&poly_trait_ref) .into_iter() .filter_map(|br| match br { - ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => Some(GenericParamDef { - name, - kind: GenericParamDefKind::Lifetime { outlives: vec![] }, - }), + ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => { + Some(GenericParamDef::lifetime(name)) + } _ => None, }) .collect(); @@ -227,7 +226,7 @@ pub(crate) fn clean_middle_const<'tcx>( // FIXME: instead of storing the stringified expression, store `self` directly instead. Constant { type_: clean_middle_ty(constant.ty(), cx, None), - kind: ConstantKind::TyConst { expr: constant.to_string() }, + kind: ConstantKind::TyConst { expr: constant.to_string().into() }, } } @@ -601,7 +600,7 @@ pub(crate) fn clean_generics<'tcx>( }) .collect::<Vec<_>>(); - let mut params = Vec::with_capacity(gens.params.len()); + let mut params = ThinVec::with_capacity(gens.params.len()); for p in gens.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) { let p = clean_generic_param(cx, Some(gens), p); params.push(p); @@ -675,7 +674,7 @@ fn clean_ty_generics<'tcx>( } ty::GenericParamDefKind::Const { .. } => Some(clean_generic_param_def(param, cx)), }) - .collect::<Vec<GenericParamDef>>(); + .collect::<ThinVec<GenericParamDef>>(); // param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)] let mut impl_trait_proj = @@ -741,10 +740,7 @@ fn clean_ty_generics<'tcx>( p.get_bound_params() .into_iter() .flatten() - .map(|param| GenericParamDef { - name: param.0, - kind: GenericParamDefKind::Lifetime { outlives: Vec::new() }, - }) + .map(|param| GenericParamDef::lifetime(param.0)) .collect(), )); } @@ -880,7 +876,7 @@ fn clean_fn_or_proc_macro<'tcx>( ProcMacroItem(ProcMacro { kind, helpers }) } None => { - let mut func = clean_function(cx, sig, generics, body_id); + let mut func = clean_function(cx, sig, generics, FunctionArgs::Body(body_id)); clean_fn_decl_legacy_const_generics(&mut func, attrs); FunctionItem(func) } @@ -917,16 +913,28 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[ast::Attrib } } +enum FunctionArgs<'tcx> { + Body(hir::BodyId), + Names(&'tcx [Ident]), +} + fn clean_function<'tcx>( cx: &mut DocContext<'tcx>, sig: &hir::FnSig<'tcx>, generics: &hir::Generics<'tcx>, - body_id: hir::BodyId, + args: FunctionArgs<'tcx>, ) -> Box<Function> { let (generics, decl) = enter_impl_trait(cx, |cx| { // NOTE: generics must be cleaned before args let generics = clean_generics(generics, cx); - let args = clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id); + let args = match args { + FunctionArgs::Body(body_id) => { + clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id) + } + FunctionArgs::Names(names) => { + clean_args_from_types_and_names(cx, sig.decl.inputs, names) + } + }; let mut decl = clean_fn_decl_with_args(cx, sig.decl, args); if sig.header.is_async() { decl.output = decl.sugared_async_return_type(); @@ -945,12 +953,14 @@ fn clean_args_from_types_and_names<'tcx>( values: types .iter() .enumerate() - .map(|(i, ty)| { - let mut name = names.get(i).map_or(kw::Empty, |ident| ident.name); - if name.is_empty() { - name = kw::Underscore; - } - Argument { name, type_: clean_ty(ty, cx), is_const: false } + .map(|(i, ty)| Argument { + type_: clean_ty(ty, cx), + name: names + .get(i) + .map(|ident| ident.name) + .filter(|ident| !ident.is_empty()) + .unwrap_or(kw::Underscore), + is_const: false, }) .collect(), } @@ -1012,7 +1022,11 @@ fn clean_fn_decl_from_did_and_sig<'tcx>( .iter() .map(|t| Argument { type_: clean_middle_ty(*t, cx, None), - name: names.next().map_or(kw::Empty, |i| i.name), + name: names + .next() + .map(|i| i.name) + .filter(|i| !i.is_empty()) + .unwrap_or(kw::Underscore), is_const: false, }) .collect(), @@ -1051,18 +1065,12 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext ), hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(clean_ty(ty, cx)), hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { - let m = clean_function(cx, sig, trait_item.generics, body); + let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body)); MethodItem(m, None) } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => { - let (generics, decl) = enter_impl_trait(cx, |cx| { - // NOTE: generics must be cleaned before args - let generics = clean_generics(trait_item.generics, cx); - let args = clean_args_from_types_and_names(cx, sig.decl.inputs, names); - let decl = clean_fn_decl_with_args(cx, sig.decl, args); - (generics, decl) - }); - TyMethodItem(Box::new(Function { decl, generics })) + let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names)); + TyMethodItem(m) } hir::TraitItemKind::Type(bounds, Some(default)) => { let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); @@ -1080,7 +1088,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext hir::TraitItemKind::Type(bounds, None) => { let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(); - TyAssocTypeItem(Box::new(generics), bounds) + TyAssocTypeItem(generics, bounds) } }; Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx) @@ -1099,7 +1107,7 @@ pub(crate) fn clean_impl_item<'tcx>( AssocConstItem(clean_ty(ty, cx), default) } hir::ImplItemKind::Fn(ref sig, body) => { - let m = clean_function(cx, sig, impl_.generics, body); + let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body)); let defaultness = cx.tcx.impl_defaultness(impl_.owner_id); MethodItem(m, Some(defaultness)) } @@ -1138,12 +1146,25 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } } ty::AssocKind::Fn => { - let generics = clean_ty_generics( + let sig = tcx.fn_sig(assoc_item.def_id); + + let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var { + ty::BoundVariableKind::Region(ty::BrNamed(_, name)) + if name != kw::UnderscoreLifetime => + { + Some(GenericParamDef::lifetime(name)) + } + _ => None, + }); + + let mut generics = clean_ty_generics( cx, tcx.generics_of(assoc_item.def_id), tcx.explicit_predicates_of(assoc_item.def_id), ); - let sig = tcx.fn_sig(assoc_item.def_id); + // FIXME: This does not place parameters in source order (late-bound ones come last) + generics.params.extend(late_bound_regions); + let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig); if assoc_item.fn_has_self_parameter { @@ -1194,7 +1215,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( true } (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &c.kind { - ConstantKind::TyConst { expr } => expr == param.name.as_str(), + ConstantKind::TyConst { expr } => **expr == *param.name.as_str(), _ => false, }, _ => false, @@ -1211,56 +1232,47 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( tcx.generics_of(assoc_item.def_id), ty::GenericPredicates { parent: None, predicates }, ); - // Move bounds that are (likely) directly attached to the associated type - // from the where clause to the associated type. - // There is no guarantee that this is what the user actually wrote but we have - // no way of knowing. - let mut bounds = generics - .where_predicates - .drain_filter(|pred| match *pred { - WherePredicate::BoundPredicate { - ty: QPath(box QPathData { ref assoc, ref self_type, ref trait_, .. }), - .. - } => { - if assoc.name != my_name { - return false; - } - if trait_.def_id() != assoc_item.container_id(tcx) { - return false; - } - match *self_type { - Generic(ref s) if *s == kw::SelfUpper => {} - _ => return false, - } - match &assoc.args { - GenericArgs::AngleBracketed { args, bindings } => { - if !bindings.is_empty() - || generics - .params - .iter() - .zip(args.iter()) - .any(|(param, arg)| !param_eq_arg(param, arg)) - { - return false; - } - } - GenericArgs::Parenthesized { .. } => { - // The only time this happens is if we're inside the rustdoc for Fn(), - // which only has one associated type, which is not a GAT, so whatever. + // Filter out the bounds that are (likely?) directly attached to the associated type, + // as opposed to being located in the where clause. + let mut bounds: Vec<GenericBound> = Vec::new(); + generics.where_predicates.retain_mut(|pred| match *pred { + WherePredicate::BoundPredicate { + ty: QPath(box QPathData { ref assoc, ref self_type, ref trait_, .. }), + bounds: ref mut pred_bounds, + .. + } => { + if assoc.name != my_name { + return true; + } + if trait_.def_id() != assoc_item.container_id(tcx) { + return true; + } + match *self_type { + Generic(ref s) if *s == kw::SelfUpper => {} + _ => return true, + } + match &assoc.args { + GenericArgs::AngleBracketed { args, bindings } => { + if !bindings.is_empty() + || generics + .params + .iter() + .zip(args.iter()) + .any(|(param, arg)| !param_eq_arg(param, arg)) + { + return true; } } - true - } - _ => false, - }) - .flat_map(|pred| { - if let WherePredicate::BoundPredicate { bounds, .. } = pred { - bounds - } else { - unreachable!() + GenericArgs::Parenthesized { .. } => { + // The only time this happens is if we're inside the rustdoc for Fn(), + // which only has one associated type, which is not a GAT, so whatever. + } } - }) - .collect::<Vec<_>>(); + bounds.extend(mem::replace(pred_bounds, Vec::new())); + false + } + _ => true, + }); // Our Sized/?Sized bound didn't get handled when creating the generics // because we didn't actually get our whole set of bounds until just now // (some of them may have come from the trait). If we do have a sized @@ -1276,7 +1288,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( // (generic) associated type from the where clause to the respective parameter. // There is no guarantee that this is what the user actually wrote but we have // no way of knowing. - let mut where_predicates = Vec::new(); + let mut where_predicates = ThinVec::new(); for mut pred in generics.where_predicates { if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred && let Some(GenericParamDef { @@ -1284,7 +1296,16 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( .. }) = generics.params.iter_mut().find(|param| ¶m.name == arg) { - param_bounds.extend(mem::take(bounds)); + param_bounds.append(bounds); + } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) { + param_bounds.extend(bounds.drain(..).map(|bound| match bound { + GenericBound::Outlives(lifetime) => lifetime, + _ => unreachable!(), + })); } else { where_predicates.push(pred); } @@ -1306,7 +1327,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( bounds, ) } else { - TyAssocTypeItem(Box::new(generics), bounds) + TyAssocTypeItem(generics, bounds) } } else { // FIXME: when could this happen? Associated items in inherent impls? @@ -1317,7 +1338,10 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( cx, Some(assoc_item.def_id), ), - generics: Generics { params: Vec::new(), where_predicates: Vec::new() }, + generics: Generics { + params: ThinVec::new(), + where_predicates: ThinVec::new(), + }, item_type: None, }), Vec::new(), @@ -1381,7 +1405,8 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id), // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s. ty::Error(_) => return Type::Infer, - _ => bug!("clean: expected associated type, found `{:?}`", ty), + // Otherwise, this is an inherent associated type. + _ => return clean_middle_ty(ty, cx, None), }; let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx); register_res(cx, trait_.res); @@ -1529,7 +1554,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T } }; - Array(Box::new(clean_ty(ty, cx)), length) + Array(Box::new(clean_ty(ty, cx)), length.into()) } TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()), TyKind::OpaqueDef(item_id, _, _) => { @@ -1601,7 +1626,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Array(ty, mut n) => { n = n.eval(cx.tcx, ty::ParamEnv::reveal_all()); let n = print_const(cx, n); - Array(Box::new(clean_middle_ty(ty, cx, None)), n) + Array(Box::new(clean_middle_ty(ty, cx, None)), n.into()) } ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))), ty::Ref(r, ty, mutbl) => BorrowedRef { @@ -1652,6 +1677,9 @@ pub(crate) fn clean_middle_ty<'tcx>( inline::record_extern_fqn(cx, did, ItemType::Trait); + // FIXME(fmease): Hide the trait-object lifetime bound if it coincides with its default + // to partially address #44306. Follow the rules outlined at + // https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes let lifetime = clean_middle_region(*reg); let mut bounds = dids .map(|did| { @@ -1679,8 +1707,22 @@ pub(crate) fn clean_middle_ty<'tcx>( }) .collect(); + let late_bound_regions: FxIndexSet<_> = obj + .iter() + .flat_map(|pb| pb.bound_vars()) + .filter_map(|br| match br { + ty::BoundVariableKind::Region(ty::BrNamed(_, name)) + if name != kw::UnderscoreLifetime => + { + Some(GenericParamDef::lifetime(name)) + } + _ => None, + }) + .collect(); + let late_bound_regions = late_bound_regions.into_iter().collect(); + let path = external_path(cx, did, false, bindings, substs); - bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() }); + bounds.insert(0, PolyTrait { trait_: path, generic_params: late_bound_regions }); DynTrait(bounds, lifetime) } @@ -1799,13 +1841,6 @@ pub(crate) fn clean_field_with_def_id( Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx) } -pub(crate) fn clean_visibility(vis: ty::Visibility<DefId>) -> Visibility { - match vis { - ty::Visibility::Public => Visibility::Public, - ty::Visibility::Restricted(module) => Visibility::Restricted(module), - } -} - pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item { let kind = match variant.ctor_kind { CtorKind::Const => Variant::CLike(match variant.discr { @@ -1962,7 +1997,7 @@ fn clean_maybe_renamed_item<'tcx>( clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) } ItemKind::Macro(ref macro_def, _) => { - let ty_vis = clean_visibility(cx.tcx.visibility(def_id)); + let ty_vis = cx.tcx.visibility(def_id); MacroItem(Macro { source: display_macro_source(cx, name, macro_def, def_id, ty_vis), }) diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 1bcb9fcd5a4..7d97d2994e4 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -14,13 +14,14 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use rustc_middle::ty; +use thin_vec::ThinVec; use crate::clean; use crate::clean::GenericArgs as PP; use crate::clean::WherePredicate as WP; use crate::core::DocContext; -pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> { +pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP> { // First, partition the where clause into its separate components. // // We use `FxIndexMap` so that the insertion order is preserved to prevent messing up to @@ -50,16 +51,13 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> { let Some((bounds, _)) = tybounds.get_mut(ty) else { return true }; let bound_params = bound_params .into_iter() - .map(|param| clean::GenericParamDef { - name: param.0, - kind: clean::GenericParamDefKind::Lifetime { outlives: Vec::new() }, - }) + .map(|param| clean::GenericParamDef::lifetime(param.0)) .collect(); merge_bounds(cx, bounds, bound_params, trait_did, name, rhs) }); // And finally, let's reassemble everything - let mut clauses = Vec::new(); + let mut clauses = ThinVec::with_capacity(lifetimes.len() + tybounds.len() + equalities.len()); clauses.extend( lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }), ); @@ -98,9 +96,8 @@ pub(crate) fn merge_bounds( let last = trait_ref.trait_.segments.last_mut().expect("segments were empty"); trait_ref.generic_params.append(&mut bound_params); - // Since the parameters (probably) originate from `tcx.collect_*_late_bound_regions` which - // returns a hash set, sort them alphabetically to guarantee a stable and deterministic - // output (and to fully deduplicate them). + // Sort parameters (likely) originating from a hashset alphabetically to + // produce predictable output (and to allow for full deduplication). trait_ref.generic_params.sort_unstable_by(|p, q| p.name.as_str().cmp(q.name.as_str())); trait_ref.generic_params.dedup_by_key(|p| p.name); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 439311f0640..3d13f7463cb 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -24,7 +24,7 @@ use rustc_hir::{BodyId, Mutability}; use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety; use rustc_index::vec::IndexVec; use rustc_middle::ty::fast_reject::SimplifiedType; -use rustc_middle::ty::{self, DefIdTree, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility}; use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DUMMY_SP; @@ -34,7 +34,6 @@ use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; use crate::clean::cfg::Cfg; -use crate::clean::clean_visibility; use crate::clean::external_path; use crate::clean::inline::{self, print_inlined_const}; use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const}; @@ -51,7 +50,6 @@ pub(crate) use self::Type::{ Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, RawPointer, Slice, Tuple, }; -pub(crate) use self::Visibility::{Inherited, Public}; #[cfg(test)] mod tests; @@ -694,38 +692,37 @@ impl Item { asyncness: hir::IsAsync::NotAsync, } } - ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) => { + ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => { let def_id = self.item_id.as_def_id().unwrap(); build_fn_header(def_id, tcx, tcx.asyncness(def_id)) } - ItemKind::TyMethodItem(_) => { - build_fn_header(self.item_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync) - } _ => return None, }; Some(header) } - pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Visibility { + /// Returns the visibility of the current item. If the visibility is "inherited", then `None` + /// is returned. + pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> { let def_id = match self.item_id { // Anything but DefId *shouldn't* matter, but return a reasonable value anyway. - ItemId::Auto { .. } | ItemId::Blanket { .. } => return Visibility::Inherited, + ItemId::Auto { .. } | ItemId::Blanket { .. } => return None, // Primitives and Keywords are written in the source code as private modules. // The modules need to be private so that nobody actually uses them, but the // keywords and primitives that they are documenting are public. - ItemId::Primitive(..) => return Visibility::Public, + ItemId::Primitive(..) => return Some(Visibility::Public), ItemId::DefId(def_id) => def_id, }; match *self.kind { // Explication on `ItemId::Primitive` just above. - ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Visibility::Public, + ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public), // Variant fields inherit their enum's visibility. StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => { - return Visibility::Inherited; + return None; } // Variants always inherit visibility - VariantItem(..) => return Visibility::Inherited, + VariantItem(..) => return None, // Trait items inherit the trait's visibility AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..) | TyMethodItem(..) | MethodItem(..) => { @@ -739,7 +736,7 @@ impl Item { } }; if is_trait_item { - return Visibility::Inherited; + return None; } } _ => {} @@ -748,7 +745,7 @@ impl Item { Some(inlined) => inlined, None => def_id, }; - clean_visibility(tcx.visibility(def_id)) + Some(tcx.visibility(def_id)) } } @@ -795,7 +792,7 @@ pub(crate) enum ItemKind { /// A required associated type in a trait declaration. /// /// The bounds may be non-empty if there is a `where` clause. - TyAssocTypeItem(Box<Generics>, Vec<GenericBound>), + TyAssocTypeItem(Generics, Vec<GenericBound>), /// An associated type in a trait impl or a provided one in a trait declaration. AssocTypeItem(Box<Typedef>, Vec<GenericBound>), /// An item that has been stripped by a rustdoc pass @@ -1440,6 +1437,10 @@ pub(crate) struct GenericParamDef { } impl GenericParamDef { + pub(crate) fn lifetime(name: Symbol) -> Self { + Self { name, kind: GenericParamDefKind::Lifetime { outlives: Vec::new() } } + } + pub(crate) fn is_synthetic_type_param(&self) -> bool { match self.kind { GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false, @@ -1462,8 +1463,8 @@ impl GenericParamDef { // maybe use a Generic enum and use Vec<Generic>? #[derive(Clone, Debug, Default)] pub(crate) struct Generics { - pub(crate) params: Vec<GenericParamDef>, - pub(crate) where_predicates: Vec<WherePredicate>, + pub(crate) params: ThinVec<GenericParamDef>, + pub(crate) where_predicates: ThinVec<WherePredicate>, } impl Generics { @@ -1624,7 +1625,7 @@ pub(crate) enum Type { /// An array type. /// /// The `String` field is a stringified version of the array's length parameter. - Array(Box<Type>, String), + Array(Box<Type>, Box<str>), /// A raw pointer type: `*const i32`, `*mut i32` RawPointer(Mutability, Box<Type>), /// A reference type: `&i32`, `&'a mut Foo` @@ -2078,24 +2079,6 @@ impl From<hir::PrimTy> for PrimitiveType { } } -#[derive(Copy, Clone, Debug)] -pub(crate) enum Visibility { - /// `pub` - Public, - /// Visibility inherited from parent. - /// - /// For example, this is the visibility of private items and of enum variants. - Inherited, - /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)` - Restricted(DefId), -} - -impl Visibility { - pub(crate) fn is_public(&self) -> bool { - matches!(self, Visibility::Public) - } -} - #[derive(Clone, Debug)] pub(crate) struct Struct { pub(crate) struct_type: CtorKind, @@ -2227,7 +2210,7 @@ impl Span { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct Path { pub(crate) res: Res, - pub(crate) segments: Vec<PathSegment>, + pub(crate) segments: ThinVec<PathSegment>, } impl Path { @@ -2377,7 +2360,7 @@ pub(crate) enum ConstantKind { /// /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified /// by a DefId. So this field must be different from `Extern`. - TyConst { expr: String }, + TyConst { expr: Box<str> }, /// A constant (expression) that's not an item or associated item. These are usually found /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also /// used to define explicit discriminant values for enum variants. @@ -2405,7 +2388,7 @@ impl Constant { impl ConstantKind { pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String { match *self { - ConstantKind::TyConst { ref expr } => expr.clone(), + ConstantKind::TyConst { ref expr } => expr.to_string(), ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id), ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { print_const_expr(tcx, body) @@ -2591,12 +2574,13 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(Crate, 72); // frequently moved by-value static_assert_size!(DocFragment, 32); - static_assert_size!(GenericArg, 48); + static_assert_size!(GenericArg, 32); static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 56); + static_assert_size!(Generics, 16); static_assert_size!(Item, 56); - static_assert_size!(ItemKind, 88); + static_assert_size!(ItemKind, 64); static_assert_size!(PathSegment, 40); - static_assert_size!(Type, 48); + static_assert_size!(Type, 32); // tidy-alphabetical-end } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 518e320235f..21f8fbe36f1 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -4,9 +4,10 @@ use crate::clean::render_macro_matchers::render_macro_matcher; use crate::clean::{ clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, - PathSegment, Primitive, PrimitiveType, Type, TypeBinding, Visibility, + PathSegment, Primitive, PrimitiveType, Term, Type, TypeBinding, TypeBindingKind, }; use crate::core::DocContext; +use crate::html::format::visibility_to_src_with_space; use rustc_ast as ast; use rustc_ast::tokenstream::TokenTree; @@ -20,7 +21,7 @@ use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; use std::fmt::Write as _; use std::mem; -use thin_vec::ThinVec; +use thin_vec::{thin_vec, ThinVec}; #[cfg(test)] mod tests; @@ -112,12 +113,12 @@ fn external_generic_args<'tcx>( ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::<Vec<_>>().into(), _ => return GenericArgs::AngleBracketed { args: args.into(), bindings }, }; - let output = None; - // FIXME(#20299) return type comes from a projection now - // match types[1].kind { - // ty::Tuple(ref v) if v.is_empty() => None, // -> () - // _ => Some(types[1].clean(cx)) - // }; + let output = bindings.into_iter().next().and_then(|binding| match binding.kind { + TypeBindingKind::Equality { term: Term::Type(ty) } if ty != Type::Tuple(Vec::new()) => { + Some(Box::new(ty)) + } + _ => None, + }); GenericArgs::Parenthesized { inputs, output } } else { GenericArgs::AngleBracketed { args: args.into(), bindings: bindings.into() } @@ -135,7 +136,7 @@ pub(super) fn external_path<'tcx>( let name = cx.tcx.item_name(did); Path { res: Res::Def(def_kind, did), - segments: vec![PathSegment { + segments: thin_vec![PathSegment { name, args: external_generic_args(cx, did, has_self, bindings, substs), }], @@ -241,19 +242,13 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { s } - _ => { - let mut s = n.to_string(); - // array lengths are obviously usize - if s.ends_with("_usize") { - let n = s.len() - "_usize".len(); - s.truncate(n); - if s.ends_with(": ") { - let n = s.len() - ": ".len(); - s.truncate(n); - } - } - s + // array lengths are obviously usize + ty::ConstKind::Value(ty::ValTree::Leaf(scalar)) + if *n.ty().kind() == ty::Uint(ty::UintTy::Usize) => + { + scalar.to_string() } + _ => n.to_string(), } } @@ -583,7 +578,7 @@ pub(super) fn display_macro_source( name: Symbol, def: &ast::MacroDef, def_id: DefId, - vis: Visibility, + vis: ty::Visibility<DefId>, ) -> String { let tts: Vec<_> = def.body.inner_tokens().into_trees().collect(); // Extract the spans of all matchers. They represent the "interface" of the macro. @@ -595,14 +590,14 @@ pub(super) fn display_macro_source( if matchers.len() <= 1 { format!( "{}macro {}{} {{\n ...\n}}", - vis.to_src_with_space(cx.tcx, def_id), + visibility_to_src_with_space(Some(vis), cx.tcx, def_id), name, matchers.map(|matcher| render_macro_matcher(cx.tcx, matcher)).collect::<String>(), ) } else { format!( "{}macro {} {{\n{}}}", - vis.to_src_with_space(cx.tcx, def_id), + visibility_to_src_with_space(Some(vis), cx.tcx, def_id), name, render_macro_arms(cx.tcx, matchers, ","), ) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 67ea39fb965..789dd398be5 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -239,9 +239,6 @@ pub(crate) struct RenderOptions { pub(crate) default_settings: FxHashMap<String, String>, /// If present, suffix added to CSS/JavaScript files when referencing them in generated pages. pub(crate) resource_suffix: String, - /// Whether to run the static CSS/JavaScript through a minifier when outputting them. `true` by - /// default. - pub(crate) enable_minification: bool, /// Whether to create an index page in the root of the output directory. If this is true but /// `enable_index_page` is None, generate a static listing of crates instead. pub(crate) enable_index_page: bool, @@ -329,7 +326,7 @@ impl Options { crate::usage("rustdoc"); return Err(0); } else if matches.opt_present("version") { - rustc_driver::version("rustdoc", matches); + rustc_driver::version!("rustdoc", matches); return Err(0); } @@ -416,7 +413,9 @@ impl Options { let to_check = matches.opt_strs("check-theme"); if !to_check.is_empty() { - let paths = match theme::load_css_paths(static_files::themes::LIGHT) { + let paths = match theme::load_css_paths( + std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(), + ) { Ok(p) => p, Err(e) => { diag.struct_err(&e.to_string()).emit(); @@ -557,7 +556,9 @@ impl Options { let mut themes = Vec::new(); if matches.opt_present("theme") { - let paths = match theme::load_css_paths(static_files::themes::LIGHT) { + let paths = match theme::load_css_paths( + std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(), + ) { Ok(p) => p, Err(e) => { diag.struct_err(&e.to_string()).emit(); @@ -675,7 +676,6 @@ impl Options { ModuleSorting::Alphabetical }; let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default(); - let enable_minification = !matches.opt_present("disable-minification"); let markdown_no_toc = matches.opt_present("markdown-no-toc"); let markdown_css = matches.opt_strs("markdown-css"); let markdown_playground_url = matches.opt_str("markdown-playground-url"); @@ -768,7 +768,6 @@ impl Options { extern_html_root_takes_precedence, default_settings, resource_suffix, - enable_minification, enable_index_page, index_page, static_root_path, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 37202f786ed..39e2a902226 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -107,10 +107,6 @@ impl Buffer { self.buffer } - pub(crate) fn insert_str(&mut self, idx: usize, s: &str) { - self.buffer.insert_str(idx, s); - } - pub(crate) fn push_str(&mut self, s: &str) { self.buffer.push_str(s); } @@ -1232,9 +1228,8 @@ impl clean::Arguments { ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { for (i, input) in self.values.iter().enumerate() { - if !input.name.is_empty() { - write!(f, "{}: ", input.name)?; - } + write!(f, "{}: ", input.name)?; + if f.alternate() { write!(f, "{:#}", input.type_.print(cx))?; } else { @@ -1367,10 +1362,8 @@ impl clean::FnDecl { args.push_str("const "); args_plain.push_str("const "); } - if !input.name.is_empty() { - write!(args, "{}: ", input.name); - write!(args_plain, "{}: ", input.name); - } + write!(args, "{}: ", input.name); + write!(args_plain, "{}: ", input.name); if f.alternate() { write!(args, "{:#}", input.type_.print(cx)); @@ -1420,87 +1413,84 @@ impl clean::FnDecl { } } -impl clean::Visibility { - pub(crate) fn print_with_space<'a, 'tcx: 'a>( - self, - item_did: ItemId, - cx: &'a Context<'tcx>, - ) -> impl fmt::Display + 'a + Captures<'tcx> { - use std::fmt::Write as _; - - let to_print: Cow<'static, str> = match self { - clean::Public => "pub ".into(), - clean::Inherited => "".into(), - clean::Visibility::Restricted(vis_did) => { - // FIXME(camelid): This may not work correctly if `item_did` is a module. - // However, rustdoc currently never displays a module's - // visibility, so it shouldn't matter. - let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id()); - - if vis_did.is_crate_root() { - "pub(crate) ".into() - } else if parent_module == Some(vis_did) { - // `pub(in foo)` where `foo` is the parent module - // is the same as no visibility modifier - "".into() - } else if parent_module - .and_then(|parent| find_nearest_parent_module(cx.tcx(), parent)) - == Some(vis_did) - { - "pub(super) ".into() - } else { - let path = cx.tcx().def_path(vis_did); - debug!("path={:?}", path); - // modified from `resolved_path()` to work with `DefPathData` - let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); - let anchor = anchor(vis_did, last_name, cx).to_string(); - - let mut s = "pub(in ".to_owned(); - for seg in &path.data[..path.data.len() - 1] { - let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap()); - } - let _ = write!(s, "{}) ", anchor); - s.into() +pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>( + visibility: Option<ty::Visibility<DefId>>, + item_did: ItemId, + cx: &'a Context<'tcx>, +) -> impl fmt::Display + 'a + Captures<'tcx> { + use std::fmt::Write as _; + + let to_print: Cow<'static, str> = match visibility { + None => "".into(), + Some(ty::Visibility::Public) => "pub ".into(), + Some(ty::Visibility::Restricted(vis_did)) => { + // FIXME(camelid): This may not work correctly if `item_did` is a module. + // However, rustdoc currently never displays a module's + // visibility, so it shouldn't matter. + let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id()); + + if vis_did.is_crate_root() { + "pub(crate) ".into() + } else if parent_module == Some(vis_did) { + // `pub(in foo)` where `foo` is the parent module + // is the same as no visibility modifier + "".into() + } else if parent_module.and_then(|parent| find_nearest_parent_module(cx.tcx(), parent)) + == Some(vis_did) + { + "pub(super) ".into() + } else { + let path = cx.tcx().def_path(vis_did); + debug!("path={:?}", path); + // modified from `resolved_path()` to work with `DefPathData` + let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); + let anchor = anchor(vis_did, last_name, cx).to_string(); + + let mut s = "pub(in ".to_owned(); + for seg in &path.data[..path.data.len() - 1] { + let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap()); } + let _ = write!(s, "{}) ", anchor); + s.into() } - }; - display_fn(move |f| write!(f, "{}", to_print)) - } + } + }; + display_fn(move |f| write!(f, "{}", to_print)) +} - /// This function is the same as print_with_space, except that it renders no links. - /// It's used for macros' rendered source view, which is syntax highlighted and cannot have - /// any HTML in it. - pub(crate) fn to_src_with_space<'a, 'tcx: 'a>( - self, - tcx: TyCtxt<'tcx>, - item_did: DefId, - ) -> impl fmt::Display + 'a + Captures<'tcx> { - let to_print = match self { - clean::Public => "pub ".to_owned(), - clean::Inherited => String::new(), - clean::Visibility::Restricted(vis_did) => { - // FIXME(camelid): This may not work correctly if `item_did` is a module. - // However, rustdoc currently never displays a module's - // visibility, so it shouldn't matter. - let parent_module = find_nearest_parent_module(tcx, item_did); - - if vis_did.is_crate_root() { - "pub(crate) ".to_owned() - } else if parent_module == Some(vis_did) { - // `pub(in foo)` where `foo` is the parent module - // is the same as no visibility modifier - String::new() - } else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent)) - == Some(vis_did) - { - "pub(super) ".to_owned() - } else { - format!("pub(in {}) ", tcx.def_path_str(vis_did)) - } +/// This function is the same as print_with_space, except that it renders no links. +/// It's used for macros' rendered source view, which is syntax highlighted and cannot have +/// any HTML in it. +pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>( + visibility: Option<ty::Visibility<DefId>>, + tcx: TyCtxt<'tcx>, + item_did: DefId, +) -> impl fmt::Display + 'a + Captures<'tcx> { + let to_print = match visibility { + None => String::new(), + Some(ty::Visibility::Public) => "pub ".to_owned(), + Some(ty::Visibility::Restricted(vis_did)) => { + // FIXME(camelid): This may not work correctly if `item_did` is a module. + // However, rustdoc currently never displays a module's + // visibility, so it shouldn't matter. + let parent_module = find_nearest_parent_module(tcx, item_did); + + if vis_did.is_crate_root() { + "pub(crate) ".to_owned() + } else if parent_module == Some(vis_did) { + // `pub(in foo)` where `foo` is the parent module + // is the same as no visibility modifier + String::new() + } else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent)) + == Some(vis_did) + { + "pub(super) ".to_owned() + } else { + format!("pub(in {}) ", tcx.def_path_str(vis_did)) } - }; - display_fn(move |f| f.write_str(&to_print)) - } + } + }; + display_fn(move |f| f.write_str(&to_print)) } pub(crate) trait PrintWithSpace { diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 7d6d4b71e2e..a60e7cb10fa 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -2,13 +2,14 @@ use std::path::PathBuf; use rustc_data_structures::fx::FxHashMap; -use crate::error::Error; use crate::externalfiles::ExternalHtml; use crate::html::format::{Buffer, Print}; use crate::html::render::{ensure_trailing_slash, StylePath}; use askama::Template; +use super::static_files::{StaticFiles, STATIC_FILES}; + #[derive(Clone)] pub(crate) struct Layout { pub(crate) logo: String, @@ -34,17 +35,23 @@ pub(crate) struct Page<'a> { } impl<'a> Page<'a> { - pub(crate) fn get_static_root_path(&self) -> &str { - self.static_root_path.unwrap_or(self.root_path) + pub(crate) fn get_static_root_path(&self) -> String { + match self.static_root_path { + Some(s) => s.to_string(), + None => format!("{}static.files/", self.root_path), + } } } #[derive(Template)] #[template(path = "page.html")] struct PageLayout<'a> { - static_root_path: &'a str, + static_root_path: String, page: &'a Page<'a>, layout: &'a Layout, + + files: &'static StaticFiles, + themes: Vec<String>, sidebar: String, content: String, @@ -61,19 +68,17 @@ pub(crate) fn render<T: Print, S: Print>( ) -> String { let static_root_path = page.get_static_root_path(); let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string(); - let mut themes: Vec<String> = style_files - .iter() - .map(StylePath::basename) - .collect::<Result<_, Error>>() - .unwrap_or_default(); + let mut themes: Vec<String> = style_files.iter().map(|s| s.basename().unwrap()).collect(); themes.sort(); - let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version"); + + let rustdoc_version = rustc_interface::util::version_str!().unwrap_or("unknown version"); let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar. let sidebar = Buffer::html().to_display(sidebar); PageLayout { static_root_path, page, layout, + files: &STATIC_FILES, themes, sidebar, content, diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5733d1f9c79..73690c86f4f 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -32,7 +32,7 @@ use crate::html::escape::Escape; use crate::html::format::{join_with_double_colon, Buffer}; use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap}; use crate::html::url_parts_builder::UrlPartsBuilder; -use crate::html::{layout, sources}; +use crate::html::{layout, sources, static_files}; use crate::scrape_examples::AllCallLocations; use crate::try_err; @@ -69,11 +69,13 @@ pub(crate) struct Context<'tcx> { /// the source files are present in the html rendering, then this will be /// `true`. pub(crate) include_sources: bool, + /// Collection of all types with notable traits referenced in the current module. + pub(crate) types_with_notable_traits: FxHashSet<clean::Type>, } // `Context` is cloned a lot, so we don't want the size to grow unexpectedly. #[cfg(all(not(windows), target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Context<'_>, 128); +rustc_data_structures::static_assert_size!(Context<'_>, 160); /// Shared mutable state used in [`Context`] and elsewhere. pub(crate) struct SharedContext<'tcx> { @@ -498,7 +500,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { ); let (sender, receiver) = channel(); - let mut scx = SharedContext { + let scx = SharedContext { tcx, src_root, local_sources, @@ -521,19 +523,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { call_locations, }; - // Add the default themes to the `Vec` of stylepaths - // - // Note that these must be added before `sources::render` is called - // so that the resulting source pages are styled - // - // `light.css` is not disabled because it is the stylesheet that stays loaded - // by the browser as the theme stylesheet. The theme system (hackily) works by - // changing the href to this stylesheet. All other themes are disabled to - // prevent rule conflicts - scx.style_files.push(StylePath { path: PathBuf::from("light.css") }); - scx.style_files.push(StylePath { path: PathBuf::from("dark.css") }); - scx.style_files.push(StylePath { path: PathBuf::from("ayu.css") }); - let dst = output; scx.ensure_dir(&dst)?; @@ -545,6 +534,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { deref_id_map: FxHashMap::default(), shared: Rc::new(scx), include_sources, + types_with_notable_traits: FxHashSet::default(), }; if emit_crate { @@ -573,6 +563,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { id_map: IdMap::new(), shared: Rc::clone(&self.shared), include_sources: self.include_sources, + types_with_notable_traits: FxHashSet::default(), } } @@ -647,10 +638,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { </section>\ </noscript>\ <link rel=\"stylesheet\" type=\"text/css\" \ - href=\"{root_path}settings{suffix}.css\">\ - <script defer src=\"{root_path}settings{suffix}.js\"></script>", - root_path = page.static_root_path.unwrap_or(""), - suffix = page.resource_suffix, + href=\"{static_root_path}{settings_css}\">\ + <script defer src=\"{static_root_path}{settings_js}\"></script>", + static_root_path = page.get_static_root_path(), + settings_css = static_files::STATIC_FILES.settings_css, + settings_js = static_files::STATIC_FILES.settings_js, ) }, &shared.style_files, @@ -815,6 +807,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } } } + Ok(()) } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index adf501a0240..266ec2ac7ad 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -59,7 +59,7 @@ use rustc_span::{ symbol::{sym, Symbol}, BytePos, FileName, RealFileName, }; -use serde::ser::SerializeSeq; +use serde::ser::{SerializeMap, SerializeSeq}; use serde::{Serialize, Serializer}; use crate::clean::{self, ItemId, RenderedLink, SelfTy}; @@ -70,8 +70,8 @@ use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; use crate::html::format::{ href, join_with_double_colon, print_abi_with_space, print_constness_with_space, - print_default_space, print_generic_bounds, print_where_clause, Buffer, Ending, HrefError, - PrintWithSpace, + print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space, + Buffer, Ending, HrefError, PrintWithSpace, }; use crate::html::highlight; use crate::html::markdown::{ @@ -752,7 +752,7 @@ fn assoc_const( w, "{extra}{vis}const <a{href} class=\"constant\">{name}</a>: {ty}", extra = extra, - vis = it.visibility(tcx).print_with_space(it.item_id, cx), + vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), href = assoc_href_attr(it, link, cx), name = it.name.as_ref().unwrap(), ty = ty.print(cx), @@ -803,13 +803,13 @@ fn assoc_method( d: &clean::FnDecl, link: AssocItemLink<'_>, parent: ItemType, - cx: &Context<'_>, + cx: &mut Context<'_>, render_mode: RenderMode, ) { let tcx = cx.tcx(); let header = meth.fn_header(tcx).expect("Trying to get header from a non-function item"); let name = meth.name.as_ref().unwrap(); - let vis = meth.visibility(tcx).print_with_space(meth.item_id, cx).to_string(); + let vis = visibility_print_with_space(meth.visibility(tcx), meth.item_id, cx).to_string(); // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove // this condition. let constness = match render_mode { @@ -836,6 +836,8 @@ fn assoc_method( + name.as_str().len() + generics_len; + let notable_traits = d.output.as_return().and_then(|output| notable_traits_button(output, cx)); + let (indent, indent_str, end_newline) = if parent == ItemType::Trait { header_len += 4; let indent_str = " "; @@ -861,9 +863,9 @@ fn assoc_method( name = name, generics = g.print(cx), decl = d.full_print(header_len, indent, cx), - notable_traits = notable_traits_decl(d, cx), + notable_traits = notable_traits.unwrap_or_default(), where_clause = print_where_clause(g, cx, indent, end_newline), - ) + ); } /// Writes a span containing the versions at which an item became stable and/or const-stable. For @@ -963,7 +965,7 @@ fn render_assoc_item( item: &clean::Item, link: AssocItemLink<'_>, parent: ItemType, - cx: &Context<'_>, + cx: &mut Context<'_>, render_mode: RenderMode, ) { match &*item.kind { @@ -1273,88 +1275,135 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> } } -fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { - let mut out = Buffer::html(); +pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> Option<String> { + let mut has_notable_trait = false; + + let did = ty.def_id(cx.cache())?; - if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t))) + // Box has pass-through impls for Read, Write, Iterator, and Future when the + // boxed type implements one of those. We don't want to treat every Box return + // as being notably an Iterator (etc), though, so we exempt it. Pin has the same + // issue, with a pass-through impl for Future. + if Some(did) == cx.tcx().lang_items().owned_box() + || Some(did) == cx.tcx().lang_items().pin_type() { - // Box has pass-through impls for Read, Write, Iterator, and Future when the - // boxed type implements one of those. We don't want to treat every Box return - // as being notably an Iterator (etc), though, so we exempt it. Pin has the same - // issue, with a pass-through impl for Future. - if Some(did) == cx.tcx().lang_items().owned_box() - || Some(did) == cx.tcx().lang_items().pin_type() - { - return "".to_string(); - } - if let Some(impls) = cx.cache().impls.get(&did) { - for i in impls { - let impl_ = i.inner_impl(); - if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache()) + return None; + } + + if let Some(impls) = cx.cache().impls.get(&did) { + for i in impls { + let impl_ = i.inner_impl(); + if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache()) { + // Two different types might have the same did, + // without actually being the same. + continue; + } + if let Some(trait_) = &impl_.trait_ { + let trait_did = trait_.def_id(); + + if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable_trait(cx.tcx())) { - // Two different types might have the same did, - // without actually being the same. - continue; + has_notable_trait = true; + } + } + } + } + + if has_notable_trait { + cx.types_with_notable_traits.insert(ty.clone()); + Some(format!( + "<span class=\"notable-traits\" data-ty=\"{ty}\">\ + <span class=\"notable-traits-tooltip\">ⓘ</span>\ + </span>", + ty = Escape(&format!("{:#}", ty.print(cx))), + )) + } else { + None + } +} + +fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { + let mut out = Buffer::html(); + + let did = ty.def_id(cx.cache()).expect("notable_traits_button already checked this"); + + let impls = cx.cache().impls.get(&did).expect("notable_traits_button already checked this"); + + for i in impls { + let impl_ = i.inner_impl(); + if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache()) { + // Two different types might have the same did, + // without actually being the same. + continue; + } + if let Some(trait_) = &impl_.trait_ { + let trait_did = trait_.def_id(); + + if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable_trait(cx.tcx())) { + if out.is_empty() { + write!( + &mut out, + "<h3 class=\"notable\">Notable traits for <code>{}</code></h3>\ + <pre class=\"content\"><code>", + impl_.for_.print(cx) + ); } - if let Some(trait_) = &impl_.trait_ { - let trait_did = trait_.def_id(); - - if cx - .cache() - .traits - .get(&trait_did) - .map_or(false, |t| t.is_notable_trait(cx.tcx())) - { - if out.is_empty() { - write!( - &mut out, - "<span class=\"notable\">Notable traits for {}</span>\ - <code class=\"content\">", - impl_.for_.print(cx) - ); - } - //use the "where" class here to make it small - write!( + //use the "where" class here to make it small + write!( + &mut out, + "<span class=\"where fmt-newline\">{}</span>", + impl_.print(false, cx) + ); + for it in &impl_.items { + if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { + out.push_str("<span class=\"where fmt-newline\"> "); + let empty_set = FxHashSet::default(); + let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set); + assoc_type( &mut out, - "<span class=\"where fmt-newline\">{}</span>", - impl_.print(false, cx) + it, + &tydef.generics, + &[], // intentionally leaving out bounds + Some(&tydef.type_), + src_link, + 0, + cx, ); - for it in &impl_.items { - if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { - out.push_str("<span class=\"where fmt-newline\"> "); - let empty_set = FxHashSet::default(); - let src_link = - AssocItemLink::GotoSource(trait_did.into(), &empty_set); - assoc_type( - &mut out, - it, - &tydef.generics, - &[], // intentionally leaving out bounds - Some(&tydef.type_), - src_link, - 0, - cx, - ); - out.push_str(";</span>"); - } - } + out.push_str(";</span>"); } } } } } - - if !out.is_empty() { - out.insert_str( - 0, - "<span class=\"notable-traits\"><span class=\"notable-traits-tooltip\">ⓘ\ - <span class=\"notable-traits-tooltiptext\"><span class=\"docblock\">", - ); - out.push_str("</code></span></span></span></span>"); + if out.is_empty() { + write!(&mut out, "</code></pre>",); } - out.into_inner() + (format!("{:#}", ty.print(cx)), out.into_inner()) +} + +pub(crate) fn notable_traits_json<'a>( + tys: impl Iterator<Item = &'a clean::Type>, + cx: &Context<'_>, +) -> String { + let mut mp: Vec<(String, String)> = tys.map(|ty| notable_traits_decl(ty, cx)).collect(); + mp.sort_by(|(name1, _html1), (name2, _html2)| name1.cmp(name2)); + struct NotableTraitsMap(Vec<(String, String)>); + impl Serialize for NotableTraitsMap { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + let mut map = serializer.serialize_map(Some(self.0.len()))?; + for item in &self.0 { + map.serialize_entry(&item.0, &item.1)?; + } + map.end() + } + } + serde_json::to_string(&NotableTraitsMap(mp)) + .expect("serialize (string, string) -> json object cannot fail") } #[derive(Clone, Copy, Debug)] diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 13df08280b5..ac11a860a4f 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::stability; use rustc_middle::span_bug; use rustc_middle::ty::layout::LayoutError; -use rustc_middle::ty::{Adt, TyCtxt}; +use rustc_middle::ty::{self, Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants}; @@ -17,9 +17,10 @@ use std::rc::Rc; use super::{ collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference, - item_ty_to_section, notable_traits_decl, render_all_impls, render_assoc_item, - render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl, - render_rightside, render_stability_since_raw, AssocItemLink, Context, ImplRenderingParameters, + item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls, + render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre, + render_impl, render_rightside, render_stability_since_raw, AssocItemLink, Context, + ImplRenderingParameters, }; use crate::clean; use crate::config::ModuleSorting; @@ -28,12 +29,12 @@ use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; use crate::html::format::{ join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause, - Buffer, Ending, PrintWithSpace, + visibility_print_with_space, Buffer, Ending, PrintWithSpace, }; -use crate::html::highlight; use crate::html::layout::Page; use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use crate::html::url_parts_builder::UrlPartsBuilder; +use crate::html::{highlight, static_files}; use askama::Template; use itertools::Itertools; @@ -52,8 +53,8 @@ struct PathComponent { #[derive(Template)] #[template(path = "print_item.html")] struct ItemVars<'a> { - page: &'a Page<'a>, static_root_path: &'a str, + clipboard_svg: &'static static_files::StaticFile, typ: &'a str, name: &'a str, item_type: &'a str, @@ -147,8 +148,8 @@ pub(super) fn print_item( }; let item_vars = ItemVars { - page, - static_root_path: page.get_static_root_path(), + static_root_path: &page.get_static_root_path(), + clipboard_svg: &static_files::STATIC_FILES.clipboard_svg, typ, name: item.name.as_ref().unwrap().as_str(), item_type: &item.type_().to_string(), @@ -183,6 +184,16 @@ pub(super) fn print_item( unreachable!(); } } + + // Render notable-traits.js used for all methods in this module. + if !cx.types_with_notable_traits.is_empty() { + write!( + buf, + r#"<script type="text/json" id="notable-traits-data">{}</script>"#, + notable_traits_json(cx.types_with_notable_traits.iter(), cx) + ); + cx.types_with_notable_traits.clear(); + } } /// For large structs, enums, unions, etc, determine whether to hide their fields @@ -328,14 +339,14 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: Some(src) => write!( w, "<div class=\"item-left\"><code>{}extern crate {} as {};", - myitem.visibility(tcx).print_with_space(myitem.item_id, cx), + visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx), anchor(myitem.item_id.expect_def_id(), src, cx), myitem.name.unwrap(), ), None => write!( w, "<div class=\"item-left\"><code>{}extern crate {};", - myitem.visibility(tcx).print_with_space(myitem.item_id, cx), + visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx), anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx), ), } @@ -385,7 +396,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: </div>\ {stab_tags_before}{stab_tags}{stab_tags_after}", stab = stab.unwrap_or_default(), - vis = myitem.visibility(tcx).print_with_space(myitem.item_id, cx), + vis = visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx), imp = import.print(cx), ); w.write_str(ITEM_TABLE_ROW_CLOSE); @@ -410,7 +421,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: let add = if stab.is_some() { " " } else { "" }; let visibility_emoji = match myitem.visibility(tcx) { - clean::Visibility::Restricted(_) => { + Some(ty::Visibility::Restricted(_)) => { "<span title=\"Restricted Visibility\"> 🔒</span> " } _ => "", @@ -503,7 +514,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle let unsafety = header.unsafety.print_with_space(); let abi = print_abi_with_space(header.abi).to_string(); let asyncness = header.asyncness.print_with_space(); - let visibility = it.visibility(tcx).print_with_space(it.item_id, cx).to_string(); + let visibility = visibility_print_with_space(it.visibility(tcx), it.item_id, cx).to_string(); let name = it.name.unwrap(); let generics_len = format!("{:#}", f.generics.print(cx)).len(); @@ -516,6 +527,9 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle + name.as_str().len() + generics_len; + let notable_traits = + f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx)); + wrap_into_item_decl(w, |w| { wrap_item(w, "fn", |w| { render_attributes_in_pre(w, it, ""); @@ -533,11 +547,11 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle generics = f.generics.print(cx), where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline), decl = f.decl.full_print(header_len, 0, cx), - notable_traits = notable_traits_decl(&f.decl, cx), + notable_traits = notable_traits.unwrap_or_default(), ); }); }); - document(w, cx, it, None, HeadingOffset::H2) + document(w, cx, it, None, HeadingOffset::H2); } fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) { @@ -561,7 +575,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: write!( w, "{}{}{}trait {}{}{}", - it.visibility(tcx).print_with_space(it.item_id, cx), + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), t.unsafety(tcx).print_with_space(), if t.is_auto(tcx) { "auto " } else { "" }, it.name.unwrap(), @@ -1086,7 +1100,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { wrap_item(w, "typedef", |w| { render_attributes_in_pre(w, it, ""); - write!(w, "{}", it.visibility(cx.tcx()).print_with_space(it.item_id, cx)); + write!(w, "{}", visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx)); write!( w, "type {}{}{where_clause} = {type_};", @@ -1183,7 +1197,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: write!( w, "{}enum {}{}", - it.visibility(tcx).print_with_space(it.item_id, cx), + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), it.name.unwrap(), e.generics.print(cx), ); @@ -1398,7 +1412,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle write!( w, "{vis}const {name}: {typ}", - vis = it.visibility(tcx).print_with_space(it.item_id, cx), + vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), name = it.name.unwrap(), typ = c.type_.print(cx), ); @@ -1499,7 +1513,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean write!( w, "{vis}static {mutability}{name}: {typ}", - vis = it.visibility(cx.tcx()).print_with_space(it.item_id, cx), + vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), mutability = s.mutability.print_with_space(), name = it.name.unwrap(), typ = s.type_.print(cx) @@ -1517,7 +1531,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { write!( w, " {}type {};\n}}", - it.visibility(cx.tcx()).print_with_space(it.item_id, cx), + visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), it.name.unwrap(), ); }); @@ -1671,7 +1685,12 @@ fn render_union( cx: &Context<'_>, ) { let tcx = cx.tcx(); - write!(w, "{}union {}", it.visibility(tcx).print_with_space(it.item_id, cx), it.name.unwrap(),); + write!( + w, + "{}union {}", + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), + it.name.unwrap(), + ); let where_displayed = g .map(|g| { @@ -1698,7 +1717,7 @@ fn render_union( write!( w, " {}{}: {},\n{}", - field.visibility(tcx).print_with_space(field.item_id, cx), + visibility_print_with_space(field.visibility(tcx), field.item_id, cx), field.name.unwrap(), ty.print(cx), tab @@ -1729,7 +1748,7 @@ fn render_struct( write!( w, "{}{}{}", - it.visibility(tcx).print_with_space(it.item_id, cx), + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), if structhead { "struct " } else { "" }, it.name.unwrap() ); @@ -1759,7 +1778,7 @@ fn render_struct( w, "\n{} {}{}: {},", tab, - field.visibility(tcx).print_with_space(field.item_id, cx), + visibility_print_with_space(field.visibility(tcx), field.item_id, cx), field.name.unwrap(), ty.print(cx), ); @@ -1791,7 +1810,7 @@ fn render_struct( write!( w, "{}{}", - field.visibility(tcx).print_with_space(field.item_id, cx), + visibility_print_with_space(field.visibility(tcx), field.item_id, cx), ty.print(cx), ) } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 85f63c985b3..94d8a9feca6 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -1,10 +1,8 @@ -use std::ffi::OsStr; use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufReader}; -use std::path::{Component, Path, PathBuf}; +use std::path::{Component, Path}; use std::rc::Rc; -use std::sync::LazyLock as Lazy; use itertools::Itertools; use rustc_data_structures::flock; @@ -20,123 +18,20 @@ use crate::error::Error; use crate::html::{layout, static_files}; use crate::{try_err, try_none}; -static FILES_UNVERSIONED: Lazy<FxHashMap<&str, &[u8]>> = Lazy::new(|| { - map! { - "FiraSans-Regular.woff2" => static_files::fira_sans::REGULAR, - "FiraSans-Medium.woff2" => static_files::fira_sans::MEDIUM, - "FiraSans-LICENSE.txt" => static_files::fira_sans::LICENSE, - "SourceSerif4-Regular.ttf.woff2" => static_files::source_serif_4::REGULAR, - "SourceSerif4-Bold.ttf.woff2" => static_files::source_serif_4::BOLD, - "SourceSerif4-It.ttf.woff2" => static_files::source_serif_4::ITALIC, - "SourceSerif4-LICENSE.md" => static_files::source_serif_4::LICENSE, - "SourceCodePro-Regular.ttf.woff2" => static_files::source_code_pro::REGULAR, - "SourceCodePro-Semibold.ttf.woff2" => static_files::source_code_pro::SEMIBOLD, - "SourceCodePro-It.ttf.woff2" => static_files::source_code_pro::ITALIC, - "SourceCodePro-LICENSE.txt" => static_files::source_code_pro::LICENSE, - "NanumBarunGothic.ttf.woff2" => static_files::nanum_barun_gothic::REGULAR, - "NanumBarunGothic-LICENSE.txt" => static_files::nanum_barun_gothic::LICENSE, - "LICENSE-MIT.txt" => static_files::LICENSE_MIT, - "LICENSE-APACHE.txt" => static_files::LICENSE_APACHE, - "COPYRIGHT.txt" => static_files::COPYRIGHT, - } -}); - -enum SharedResource<'a> { - /// This file will never change, no matter what toolchain is used to build it. - /// - /// It does not have a resource suffix. - Unversioned { name: &'static str }, - /// This file may change depending on the toolchain. - /// - /// It has a resource suffix. - ToolchainSpecific { basename: &'static str }, - /// This file may change for any crate within a build, or based on the CLI arguments. - /// - /// This differs from normal invocation-specific files because it has a resource suffix. - InvocationSpecific { basename: &'a str }, -} - -impl SharedResource<'_> { - fn extension(&self) -> Option<&OsStr> { - use SharedResource::*; - match self { - Unversioned { name } - | ToolchainSpecific { basename: name } - | InvocationSpecific { basename: name } => Path::new(name).extension(), - } - } - - fn path(&self, cx: &Context<'_>) -> PathBuf { - match self { - SharedResource::Unversioned { name } => cx.dst.join(name), - SharedResource::ToolchainSpecific { basename } => cx.suffix_path(basename), - SharedResource::InvocationSpecific { basename } => cx.suffix_path(basename), - } - } - - fn should_emit(&self, emit: &[EmitType]) -> bool { - if emit.is_empty() { - return true; - } - let kind = match self { - SharedResource::Unversioned { .. } => EmitType::Unversioned, - SharedResource::ToolchainSpecific { .. } => EmitType::Toolchain, - SharedResource::InvocationSpecific { .. } => EmitType::InvocationSpecific, - }; - emit.contains(&kind) - } -} - -impl Context<'_> { - fn suffix_path(&self, filename: &str) -> PathBuf { - // We use splitn vs Path::extension here because we might get a filename - // like `style.min.css` and we want to process that into - // `style-suffix.min.css`. Path::extension would just return `css` - // which would result in `style.min-suffix.css` which isn't what we - // want. - let (base, ext) = filename.split_once('.').unwrap(); - let filename = format!("{}{}.{}", base, self.shared.resource_suffix, ext); - self.dst.join(&filename) - } - - fn write_shared( - &self, - resource: SharedResource<'_>, - contents: impl 'static + Send + AsRef<[u8]>, - emit: &[EmitType], - ) -> Result<(), Error> { - if resource.should_emit(emit) { - self.shared.fs.write(resource.path(self), contents) - } else { - Ok(()) - } - } - - fn write_minify( - &self, - resource: SharedResource<'_>, - contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>, - minify: bool, - emit: &[EmitType], - ) -> Result<(), Error> { - if minify { - let contents = contents.as_ref(); - let contents = if resource.extension() == Some(OsStr::new("css")) { - minifier::css::minify(contents) - .map_err(|e| { - Error::new(format!("failed to minify CSS file: {}", e), resource.path(self)) - })? - .to_string() - } else { - minifier::js::minify(contents).to_string() - }; - self.write_shared(resource, contents, emit) - } else { - self.write_shared(resource, contents, emit) - } - } -} - +/// Rustdoc writes out two kinds of shared files: +/// - Static files, which are embedded in the rustdoc binary and are written with a +/// filename that includes a hash of their contents. These will always have a new +/// URL if the contents change, so they are safe to cache with the +/// `Cache-Control: immutable` directive. They are written under the static.files/ +/// directory and are written when --emit-type is empty (default) or contains +/// "toolchain-specific". If using the --static-root-path flag, it should point +/// to a URL path prefix where each of these filenames can be fetched. +/// - Invocation specific files. These are generated based on the crate(s) being +/// documented. Their filenames need to be predictable without knowing their +/// contents, so they do not include a hash in their filename and are not safe to +/// cache with `Cache-Control: immutable`. They include the contents of the +/// --resource-suffix flag and are emitted when --emit-type is empty (default) +/// or contains "invocation-specific". pub(super) fn write_shared( cx: &mut Context<'_>, krate: &Crate, @@ -149,139 +44,52 @@ pub(super) fn write_shared( let lock_file = cx.dst.join(".lock"); let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file); - // Minified resources are usually toolchain resources. If they're not, they should use `cx.write_minify` directly. - fn write_minify( - basename: &'static str, - contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>, - cx: &Context<'_>, - options: &RenderOptions, - ) -> Result<(), Error> { - cx.write_minify( - SharedResource::ToolchainSpecific { basename }, - contents, - options.enable_minification, - &options.emit, - ) - } - - // Toolchain resources should never be dynamic. - let write_toolchain = |p: &'static _, c: &'static _| { - cx.write_shared(SharedResource::ToolchainSpecific { basename: p }, c, &options.emit) - }; - - // Crate resources should always be dynamic. - let write_crate = |p: &_, make_content: &dyn Fn() -> Result<Vec<u8>, Error>| { + // InvocationSpecific resources should always be dynamic. + let write_invocation_specific = |p: &str, make_content: &dyn Fn() -> Result<Vec<u8>, Error>| { let content = make_content()?; - cx.write_shared(SharedResource::InvocationSpecific { basename: p }, content, &options.emit) + if options.emit.is_empty() || options.emit.contains(&EmitType::InvocationSpecific) { + let output_filename = static_files::suffix_path(p, &cx.shared.resource_suffix); + cx.shared.fs.write(cx.dst.join(output_filename), content) + } else { + Ok(()) + } }; - // Given "foo.svg", return e.g. "url(\"foo1.58.0.svg\")" - fn ver_url(cx: &Context<'_>, basename: &'static str) -> String { - format!( - "url(\"{}\")", - SharedResource::ToolchainSpecific { basename } - .path(cx) - .file_name() - .unwrap() - .to_str() - .unwrap() - ) - } - - // We use the AUTOREPLACE mechanism to inject into our static JS and CSS certain - // values that are only known at doc build time. Since this mechanism is somewhat - // surprising when reading the code, please limit it to rustdoc.css. - write_minify( - "rustdoc.css", - static_files::RUSTDOC_CSS - .replace( - "/* AUTOREPLACE: */url(\"toggle-minus.svg\")", - &ver_url(cx, "toggle-minus.svg"), - ) - .replace("/* AUTOREPLACE: */url(\"toggle-plus.svg\")", &ver_url(cx, "toggle-plus.svg")) - .replace("/* AUTOREPLACE: */url(\"down-arrow.svg\")", &ver_url(cx, "down-arrow.svg")), - cx, - options, - )?; - - // Add all the static files. These may already exist, but we just - // overwrite them anyway to make sure that they're fresh and up-to-date. - write_minify("settings.css", static_files::SETTINGS_CSS, cx, options)?; - write_minify("noscript.css", static_files::NOSCRIPT_CSS, cx, options)?; - - // To avoid "light.css" to be overwritten, we'll first run over the received themes and only - // then we'll run over the "official" styles. - let mut themes: FxHashSet<String> = FxHashSet::default(); + cx.shared + .fs + .create_dir_all(cx.dst.join("static.files")) + .map_err(|e| PathError::new(e, "static.files"))?; + // Handle added third-party themes for entry in &cx.shared.style_files { let theme = entry.basename()?; let extension = try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path); - // Handle the official themes - match theme.as_str() { - "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?, - "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?, - "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?, - _ => { - // Handle added third-party themes - let filename = format!("{}.{}", theme, extension); - write_crate(&filename, &|| Ok(try_err!(fs::read(&entry.path), &entry.path)))?; - } - }; - - themes.insert(theme.to_owned()); - } - - if (*cx.shared).layout.logo.is_empty() { - write_toolchain("rust-logo.svg", static_files::RUST_LOGO_SVG)?; - } - if (*cx.shared).layout.favicon.is_empty() { - write_toolchain("favicon.svg", static_files::RUST_FAVICON_SVG)?; - write_toolchain("favicon-16x16.png", static_files::RUST_FAVICON_PNG_16)?; - write_toolchain("favicon-32x32.png", static_files::RUST_FAVICON_PNG_32)?; - } - write_toolchain("wheel.svg", static_files::WHEEL_SVG)?; - write_toolchain("clipboard.svg", static_files::CLIPBOARD_SVG)?; - write_toolchain("down-arrow.svg", static_files::DOWN_ARROW_SVG)?; - write_toolchain("toggle-minus.svg", static_files::TOGGLE_MINUS_PNG)?; - write_toolchain("toggle-plus.svg", static_files::TOGGLE_PLUS_PNG)?; - - let mut themes: Vec<&String> = themes.iter().collect(); - themes.sort(); - - write_minify("main.js", static_files::MAIN_JS, cx, options)?; - write_minify("search.js", static_files::SEARCH_JS, cx, options)?; - write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?; - - if cx.include_sources { - write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?; - } - - write_minify("storage.js", static_files::STORAGE_JS, cx, options)?; + // Skip the official themes. They are written below as part of STATIC_FILES_LIST. + if matches!(theme.as_str(), "light" | "dark" | "ayu") { + continue; + } - if cx.shared.layout.scrape_examples_extension { - cx.write_minify( - SharedResource::InvocationSpecific { basename: "scrape-examples.js" }, - static_files::SCRAPE_EXAMPLES_JS, - options.enable_minification, - &options.emit, - )?; + let bytes = try_err!(fs::read(&entry.path), &entry.path); + let filename = format!("{}{}.{}", theme, cx.shared.resource_suffix, extension); + cx.shared.fs.write(cx.dst.join(filename), bytes)?; } + // When the user adds their own CSS files with --extend-css, we write that as an + // invocation-specific file (that is, with a resource suffix). if let Some(ref css) = cx.shared.layout.css_file_extension { let buffer = try_err!(fs::read_to_string(css), css); - // This varies based on the invocation, so it can't go through the write_minify wrapper. - cx.write_minify( - SharedResource::InvocationSpecific { basename: "theme.css" }, - buffer, - options.enable_minification, - &options.emit, - )?; + let path = static_files::suffix_path("theme.css", &cx.shared.resource_suffix); + cx.shared.fs.write(cx.dst.join(path), buffer)?; } - write_minify("normalize.css", static_files::NORMALIZE_CSS, cx, options)?; - for (name, contents) in &*FILES_UNVERSIONED { - cx.write_shared(SharedResource::Unversioned { name }, contents, &options.emit)?; + + if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) { + let static_dir = cx.dst.join(Path::new("static.files")); + static_files::for_each(|f: &static_files::StaticFile| { + let filename = static_dir.join(f.output_filename()); + cx.shared.fs.write(filename, f.minified()) + })?; } /// Read a file and return all lines that match the `"{crate}":{data},` format, @@ -463,7 +271,7 @@ pub(super) fn write_shared( v.push_str("\\\n}');\ncreateSourceSidebar();\n"); Ok(v.into_bytes()) }; - write_crate("source-files.js", &make_sources)?; + write_invocation_specific("source-files.js", &make_sources)?; } // Update the search index and crate list. @@ -477,7 +285,7 @@ pub(super) fn write_shared( // Sort the indexes by crate so the file will be generated identically even // with rustdoc running in parallel. all_indexes.sort(); - write_crate("search-index.js", &|| { + write_invocation_specific("search-index.js", &|| { let mut v = String::from("var searchIndex = JSON.parse('{\\\n"); v.push_str(&all_indexes.join(",\\\n")); v.push_str( @@ -490,7 +298,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; Ok(v.into_bytes()) })?; - write_crate("crates.js", &|| { + write_invocation_specific("crates.js", &|| { let krates = krates.iter().map(|k| format!("\"{}\"", k)).join(","); Ok(format!("window.ALL_CRATES = [{}];", krates).into_bytes()) })?; diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css index 301f03a1642..54e8b6561f3 100644 --- a/src/librustdoc/html/static/css/noscript.css +++ b/src/librustdoc/html/static/css/noscript.css @@ -22,3 +22,9 @@ nav.sub { .source .sidebar { display: none; } + +.notable-traits { + /* layout requires javascript + https://github.com/rust-lang/rust/issues/102576 */ + display: none; +} diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d6f2b02afd8..2a39a371f48 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -4,7 +4,7 @@ font-style: normal; font-weight: 400; src: local('Fira Sans'), - url("FiraSans-Regular.woff2") format("woff2"); + url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2"); font-display: swap; } @font-face { @@ -12,7 +12,7 @@ font-style: normal; font-weight: 500; src: local('Fira Sans Medium'), - url("FiraSans-Medium.woff2") format("woff2"); + url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2"); font-display: swap; } @@ -22,7 +22,7 @@ font-style: normal; font-weight: 400; src: local('Source Serif 4'), - url("SourceSerif4-Regular.ttf.woff2") format("woff2"); + url("SourceSerif4-Regular-1f7d512b176f0f72.ttf.woff2") format("woff2"); font-display: swap; } @font-face { @@ -30,7 +30,7 @@ font-style: italic; font-weight: 400; src: local('Source Serif 4 Italic'), - url("SourceSerif4-It.ttf.woff2") format("woff2"); + url("SourceSerif4-It-d034fe4ef9d0fa00.ttf.woff2") format("woff2"); font-display: swap; } @font-face { @@ -38,7 +38,7 @@ font-style: normal; font-weight: 700; src: local('Source Serif 4 Bold'), - url("SourceSerif4-Bold.ttf.woff2") format("woff2"); + url("SourceSerif4-Bold-124a1ca42af929b6.ttf.woff2") format("woff2"); font-display: swap; } @@ -49,28 +49,28 @@ font-weight: 400; /* Avoid using locally installed font because bad versions are in circulation: * see https://github.com/rust-lang/rust/issues/24355 */ - src: url("SourceCodePro-Regular.ttf.woff2") format("woff2"); + src: url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2"); font-display: swap; } @font-face { font-family: 'Source Code Pro'; font-style: italic; font-weight: 400; - src: url("SourceCodePro-It.ttf.woff2") format("woff2"); + src: url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2"); font-display: swap; } @font-face { font-family: 'Source Code Pro'; font-style: normal; font-weight: 600; - src: url("SourceCodePro-Semibold.ttf.woff2") format("woff2"); + src: url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2"); font-display: swap; } /* Avoid using legacy CJK serif fonts in Windows like Batang. */ @font-face { font-family: 'NanumBarunGothic'; - src: url("NanumBarunGothic.ttf.woff2") format("woff2"); + src: url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2"); font-display: swap; unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF; } @@ -367,7 +367,8 @@ img { overflow: visible; } -.sub-logo-container { +.sub-logo-container, .logo-container { + /* zero text boxes so that computed line height = image height exactly */ line-height: 0; } @@ -377,6 +378,10 @@ img { object-fit: contain; } +.rust-logo { + filter: var(--rust-logo-filter); +} + .sidebar, .mobile-topbar, .sidebar-menu-toggle { background-color: var(--sidebar-background-color); } @@ -465,10 +470,9 @@ img { } .sidebar .logo-container { - display: flex; margin-top: 10px; margin-bottom: 10px; - justify-content: center; + text-align: center; } .version { @@ -677,7 +681,6 @@ pre, .rustdoc.source .example-wrap { } #main-content > .item-info { - margin-top: 0; margin-left: 0; } @@ -827,6 +830,9 @@ table, line-height: 1.5; font-weight: 500; } +#crate-search:hover, #crate-search:focus { + border-color: var(--crate-search-hover-border); +} /* cancel stylistic differences in padding in firefox for "appearance: none"-style (or equivalent) <select>s */ @-moz-document url-prefix() { @@ -850,8 +856,13 @@ so that we can apply CSS-filters to change the arrow color in themes */ background-repeat: no-repeat; background-size: 20px; background-position: calc(100% - 2px) 56%; - /* image is black color, themes should apply a "filter" property to change the color */ - background-image: /* AUTOREPLACE: */url("down-arrow.svg"); + /* image is black color */ + background-image: url("down-arrow-927217e04c7463ac.svg"); + /* changes the arrow image color */ + filter: var(--crate-search-div-filter); +} +#crate-search-div:hover::after, #crate-search-div:focus-within::after { + filter: var(--crate-search-div-hover-filter); } #crate-search > option { font-size: 1rem; @@ -882,31 +893,24 @@ so that we can apply CSS-filters to change the arrow color in themes */ display: block; } -.search-results .desc > span { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - display: block; -} - .search-results > a { - display: block; + display: flex; /* A little margin ensures the browser's outlining of focused links has room to display. */ margin-left: 2px; margin-right: 2px; - border-bottom: 1px solid #aaa3; + border-bottom: 1px solid var(--search-result-border-color); + gap: 1em; } .search-results > a > div { - display: flex; - flex-flow: row wrap; + flex: 1; } -.search-results .result-name, .search-results div.desc { - width: 50%; -} -.search-results .result-name { - padding-right: 1em; +.search-results > a > div.desc { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + display: block; } .search-results a:hover, @@ -1212,6 +1216,12 @@ a.test-arrow { top: 5px; right: 5px; z-index: 1; + color: var(--test-arrow-color); + background-color: var(--test-arrow-background-color); +} +a.test-arrow:hover { + color: var(--test-arrow-hover-color); + background-color: var(--test-arrow-hover-background-color); } .example-wrap:hover .test-arrow { visibility: visible; @@ -1259,6 +1269,8 @@ h3.variant { :target { padding-right: 3px; + background-color: var(--target-background-color); + border-right: 3px solid var(--target-border-color); } .notable-traits-tooltip { @@ -1266,13 +1278,12 @@ h3.variant { cursor: pointer; } -.notable-traits:hover .notable-traits-tooltiptext, -.notable-traits .notable-traits-tooltiptext.force-tooltip { +.notable-traits .notable-traits-tooltiptext { display: inline-block; + visibility: hidden; } -.notable-traits .notable-traits-tooltiptext { - display: none; +.notable-traits-tooltiptext { padding: 5px 3px 3px 3px; border-radius: 6px; margin-left: 5px; @@ -1290,22 +1301,26 @@ h3.variant { content: "\00a0\00a0\00a0"; } -.notable-traits .docblock { +.notable-traits-tooltiptext .docblock { margin: 0; } -.notable-traits .notable { - margin: 0; - margin-bottom: 13px; +.notable-traits-tooltiptext .notable { font-size: 1.1875rem; font-weight: 600; display: block; } -.notable-traits .docblock code.content { +.notable-traits-tooltiptext pre, .notable-traits-tooltiptext code { + background: transparent; +} + +.notable-traits-tooltiptext .docblock pre.content { margin: 0; padding: 0; font-size: 1.25rem; + white-space: pre-wrap; + overflow: hidden; } .search-failed { @@ -1625,11 +1640,11 @@ details.rustdoc-toggle[open] > summary.hideme > span { details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle[open] > summary.hideme::before { - background-image: /* AUTOREPLACE: */url("toggle-minus.svg"); + background-image: url("toggle-minus-31bbd6e4c77f5c96.svg"); } details.rustdoc-toggle > summary::before { - background-image: /* AUTOREPLACE: */url("toggle-plus.svg"); + background-image: url("toggle-plus-1092eb4930d581b0.svg"); } details.rustdoc-toggle[open] > summary::before, @@ -1763,10 +1778,6 @@ in storage.js white-space: nowrap; } - .mobile-topbar .logo-container { - max-height: 45px; - } - .mobile-topbar .logo-container > img { max-width: 35px; max-height: 35px; @@ -1796,7 +1807,6 @@ in storage.js .sidebar-elems { margin-top: 1em; - background-color: var(--sidebar-background-color); } .content { @@ -1811,21 +1821,6 @@ in storage.js display: block; } - /* Because of ios, we need to actually have a full height sidebar title so the - * actual sidebar can show up. But then we need to make it transparent so we don't - * hide content. The filler just allows to create the background for the sidebar - * title. But because of the absolute position, I had to lower the z-index. - */ - #sidebar-filler { - position: fixed; - left: 45px; - width: calc(100% - 45px); - top: 0; - height: 45px; - z-index: -1; - border-bottom: 1px solid; - } - #main-content > details.rustdoc-toggle > summary::before, #main-content > div > details.rustdoc-toggle > summary::before { left: -11px; @@ -1869,19 +1864,16 @@ in storage.js } /* Display an alternating layout on tablets and phones */ - .item-table, .item-row, .item-left, .item-right { + .item-table, .item-row, .item-left, .item-right, + .search-results > a, .search-results > a > div { display: block; } /* Display an alternating layout on tablets and phones */ .search-results > a { - border-bottom: 1px solid #aaa9; padding: 5px 0px; } - .search-results .result-name, .search-results div.desc { - width: 100%; - } - .search-results div.desc, .item-right { + .search-results > a > div.desc, .item-right { padding-left: 2em; } diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css index 83939f63b4e..1f6fb961e91 100644 --- a/src/librustdoc/html/static/css/settings.css +++ b/src/librustdoc/html/static/css/settings.css @@ -8,7 +8,8 @@ flex-wrap: wrap; } -.setting-line .radio-line input { +.setting-line .radio-line input, +.setting-line .toggle input { margin-right: 0.3em; height: 1.2rem; width: 1.2rem; @@ -17,9 +18,18 @@ outline: none; -webkit-appearance: none; cursor: pointer; +} +.setting-line .radio-line input { border-radius: 50%; } -.setting-line .radio-line input + span { +.setting-line .toggle input:checked { + content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\ + <path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\ + <path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>'); +} + +.setting-line .radio-line input + span, +.setting-line .toggle span { padding-bottom: 1px; } @@ -49,37 +59,6 @@ cursor: pointer; } -.toggle input { - opacity: 0; - position: absolute; -} - -.slider { - position: relative; - width: 45px; - min-width: 45px; - display: block; - height: 28px; - margin-right: 20px; - cursor: pointer; - background-color: #ccc; - transition: .3s; -} - -.slider:before { - position: absolute; - content: ""; - height: 19px; - width: 19px; - left: 4px; - bottom: 4px; - transition: .3s; -} - -input:checked + .slider:before { - transform: translateX(19px); -} - .setting-line > .sub-settings { padding-left: 42px; width: 100%; @@ -94,7 +73,11 @@ input:checked + .slider:before { box-shadow: inset 0 0 0 3px var(--main-background-color); background-color: var(--settings-input-color); } -.setting-line .radio-line input:focus { +.setting-line .toggle input:checked { + background-color: var(--settings-input-color); +} +.setting-line .radio-line input:focus, +.setting-line .toggle input:focus { box-shadow: 0 0 1px 1px var(--settings-input-color); } /* In here we combine both `:focus` and `:checked` properties. */ @@ -102,9 +85,7 @@ input:checked + .slider:before { box-shadow: inset 0 0 0 3px var(--main-background-color), 0 0 2px 2px var(--settings-input-color); } -.setting-line .radio-line input:hover { +.setting-line .radio-line input:hover, +.setting-line .toggle input:hover { border-color: var(--settings-input-color) !important; } -input:checked + .slider { - background-color: var(--settings-input-color); -} diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index fdfdb3e1966..c644b8413cc 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -38,6 +38,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) --sidebar-link-color: #53b1db; --sidebar-current-link-background-color: transparent; --search-result-link-focus-background-color: #3c3c3c; + --search-result-border-color: #aaa3; --stab-background-color: #314559; --stab-code-color: #e6e1cf; --search-color: #fff; @@ -58,16 +59,22 @@ Original by Dempfi (https://github.com/dempfi/ayu) --example-line-numbers-border-color: none; --src-line-numbers-span-color: #5c6773; --src-line-number-highlighted-background-color: rgba(255, 236, 164, 0.06); -} - -.slider { - background-color: #ccc; -} -.slider:before { - background-color: white; -} -input:focus + .slider { - box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); + --test-arrow-color: #788797; + --test-arrow-background-color: rgba(57, 175, 215, 0.09); + --test-arrow-hover-color: #c5c5c5; + --test-arrow-hover-background-color: rgba(57, 175, 215, 0.368); + --target-background-color: rgba(255, 236, 164, 0.06); + --target-border-color: rgba(255, 180, 76, 0.85); + --rust-logo-filter: drop-shadow(1px 0 0px #fff) + drop-shadow(0 1px 0 #fff) + drop-shadow(-1px 0 0 #fff) + drop-shadow(0 -1px 0 #fff); + /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */ + --crate-search-div-filter: invert(41%) sepia(12%) saturate(487%) hue-rotate(171deg) + brightness(94%) contrast(94%); + --crate-search-div-hover-filter: invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) + brightness(113%) contrast(76%); + --crate-search-hover-border: #e0e0e0; } h1, h2, h3, h4 { @@ -99,13 +106,6 @@ pre, .rustdoc.source .example-wrap { color: #e6e1cf; } -.rust-logo { - filter: drop-shadow(1px 0 0px #fff) - drop-shadow(0 1px 0 #fff) - drop-shadow(-1px 0 0 #fff) - drop-shadow(0 -1px 0 #fff); -} - .sidebar .current, .sidebar a:hover { color: #ffb44c; @@ -151,17 +151,6 @@ details.rustdoc-toggle > summary::before { filter: invert(100%); } -#crate-search-div::after { - /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */ - filter: invert(41%) sepia(12%) saturate(487%) hue-rotate(171deg) brightness(94%) contrast(94%); -} -#crate-search:hover, #crate-search:focus { - border-color: #e0e0e0 !important; -} -#crate-search-div:hover::after, #crate-search-div:focus-within::after { - filter: invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%); -} - .module-item .stab, .import-item .stab { color: #000; @@ -171,27 +160,6 @@ details.rustdoc-toggle > summary::before { color: #788797; } -a.test-arrow { - font-size: 100%; - color: #788797; - border-radius: 4px; - background-color: rgba(57, 175, 215, 0.09); -} - -a.test-arrow:hover { - background-color: rgba(57, 175, 215, 0.368); - color: #c5c5c5; -} - -:target { - background: rgba(255, 236, 164, 0.06); - border-right: 3px solid rgba(255, 180, 76, 0.85); -} - -.search-failed a { - color: #39AFD7; -} - .tooltip::after { background-color: #314559; color: #c5c5c5; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 361d3d4a225..8141e99c52a 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -33,6 +33,7 @@ --sidebar-link-color: #fdbf35; --sidebar-current-link-background-color: #444; --search-result-link-focus-background-color: #616161; + --search-result-border-color: #aaa3; --stab-background-color: #314559; --stab-code-color: #e6e1cf; --search-color: #111; @@ -53,23 +54,22 @@ --example-line-numbers-border-color: #4a4949; --src-line-numbers-span-color: #3b91e2; --src-line-number-highlighted-background-color: #0a042f; -} - -.slider { - background-color: #ccc; -} -.slider:before { - background-color: white; -} -input:focus + .slider { - box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); -} - -.rust-logo { - filter: drop-shadow(1px 0 0px #fff) + --test-arrow-color: #dedede; + --test-arrow-background-color: rgba(78, 139, 202, 0.2); + --test-arrow-hover-color: #dedede; + --test-arrow-hover-background-color: #4e8bca; + --target-background-color: #494a3d; + --target-border-color: #bb7410; + --rust-logo-filter: drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) - drop-shadow(0 -1px 0 #fff) + drop-shadow(0 -1px 0 #fff); + /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */ + --crate-search-div-filter: invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) + brightness(90%) contrast(90%); + --crate-search-div-hover-filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) + brightness(100%) contrast(91%); + --crate-search-hover-border: #2196f3; } .content .item-info::before { color: #ccc; } @@ -82,35 +82,6 @@ details.rustdoc-toggle > summary::before { filter: invert(100%); } -#crate-search-div::after { - /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */ - filter: invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%); -} -#crate-search:hover, #crate-search:focus { - border-color: #2196f3 !important; -} -#crate-search-div:hover::after, #crate-search-div:focus-within::after { - filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%); -} - -a.test-arrow { - color: #dedede; - background-color: rgba(78, 139, 202, 0.2); -} - -a.test-arrow:hover{ - background-color: #4e8bca; -} - -:target { - background-color: #494a3d; - border-right: 3px solid #bb7410; -} - -.search-failed a { - color: #0089ff; -} - .tooltip::after { background-color: #000; color: #fff; diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 5eb4bbcf834..6e3d7568ffb 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -33,6 +33,7 @@ --sidebar-link-color: #356da4; --sidebar-current-link-background-color: #fff; --search-result-link-focus-background-color: #ccc; + --search-result-border-color: #aaa3; --stab-background-color: #fff5d6; --stab-code-color: #000; --search-color: #000; @@ -53,22 +54,19 @@ --example-line-numbers-border-color: #c7c7c7; --src-line-numbers-span-color: #c67e2d; --src-line-number-highlighted-background-color: #fdffd3; -} - -.slider { - background-color: #ccc; -} -.slider:before { - background-color: white; -} -input:focus + .slider { - box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); -} - -.rust-logo { - /* This rule exists to force other themes to explicitly style the logo. - * Rustdoc has a custom linter for this purpose. - */ + --test-arrow-color: #f5f5f5; + --test-arrow-background-color: rgba(78, 139, 202, 0.2); + --test-arrow-hover-color: #f5f5f5; + --test-arrow-hover-background-color: #4e8bca; + --target-background-color: #fdFfd3; + --target-border-color: #ad7c37; + --rust-logo-filter: initial; + /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */ + --crate-search-div-filter: invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) + brightness(114%) contrast(76%); + --crate-search-div-hover-filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) + brightness(96%) contrast(93%); + --crate-search-hover-border: #717171; } .content .item-info::before { color: #ccc; } @@ -77,35 +75,6 @@ body.source .example-wrap pre.rust a { background: #eee; } -#crate-search-div::after { - /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */ - filter: invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%); -} -#crate-search:hover, #crate-search:focus { - border-color: #717171 !important; -} -#crate-search-div:hover::after, #crate-search-div:focus-within::after { - filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%); -} - -a.test-arrow { - color: #f5f5f5; - background-color: rgba(78, 139, 202, 0.2); -} - -a.test-arrow:hover{ - background-color: #4e8bca; -} - -:target { - background: #FDFFD3; - border-right: 3px solid #AD7C37; -} - -.search-failed a { - color: #3873AD; -} - .tooltip::after { background-color: #000; color: #fff; diff --git a/src/librustdoc/html/static/fonts/README.txt b/src/librustdoc/html/static/fonts/README.txt new file mode 100644 index 00000000000..0db15996d2e --- /dev/null +++ b/src/librustdoc/html/static/fonts/README.txt @@ -0,0 +1,12 @@ +The Nanum Barun Gothic fonts are shipped with rustdoc because the default fonts +on many Windows installs render Korean very badly. See: + - https://github.com/rust-lang/rust/pull/84048, + - https://github.com/rust-lang/rust/issues/84035 + - https://github.com/rust-lang/rust/pull/90232 + +The font files were generated with these commands: + +```sh +pyftsubset NanumBarunGothic.ttf \ +--unicodes=U+AC00-D7AF:U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \ +--output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2 diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 33480fa41cf..0426774e80d 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -183,9 +183,9 @@ function browserSupportsHistoryApi() { } // eslint-disable-next-line no-unused-vars -function loadCss(cssFileName) { +function loadCss(cssUrl) { const link = document.createElement("link"); - link.href = resourcePath(cssFileName, ".css"); + link.href = cssUrl; link.type = "text/css"; link.rel = "stylesheet"; document.getElementsByTagName("head")[0].appendChild(link); @@ -208,8 +208,8 @@ function loadCss(cssFileName) { event.preventDefault(); // Sending request for the CSS and the JS files at the same time so it will // hopefully be loaded when the JS will generate the settings content. - loadCss("settings"); - loadScript(resourcePath("settings", ".js")); + loadCss(getVar("static-root-path") + getVar("settings-css")); + loadScript(getVar("static-root-path") + getVar("settings-js")); }; window.searchState = { @@ -286,7 +286,7 @@ function loadCss(cssFileName) { function loadSearch() { if (!searchLoaded) { searchLoaded = true; - loadScript(resourcePath("search", ".js")); + loadScript(getVar("static-root-path") + getVar("search-js")); loadScript(resourcePath("search-index", ".js")); } } @@ -790,6 +790,19 @@ function loadCss(cssFileName) { // we need to switch away from mobile mode and make the main content area scrollable. hideSidebar(); } + if (window.CURRENT_NOTABLE_ELEMENT) { + // As a workaround to the behavior of `contains: layout` used in doc togglers, the + // notable traits popup is positioned using javascript. + // + // This means when the window is resized, we need to redo the layout. + const base = window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE; + const force_visible = base.NOTABLE_FORCE_VISIBLE; + hideNotable(); + if (force_visible) { + showNotable(base); + base.NOTABLE_FORCE_VISIBLE = true; + } + } }); function handleClick(id, f) { @@ -822,10 +835,80 @@ function loadCss(cssFileName) { }); }); + function showNotable(e) { + if (!window.NOTABLE_TRAITS) { + const data = document.getElementById("notable-traits-data"); + if (data) { + window.NOTABLE_TRAITS = JSON.parse(data.innerText); + } else { + throw new Error("showNotable() called on page without any notable traits!"); + } + } + if (window.CURRENT_NOTABLE_ELEMENT && window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE === e) { + // Make this function idempotent. + return; + } + hideNotable(); + const ty = e.getAttribute("data-ty"); + const tooltip = e.getElementsByClassName("notable-traits-tooltip")[0]; + const wrapper = document.createElement("div"); + wrapper.innerHTML = "<div class=\"docblock\">" + window.NOTABLE_TRAITS[ty] + "</div>"; + wrapper.className = "notable-traits-tooltiptext"; + tooltip.appendChild(wrapper); + const pos = wrapper.getBoundingClientRect(); + tooltip.removeChild(wrapper); + wrapper.style.top = (pos.top + window.scrollY) + "px"; + wrapper.style.left = (pos.left + window.scrollX) + "px"; + wrapper.style.width = pos.width + "px"; + const body = document.getElementsByTagName("body")[0]; + body.appendChild(wrapper); + window.CURRENT_NOTABLE_ELEMENT = wrapper; + window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE = e; + wrapper.onpointerleave = function(ev) { + // If this is a synthetic touch event, ignore it. A click event will be along shortly. + if (ev.pointerType !== "mouse") { + return; + } + if (!e.NOTABLE_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) { + hideNotable(); + } + }; + } + + function hideNotable() { + if (window.CURRENT_NOTABLE_ELEMENT) { + window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE = false; + const body = document.getElementsByTagName("body")[0]; + body.removeChild(window.CURRENT_NOTABLE_ELEMENT); + window.CURRENT_NOTABLE_ELEMENT = null; + } + } + onEachLazy(document.getElementsByClassName("notable-traits"), e => { e.onclick = function() { - this.getElementsByClassName("notable-traits-tooltiptext")[0] - .classList.toggle("force-tooltip"); + this.NOTABLE_FORCE_VISIBLE = this.NOTABLE_FORCE_VISIBLE ? false : true; + if (window.CURRENT_NOTABLE_ELEMENT && !this.NOTABLE_FORCE_VISIBLE) { + hideNotable(); + } else { + showNotable(this); + } + }; + e.onpointerenter = function(ev) { + // If this is a synthetic touch event, ignore it. A click event will be along shortly. + if (ev.pointerType !== "mouse") { + return; + } + showNotable(this); + }; + e.onpointerleave = function(ev) { + // If this is a synthetic touch event, ignore it. A click event will be along shortly. + if (ev.pointerType !== "mouse") { + return; + } + if (!this.NOTABLE_FORCE_VISIBLE && + !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT)) { + hideNotable(); + } }; }); diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index d04ec357c40..dd0531c5e70 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1593,7 +1593,6 @@ function initSearch(rawSearchIndex) { link.className = "result-" + type; link.href = item.href; - const wrapper = document.createElement("div"); const resultName = document.createElement("div"); resultName.className = "result-name"; @@ -1614,16 +1613,13 @@ function initSearch(rawSearchIndex) { resultName.insertAdjacentHTML( "beforeend", item.displayPath + "<span class=\"" + type + "\">" + name + extra + "</span>"); - wrapper.appendChild(resultName); + link.appendChild(resultName); const description = document.createElement("div"); description.className = "desc"; - const spanDesc = document.createElement("span"); - spanDesc.insertAdjacentHTML("beforeend", item.desc); + description.insertAdjacentHTML("beforeend", item.desc); - description.appendChild(spanDesc); - wrapper.appendChild(description); - link.appendChild(wrapper); + link.appendChild(description); output.appendChild(link); }); } else if (query.error === null) { diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 5e1c7e6f03e..95cc265f1bd 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -66,8 +66,7 @@ function setEvents(settingsElement) { updateLightAndDark(); - onEachLazy(settingsElement.getElementsByClassName("slider"), elem => { - const toggle = elem.previousElementSibling; + onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"), toggle => { const settingId = toggle.id; const settingValue = getSettingValue(settingId); if (settingValue !== null) { @@ -139,7 +138,6 @@ const checked = setting["default"] === true ? " checked" : ""; output += `<label class="toggle">\ <input type="checkbox" id="${js_data_name}"${checked}>\ - <span class="slider"></span>\ <span class="label">${setting_name}</span>\ </label>`; } @@ -154,7 +152,9 @@ * @return {HTMLElement} */ function buildSettingsPage() { - const themes = getVar("themes").split(","); + const theme_names = getVar("themes").split(",").filter(t => t); + theme_names.push("light", "dark", "ayu"); + const settings = [ { "name": "Use system theme", @@ -165,19 +165,19 @@ "name": "Theme", "js_name": "theme", "default": "light", - "options": themes, + "options": theme_names, }, { "name": "Preferred light theme", "js_name": "preferred-light-theme", "default": "light", - "options": themes, + "options": theme_names, }, { "name": "Preferred dark theme", "js_name": "preferred-dark-theme", "default": "dark", - "options": themes, + "options": theme_names, }, { "name": "Auto-hide item contents for large items", diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index b462a2c50f1..db2db83ca63 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -126,33 +126,29 @@ function getCurrentValue(name) { } } -function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { - const newHref = mainStyleElem.href.replace( - /\/rustdoc([^/]*)\.css/, "/" + newTheme + "$1" + ".css"); - +function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) { // If this new value comes from a system setting or from the previously // saved theme, no need to save it. if (saveTheme) { - updateLocalStorage("theme", newTheme); - } - - if (styleElem.href === newHref) { - return; + updateLocalStorage("theme", newThemeName); } - let found = false; if (savedHref.length === 0) { onEachLazy(document.getElementsByTagName("link"), el => { savedHref.push(el.href); }); } - onEach(savedHref, el => { - if (el === newHref) { - found = true; + const newHref = savedHref.find(url => { + const m = url.match(/static\.files\/(.*)-[a-f0-9]{16}\.css$/); + if (m && m[1] === newThemeName) { + return true; + } + const m2 = url.match(/\/([^/]*)\.css$/); + if (m2 && m2[1].startsWith(newThemeName)) { return true; } }); - if (found) { + if (newHref && newHref !== styleElem.href) { styleElem.href = newHref; } } diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 75f2b7e3570..afe920b7fa1 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -2,167 +2,128 @@ //! //! All the static files are included here for centralized access in case anything other than the //! HTML rendering code (say, the theme checker) needs to access one of these files. -//! -//! Note about types: CSS and JavaScript files are included as `&'static str` to allow for the -//! minifier to run on them. All other files are included as `&'static [u8]` so they can be -//! directly written to a `Write` handle. - -/// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page. -pub(crate) static RUSTDOC_CSS: &str = include_str!("static/css/rustdoc.css"); - -/// The file contents of `settings.css`, responsible for the items on the settings page. -pub(crate) static SETTINGS_CSS: &str = include_str!("static/css/settings.css"); - -/// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled. -pub(crate) static NOSCRIPT_CSS: &str = include_str!("static/css/noscript.css"); - -/// The file contents of `normalize.css`, included to even out standard elements between browser -/// implementations. -pub(crate) static NORMALIZE_CSS: &str = include_str!("static/css/normalize.css"); - -/// The file contents of `main.js`, which contains the core JavaScript used on documentation pages, -/// including search behavior and docblock folding, among others. -pub(crate) static MAIN_JS: &str = include_str!("static/js/main.js"); - -/// The file contents of `search.js`, which contains the search behavior. -pub(crate) static SEARCH_JS: &str = include_str!("static/js/search.js"); - -/// The file contents of `settings.js`, which contains the JavaScript used to handle the settings -/// page. -pub(crate) static SETTINGS_JS: &str = include_str!("static/js/settings.js"); - -/// The file contents of `storage.js`, which contains functionality related to browser Local -/// Storage, used to store documentation settings. -pub(crate) static STORAGE_JS: &str = include_str!("static/js/storage.js"); - -/// The file contents of `scraped-examples.js`, which contains functionality related to the -/// --scrape-examples flag that inserts automatically-found examples of usages of items. -pub(crate) static SCRAPE_EXAMPLES_JS: &str = include_str!("static/js/scrape-examples.js"); - -pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md"); - -/// The file contents of `wheel.svg`, the icon used for the settings button. -pub(crate) static WHEEL_SVG: &[u8] = include_bytes!("static/images/wheel.svg"); - -/// The file contents of `clipboard.svg`, the icon used for the "copy path" button. -pub(crate) static CLIPBOARD_SVG: &[u8] = include_bytes!("static/images/clipboard.svg"); - -/// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox. -pub(crate) static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/images/down-arrow.svg"); - -/// The file contents of `toggle-minus.svg`, the icon used for opened toggles. -pub(crate) static TOGGLE_MINUS_PNG: &[u8] = include_bytes!("static/images/toggle-minus.svg"); - -/// The file contents of `toggle-plus.svg`, the icon used for closed toggles. -pub(crate) static TOGGLE_PLUS_PNG: &[u8] = include_bytes!("static/images/toggle-plus.svg"); -/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation -/// output. -pub(crate) static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt"); +use rustc_data_structures::fx::FxHasher; +use std::hash::Hasher; +use std::path::{Path, PathBuf}; +use std::{fmt, str}; -/// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0. -pub(crate) static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt"); - -/// The contents of `LICENSE-MIT.txt`, the text of the MIT License. -pub(crate) static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt"); - -/// The contents of `rust-logo.svg`, the default icon of the documentation. -pub(crate) static RUST_LOGO_SVG: &[u8] = include_bytes!("static/images/rust-logo.svg"); - -/// The default documentation favicons (SVG and PNG fallbacks) -pub(crate) static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/images/favicon.svg"); -pub(crate) static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/images/favicon-16x16.png"); -pub(crate) static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/images/favicon-32x32.png"); - -/// The built-in themes given to every documentation site. -pub(crate) mod themes { - /// The "light" theme, selected by default when no setting is available. Used as the basis for - /// the `--check-theme` functionality. - pub(crate) static LIGHT: &str = include_str!("static/css/themes/light.css"); - - /// The "dark" theme. - pub(crate) static DARK: &str = include_str!("static/css/themes/dark.css"); - - /// The "ayu" theme. - pub(crate) static AYU: &str = include_str!("static/css/themes/ayu.css"); +pub(crate) struct StaticFile { + pub(crate) filename: PathBuf, + pub(crate) bytes: &'static [u8], } -/// Files related to the Fira Sans font. -pub(crate) mod fira_sans { - /// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2. - pub(crate) static REGULAR: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff2"); - - /// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2. - pub(crate) static MEDIUM: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff2"); - - /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font. - pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/FiraSans-LICENSE.txt"); +impl StaticFile { + fn new(filename: &str, bytes: &'static [u8]) -> StaticFile { + Self { filename: static_filename(filename, bytes), bytes } + } + + pub(crate) fn minified(&self) -> Vec<u8> { + if self.filename.ends_with(".css") { + minifier::css::minify(str::from_utf8(self.bytes).unwrap()).unwrap().to_string().into() + } else if self.filename.ends_with(".js") { + minifier::js::minify(str::from_utf8(self.bytes).unwrap()).to_string().into() + } else { + self.bytes.to_owned() + } + } + + pub(crate) fn output_filename(&self) -> &Path { + &self.filename + } } -/// Files related to the Source Serif 4 font. -pub(crate) mod source_serif_4 { - /// The file `SourceSerif4-Regular.ttf.woff2`, the Regular variant of the Source Serif 4 font in - /// woff2. - pub(crate) static REGULAR: &[u8] = - include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff2"); - - /// The file `SourceSerif4-Bold.ttf.woff2`, the Bold variant of the Source Serif 4 font in - /// woff2. - pub(crate) static BOLD: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff2"); - - /// The file `SourceSerif4-It.ttf.woff2`, the Italic variant of the Source Serif 4 font in - /// woff2. - pub(crate) static ITALIC: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff2"); - - /// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font. - pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/SourceSerif4-LICENSE.md"); +/// The Display implementation for a StaticFile outputs its filename. This makes it +/// convenient to interpolate static files into HTML templates. +impl fmt::Display for StaticFile { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.output_filename().display()) + } } -/// Files related to the Source Code Pro font. -pub(crate) mod source_code_pro { - /// The file `SourceCodePro-Regular.ttf.woff2`, the Regular variant of the Source Code Pro font - /// in woff2. - pub(crate) static REGULAR: &[u8] = - include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff2"); - - /// The file `SourceCodePro-Semibold.ttf.woff2`, the Semibold variant of the Source Code Pro - /// font in woff2. - pub(crate) static SEMIBOLD: &[u8] = - include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff2"); - - /// The file `SourceCodePro-It.ttf.woff2`, the Italic variant of the Source Code Pro font in - /// woff2. - pub(crate) static ITALIC: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff2"); +/// Insert the provided suffix into a filename just before the extension. +pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf { + // We use splitn vs Path::extension here because we might get a filename + // like `style.min.css` and we want to process that into + // `style-suffix.min.css`. Path::extension would just return `css` + // which would result in `style.min-suffix.css` which isn't what we + // want. + let (base, ext) = filename.split_once('.').unwrap(); + let filename = format!("{}{}.{}", base, suffix, ext); + filename.into() +} - /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font. - pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/SourceCodePro-LICENSE.txt"); +pub(crate) fn static_filename(filename: &str, contents: &[u8]) -> PathBuf { + let filename = filename.rsplit("/").next().unwrap(); + suffix_path(filename, &static_suffix(contents)) } -/// Files related to the Nanum Barun Gothic font. -/// -/// These files are used to avoid some legacy CJK serif fonts in Windows. -/// -/// Note that the Noto Sans KR font, which was used previously but was not very readable on Windows, -/// has been replaced by the Nanum Barun Gothic font. This is due to Windows' implementation of font -/// rendering that distorts OpenType fonts too much. -/// -/// The font files were generated with these commands: -/// -/// ```sh -/// pyftsubset NanumBarunGothic.ttf \ -/// --unicodes=U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \ -/// --output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2 -/// ``` -pub(crate) mod nanum_barun_gothic { - /// The file `NanumBarunGothic.ttf.woff2`, the Regular variant of the Nanum Barun Gothic font. - pub(crate) static REGULAR: &[u8] = include_bytes!("static/fonts/NanumBarunGothic.ttf.woff2"); +fn static_suffix(bytes: &[u8]) -> String { + let mut hasher = FxHasher::default(); + hasher.write(bytes); + format!("-{:016x}", hasher.finish()) +} - /// The file `NanumBarunGothic-LICENSE.txt`, the license text of the Nanum Barun Gothic font. - pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/NanumBarunGothic-LICENSE.txt"); +macro_rules! static_files { + ($($field:ident => $file_path:literal,)+) => { + pub(crate) struct StaticFiles { + $(pub $field: StaticFile,)+ + } + + pub(crate) static STATIC_FILES: std::sync::LazyLock<StaticFiles> = std::sync::LazyLock::new(|| StaticFiles { + $($field: StaticFile::new($file_path, include_bytes!($file_path)),)+ + }); + + pub(crate) fn for_each<E>(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> { + for sf in [ + $(&STATIC_FILES.$field,)+ + ] { + f(sf)? + } + Ok(()) + } + } } -/// Files related to the sidebar in rustdoc sources. -pub(crate) mod sidebar { - /// File script to handle sidebar. - pub(crate) static SOURCE_SCRIPT: &str = include_str!("static/js/source-script.js"); +static_files! { + rustdoc_css => "static/css/rustdoc.css", + settings_css => "static/css/settings.css", + noscript_css => "static/css/noscript.css", + normalize_css => "static/css/normalize.css", + main_js => "static/js/main.js", + search_js => "static/js/search.js", + settings_js => "static/js/settings.js", + source_script_js => "static/js/source-script.js", + storage_js => "static/js/storage.js", + scrape_examples_js => "static/js/scrape-examples.js", + wheel_svg => "static/images/wheel.svg", + clipboard_svg => "static/images/clipboard.svg", + down_arrow_svg => "static/images/down-arrow.svg", + toggle_minus_png => "static/images/toggle-minus.svg", + toggle_plus_png => "static/images/toggle-plus.svg", + copyright => "static/COPYRIGHT.txt", + license_apache => "static/LICENSE-APACHE.txt", + license_mit => "static/LICENSE-MIT.txt", + rust_logo_svg => "static/images/rust-logo.svg", + rust_favicon_svg => "static/images/favicon.svg", + rust_favicon_png_16 => "static/images/favicon-16x16.png", + rust_favicon_png_32 => "static/images/favicon-32x32.png", + theme_light_css => "static/css/themes/light.css", + theme_dark_css => "static/css/themes/dark.css", + theme_ayu_css => "static/css/themes/ayu.css", + fira_sans_regular => "static/fonts/FiraSans-Regular.woff2", + fira_sans_medium => "static/fonts/FiraSans-Medium.woff2", + fira_sans_license => "static/fonts/FiraSans-LICENSE.txt", + source_serif_4_regular => "static/fonts/SourceSerif4-Regular.ttf.woff2", + source_serif_4_bold => "static/fonts/SourceSerif4-Bold.ttf.woff2", + source_serif_4_italic => "static/fonts/SourceSerif4-It.ttf.woff2", + source_serif_4_license => "static/fonts/SourceSerif4-LICENSE.md", + source_code_pro_regular => "static/fonts/SourceCodePro-Regular.ttf.woff2", + source_code_pro_semibold => "static/fonts/SourceCodePro-Semibold.ttf.woff2", + source_code_pro_italic => "static/fonts/SourceCodePro-It.ttf.woff2", + source_code_pro_license => "static/fonts/SourceCodePro-LICENSE.txt", + nanum_barun_gothic_regular => "static/fonts/NanumBarunGothic.ttf.woff2", + nanum_barun_gothic_license => "static/fonts/NanumBarunGothic-LICENSE.txt", } + +pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/js/scrape-examples.js"); diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index c3238691687..4efcfc510a2 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -7,48 +7,44 @@ <meta name="description" content="{{page.description}}"> {#- -#} <meta name="keywords" content="{{page.keywords}}"> {#- -#} <title>{{page.title}}</title> {#- -#} - <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceSerif4-Regular.ttf.woff2"> {#- -#} - <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}FiraSans-Regular.woff2"> {#- -#} - <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}FiraSans-Medium.woff2"> {#- -#} - <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Regular.ttf.woff2"> {#- -#} - <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceSerif4-Bold.ttf.woff2"> {#- -#} - <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Semibold.ttf.woff2"> {#- -#} + <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_regular}}"> {#- -#} + <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_regular}}"> {#- -#} + <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_medium}}"> {#- -#} + <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_regular}}"> {#- -#} + <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_bold}}"> {#- -#} + <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_semibold}}"> {#- -#} <link rel="stylesheet" {# -#} - href="{{static_root_path|safe}}normalize{{page.resource_suffix}}.css"> {#- -#} + href="{{static_root_path|safe}}{{files.normalize_css}}"> {#- -#} <link rel="stylesheet" {# -#} - href="{{static_root_path|safe}}rustdoc{{page.resource_suffix}}.css" {# -#} + href="{{static_root_path|safe}}{{files.rustdoc_css}}" {# -#} id="mainThemeStyle"> {#- -#} + <link rel="stylesheet" id="themeStyle" href="{{static_root_path|safe}}{{files.theme_light_css}}"> {#- -#} + <link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_dark_css}}"> {#- -#} + <link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_ayu_css}}"> {#- -#} {%- for theme in themes -%} - <link rel="stylesheet" {# -#} - href="{{static_root_path|safe}}{{theme}}{{page.resource_suffix}}.css" {# -#} - {%- if theme == "light" -%} - id="themeStyle" - {%- else -%} - disabled - {%- endif -%} - > + <link rel="stylesheet" disabled href="{{page.root_path|safe}}{{theme}}{{page.resource_suffix}}.css"> {#- -#} {%- endfor -%} <script id="default-settings" {# -#} {% for (k, v) in layout.default_settings %} data-{{k}}="{{v}}" {%- endfor -%} ></script> {#- -#} - <script src="{{static_root_path|safe}}storage{{page.resource_suffix}}.js"></script> {#- -#} + <script src="{{static_root_path|safe}}{{files.storage_js}}"></script> {#- -#} {%- if page.css_class.contains("crate") -%} <script defer src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {#- -#} {%- else if page.css_class == "source" -%} - <script defer src="{{static_root_path|safe}}source-script{{page.resource_suffix}}.js"></script> {#- -#} + <script defer src="{{static_root_path|safe}}{{files.source_script_js}}"></script> {#- -#} <script defer src="{{page.root_path|safe}}source-files{{page.resource_suffix}}.js"></script> {#- -#} {%- else if !page.css_class.contains("mod") -%} <script defer src="sidebar-items{{page.resource_suffix}}.js"></script> {#- -#} {%- endif -%} - <script defer src="{{static_root_path|safe}}main{{page.resource_suffix}}.js"></script> {#- -#} + <script defer src="{{static_root_path|safe}}{{files.main_js}}"></script> {#- -#} {%- if layout.scrape_examples_extension -%} - <script defer src="{{page.root_path|safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#} + <script defer src="{{page.root_path|safe}}{{files.scrape_examples_js}}"></script> {#- -#} {%- endif -%} <noscript> {#- -#} <link rel="stylesheet" {# -#} - href="{{static_root_path|safe}}noscript{{page.resource_suffix}}.css"> {#- -#} + href="{{static_root_path|safe}}{{files.noscript_css}}"> {#- -#} </noscript> {#- -#} {%- if layout.css_file_extension.is_some() -%} <link rel="stylesheet" {# -#} @@ -58,11 +54,11 @@ <link rel="icon" href="{{layout.favicon}}"> {#- -#} {%- else -%} <link rel="alternate icon" type="image/png" {# -#} - href="{{static_root_path|safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#} + href="{{static_root_path|safe}}{{files.rust_favicon_png_16}}"> {#- -#} <link rel="alternate icon" type="image/png" {# -#} - href="{{static_root_path|safe}}favicon-32x32{{page.resource_suffix}}.png"> {#- -#} + href="{{static_root_path|safe}}{{files.rust_favicon_png_32}}"> {#- -#} <link rel="icon" type="image/svg+xml" {# -#} - href="{{static_root_path|safe}}favicon{{page.resource_suffix}}.svg"> {#- -#} + href="{{static_root_path|safe}}{{files.rust_favicon_svg}}"> {#- -#} {%- endif -%} {{- layout.external_html.in_header|safe -}} </head> {#- -#} @@ -81,7 +77,7 @@ {%- if !layout.logo.is_empty() -%} <img src="{{layout.logo}}" alt="logo"> {#- -#} {%- else -%} - <img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#} + <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#} {%- endif -%} </div> {#- -#} </a> {#- -#} @@ -95,7 +91,7 @@ {%- if !layout.logo.is_empty() %} <img src="{{layout.logo}}" alt="logo"> {#- -#} {%- else -%} - <img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#} + <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#} {%- endif -%} </div> {#- -#} </a> {#- -#} @@ -110,7 +106,7 @@ {%- if !layout.logo.is_empty() %} <img src="{{layout.logo}}" alt="logo"> {#- -#} {%- else -%} - <img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#} + <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#} {%- endif -%} </a> {#- -#} {%- endif -%} @@ -129,7 +125,7 @@ <div id="settings-menu" tabindex="-1"> {#- -#} <a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#} <img width="22" height="22" alt="Change settings" {# -#} - src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#} + src="{{static_root_path|safe}}{{files.wheel_svg}}"> {#- -#} </a> {#- -#} </div> {#- -#} </form> {#- -#} @@ -140,10 +136,14 @@ {{- layout.external_html.after_content|safe -}} <div id="rustdoc-vars" {# -#} data-root-path="{{page.root_path|safe}}" {# -#} + data-static-root-path="{{static_root_path|safe}}" {# -#} data-current-crate="{{layout.krate}}" {# -#} data-themes="{{themes|join(",") }}" {# -#} data-resource-suffix="{{page.resource_suffix}}" {# -#} data-rustdoc-version="{{rustdoc_version}}" {# -#} + data-search-js="{{files.search_js}}" {# -#} + data-settings-js="{{files.settings_js}}" {# -#} + data-settings-css="{{files.settings_css}}" {# -#} > {#- -#} </div> {#- -#} </body> {#- -#} diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html index e497b619366..611d124d4b9 100644 --- a/src/librustdoc/html/templates/print_item.html +++ b/src/librustdoc/html/templates/print_item.html @@ -7,7 +7,7 @@ {%- endfor -%} <a class="{{item_type}}" href="#">{{name}}</a> {#- -#} <button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"> {#- -#} - <img src="{{static_root_path|safe}}clipboard{{page.resource_suffix}}.svg" {# -#} + <img src="{{static_root_path|safe}}{{clipboard_svg}}" {# -#} width="19" height="18" {# -#} alt="Copy item path"> {#- -#} </button> {#- -#} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4962eb8f8e1..091a1ba70ca 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -100,13 +100,12 @@ impl JsonRenderer<'_> { } } - fn convert_visibility(&self, v: clean::Visibility) -> Visibility { - use clean::Visibility::*; + fn convert_visibility(&self, v: Option<ty::Visibility<DefId>>) -> Visibility { match v { - Public => Visibility::Public, - Inherited => Visibility::Default, - Restricted(did) if did.is_crate_root() => Visibility::Crate, - Restricted(did) => Visibility::Restricted { + None => Visibility::Default, + Some(ty::Visibility::Public) => Visibility::Public, + Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate, + Some(ty::Visibility::Restricted(did)) => Visibility::Restricted { parent: from_item_id(did.into(), self.tcx), path: self.tcx.def_path(did).to_string_no_crate_verbose(), }, @@ -284,7 +283,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: Some(default.expr(tcx)) } } TyAssocTypeItem(g, b) => ItemEnum::AssocType { - generics: (*g).into_tcx(tcx), + generics: g.into_tcx(tcx), bounds: b.into_tcx(tcx), default: None, }, @@ -486,7 +485,7 @@ impl FromWithTcx<clean::Type> for Type { BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))), Tuple(t) => Type::Tuple(t.into_tcx(tcx)), Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))), - Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s }, + Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s.to_string() }, ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4cf9435d9c8..1982c066b6f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -469,9 +469,6 @@ fn opts() -> Vec<RustcOptGroup> { stable("json", |o| { o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG") }), - unstable("disable-minification", |o| { - o.optflagmulti("", "disable-minification", "Disable minification applied on JS files") - }), stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "LINT")), stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "LINT")), stable("force-warn", |o| o.optmulti("", "force-warn", "Set lint force-warn", "LINT")), @@ -610,6 +607,7 @@ fn opts() -> Vec<RustcOptGroup> { ) }), // deprecated / removed options + unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")), stable("plugin-path", |o| { o.optmulti( "", diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 0bd0dbbeb70..37a28b6b7bd 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -402,6 +402,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { }) .and_then(|self_id| match tcx.def_kind(self_id) { DefKind::Impl => self.def_id_to_res(self_id), + DefKind::Use => None, def_kind => Some(Res::Def(def_kind, self_id)), }) } @@ -1772,7 +1773,6 @@ fn resolution_failure( // Otherwise, it must be an associated item or variant let res = partial_res.expect("None case was handled by `last_found_module`"); - let name = res.name(tcx); let kind = match res { Res::Def(kind, _) => Some(kind), Res::Primitive(_) => None, @@ -1814,6 +1814,7 @@ fn resolution_failure( } else { "associated item" }; + let name = res.name(tcx); let note = format!( "the {} `{}` has no {} named `{}`", res.descr(), diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index b2047360ccd..995fb5dcc1c 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -1,6 +1,6 @@ //! A collection of utility functions for the `strip_*` passes. use rustc_hir::def_id::DefId; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{TyCtxt, Visibility}; use rustc_span::symbol::sym; use std::mem; @@ -81,13 +81,13 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { } clean::StructFieldItem(..) => { - if !i.visibility(self.tcx).is_public() { + if i.visibility(self.tcx) != Some(Visibility::Public) { return Some(strip_item(i)); } } clean::ModuleItem(..) => { - if i.item_id.is_local() && !i.visibility(self.tcx).is_public() { + if i.item_id.is_local() && i.visibility(self.tcx) != Some(Visibility::Public) { debug!("Stripper: stripping module {:?}", i.name); let old = mem::replace(&mut self.update_retained, false); let ret = strip_item(self.fold_item_recur(i)); @@ -246,7 +246,7 @@ impl<'tcx> DocFolder for ImportStripper<'tcx> { fn fold_item(&mut self, i: Item) -> Option<Item> { match *i.kind { clean::ExternCrateItem { .. } | clean::ImportItem(..) - if !i.visibility(self.tcx).is_public() => + if i.visibility(self.tcx) != Some(Visibility::Public) => { None } diff --git a/src/llvm-project b/src/llvm-project -Subproject 2a2ea6b49e79325e0d10d33fac2b10ea3bebcc7 +Subproject a1232c451fc27173f8718e05d174b2503ca0b60 diff --git a/src/test/assembly/strict_provenance.rs b/src/test/assembly/strict_provenance.rs new file mode 100644 index 00000000000..01f1957d5f6 --- /dev/null +++ b/src/test/assembly/strict_provenance.rs @@ -0,0 +1,37 @@ +// assembly-output: emit-asm +// compile-flags: -Copt-level=1 +// only-x86_64 +// min-llvm-version: 15.0 +#![crate_type = "rlib"] + +// CHECK-LABEL: old_style +// CHECK: movq %{{.*}}, %rax +// CHECK: orq $1, %rax +// CHECK: retq +#[no_mangle] +pub fn old_style(a: *mut u8) -> *mut u8 { + (a as usize | 1) as *mut u8 +} + +// CHECK-LABEL: cheri_compat +// CHECK: movq %{{.*}}, %rax +// CHECK: orq $1, %rax +// CHECK: retq +#[no_mangle] +pub fn cheri_compat(a: *mut u8) -> *mut u8 { + let old = a as usize; + let new = old | 1; + let diff = new.wrapping_sub(old); + a.wrapping_add(diff) +} + +// CHECK-LABEL: definitely_not_a_null_pointer +// CHECK: movq %{{.*}}, %rax +// CHECK: orq $1, %rax +// CHECK: retq +#[no_mangle] +pub fn definitely_not_a_null_pointer(a: *mut u8) -> *mut u8 { + let old = a as usize; + let new = old | 1; + a.wrapping_sub(old).wrapping_add(new) +} diff --git a/src/test/codegen/abi-efiapi.rs b/src/test/codegen/abi-efiapi.rs index b4fda5f8c84..9061d7432a3 100644 --- a/src/test/codegen/abi-efiapi.rs +++ b/src/test/codegen/abi-efiapi.rs @@ -27,7 +27,7 @@ trait Copy { } //x86_64: define win64cc void @has_efiapi //i686: define void @has_efiapi //aarch64: define dso_local void @has_efiapi -//arm: define dso_local void @has_efiapi +//arm: define dso_local arm_aapcscc void @has_efiapi //riscv: define dso_local void @has_efiapi #[no_mangle] pub extern "efiapi" fn has_efiapi() {} diff --git a/src/test/codegen/auxiliary/static_dllimport_aux.rs b/src/test/codegen/auxiliary/static_dllimport_aux.rs new file mode 100644 index 00000000000..afb0dc42f44 --- /dev/null +++ b/src/test/codegen/auxiliary/static_dllimport_aux.rs @@ -0,0 +1,13 @@ +use std::sync::atomic::{AtomicPtr, Ordering}; + +#[inline(always)] +pub fn memrchr() { + fn detect() {} + + static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ()); + + unsafe { + let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst); + std::mem::transmute::<*mut (), fn()>(fun)() + } +} diff --git a/src/test/codegen/avr/avr-func-addrspace.rs b/src/test/codegen/avr/avr-func-addrspace.rs index a038dfe76f7..cbbcfad3ef4 100644 --- a/src/test/codegen/avr/avr-func-addrspace.rs +++ b/src/test/codegen/avr/avr-func-addrspace.rs @@ -19,6 +19,8 @@ pub trait Sized { } pub trait Copy { } #[lang = "receiver"] pub trait Receiver { } +#[lang = "tuple_trait"] +pub trait Tuple { } pub struct Result<T, E> { _a: T, _b: E } @@ -29,7 +31,7 @@ impl Copy for &usize {} pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {} #[lang = "fn_once"] -pub trait FnOnce<Args> { +pub trait FnOnce<Args: Tuple> { #[lang = "fn_once_output"] type Output; @@ -37,24 +39,16 @@ pub trait FnOnce<Args> { } #[lang = "fn_mut"] -pub trait FnMut<Args> : FnOnce<Args> { +pub trait FnMut<Args: Tuple> : FnOnce<Args> { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } #[lang = "fn"] -pub trait Fn<Args>: FnOnce<Args> { +pub trait Fn<Args: Tuple>: FnOnce<Args> { /// Performs the call operation. extern "rust-call" fn call(&self, args: Args) -> Self::Output; } -impl<'a, A, R> FnOnce<A> for &'a fn(A) -> R { - type Output = R; - - extern "rust-call" fn call_once(self, args: A) -> R { - (*self)(args) - } -} - pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box; pub static mut STORAGE_BAR: u32 = 12; diff --git a/src/test/codegen/enum-match.rs b/src/test/codegen/enum-match.rs new file mode 100644 index 00000000000..efab189fd7b --- /dev/null +++ b/src/test/codegen/enum-match.rs @@ -0,0 +1,112 @@ +// compile-flags: -Copt-level=1 +// only-x86_64 + +#![crate_type = "lib"] + +// Check each of the 3 cases for `codegen_get_discr`. + +// Case 0: One tagged variant. +pub enum Enum0 { + A(bool), + B, +} + +// CHECK: define i8 @match0{{.*}} +// CHECK-NEXT: start: +// CHECK-NEXT: %1 = icmp eq i8 %0, 2 +// CHECK-NEXT: %2 = and i8 %0, 1 +// CHECK-NEXT: %.0 = select i1 %1, i8 13, i8 %2 +#[no_mangle] +pub fn match0(e: Enum0) -> u8 { + use Enum0::*; + match e { + A(b) => b as u8, + B => 13, + } +} + +// Case 1: Niche values are on a boundary for `range`. +pub enum Enum1 { + A(bool), + B, + C, +} + +// CHECK: define i8 @match1{{.*}} +// CHECK-NEXT: start: +// CHECK-NEXT: %1 = icmp ugt i8 %0, 1 +// CHECK-NEXT: %2 = zext i8 %0 to i64 +// CHECK-NEXT: %3 = add nsw i64 %2, -1 +// CHECK-NEXT: %_2 = select i1 %1, i64 %3, i64 0 +// CHECK-NEXT: switch i64 %_2, label {{.*}} [ +#[no_mangle] +pub fn match1(e: Enum1) -> u8 { + use Enum1::*; + match e { + A(b) => b as u8, + B => 13, + C => 100, + } +} + +// Case 2: Special cases don't apply. +pub enum X { + _2=2, _3, _4, _5, _6, _7, _8, _9, _10, _11, + _12, _13, _14, _15, _16, _17, _18, _19, _20, + _21, _22, _23, _24, _25, _26, _27, _28, _29, + _30, _31, _32, _33, _34, _35, _36, _37, _38, + _39, _40, _41, _42, _43, _44, _45, _46, _47, + _48, _49, _50, _51, _52, _53, _54, _55, _56, + _57, _58, _59, _60, _61, _62, _63, _64, _65, + _66, _67, _68, _69, _70, _71, _72, _73, _74, + _75, _76, _77, _78, _79, _80, _81, _82, _83, + _84, _85, _86, _87, _88, _89, _90, _91, _92, + _93, _94, _95, _96, _97, _98, _99, _100, _101, + _102, _103, _104, _105, _106, _107, _108, _109, + _110, _111, _112, _113, _114, _115, _116, _117, + _118, _119, _120, _121, _122, _123, _124, _125, + _126, _127, _128, _129, _130, _131, _132, _133, + _134, _135, _136, _137, _138, _139, _140, _141, + _142, _143, _144, _145, _146, _147, _148, _149, + _150, _151, _152, _153, _154, _155, _156, _157, + _158, _159, _160, _161, _162, _163, _164, _165, + _166, _167, _168, _169, _170, _171, _172, _173, + _174, _175, _176, _177, _178, _179, _180, _181, + _182, _183, _184, _185, _186, _187, _188, _189, + _190, _191, _192, _193, _194, _195, _196, _197, + _198, _199, _200, _201, _202, _203, _204, _205, + _206, _207, _208, _209, _210, _211, _212, _213, + _214, _215, _216, _217, _218, _219, _220, _221, + _222, _223, _224, _225, _226, _227, _228, _229, + _230, _231, _232, _233, _234, _235, _236, _237, + _238, _239, _240, _241, _242, _243, _244, _245, + _246, _247, _248, _249, _250, _251, _252, _253, +} + +pub enum Enum2 { + A(X), + B, + C, + D, + E, +} + +// CHECK: define i8 @match2{{.*}} +// CHECK-NEXT: start: +// CHECK-NEXT: %1 = add i8 %0, 2 +// CHECK-NEXT: %2 = zext i8 %1 to i64 +// CHECK-NEXT: %3 = icmp ult i8 %1, 4 +// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1 +// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0 +// CHECK-NEXT: switch i64 %_2, label {{.*}} [ +#[no_mangle] +pub fn match2(e: Enum2) -> u8 { + use Enum2::*; + match e { + A(b) => b as u8, + B => 13, + C => 100, + D => 200, + E => 250, + } +} diff --git a/src/test/codegen/ffi-const.rs b/src/test/codegen/ffi-const.rs index d9cfa5429b5..93720503480 100644 --- a/src/test/codegen/ffi-const.rs +++ b/src/test/codegen/ffi-const.rs @@ -7,6 +7,7 @@ pub fn bar() { unsafe { foo() } } extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] - // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readnone{{.*}} } + // The attribute changed from `readnone` to `memory(none)` with LLVM 16.0. + // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readnone|memory\(none\)}}{{.*}} } #[ffi_const] pub fn foo(); } diff --git a/src/test/codegen/ffi-pure.rs b/src/test/codegen/ffi-pure.rs index 5bdb2ee912a..2ed73581358 100644 --- a/src/test/codegen/ffi-pure.rs +++ b/src/test/codegen/ffi-pure.rs @@ -7,6 +7,7 @@ pub fn bar() { unsafe { foo() } } extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] - // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readonly{{.*}} } + // The attribute changed from `readonly` to `memory(read)` with LLVM 16.0. + // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readonly|memory\(read\)}}{{.*}} } #[ffi_pure] pub fn foo(); } diff --git a/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs new file mode 100644 index 00000000000..0b6ab4f7ecb --- /dev/null +++ b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs @@ -0,0 +1,15 @@ +// compile-flags: -O -C lto=thin -C prefer-dynamic=no +// only-windows +// aux-build:static_dllimport_aux.rs + +// Test that on Windows, when performing ThinLTO, we do not mark cross-crate static items with +// dllimport because lld does not fix the symbol names for us. + +extern crate static_dllimport_aux; + +// CHECK-LABEL: @{{.+}}CROSS_CRATE_STATIC_ITEM{{.+}} = +// CHECK-SAME: external local_unnamed_addr global %"{{.+}}AtomicPtr + +pub fn main() { + static_dllimport_aux::memrchr(); +} diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 07d33be2a07..9e82f071469 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -47,7 +47,6 @@ // gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13} // gdbr-check:$15 = "Hello, World!" - // === LLDB TESTS ================================================================================== // lldb-command:run @@ -96,7 +95,6 @@ // lldbg-check:[...]$12 = 3.5 // lldbr-check:(f64) f64 = 3.5 - // === CDB TESTS =================================================================================== // cdb-command:g @@ -131,7 +129,7 @@ // cdb-command:.enable_unicode 1 // FIXME(#88840): The latest version of the Windows SDK broke the visualizer for str. // cdb-command:dx s -// cdb-check:s : [...] [Type: str] +// cdb-check:s : [...] [Type: ref$<str$>] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] @@ -156,4 +154,6 @@ fn main() { _zzz(); // #break } -fn _zzz() {()} +fn _zzz() { + () +} diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 7f1be6f2784..d66e4c660f7 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -116,13 +116,13 @@ // cdb-check: niche_w_fields_3_niche5,d : F [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields3>] // cdb-command: dx -r3 niche_w_fields_std_result_ok,d -// cdb-check: niche_w_fields_std_result_ok,d : Ok [Type: enum2$<core::result::Result<alloc::boxed::Box<slice$<u8>,alloc::alloc::Global>,u64> >] -// cdb-check: [+0x[...]] __0 [Type: alloc::boxed::Box<slice$<u8>,alloc::alloc::Global>] +// cdb-check: niche_w_fields_std_result_ok,d : Ok [Type: enum2$<core::result::Result<alloc::boxed::Box<slice2$<u8>,alloc::alloc::Global>,u64> >] +// cdb-check: [+0x[...]] __0 [Type: alloc::boxed::Box<slice2$<u8>,alloc::alloc::Global>] // cdb-check: [+0x[...]] data_ptr : [...] // cdb-check: [+0x[...]] length : 3 [...] // cdb-command: dx -r3 niche_w_fields_std_result_err,d -// cdb-check: niche_w_fields_std_result_err,d : Err [Type: enum2$<core::result::Result<alloc::boxed::Box<slice$<u8>,alloc::alloc::Global>,u64> >] +// cdb-check: niche_w_fields_std_result_err,d : Err [Type: enum2$<core::result::Result<alloc::boxed::Box<slice2$<u8>,alloc::alloc::Global>,u64> >] // cdb-check: [+0x[...]] __0 : 789 [Type: unsigned __int64] // cdb-command: dx -r2 arbitrary_discr1,d diff --git a/src/test/debuginfo/msvc-scalarpair-params.rs b/src/test/debuginfo/msvc-scalarpair-params.rs index 9630952cbaa..ae67f698151 100644 --- a/src/test/debuginfo/msvc-scalarpair-params.rs +++ b/src/test/debuginfo/msvc-scalarpair-params.rs @@ -38,14 +38,14 @@ // cdb-command: g // cdb-command: dx s -// cdb-check:s : "this is a static str" [Type: str] +// cdb-check:s : "this is a static str" [Type: ref$<str$>] // cdb-check: [len] : 0x14 [Type: unsigned [...]] // cdb-check: [chars] // cdb-command: g // cdb-command: dx s -// cdb-check:s : { len=0x5 } [Type: slice$<u8>] +// cdb-check:s : { len=0x5 } [Type: ref$<slice2$<u8> >] // cdb-check: [len] : 0x5 [Type: unsigned [...]] // cdb-check: [0] : 0x1 [Type: unsigned char] // cdb-check: [1] : 0x2 [Type: unsigned char] diff --git a/src/test/debuginfo/mutex.rs b/src/test/debuginfo/mutex.rs index 314ba40b0e3..61ec6a81243 100644 --- a/src/test/debuginfo/mutex.rs +++ b/src/test/debuginfo/mutex.rs @@ -10,7 +10,7 @@ // // cdb-command:dx m,d // cdb-check:m,d [Type: std::sync::mutex::Mutex<i32>] -// cdb-check: [...] inner [Type: std::sys_common::mutex::MovableMutex] +// cdb-check: [...] inner [Type: std::sys::windows::locks::mutex::Mutex] // cdb-check: [...] poison [Type: std::sync::poison::Flag] // cdb-check: [...] data : 0 [Type: core::cell::UnsafeCell<i32>] diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index a51b37205e8..d8c6344e0b6 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -69,7 +69,7 @@ // cdb-command: g // cdb-command: dx slice,d -// cdb-check:slice,d : { len=4 } [Type: slice$<i32>] +// cdb-check:slice,d : { len=4 } [Type: ref$<slice2$<i32> >] // cdb-check: [len] : 4 [Type: [...]] // cdb-check: [0] : 0 [Type: int] // cdb-check: [1] : 1 [Type: int] @@ -86,7 +86,7 @@ // cdb-check: [3] : 7 [Type: unsigned __int64] // cdb-command: dx str_slice -// cdb-check:str_slice : "IAMA string slice!" [Type: str] +// cdb-check:str_slice : "IAMA string slice!" [Type: ref$<str$>] // cdb-command: dx string // cdb-check:string : "IAMA string!" [Type: [...]::String] diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs index c05c565d956..5d5492d7217 100644 --- a/src/test/debuginfo/rc_arc.rs +++ b/src/test/debuginfo/rc_arc.rs @@ -57,7 +57,7 @@ // cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell<usize>] // cdb-command:dx slice_rc,d -// cdb-check:slice_rc,d : { len=3 } [Type: alloc::rc::Rc<slice$<u32> >] +// cdb-check:slice_rc,d : { len=3 } [Type: alloc::rc::Rc<slice2$<u32> >] // cdb-check: [Length] : 3 [Type: [...]] // cdb-check: [Reference count] : 41 [Type: core::cell::Cell<usize>] // cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell<usize>] @@ -66,7 +66,7 @@ // cdb-check: [2] : 3 [Type: u32] // cdb-command:dx slice_rc_weak,d -// cdb-check:slice_rc_weak,d : { len=3 } [Type: alloc::rc::Weak<slice$<u32> >] +// cdb-check:slice_rc_weak,d : { len=3 } [Type: alloc::rc::Weak<slice2$<u32> >] // cdb-check: [Length] : 3 [Type: [...]] // cdb-check: [Reference count] : 41 [Type: core::cell::Cell<usize>] // cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell<usize>] @@ -85,7 +85,7 @@ // cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize] // cdb-command:dx slice_arc,d -// cdb-check:slice_arc,d : { len=3 } [Type: alloc::sync::Arc<slice$<u32> >] +// cdb-check:slice_arc,d : { len=3 } [Type: alloc::sync::Arc<slice2$<u32> >] // cdb-check: [Length] : 3 [Type: [...]] // cdb-check: [Reference count] : 61 [Type: core::sync::atomic::AtomicUsize] // cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize] @@ -94,7 +94,7 @@ // cdb-check: [2] : 6 [Type: u32] // cdb-command:dx slice_arc_weak,d -// cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::sync::Weak<slice$<u32> >] +// cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::sync::Weak<slice2$<u32> >] // cdb-check: [Length] : 3 [Type: [...]] // cdb-check: [Reference count] : 61 [Type: core::sync::atomic::AtomicUsize] // cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize] diff --git a/src/test/debuginfo/result-types.rs b/src/test/debuginfo/result-types.rs index cdac47a784d..f1944fa38d2 100644 --- a/src/test/debuginfo/result-types.rs +++ b/src/test/debuginfo/result-types.rs @@ -7,12 +7,12 @@ // cdb-command: g // cdb-command: dx x,d -// cdb-check:x,d : Ok [Type: enum2$<core::result::Result<i32,str> >] +// cdb-check:x,d : Ok [Type: enum2$<core::result::Result<i32,ref$<str$> > >] // cdb-check: [...] __0 : -3 [Type: int] // cdb-command: dx y -// cdb-check:y : Err [Type: enum2$<core::result::Result<i32,str> >] -// cdb-check: [...] __0 : "Some error message" [Type: str] +// cdb-check:y : Err [Type: enum2$<core::result::Result<i32,ref$<str$> > >] +// cdb-check: [...] __0 : "Some error message" [Type: ref$<str$>] fn main() { let x: Result<i32, &str> = Ok(-3); diff --git a/src/test/debuginfo/rwlock-read.rs b/src/test/debuginfo/rwlock-read.rs index ed9aae16b0d..bc42f92f053 100644 --- a/src/test/debuginfo/rwlock-read.rs +++ b/src/test/debuginfo/rwlock-read.rs @@ -16,7 +16,7 @@ // cdb-command:dx r // cdb-check:r [Type: std::sync::rwlock::RwLockReadGuard<i32>] // cdb-check: [...] data : NonNull([...]: 0) [Type: core::ptr::non_null::NonNull<i32>] -// cdb-check: [...] inner_lock : [...] [Type: std::sys_common::rwlock::MovableRwLock *] +// cdb-check: [...] inner_lock : [...] [Type: std::sys::windows::locks::rwlock::RwLock *] #[allow(unused_variables)] diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index 9cc99d7767c..d7b79a845d2 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -95,7 +95,7 @@ // gdb-check:type = &[usize] // gdb-command:whatis slice2 -// gdb-check:type = &[type_names::mod1::Enum2] +// gdb-check:type = &mut [type_names::mod1::Enum2] // TRAITS // gdb-command:whatis box_trait @@ -218,8 +218,8 @@ // cdb-check:struct alloc::vec::Vec<usize,alloc::alloc::Global> vec1 = [...] // cdb-check:struct alloc::vec::Vec<enum2$<type_names::mod1::Enum2>,alloc::alloc::Global> vec2 = [...] // cdb-command:dv /t slice* -// cdb-check:struct slice$<usize> slice1 = [...] -// cdb-check:struct slice$<enum2$<type_names::mod1::Enum2> > slice2 = [...] +// cdb-check:struct ref$<slice2$<usize> > slice1 = [...] +// cdb-check:struct ref_mut$<slice2$<enum2$<type_names::mod1::Enum2> > > slice2 = [...] // TRAITS // cdb-command:dv /t *_trait @@ -417,8 +417,8 @@ fn main() { let vec1 = vec![0_usize, 2, 3]; let slice1 = &*vec1; - let vec2 = vec![mod1::Enum2::Variant2(Struct1)]; - let slice2 = &*vec2; + let mut vec2 = vec![mod1::Enum2::Variant2(Struct1)]; + let slice2 = &mut *vec2; // Trait Objects let box_trait = Box::new(0_isize) as Box<dyn Trait1>; diff --git a/src/test/debuginfo/unsized.rs b/src/test/debuginfo/unsized.rs index 7cb0002ca51..b1ec9b06830 100644 --- a/src/test/debuginfo/unsized.rs +++ b/src/test/debuginfo/unsized.rs @@ -32,13 +32,13 @@ // cdb-command: g // cdb-command:dx a -// cdb-check:a [Type: ref$<unsized::Foo<slice$<u8> > >] -// cdb-check: [+0x000] data_ptr : 0x[...] [Type: unsized::Foo<slice$<u8> > *] +// cdb-check:a [Type: ref$<unsized::Foo<slice2$<u8> > >] +// cdb-check: [+0x000] data_ptr : 0x[...] [Type: unsized::Foo<slice2$<u8> > *] // cdb-check: [...] length : 0x4 [Type: unsigned [...]int[...] // cdb-command:dx b -// cdb-check:b [Type: ref$<unsized::Foo<unsized::Foo<slice$<u8> > > >] -// cdb-check: [+0x000] data_ptr : 0x[...] [Type: unsized::Foo<unsized::Foo<slice$<u8> > > *] +// cdb-check:b [Type: ref$<unsized::Foo<unsized::Foo<slice2$<u8> > > >] +// cdb-check: [+0x000] data_ptr : 0x[...] [Type: unsized::Foo<unsized::Foo<slice2$<u8> > > *] // cdb-check: [...] length : 0x4 [Type: unsigned [...]int[...] // cdb-command:dx c @@ -53,8 +53,8 @@ // cdb-check:[...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[3]] // cdb-command:dx tuple_slice -// cdb-check:tuple_slice [Type: ref$<tuple$<i32,i32,slice$<i32> > >] -// cdb-check: [+0x000] data_ptr : 0x[...] [Type: tuple$<i32,i32,slice$<i32> > *] +// cdb-check:tuple_slice [Type: ref$<tuple$<i32,i32,slice2$<i32> > >] +// cdb-check: [+0x000] data_ptr : 0x[...] [Type: tuple$<i32,i32,slice2$<i32> > *] // cdb-check: [...] length : 0x2 [Type: unsigned [...]int[...] // cdb-command:dx tuple_dyn diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs index ff79acc7f63..3121abbea36 100644 --- a/src/test/incremental/hashes/extern_mods.rs +++ b/src/test/incremental/hashes/extern_mods.rs @@ -128,7 +128,7 @@ extern "C" { // Change calling convention --------------------------------------------------- #[cfg(any(cfail1,cfail4))] extern "C" { - pub fn change_calling_convention(c: i32); + pub fn change_calling_convention(c: (i32,)); } #[cfg(not(any(cfail1,cfail4)))] @@ -137,7 +137,7 @@ extern "C" { #[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "rust-call" { - pub fn change_calling_convention(c: i32); + pub fn change_calling_convention(c: (i32,)); } // Make function public -------------------------------------------------------- diff --git a/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir index d41a66871cc..5f8b2f9312b 100644 --- a/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -1,115 +1,115 @@ // MIR for `address_of_reborrow` after SimplifyCfg-initial | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address-of.rs:7:5: 7:18, inferred_ty: *const [i32; 10] -| 1: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address-of.rs:9:5: 9:25, inferred_ty: *const dyn std::marker::Send -| 2: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address-of.rs:13:12: 13:20, inferred_ty: *const [i32; 10] -| 3: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address-of.rs:13:12: 13:20, inferred_ty: *const [i32; 10] -| 4: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address-of.rs:14:12: 14:28, inferred_ty: *const [i32; 10] -| 5: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address-of.rs:14:12: 14:28, inferred_ty: *const [i32; 10] -| 6: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address-of.rs:15:12: 15:27, inferred_ty: *const dyn std::marker::Send -| 7: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address-of.rs:15:12: 15:27, inferred_ty: *const dyn std::marker::Send -| 8: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address-of.rs:16:12: 16:24, inferred_ty: *const [i32] -| 9: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address-of.rs:16:12: 16:24, inferred_ty: *const [i32] -| 10: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address-of.rs:18:5: 18:18, inferred_ty: *const [i32; 10] -| 11: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address-of.rs:20:5: 20:25, inferred_ty: *const dyn std::marker::Send -| 12: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address-of.rs:23:12: 23:20, inferred_ty: *const [i32; 10] -| 13: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address-of.rs:23:12: 23:20, inferred_ty: *const [i32; 10] -| 14: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address-of.rs:24:12: 24:28, inferred_ty: *const [i32; 10] -| 15: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address-of.rs:24:12: 24:28, inferred_ty: *const [i32; 10] -| 16: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address-of.rs:25:12: 25:27, inferred_ty: *const dyn std::marker::Send -| 17: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address-of.rs:25:12: 25:27, inferred_ty: *const dyn std::marker::Send -| 18: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address-of.rs:26:12: 26:24, inferred_ty: *const [i32] -| 19: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address-of.rs:26:12: 26:24, inferred_ty: *const [i32] -| 20: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) }, span: $DIR/address-of.rs:28:5: 28:16, inferred_ty: *mut [i32; 10] -| 21: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) }, span: $DIR/address-of.rs:30:5: 30:23, inferred_ty: *mut dyn std::marker::Send -| 22: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) }, span: $DIR/address-of.rs:33:12: 33:18, inferred_ty: *mut [i32; 10] -| 23: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) }, span: $DIR/address-of.rs:33:12: 33:18, inferred_ty: *mut [i32; 10] -| 24: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) }, span: $DIR/address-of.rs:34:12: 34:26, inferred_ty: *mut [i32; 10] -| 25: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) }, span: $DIR/address-of.rs:34:12: 34:26, inferred_ty: *mut [i32; 10] -| 26: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) }, span: $DIR/address-of.rs:35:12: 35:25, inferred_ty: *mut dyn std::marker::Send -| 27: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) }, span: $DIR/address-of.rs:35:12: 35:25, inferred_ty: *mut dyn std::marker::Send -| 28: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32]) }, span: $DIR/address-of.rs:36:12: 36:22, inferred_ty: *mut [i32] -| 29: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32]) }, span: $DIR/address-of.rs:36:12: 36:22, inferred_ty: *mut [i32] +| 0: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:7:5: 7:18, inferred_ty: *const [i32; 10] +| 1: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:9:5: 9:25, inferred_ty: *const dyn std::marker::Send +| 2: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:13:12: 13:20, inferred_ty: *const [i32; 10] +| 3: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:13:12: 13:20, inferred_ty: *const [i32; 10] +| 4: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address_of.rs:14:12: 14:28, inferred_ty: *const [i32; 10] +| 5: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address_of.rs:14:12: 14:28, inferred_ty: *const [i32; 10] +| 6: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:15:12: 15:27, inferred_ty: *const dyn std::marker::Send +| 7: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:15:12: 15:27, inferred_ty: *const dyn std::marker::Send +| 8: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address_of.rs:16:12: 16:24, inferred_ty: *const [i32] +| 9: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address_of.rs:16:12: 16:24, inferred_ty: *const [i32] +| 10: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:18:5: 18:18, inferred_ty: *const [i32; 10] +| 11: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:20:5: 20:25, inferred_ty: *const dyn std::marker::Send +| 12: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:23:12: 23:20, inferred_ty: *const [i32; 10] +| 13: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:23:12: 23:20, inferred_ty: *const [i32; 10] +| 14: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address_of.rs:24:12: 24:28, inferred_ty: *const [i32; 10] +| 15: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address_of.rs:24:12: 24:28, inferred_ty: *const [i32; 10] +| 16: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:25:12: 25:27, inferred_ty: *const dyn std::marker::Send +| 17: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:25:12: 25:27, inferred_ty: *const dyn std::marker::Send +| 18: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address_of.rs:26:12: 26:24, inferred_ty: *const [i32] +| 19: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address_of.rs:26:12: 26:24, inferred_ty: *const [i32] +| 20: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) }, span: $DIR/address_of.rs:28:5: 28:16, inferred_ty: *mut [i32; 10] +| 21: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) }, span: $DIR/address_of.rs:30:5: 30:23, inferred_ty: *mut dyn std::marker::Send +| 22: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) }, span: $DIR/address_of.rs:33:12: 33:18, inferred_ty: *mut [i32; 10] +| 23: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) }, span: $DIR/address_of.rs:33:12: 33:18, inferred_ty: *mut [i32; 10] +| 24: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) }, span: $DIR/address_of.rs:34:12: 34:26, inferred_ty: *mut [i32; 10] +| 25: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) }, span: $DIR/address_of.rs:34:12: 34:26, inferred_ty: *mut [i32; 10] +| 26: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) }, span: $DIR/address_of.rs:35:12: 35:25, inferred_ty: *mut dyn std::marker::Send +| 27: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) }, span: $DIR/address_of.rs:35:12: 35:25, inferred_ty: *mut dyn std::marker::Send +| 28: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32]) }, span: $DIR/address_of.rs:36:12: 36:22, inferred_ty: *mut [i32] +| 29: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32]) }, span: $DIR/address_of.rs:36:12: 36:22, inferred_ty: *mut [i32] | fn address_of_reborrow() -> () { - let mut _0: (); // return place in scope 0 at $DIR/address-of.rs:+0:26: +0:26 - let _1: &[i32; 10]; // in scope 0 at $DIR/address-of.rs:+1:9: +1:10 - let _2: [i32; 10]; // in scope 0 at $DIR/address-of.rs:+1:14: +1:21 - let mut _4: [i32; 10]; // in scope 0 at $DIR/address-of.rs:+2:22: +2:29 - let _5: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+4:5: +4:18 - let mut _6: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+4:5: +4:18 - let _7: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+5:5: +5:26 - let _8: *const dyn std::marker::Send; // in scope 0 at $DIR/address-of.rs:+6:5: +6:25 - let mut _9: *const dyn std::marker::Send; // in scope 0 at $DIR/address-of.rs:+6:5: +6:25 - let mut _10: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+6:5: +6:6 - let _11: *const [i32]; // in scope 0 at $DIR/address-of.rs:+7:5: +7:22 - let mut _12: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+7:5: +7:6 - let _13: *const i32; // in scope 0 at $DIR/address-of.rs:+8:5: +8:20 - let mut _14: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+8:5: +8:6 - let mut _18: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+12:30: +12:31 - let mut _20: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+13:27: +13:28 - let _21: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+15:5: +15:18 - let mut _22: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+15:5: +15:18 - let _23: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+16:5: +16:26 - let _24: *const dyn std::marker::Send; // in scope 0 at $DIR/address-of.rs:+17:5: +17:25 - let mut _25: *const dyn std::marker::Send; // in scope 0 at $DIR/address-of.rs:+17:5: +17:25 - let mut _26: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+17:5: +17:6 - let _27: *const [i32]; // in scope 0 at $DIR/address-of.rs:+18:5: +18:22 - let mut _28: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+18:5: +18:6 - let mut _32: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+22:30: +22:31 - let mut _34: *const [i32; 10]; // in scope 0 at $DIR/address-of.rs:+23:27: +23:28 - let _35: *mut [i32; 10]; // in scope 0 at $DIR/address-of.rs:+25:5: +25:16 - let mut _36: *mut [i32; 10]; // in scope 0 at $DIR/address-of.rs:+25:5: +25:16 - let _37: *mut [i32; 10]; // in scope 0 at $DIR/address-of.rs:+26:5: +26:24 - let _38: *mut dyn std::marker::Send; // in scope 0 at $DIR/address-of.rs:+27:5: +27:23 - let mut _39: *mut dyn std::marker::Send; // in scope 0 at $DIR/address-of.rs:+27:5: +27:23 - let mut _40: *mut [i32; 10]; // in scope 0 at $DIR/address-of.rs:+27:5: +27:6 - let _41: *mut [i32]; // in scope 0 at $DIR/address-of.rs:+28:5: +28:20 - let mut _42: *mut [i32; 10]; // in scope 0 at $DIR/address-of.rs:+28:5: +28:6 - let mut _46: *mut [i32; 10]; // in scope 0 at $DIR/address-of.rs:+32:28: +32:29 - let mut _48: *mut [i32; 10]; // in scope 0 at $DIR/address-of.rs:+33:25: +33:26 + let mut _0: (); // return place in scope 0 at $DIR/address_of.rs:+0:26: +0:26 + let _1: &[i32; 10]; // in scope 0 at $DIR/address_of.rs:+1:9: +1:10 + let _2: [i32; 10]; // in scope 0 at $DIR/address_of.rs:+1:14: +1:21 + let mut _4: [i32; 10]; // in scope 0 at $DIR/address_of.rs:+2:22: +2:29 + let _5: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+4:5: +4:18 + let mut _6: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+4:5: +4:18 + let _7: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+5:5: +5:26 + let _8: *const dyn std::marker::Send; // in scope 0 at $DIR/address_of.rs:+6:5: +6:25 + let mut _9: *const dyn std::marker::Send; // in scope 0 at $DIR/address_of.rs:+6:5: +6:25 + let mut _10: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+6:5: +6:6 + let _11: *const [i32]; // in scope 0 at $DIR/address_of.rs:+7:5: +7:22 + let mut _12: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+7:5: +7:6 + let _13: *const i32; // in scope 0 at $DIR/address_of.rs:+8:5: +8:20 + let mut _14: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+8:5: +8:6 + let mut _18: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+12:30: +12:31 + let mut _20: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+13:27: +13:28 + let _21: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+15:5: +15:18 + let mut _22: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+15:5: +15:18 + let _23: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+16:5: +16:26 + let _24: *const dyn std::marker::Send; // in scope 0 at $DIR/address_of.rs:+17:5: +17:25 + let mut _25: *const dyn std::marker::Send; // in scope 0 at $DIR/address_of.rs:+17:5: +17:25 + let mut _26: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+17:5: +17:6 + let _27: *const [i32]; // in scope 0 at $DIR/address_of.rs:+18:5: +18:22 + let mut _28: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+18:5: +18:6 + let mut _32: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+22:30: +22:31 + let mut _34: *const [i32; 10]; // in scope 0 at $DIR/address_of.rs:+23:27: +23:28 + let _35: *mut [i32; 10]; // in scope 0 at $DIR/address_of.rs:+25:5: +25:16 + let mut _36: *mut [i32; 10]; // in scope 0 at $DIR/address_of.rs:+25:5: +25:16 + let _37: *mut [i32; 10]; // in scope 0 at $DIR/address_of.rs:+26:5: +26:24 + let _38: *mut dyn std::marker::Send; // in scope 0 at $DIR/address_of.rs:+27:5: +27:23 + let mut _39: *mut dyn std::marker::Send; // in scope 0 at $DIR/address_of.rs:+27:5: +27:23 + let mut _40: *mut [i32; 10]; // in scope 0 at $DIR/address_of.rs:+27:5: +27:6 + let _41: *mut [i32]; // in scope 0 at $DIR/address_of.rs:+28:5: +28:20 + let mut _42: *mut [i32; 10]; // in scope 0 at $DIR/address_of.rs:+28:5: +28:6 + let mut _46: *mut [i32; 10]; // in scope 0 at $DIR/address_of.rs:+32:28: +32:29 + let mut _48: *mut [i32; 10]; // in scope 0 at $DIR/address_of.rs:+33:25: +33:26 scope 1 { - debug y => _1; // in scope 1 at $DIR/address-of.rs:+1:9: +1:10 - let mut _3: &mut [i32; 10]; // in scope 1 at $DIR/address-of.rs:+2:9: +2:14 + debug y => _1; // in scope 1 at $DIR/address_of.rs:+1:9: +1:10 + let mut _3: &mut [i32; 10]; // in scope 1 at $DIR/address_of.rs:+2:9: +2:14 scope 2 { - debug z => _3; // in scope 2 at $DIR/address-of.rs:+2:9: +2:14 - let _15: *const [i32; 10] as UserTypeProjection { base: UserType(2), projs: [] }; // in scope 2 at $DIR/address-of.rs:+10:9: +10:10 + debug z => _3; // in scope 2 at $DIR/address_of.rs:+2:9: +2:14 + let _15: *const [i32; 10] as UserTypeProjection { base: UserType(2), projs: [] }; // in scope 2 at $DIR/address_of.rs:+10:9: +10:10 scope 3 { - debug p => _15; // in scope 3 at $DIR/address-of.rs:+10:9: +10:10 - let _16: *const [i32; 10] as UserTypeProjection { base: UserType(4), projs: [] }; // in scope 3 at $DIR/address-of.rs:+11:9: +11:10 + debug p => _15; // in scope 3 at $DIR/address_of.rs:+10:9: +10:10 + let _16: *const [i32; 10] as UserTypeProjection { base: UserType(4), projs: [] }; // in scope 3 at $DIR/address_of.rs:+11:9: +11:10 scope 4 { - debug p => _16; // in scope 4 at $DIR/address-of.rs:+11:9: +11:10 - let _17: *const dyn std::marker::Send as UserTypeProjection { base: UserType(6), projs: [] }; // in scope 4 at $DIR/address-of.rs:+12:9: +12:10 + debug p => _16; // in scope 4 at $DIR/address_of.rs:+11:9: +11:10 + let _17: *const dyn std::marker::Send as UserTypeProjection { base: UserType(6), projs: [] }; // in scope 4 at $DIR/address_of.rs:+12:9: +12:10 scope 5 { - debug p => _17; // in scope 5 at $DIR/address-of.rs:+12:9: +12:10 - let _19: *const [i32] as UserTypeProjection { base: UserType(8), projs: [] }; // in scope 5 at $DIR/address-of.rs:+13:9: +13:10 + debug p => _17; // in scope 5 at $DIR/address_of.rs:+12:9: +12:10 + let _19: *const [i32] as UserTypeProjection { base: UserType(8), projs: [] }; // in scope 5 at $DIR/address_of.rs:+13:9: +13:10 scope 6 { - debug p => _19; // in scope 6 at $DIR/address-of.rs:+13:9: +13:10 - let _29: *const [i32; 10] as UserTypeProjection { base: UserType(12), projs: [] }; // in scope 6 at $DIR/address-of.rs:+20:9: +20:10 + debug p => _19; // in scope 6 at $DIR/address_of.rs:+13:9: +13:10 + let _29: *const [i32; 10] as UserTypeProjection { base: UserType(12), projs: [] }; // in scope 6 at $DIR/address_of.rs:+20:9: +20:10 scope 7 { - debug p => _29; // in scope 7 at $DIR/address-of.rs:+20:9: +20:10 - let _30: *const [i32; 10] as UserTypeProjection { base: UserType(14), projs: [] }; // in scope 7 at $DIR/address-of.rs:+21:9: +21:10 + debug p => _29; // in scope 7 at $DIR/address_of.rs:+20:9: +20:10 + let _30: *const [i32; 10] as UserTypeProjection { base: UserType(14), projs: [] }; // in scope 7 at $DIR/address_of.rs:+21:9: +21:10 scope 8 { - debug p => _30; // in scope 8 at $DIR/address-of.rs:+21:9: +21:10 - let _31: *const dyn std::marker::Send as UserTypeProjection { base: UserType(16), projs: [] }; // in scope 8 at $DIR/address-of.rs:+22:9: +22:10 + debug p => _30; // in scope 8 at $DIR/address_of.rs:+21:9: +21:10 + let _31: *const dyn std::marker::Send as UserTypeProjection { base: UserType(16), projs: [] }; // in scope 8 at $DIR/address_of.rs:+22:9: +22:10 scope 9 { - debug p => _31; // in scope 9 at $DIR/address-of.rs:+22:9: +22:10 - let _33: *const [i32] as UserTypeProjection { base: UserType(18), projs: [] }; // in scope 9 at $DIR/address-of.rs:+23:9: +23:10 + debug p => _31; // in scope 9 at $DIR/address_of.rs:+22:9: +22:10 + let _33: *const [i32] as UserTypeProjection { base: UserType(18), projs: [] }; // in scope 9 at $DIR/address_of.rs:+23:9: +23:10 scope 10 { - debug p => _33; // in scope 10 at $DIR/address-of.rs:+23:9: +23:10 - let _43: *mut [i32; 10] as UserTypeProjection { base: UserType(22), projs: [] }; // in scope 10 at $DIR/address-of.rs:+30:9: +30:10 + debug p => _33; // in scope 10 at $DIR/address_of.rs:+23:9: +23:10 + let _43: *mut [i32; 10] as UserTypeProjection { base: UserType(22), projs: [] }; // in scope 10 at $DIR/address_of.rs:+30:9: +30:10 scope 11 { - debug p => _43; // in scope 11 at $DIR/address-of.rs:+30:9: +30:10 - let _44: *mut [i32; 10] as UserTypeProjection { base: UserType(24), projs: [] }; // in scope 11 at $DIR/address-of.rs:+31:9: +31:10 + debug p => _43; // in scope 11 at $DIR/address_of.rs:+30:9: +30:10 + let _44: *mut [i32; 10] as UserTypeProjection { base: UserType(24), projs: [] }; // in scope 11 at $DIR/address_of.rs:+31:9: +31:10 scope 12 { - debug p => _44; // in scope 12 at $DIR/address-of.rs:+31:9: +31:10 - let _45: *mut dyn std::marker::Send as UserTypeProjection { base: UserType(26), projs: [] }; // in scope 12 at $DIR/address-of.rs:+32:9: +32:10 + debug p => _44; // in scope 12 at $DIR/address_of.rs:+31:9: +31:10 + let _45: *mut dyn std::marker::Send as UserTypeProjection { base: UserType(26), projs: [] }; // in scope 12 at $DIR/address_of.rs:+32:9: +32:10 scope 13 { - debug p => _45; // in scope 13 at $DIR/address-of.rs:+32:9: +32:10 - let _47: *mut [i32] as UserTypeProjection { base: UserType(28), projs: [] }; // in scope 13 at $DIR/address-of.rs:+33:9: +33:10 + debug p => _45; // in scope 13 at $DIR/address_of.rs:+32:9: +32:10 + let _47: *mut [i32] as UserTypeProjection { base: UserType(28), projs: [] }; // in scope 13 at $DIR/address_of.rs:+33:9: +33:10 scope 14 { - debug p => _47; // in scope 14 at $DIR/address-of.rs:+33:9: +33:10 + debug p => _47; // in scope 14 at $DIR/address_of.rs:+33:9: +33:10 } } } @@ -126,183 +126,183 @@ fn address_of_reborrow() -> () { } bb0: { - StorageLive(_1); // scope 0 at $DIR/address-of.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/address-of.rs:+1:14: +1:21 - _2 = [const 0_i32; 10]; // scope 0 at $DIR/address-of.rs:+1:14: +1:21 - _1 = &_2; // scope 0 at $DIR/address-of.rs:+1:13: +1:21 - FakeRead(ForLet(None), _1); // scope 0 at $DIR/address-of.rs:+1:9: +1:10 - StorageLive(_3); // scope 1 at $DIR/address-of.rs:+2:9: +2:14 - StorageLive(_4); // scope 1 at $DIR/address-of.rs:+2:22: +2:29 - _4 = [const 0_i32; 10]; // scope 1 at $DIR/address-of.rs:+2:22: +2:29 - _3 = &mut _4; // scope 1 at $DIR/address-of.rs:+2:17: +2:29 - FakeRead(ForLet(None), _3); // scope 1 at $DIR/address-of.rs:+2:9: +2:14 - StorageLive(_5); // scope 2 at $DIR/address-of.rs:+4:5: +4:18 - StorageLive(_6); // scope 2 at $DIR/address-of.rs:+4:5: +4:18 - _6 = &raw const (*_1); // scope 2 at $DIR/address-of.rs:+4:5: +4:6 - AscribeUserType(_6, o, UserTypeProjection { base: UserType(0), projs: [] }); // scope 2 at $DIR/address-of.rs:+4:5: +4:18 - _5 = _6; // scope 2 at $DIR/address-of.rs:+4:5: +4:18 - StorageDead(_6); // scope 2 at $DIR/address-of.rs:+4:18: +4:19 - StorageDead(_5); // scope 2 at $DIR/address-of.rs:+4:18: +4:19 - StorageLive(_7); // scope 2 at $DIR/address-of.rs:+5:5: +5:26 - _7 = &raw const (*_1); // scope 2 at $DIR/address-of.rs:+5:5: +5:6 - StorageDead(_7); // scope 2 at $DIR/address-of.rs:+5:26: +5:27 - StorageLive(_8); // scope 2 at $DIR/address-of.rs:+6:5: +6:25 - StorageLive(_9); // scope 2 at $DIR/address-of.rs:+6:5: +6:25 - StorageLive(_10); // scope 2 at $DIR/address-of.rs:+6:5: +6:6 - _10 = &raw const (*_1); // scope 2 at $DIR/address-of.rs:+6:5: +6:6 - _9 = move _10 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 2 at $DIR/address-of.rs:+6:5: +6:6 - StorageDead(_10); // scope 2 at $DIR/address-of.rs:+6:5: +6:6 - AscribeUserType(_9, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 2 at $DIR/address-of.rs:+6:5: +6:25 - _8 = _9; // scope 2 at $DIR/address-of.rs:+6:5: +6:25 - StorageDead(_9); // scope 2 at $DIR/address-of.rs:+6:25: +6:26 - StorageDead(_8); // scope 2 at $DIR/address-of.rs:+6:25: +6:26 - StorageLive(_11); // scope 2 at $DIR/address-of.rs:+7:5: +7:22 - StorageLive(_12); // scope 2 at $DIR/address-of.rs:+7:5: +7:6 - _12 = &raw const (*_1); // scope 2 at $DIR/address-of.rs:+7:5: +7:6 - _11 = move _12 as *const [i32] (Pointer(Unsize)); // scope 2 at $DIR/address-of.rs:+7:5: +7:6 - StorageDead(_12); // scope 2 at $DIR/address-of.rs:+7:5: +7:6 - StorageDead(_11); // scope 2 at $DIR/address-of.rs:+7:22: +7:23 - StorageLive(_13); // scope 2 at $DIR/address-of.rs:+8:5: +8:20 - StorageLive(_14); // scope 2 at $DIR/address-of.rs:+8:5: +8:6 - _14 = &raw const (*_1); // scope 2 at $DIR/address-of.rs:+8:5: +8:6 - _13 = move _14 as *const i32 (Pointer(ArrayToPointer)); // scope 2 at $DIR/address-of.rs:+8:5: +8:20 - StorageDead(_14); // scope 2 at $DIR/address-of.rs:+8:19: +8:20 - StorageDead(_13); // scope 2 at $DIR/address-of.rs:+8:20: +8:21 - StorageLive(_15); // scope 2 at $DIR/address-of.rs:+10:9: +10:10 - _15 = &raw const (*_1); // scope 2 at $DIR/address-of.rs:+10:23: +10:24 - FakeRead(ForLet(None), _15); // scope 2 at $DIR/address-of.rs:+10:9: +10:10 - AscribeUserType(_15, o, UserTypeProjection { base: UserType(3), projs: [] }); // scope 2 at $DIR/address-of.rs:+10:12: +10:20 - StorageLive(_16); // scope 3 at $DIR/address-of.rs:+11:9: +11:10 - _16 = &raw const (*_1); // scope 3 at $DIR/address-of.rs:+11:31: +11:32 - FakeRead(ForLet(None), _16); // scope 3 at $DIR/address-of.rs:+11:9: +11:10 - AscribeUserType(_16, o, UserTypeProjection { base: UserType(5), projs: [] }); // scope 3 at $DIR/address-of.rs:+11:12: +11:28 - StorageLive(_17); // scope 4 at $DIR/address-of.rs:+12:9: +12:10 - StorageLive(_18); // scope 4 at $DIR/address-of.rs:+12:30: +12:31 - _18 = &raw const (*_1); // scope 4 at $DIR/address-of.rs:+12:30: +12:31 - _17 = move _18 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 4 at $DIR/address-of.rs:+12:30: +12:31 - StorageDead(_18); // scope 4 at $DIR/address-of.rs:+12:30: +12:31 - FakeRead(ForLet(None), _17); // scope 4 at $DIR/address-of.rs:+12:9: +12:10 - AscribeUserType(_17, o, UserTypeProjection { base: UserType(7), projs: [] }); // scope 4 at $DIR/address-of.rs:+12:12: +12:27 - StorageLive(_19); // scope 5 at $DIR/address-of.rs:+13:9: +13:10 - StorageLive(_20); // scope 5 at $DIR/address-of.rs:+13:27: +13:28 - _20 = &raw const (*_1); // scope 5 at $DIR/address-of.rs:+13:27: +13:28 - _19 = move _20 as *const [i32] (Pointer(Unsize)); // scope 5 at $DIR/address-of.rs:+13:27: +13:28 - StorageDead(_20); // scope 5 at $DIR/address-of.rs:+13:27: +13:28 - FakeRead(ForLet(None), _19); // scope 5 at $DIR/address-of.rs:+13:9: +13:10 - AscribeUserType(_19, o, UserTypeProjection { base: UserType(9), projs: [] }); // scope 5 at $DIR/address-of.rs:+13:12: +13:24 - StorageLive(_21); // scope 6 at $DIR/address-of.rs:+15:5: +15:18 - StorageLive(_22); // scope 6 at $DIR/address-of.rs:+15:5: +15:18 - _22 = &raw const (*_3); // scope 6 at $DIR/address-of.rs:+15:5: +15:6 - AscribeUserType(_22, o, UserTypeProjection { base: UserType(10), projs: [] }); // scope 6 at $DIR/address-of.rs:+15:5: +15:18 - _21 = _22; // scope 6 at $DIR/address-of.rs:+15:5: +15:18 - StorageDead(_22); // scope 6 at $DIR/address-of.rs:+15:18: +15:19 - StorageDead(_21); // scope 6 at $DIR/address-of.rs:+15:18: +15:19 - StorageLive(_23); // scope 6 at $DIR/address-of.rs:+16:5: +16:26 - _23 = &raw const (*_3); // scope 6 at $DIR/address-of.rs:+16:5: +16:6 - StorageDead(_23); // scope 6 at $DIR/address-of.rs:+16:26: +16:27 - StorageLive(_24); // scope 6 at $DIR/address-of.rs:+17:5: +17:25 - StorageLive(_25); // scope 6 at $DIR/address-of.rs:+17:5: +17:25 - StorageLive(_26); // scope 6 at $DIR/address-of.rs:+17:5: +17:6 - _26 = &raw const (*_3); // scope 6 at $DIR/address-of.rs:+17:5: +17:6 - _25 = move _26 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 6 at $DIR/address-of.rs:+17:5: +17:6 - StorageDead(_26); // scope 6 at $DIR/address-of.rs:+17:5: +17:6 - AscribeUserType(_25, o, UserTypeProjection { base: UserType(11), projs: [] }); // scope 6 at $DIR/address-of.rs:+17:5: +17:25 - _24 = _25; // scope 6 at $DIR/address-of.rs:+17:5: +17:25 - StorageDead(_25); // scope 6 at $DIR/address-of.rs:+17:25: +17:26 - StorageDead(_24); // scope 6 at $DIR/address-of.rs:+17:25: +17:26 - StorageLive(_27); // scope 6 at $DIR/address-of.rs:+18:5: +18:22 - StorageLive(_28); // scope 6 at $DIR/address-of.rs:+18:5: +18:6 - _28 = &raw const (*_3); // scope 6 at $DIR/address-of.rs:+18:5: +18:6 - _27 = move _28 as *const [i32] (Pointer(Unsize)); // scope 6 at $DIR/address-of.rs:+18:5: +18:6 - StorageDead(_28); // scope 6 at $DIR/address-of.rs:+18:5: +18:6 - StorageDead(_27); // scope 6 at $DIR/address-of.rs:+18:22: +18:23 - StorageLive(_29); // scope 6 at $DIR/address-of.rs:+20:9: +20:10 - _29 = &raw const (*_3); // scope 6 at $DIR/address-of.rs:+20:23: +20:24 - FakeRead(ForLet(None), _29); // scope 6 at $DIR/address-of.rs:+20:9: +20:10 - AscribeUserType(_29, o, UserTypeProjection { base: UserType(13), projs: [] }); // scope 6 at $DIR/address-of.rs:+20:12: +20:20 - StorageLive(_30); // scope 7 at $DIR/address-of.rs:+21:9: +21:10 - _30 = &raw const (*_3); // scope 7 at $DIR/address-of.rs:+21:31: +21:32 - FakeRead(ForLet(None), _30); // scope 7 at $DIR/address-of.rs:+21:9: +21:10 - AscribeUserType(_30, o, UserTypeProjection { base: UserType(15), projs: [] }); // scope 7 at $DIR/address-of.rs:+21:12: +21:28 - StorageLive(_31); // scope 8 at $DIR/address-of.rs:+22:9: +22:10 - StorageLive(_32); // scope 8 at $DIR/address-of.rs:+22:30: +22:31 - _32 = &raw const (*_3); // scope 8 at $DIR/address-of.rs:+22:30: +22:31 - _31 = move _32 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 8 at $DIR/address-of.rs:+22:30: +22:31 - StorageDead(_32); // scope 8 at $DIR/address-of.rs:+22:30: +22:31 - FakeRead(ForLet(None), _31); // scope 8 at $DIR/address-of.rs:+22:9: +22:10 - AscribeUserType(_31, o, UserTypeProjection { base: UserType(17), projs: [] }); // scope 8 at $DIR/address-of.rs:+22:12: +22:27 - StorageLive(_33); // scope 9 at $DIR/address-of.rs:+23:9: +23:10 - StorageLive(_34); // scope 9 at $DIR/address-of.rs:+23:27: +23:28 - _34 = &raw const (*_3); // scope 9 at $DIR/address-of.rs:+23:27: +23:28 - _33 = move _34 as *const [i32] (Pointer(Unsize)); // scope 9 at $DIR/address-of.rs:+23:27: +23:28 - StorageDead(_34); // scope 9 at $DIR/address-of.rs:+23:27: +23:28 - FakeRead(ForLet(None), _33); // scope 9 at $DIR/address-of.rs:+23:9: +23:10 - AscribeUserType(_33, o, UserTypeProjection { base: UserType(19), projs: [] }); // scope 9 at $DIR/address-of.rs:+23:12: +23:24 - StorageLive(_35); // scope 10 at $DIR/address-of.rs:+25:5: +25:16 - StorageLive(_36); // scope 10 at $DIR/address-of.rs:+25:5: +25:16 - _36 = &raw mut (*_3); // scope 10 at $DIR/address-of.rs:+25:5: +25:6 - AscribeUserType(_36, o, UserTypeProjection { base: UserType(20), projs: [] }); // scope 10 at $DIR/address-of.rs:+25:5: +25:16 - _35 = _36; // scope 10 at $DIR/address-of.rs:+25:5: +25:16 - StorageDead(_36); // scope 10 at $DIR/address-of.rs:+25:16: +25:17 - StorageDead(_35); // scope 10 at $DIR/address-of.rs:+25:16: +25:17 - StorageLive(_37); // scope 10 at $DIR/address-of.rs:+26:5: +26:24 - _37 = &raw mut (*_3); // scope 10 at $DIR/address-of.rs:+26:5: +26:6 - StorageDead(_37); // scope 10 at $DIR/address-of.rs:+26:24: +26:25 - StorageLive(_38); // scope 10 at $DIR/address-of.rs:+27:5: +27:23 - StorageLive(_39); // scope 10 at $DIR/address-of.rs:+27:5: +27:23 - StorageLive(_40); // scope 10 at $DIR/address-of.rs:+27:5: +27:6 - _40 = &raw mut (*_3); // scope 10 at $DIR/address-of.rs:+27:5: +27:6 - _39 = move _40 as *mut dyn std::marker::Send (Pointer(Unsize)); // scope 10 at $DIR/address-of.rs:+27:5: +27:6 - StorageDead(_40); // scope 10 at $DIR/address-of.rs:+27:5: +27:6 - AscribeUserType(_39, o, UserTypeProjection { base: UserType(21), projs: [] }); // scope 10 at $DIR/address-of.rs:+27:5: +27:23 - _38 = _39; // scope 10 at $DIR/address-of.rs:+27:5: +27:23 - StorageDead(_39); // scope 10 at $DIR/address-of.rs:+27:23: +27:24 - StorageDead(_38); // scope 10 at $DIR/address-of.rs:+27:23: +27:24 - StorageLive(_41); // scope 10 at $DIR/address-of.rs:+28:5: +28:20 - StorageLive(_42); // scope 10 at $DIR/address-of.rs:+28:5: +28:6 - _42 = &raw mut (*_3); // scope 10 at $DIR/address-of.rs:+28:5: +28:6 - _41 = move _42 as *mut [i32] (Pointer(Unsize)); // scope 10 at $DIR/address-of.rs:+28:5: +28:6 - StorageDead(_42); // scope 10 at $DIR/address-of.rs:+28:5: +28:6 - StorageDead(_41); // scope 10 at $DIR/address-of.rs:+28:20: +28:21 - StorageLive(_43); // scope 10 at $DIR/address-of.rs:+30:9: +30:10 - _43 = &raw mut (*_3); // scope 10 at $DIR/address-of.rs:+30:21: +30:22 - FakeRead(ForLet(None), _43); // scope 10 at $DIR/address-of.rs:+30:9: +30:10 - AscribeUserType(_43, o, UserTypeProjection { base: UserType(23), projs: [] }); // scope 10 at $DIR/address-of.rs:+30:12: +30:18 - StorageLive(_44); // scope 11 at $DIR/address-of.rs:+31:9: +31:10 - _44 = &raw mut (*_3); // scope 11 at $DIR/address-of.rs:+31:29: +31:30 - FakeRead(ForLet(None), _44); // scope 11 at $DIR/address-of.rs:+31:9: +31:10 - AscribeUserType(_44, o, UserTypeProjection { base: UserType(25), projs: [] }); // scope 11 at $DIR/address-of.rs:+31:12: +31:26 - StorageLive(_45); // scope 12 at $DIR/address-of.rs:+32:9: +32:10 - StorageLive(_46); // scope 12 at $DIR/address-of.rs:+32:28: +32:29 - _46 = &raw mut (*_3); // scope 12 at $DIR/address-of.rs:+32:28: +32:29 - _45 = move _46 as *mut dyn std::marker::Send (Pointer(Unsize)); // scope 12 at $DIR/address-of.rs:+32:28: +32:29 - StorageDead(_46); // scope 12 at $DIR/address-of.rs:+32:28: +32:29 - FakeRead(ForLet(None), _45); // scope 12 at $DIR/address-of.rs:+32:9: +32:10 - AscribeUserType(_45, o, UserTypeProjection { base: UserType(27), projs: [] }); // scope 12 at $DIR/address-of.rs:+32:12: +32:25 - StorageLive(_47); // scope 13 at $DIR/address-of.rs:+33:9: +33:10 - StorageLive(_48); // scope 13 at $DIR/address-of.rs:+33:25: +33:26 - _48 = &raw mut (*_3); // scope 13 at $DIR/address-of.rs:+33:25: +33:26 - _47 = move _48 as *mut [i32] (Pointer(Unsize)); // scope 13 at $DIR/address-of.rs:+33:25: +33:26 - StorageDead(_48); // scope 13 at $DIR/address-of.rs:+33:25: +33:26 - FakeRead(ForLet(None), _47); // scope 13 at $DIR/address-of.rs:+33:9: +33:10 - AscribeUserType(_47, o, UserTypeProjection { base: UserType(29), projs: [] }); // scope 13 at $DIR/address-of.rs:+33:12: +33:22 - _0 = const (); // scope 0 at $DIR/address-of.rs:+0:26: +34:2 - StorageDead(_47); // scope 13 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_45); // scope 12 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_44); // scope 11 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_43); // scope 10 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_33); // scope 9 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_31); // scope 8 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_30); // scope 7 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_29); // scope 6 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_19); // scope 5 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_17); // scope 4 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_16); // scope 3 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_15); // scope 2 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_4); // scope 1 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_3); // scope 1 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_2); // scope 0 at $DIR/address-of.rs:+34:1: +34:2 - StorageDead(_1); // scope 0 at $DIR/address-of.rs:+34:1: +34:2 - return; // scope 0 at $DIR/address-of.rs:+34:2: +34:2 + StorageLive(_1); // scope 0 at $DIR/address_of.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/address_of.rs:+1:14: +1:21 + _2 = [const 0_i32; 10]; // scope 0 at $DIR/address_of.rs:+1:14: +1:21 + _1 = &_2; // scope 0 at $DIR/address_of.rs:+1:13: +1:21 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/address_of.rs:+1:9: +1:10 + StorageLive(_3); // scope 1 at $DIR/address_of.rs:+2:9: +2:14 + StorageLive(_4); // scope 1 at $DIR/address_of.rs:+2:22: +2:29 + _4 = [const 0_i32; 10]; // scope 1 at $DIR/address_of.rs:+2:22: +2:29 + _3 = &mut _4; // scope 1 at $DIR/address_of.rs:+2:17: +2:29 + FakeRead(ForLet(None), _3); // scope 1 at $DIR/address_of.rs:+2:9: +2:14 + StorageLive(_5); // scope 2 at $DIR/address_of.rs:+4:5: +4:18 + StorageLive(_6); // scope 2 at $DIR/address_of.rs:+4:5: +4:18 + _6 = &raw const (*_1); // scope 2 at $DIR/address_of.rs:+4:5: +4:6 + AscribeUserType(_6, o, UserTypeProjection { base: UserType(0), projs: [] }); // scope 2 at $DIR/address_of.rs:+4:5: +4:18 + _5 = _6; // scope 2 at $DIR/address_of.rs:+4:5: +4:18 + StorageDead(_6); // scope 2 at $DIR/address_of.rs:+4:18: +4:19 + StorageDead(_5); // scope 2 at $DIR/address_of.rs:+4:18: +4:19 + StorageLive(_7); // scope 2 at $DIR/address_of.rs:+5:5: +5:26 + _7 = &raw const (*_1); // scope 2 at $DIR/address_of.rs:+5:5: +5:6 + StorageDead(_7); // scope 2 at $DIR/address_of.rs:+5:26: +5:27 + StorageLive(_8); // scope 2 at $DIR/address_of.rs:+6:5: +6:25 + StorageLive(_9); // scope 2 at $DIR/address_of.rs:+6:5: +6:25 + StorageLive(_10); // scope 2 at $DIR/address_of.rs:+6:5: +6:6 + _10 = &raw const (*_1); // scope 2 at $DIR/address_of.rs:+6:5: +6:6 + _9 = move _10 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 2 at $DIR/address_of.rs:+6:5: +6:6 + StorageDead(_10); // scope 2 at $DIR/address_of.rs:+6:5: +6:6 + AscribeUserType(_9, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 2 at $DIR/address_of.rs:+6:5: +6:25 + _8 = _9; // scope 2 at $DIR/address_of.rs:+6:5: +6:25 + StorageDead(_9); // scope 2 at $DIR/address_of.rs:+6:25: +6:26 + StorageDead(_8); // scope 2 at $DIR/address_of.rs:+6:25: +6:26 + StorageLive(_11); // scope 2 at $DIR/address_of.rs:+7:5: +7:22 + StorageLive(_12); // scope 2 at $DIR/address_of.rs:+7:5: +7:6 + _12 = &raw const (*_1); // scope 2 at $DIR/address_of.rs:+7:5: +7:6 + _11 = move _12 as *const [i32] (Pointer(Unsize)); // scope 2 at $DIR/address_of.rs:+7:5: +7:6 + StorageDead(_12); // scope 2 at $DIR/address_of.rs:+7:5: +7:6 + StorageDead(_11); // scope 2 at $DIR/address_of.rs:+7:22: +7:23 + StorageLive(_13); // scope 2 at $DIR/address_of.rs:+8:5: +8:20 + StorageLive(_14); // scope 2 at $DIR/address_of.rs:+8:5: +8:6 + _14 = &raw const (*_1); // scope 2 at $DIR/address_of.rs:+8:5: +8:6 + _13 = move _14 as *const i32 (Pointer(ArrayToPointer)); // scope 2 at $DIR/address_of.rs:+8:5: +8:20 + StorageDead(_14); // scope 2 at $DIR/address_of.rs:+8:19: +8:20 + StorageDead(_13); // scope 2 at $DIR/address_of.rs:+8:20: +8:21 + StorageLive(_15); // scope 2 at $DIR/address_of.rs:+10:9: +10:10 + _15 = &raw const (*_1); // scope 2 at $DIR/address_of.rs:+10:23: +10:24 + FakeRead(ForLet(None), _15); // scope 2 at $DIR/address_of.rs:+10:9: +10:10 + AscribeUserType(_15, o, UserTypeProjection { base: UserType(3), projs: [] }); // scope 2 at $DIR/address_of.rs:+10:12: +10:20 + StorageLive(_16); // scope 3 at $DIR/address_of.rs:+11:9: +11:10 + _16 = &raw const (*_1); // scope 3 at $DIR/address_of.rs:+11:31: +11:32 + FakeRead(ForLet(None), _16); // scope 3 at $DIR/address_of.rs:+11:9: +11:10 + AscribeUserType(_16, o, UserTypeProjection { base: UserType(5), projs: [] }); // scope 3 at $DIR/address_of.rs:+11:12: +11:28 + StorageLive(_17); // scope 4 at $DIR/address_of.rs:+12:9: +12:10 + StorageLive(_18); // scope 4 at $DIR/address_of.rs:+12:30: +12:31 + _18 = &raw const (*_1); // scope 4 at $DIR/address_of.rs:+12:30: +12:31 + _17 = move _18 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 4 at $DIR/address_of.rs:+12:30: +12:31 + StorageDead(_18); // scope 4 at $DIR/address_of.rs:+12:30: +12:31 + FakeRead(ForLet(None), _17); // scope 4 at $DIR/address_of.rs:+12:9: +12:10 + AscribeUserType(_17, o, UserTypeProjection { base: UserType(7), projs: [] }); // scope 4 at $DIR/address_of.rs:+12:12: +12:27 + StorageLive(_19); // scope 5 at $DIR/address_of.rs:+13:9: +13:10 + StorageLive(_20); // scope 5 at $DIR/address_of.rs:+13:27: +13:28 + _20 = &raw const (*_1); // scope 5 at $DIR/address_of.rs:+13:27: +13:28 + _19 = move _20 as *const [i32] (Pointer(Unsize)); // scope 5 at $DIR/address_of.rs:+13:27: +13:28 + StorageDead(_20); // scope 5 at $DIR/address_of.rs:+13:27: +13:28 + FakeRead(ForLet(None), _19); // scope 5 at $DIR/address_of.rs:+13:9: +13:10 + AscribeUserType(_19, o, UserTypeProjection { base: UserType(9), projs: [] }); // scope 5 at $DIR/address_of.rs:+13:12: +13:24 + StorageLive(_21); // scope 6 at $DIR/address_of.rs:+15:5: +15:18 + StorageLive(_22); // scope 6 at $DIR/address_of.rs:+15:5: +15:18 + _22 = &raw const (*_3); // scope 6 at $DIR/address_of.rs:+15:5: +15:6 + AscribeUserType(_22, o, UserTypeProjection { base: UserType(10), projs: [] }); // scope 6 at $DIR/address_of.rs:+15:5: +15:18 + _21 = _22; // scope 6 at $DIR/address_of.rs:+15:5: +15:18 + StorageDead(_22); // scope 6 at $DIR/address_of.rs:+15:18: +15:19 + StorageDead(_21); // scope 6 at $DIR/address_of.rs:+15:18: +15:19 + StorageLive(_23); // scope 6 at $DIR/address_of.rs:+16:5: +16:26 + _23 = &raw const (*_3); // scope 6 at $DIR/address_of.rs:+16:5: +16:6 + StorageDead(_23); // scope 6 at $DIR/address_of.rs:+16:26: +16:27 + StorageLive(_24); // scope 6 at $DIR/address_of.rs:+17:5: +17:25 + StorageLive(_25); // scope 6 at $DIR/address_of.rs:+17:5: +17:25 + StorageLive(_26); // scope 6 at $DIR/address_of.rs:+17:5: +17:6 + _26 = &raw const (*_3); // scope 6 at $DIR/address_of.rs:+17:5: +17:6 + _25 = move _26 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 6 at $DIR/address_of.rs:+17:5: +17:6 + StorageDead(_26); // scope 6 at $DIR/address_of.rs:+17:5: +17:6 + AscribeUserType(_25, o, UserTypeProjection { base: UserType(11), projs: [] }); // scope 6 at $DIR/address_of.rs:+17:5: +17:25 + _24 = _25; // scope 6 at $DIR/address_of.rs:+17:5: +17:25 + StorageDead(_25); // scope 6 at $DIR/address_of.rs:+17:25: +17:26 + StorageDead(_24); // scope 6 at $DIR/address_of.rs:+17:25: +17:26 + StorageLive(_27); // scope 6 at $DIR/address_of.rs:+18:5: +18:22 + StorageLive(_28); // scope 6 at $DIR/address_of.rs:+18:5: +18:6 + _28 = &raw const (*_3); // scope 6 at $DIR/address_of.rs:+18:5: +18:6 + _27 = move _28 as *const [i32] (Pointer(Unsize)); // scope 6 at $DIR/address_of.rs:+18:5: +18:6 + StorageDead(_28); // scope 6 at $DIR/address_of.rs:+18:5: +18:6 + StorageDead(_27); // scope 6 at $DIR/address_of.rs:+18:22: +18:23 + StorageLive(_29); // scope 6 at $DIR/address_of.rs:+20:9: +20:10 + _29 = &raw const (*_3); // scope 6 at $DIR/address_of.rs:+20:23: +20:24 + FakeRead(ForLet(None), _29); // scope 6 at $DIR/address_of.rs:+20:9: +20:10 + AscribeUserType(_29, o, UserTypeProjection { base: UserType(13), projs: [] }); // scope 6 at $DIR/address_of.rs:+20:12: +20:20 + StorageLive(_30); // scope 7 at $DIR/address_of.rs:+21:9: +21:10 + _30 = &raw const (*_3); // scope 7 at $DIR/address_of.rs:+21:31: +21:32 + FakeRead(ForLet(None), _30); // scope 7 at $DIR/address_of.rs:+21:9: +21:10 + AscribeUserType(_30, o, UserTypeProjection { base: UserType(15), projs: [] }); // scope 7 at $DIR/address_of.rs:+21:12: +21:28 + StorageLive(_31); // scope 8 at $DIR/address_of.rs:+22:9: +22:10 + StorageLive(_32); // scope 8 at $DIR/address_of.rs:+22:30: +22:31 + _32 = &raw const (*_3); // scope 8 at $DIR/address_of.rs:+22:30: +22:31 + _31 = move _32 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 8 at $DIR/address_of.rs:+22:30: +22:31 + StorageDead(_32); // scope 8 at $DIR/address_of.rs:+22:30: +22:31 + FakeRead(ForLet(None), _31); // scope 8 at $DIR/address_of.rs:+22:9: +22:10 + AscribeUserType(_31, o, UserTypeProjection { base: UserType(17), projs: [] }); // scope 8 at $DIR/address_of.rs:+22:12: +22:27 + StorageLive(_33); // scope 9 at $DIR/address_of.rs:+23:9: +23:10 + StorageLive(_34); // scope 9 at $DIR/address_of.rs:+23:27: +23:28 + _34 = &raw const (*_3); // scope 9 at $DIR/address_of.rs:+23:27: +23:28 + _33 = move _34 as *const [i32] (Pointer(Unsize)); // scope 9 at $DIR/address_of.rs:+23:27: +23:28 + StorageDead(_34); // scope 9 at $DIR/address_of.rs:+23:27: +23:28 + FakeRead(ForLet(None), _33); // scope 9 at $DIR/address_of.rs:+23:9: +23:10 + AscribeUserType(_33, o, UserTypeProjection { base: UserType(19), projs: [] }); // scope 9 at $DIR/address_of.rs:+23:12: +23:24 + StorageLive(_35); // scope 10 at $DIR/address_of.rs:+25:5: +25:16 + StorageLive(_36); // scope 10 at $DIR/address_of.rs:+25:5: +25:16 + _36 = &raw mut (*_3); // scope 10 at $DIR/address_of.rs:+25:5: +25:6 + AscribeUserType(_36, o, UserTypeProjection { base: UserType(20), projs: [] }); // scope 10 at $DIR/address_of.rs:+25:5: +25:16 + _35 = _36; // scope 10 at $DIR/address_of.rs:+25:5: +25:16 + StorageDead(_36); // scope 10 at $DIR/address_of.rs:+25:16: +25:17 + StorageDead(_35); // scope 10 at $DIR/address_of.rs:+25:16: +25:17 + StorageLive(_37); // scope 10 at $DIR/address_of.rs:+26:5: +26:24 + _37 = &raw mut (*_3); // scope 10 at $DIR/address_of.rs:+26:5: +26:6 + StorageDead(_37); // scope 10 at $DIR/address_of.rs:+26:24: +26:25 + StorageLive(_38); // scope 10 at $DIR/address_of.rs:+27:5: +27:23 + StorageLive(_39); // scope 10 at $DIR/address_of.rs:+27:5: +27:23 + StorageLive(_40); // scope 10 at $DIR/address_of.rs:+27:5: +27:6 + _40 = &raw mut (*_3); // scope 10 at $DIR/address_of.rs:+27:5: +27:6 + _39 = move _40 as *mut dyn std::marker::Send (Pointer(Unsize)); // scope 10 at $DIR/address_of.rs:+27:5: +27:6 + StorageDead(_40); // scope 10 at $DIR/address_of.rs:+27:5: +27:6 + AscribeUserType(_39, o, UserTypeProjection { base: UserType(21), projs: [] }); // scope 10 at $DIR/address_of.rs:+27:5: +27:23 + _38 = _39; // scope 10 at $DIR/address_of.rs:+27:5: +27:23 + StorageDead(_39); // scope 10 at $DIR/address_of.rs:+27:23: +27:24 + StorageDead(_38); // scope 10 at $DIR/address_of.rs:+27:23: +27:24 + StorageLive(_41); // scope 10 at $DIR/address_of.rs:+28:5: +28:20 + StorageLive(_42); // scope 10 at $DIR/address_of.rs:+28:5: +28:6 + _42 = &raw mut (*_3); // scope 10 at $DIR/address_of.rs:+28:5: +28:6 + _41 = move _42 as *mut [i32] (Pointer(Unsize)); // scope 10 at $DIR/address_of.rs:+28:5: +28:6 + StorageDead(_42); // scope 10 at $DIR/address_of.rs:+28:5: +28:6 + StorageDead(_41); // scope 10 at $DIR/address_of.rs:+28:20: +28:21 + StorageLive(_43); // scope 10 at $DIR/address_of.rs:+30:9: +30:10 + _43 = &raw mut (*_3); // scope 10 at $DIR/address_of.rs:+30:21: +30:22 + FakeRead(ForLet(None), _43); // scope 10 at $DIR/address_of.rs:+30:9: +30:10 + AscribeUserType(_43, o, UserTypeProjection { base: UserType(23), projs: [] }); // scope 10 at $DIR/address_of.rs:+30:12: +30:18 + StorageLive(_44); // scope 11 at $DIR/address_of.rs:+31:9: +31:10 + _44 = &raw mut (*_3); // scope 11 at $DIR/address_of.rs:+31:29: +31:30 + FakeRead(ForLet(None), _44); // scope 11 at $DIR/address_of.rs:+31:9: +31:10 + AscribeUserType(_44, o, UserTypeProjection { base: UserType(25), projs: [] }); // scope 11 at $DIR/address_of.rs:+31:12: +31:26 + StorageLive(_45); // scope 12 at $DIR/address_of.rs:+32:9: +32:10 + StorageLive(_46); // scope 12 at $DIR/address_of.rs:+32:28: +32:29 + _46 = &raw mut (*_3); // scope 12 at $DIR/address_of.rs:+32:28: +32:29 + _45 = move _46 as *mut dyn std::marker::Send (Pointer(Unsize)); // scope 12 at $DIR/address_of.rs:+32:28: +32:29 + StorageDead(_46); // scope 12 at $DIR/address_of.rs:+32:28: +32:29 + FakeRead(ForLet(None), _45); // scope 12 at $DIR/address_of.rs:+32:9: +32:10 + AscribeUserType(_45, o, UserTypeProjection { base: UserType(27), projs: [] }); // scope 12 at $DIR/address_of.rs:+32:12: +32:25 + StorageLive(_47); // scope 13 at $DIR/address_of.rs:+33:9: +33:10 + StorageLive(_48); // scope 13 at $DIR/address_of.rs:+33:25: +33:26 + _48 = &raw mut (*_3); // scope 13 at $DIR/address_of.rs:+33:25: +33:26 + _47 = move _48 as *mut [i32] (Pointer(Unsize)); // scope 13 at $DIR/address_of.rs:+33:25: +33:26 + StorageDead(_48); // scope 13 at $DIR/address_of.rs:+33:25: +33:26 + FakeRead(ForLet(None), _47); // scope 13 at $DIR/address_of.rs:+33:9: +33:10 + AscribeUserType(_47, o, UserTypeProjection { base: UserType(29), projs: [] }); // scope 13 at $DIR/address_of.rs:+33:12: +33:22 + _0 = const (); // scope 0 at $DIR/address_of.rs:+0:26: +34:2 + StorageDead(_47); // scope 13 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_45); // scope 12 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_44); // scope 11 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_43); // scope 10 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_33); // scope 9 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_31); // scope 8 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_30); // scope 7 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_29); // scope 6 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_19); // scope 5 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_17); // scope 4 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_16); // scope 3 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_15); // scope 2 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_4); // scope 1 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_3); // scope 1 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_2); // scope 0 at $DIR/address_of.rs:+34:1: +34:2 + StorageDead(_1); // scope 0 at $DIR/address_of.rs:+34:1: +34:2 + return; // scope 0 at $DIR/address_of.rs:+34:2: +34:2 } } diff --git a/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir index 060077b8adb..4c67376b56a 100644 --- a/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir @@ -1,47 +1,47 @@ // MIR for `borrow_and_cast` after SimplifyCfg-initial fn borrow_and_cast(_1: i32) -> () { - debug x => _1; // in scope 0 at $DIR/address-of.rs:+0:20: +0:25 - let mut _0: (); // return place in scope 0 at $DIR/address-of.rs:+0:32: +0:32 - let _2: *const i32; // in scope 0 at $DIR/address-of.rs:+1:9: +1:10 - let _3: &i32; // in scope 0 at $DIR/address-of.rs:+1:13: +1:15 - let _5: &mut i32; // in scope 0 at $DIR/address-of.rs:+2:13: +2:19 - let mut _7: &mut i32; // in scope 0 at $DIR/address-of.rs:+3:13: +3:19 + debug x => _1; // in scope 0 at $DIR/address_of.rs:+0:20: +0:25 + let mut _0: (); // return place in scope 0 at $DIR/address_of.rs:+0:32: +0:32 + let _2: *const i32; // in scope 0 at $DIR/address_of.rs:+1:9: +1:10 + let _3: &i32; // in scope 0 at $DIR/address_of.rs:+1:13: +1:15 + let _5: &mut i32; // in scope 0 at $DIR/address_of.rs:+2:13: +2:19 + let mut _7: &mut i32; // in scope 0 at $DIR/address_of.rs:+3:13: +3:19 scope 1 { - debug p => _2; // in scope 1 at $DIR/address-of.rs:+1:9: +1:10 - let _4: *const i32; // in scope 1 at $DIR/address-of.rs:+2:9: +2:10 + debug p => _2; // in scope 1 at $DIR/address_of.rs:+1:9: +1:10 + let _4: *const i32; // in scope 1 at $DIR/address_of.rs:+2:9: +2:10 scope 2 { - debug q => _4; // in scope 2 at $DIR/address-of.rs:+2:9: +2:10 - let _6: *mut i32; // in scope 2 at $DIR/address-of.rs:+3:9: +3:10 + debug q => _4; // in scope 2 at $DIR/address_of.rs:+2:9: +2:10 + let _6: *mut i32; // in scope 2 at $DIR/address_of.rs:+3:9: +3:10 scope 3 { - debug r => _6; // in scope 3 at $DIR/address-of.rs:+3:9: +3:10 + debug r => _6; // in scope 3 at $DIR/address_of.rs:+3:9: +3:10 } } } bb0: { - StorageLive(_2); // scope 0 at $DIR/address-of.rs:+1:9: +1:10 - StorageLive(_3); // scope 0 at $DIR/address-of.rs:+1:13: +1:15 - _3 = &_1; // scope 0 at $DIR/address-of.rs:+1:13: +1:15 - _2 = &raw const (*_3); // scope 0 at $DIR/address-of.rs:+1:13: +1:15 - FakeRead(ForLet(None), _2); // scope 0 at $DIR/address-of.rs:+1:9: +1:10 - StorageDead(_3); // scope 0 at $DIR/address-of.rs:+1:29: +1:30 - StorageLive(_4); // scope 1 at $DIR/address-of.rs:+2:9: +2:10 - StorageLive(_5); // scope 1 at $DIR/address-of.rs:+2:13: +2:19 - _5 = &mut _1; // scope 1 at $DIR/address-of.rs:+2:13: +2:19 - _4 = &raw const (*_5); // scope 1 at $DIR/address-of.rs:+2:13: +2:19 - FakeRead(ForLet(None), _4); // scope 1 at $DIR/address-of.rs:+2:9: +2:10 - StorageDead(_5); // scope 1 at $DIR/address-of.rs:+2:33: +2:34 - StorageLive(_6); // scope 2 at $DIR/address-of.rs:+3:9: +3:10 - StorageLive(_7); // scope 2 at $DIR/address-of.rs:+3:13: +3:19 - _7 = &mut _1; // scope 2 at $DIR/address-of.rs:+3:13: +3:19 - _6 = &raw mut (*_7); // scope 2 at $DIR/address-of.rs:+3:13: +3:19 - FakeRead(ForLet(None), _6); // scope 2 at $DIR/address-of.rs:+3:9: +3:10 - StorageDead(_7); // scope 2 at $DIR/address-of.rs:+3:31: +3:32 - _0 = const (); // scope 0 at $DIR/address-of.rs:+0:32: +4:2 - StorageDead(_6); // scope 2 at $DIR/address-of.rs:+4:1: +4:2 - StorageDead(_4); // scope 1 at $DIR/address-of.rs:+4:1: +4:2 - StorageDead(_2); // scope 0 at $DIR/address-of.rs:+4:1: +4:2 - return; // scope 0 at $DIR/address-of.rs:+4:2: +4:2 + StorageLive(_2); // scope 0 at $DIR/address_of.rs:+1:9: +1:10 + StorageLive(_3); // scope 0 at $DIR/address_of.rs:+1:13: +1:15 + _3 = &_1; // scope 0 at $DIR/address_of.rs:+1:13: +1:15 + _2 = &raw const (*_3); // scope 0 at $DIR/address_of.rs:+1:13: +1:15 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/address_of.rs:+1:9: +1:10 + StorageDead(_3); // scope 0 at $DIR/address_of.rs:+1:29: +1:30 + StorageLive(_4); // scope 1 at $DIR/address_of.rs:+2:9: +2:10 + StorageLive(_5); // scope 1 at $DIR/address_of.rs:+2:13: +2:19 + _5 = &mut _1; // scope 1 at $DIR/address_of.rs:+2:13: +2:19 + _4 = &raw const (*_5); // scope 1 at $DIR/address_of.rs:+2:13: +2:19 + FakeRead(ForLet(None), _4); // scope 1 at $DIR/address_of.rs:+2:9: +2:10 + StorageDead(_5); // scope 1 at $DIR/address_of.rs:+2:33: +2:34 + StorageLive(_6); // scope 2 at $DIR/address_of.rs:+3:9: +3:10 + StorageLive(_7); // scope 2 at $DIR/address_of.rs:+3:13: +3:19 + _7 = &mut _1; // scope 2 at $DIR/address_of.rs:+3:13: +3:19 + _6 = &raw mut (*_7); // scope 2 at $DIR/address_of.rs:+3:13: +3:19 + FakeRead(ForLet(None), _6); // scope 2 at $DIR/address_of.rs:+3:9: +3:10 + StorageDead(_7); // scope 2 at $DIR/address_of.rs:+3:31: +3:32 + _0 = const (); // scope 0 at $DIR/address_of.rs:+0:32: +4:2 + StorageDead(_6); // scope 2 at $DIR/address_of.rs:+4:1: +4:2 + StorageDead(_4); // scope 1 at $DIR/address_of.rs:+4:1: +4:2 + StorageDead(_2); // scope 0 at $DIR/address_of.rs:+4:1: +4:2 + return; // scope 0 at $DIR/address_of.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/address-of.rs b/src/test/mir-opt/address_of.rs index c4bea5613e4..c4bea5613e4 100644 --- a/src/test/mir-opt/address-of.rs +++ b/src/test/mir-opt/address_of.rs diff --git a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir index 27f883ed321..af5178d4079 100644 --- a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir @@ -1,22 +1,22 @@ // MIR for `main` after SimplifyCfg-elaborate-drops fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/array-index-is-temporary.rs:+0:11: +0:11 - let mut _1: [u32; 3]; // in scope 0 at $DIR/array-index-is-temporary.rs:+1:9: +1:14 - let mut _4: &mut usize; // in scope 0 at $DIR/array-index-is-temporary.rs:+3:25: +3:31 - let mut _5: u32; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:12: +4:29 - let mut _6: *mut usize; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:25: +4:26 - let _7: usize; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:7: +4:8 - let mut _8: usize; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 - let mut _9: bool; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 + let mut _0: (); // return place in scope 0 at $DIR/array_index_is_temporary.rs:+0:11: +0:11 + let mut _1: [u32; 3]; // in scope 0 at $DIR/array_index_is_temporary.rs:+1:9: +1:14 + let mut _4: &mut usize; // in scope 0 at $DIR/array_index_is_temporary.rs:+3:25: +3:31 + let mut _5: u32; // in scope 0 at $DIR/array_index_is_temporary.rs:+4:12: +4:29 + let mut _6: *mut usize; // in scope 0 at $DIR/array_index_is_temporary.rs:+4:25: +4:26 + let _7: usize; // in scope 0 at $DIR/array_index_is_temporary.rs:+4:7: +4:8 + let mut _8: usize; // in scope 0 at $DIR/array_index_is_temporary.rs:+4:5: +4:9 + let mut _9: bool; // in scope 0 at $DIR/array_index_is_temporary.rs:+4:5: +4:9 scope 1 { - debug x => _1; // in scope 1 at $DIR/array-index-is-temporary.rs:+1:9: +1:14 - let mut _2: usize; // in scope 1 at $DIR/array-index-is-temporary.rs:+2:9: +2:14 + debug x => _1; // in scope 1 at $DIR/array_index_is_temporary.rs:+1:9: +1:14 + let mut _2: usize; // in scope 1 at $DIR/array_index_is_temporary.rs:+2:9: +2:14 scope 2 { - debug y => _2; // in scope 2 at $DIR/array-index-is-temporary.rs:+2:9: +2:14 - let _3: *mut usize; // in scope 2 at $DIR/array-index-is-temporary.rs:+3:9: +3:10 + debug y => _2; // in scope 2 at $DIR/array_index_is_temporary.rs:+2:9: +2:14 + let _3: *mut usize; // in scope 2 at $DIR/array_index_is_temporary.rs:+3:9: +3:10 scope 3 { - debug z => _3; // in scope 3 at $DIR/array-index-is-temporary.rs:+3:9: +3:10 + debug z => _3; // in scope 3 at $DIR/array_index_is_temporary.rs:+3:9: +3:10 scope 4 { } } @@ -24,41 +24,41 @@ fn main() -> () { } bb0: { - StorageLive(_1); // scope 0 at $DIR/array-index-is-temporary.rs:+1:9: +1:14 - _1 = [const 42_u32, const 43_u32, const 44_u32]; // scope 0 at $DIR/array-index-is-temporary.rs:+1:17: +1:29 - StorageLive(_2); // scope 1 at $DIR/array-index-is-temporary.rs:+2:9: +2:14 - _2 = const 1_usize; // scope 1 at $DIR/array-index-is-temporary.rs:+2:17: +2:18 - StorageLive(_3); // scope 2 at $DIR/array-index-is-temporary.rs:+3:9: +3:10 - StorageLive(_4); // scope 2 at $DIR/array-index-is-temporary.rs:+3:25: +3:31 - _4 = &mut _2; // scope 2 at $DIR/array-index-is-temporary.rs:+3:25: +3:31 - _3 = &raw mut (*_4); // scope 2 at $DIR/array-index-is-temporary.rs:+3:25: +3:31 - StorageDead(_4); // scope 2 at $DIR/array-index-is-temporary.rs:+3:31: +3:32 - StorageLive(_5); // scope 3 at $DIR/array-index-is-temporary.rs:+4:12: +4:29 - StorageLive(_6); // scope 4 at $DIR/array-index-is-temporary.rs:+4:25: +4:26 - _6 = _3; // scope 4 at $DIR/array-index-is-temporary.rs:+4:25: +4:26 - _5 = foo(move _6) -> bb1; // scope 4 at $DIR/array-index-is-temporary.rs:+4:21: +4:27 + StorageLive(_1); // scope 0 at $DIR/array_index_is_temporary.rs:+1:9: +1:14 + _1 = [const 42_u32, const 43_u32, const 44_u32]; // scope 0 at $DIR/array_index_is_temporary.rs:+1:17: +1:29 + StorageLive(_2); // scope 1 at $DIR/array_index_is_temporary.rs:+2:9: +2:14 + _2 = const 1_usize; // scope 1 at $DIR/array_index_is_temporary.rs:+2:17: +2:18 + StorageLive(_3); // scope 2 at $DIR/array_index_is_temporary.rs:+3:9: +3:10 + StorageLive(_4); // scope 2 at $DIR/array_index_is_temporary.rs:+3:25: +3:31 + _4 = &mut _2; // scope 2 at $DIR/array_index_is_temporary.rs:+3:25: +3:31 + _3 = &raw mut (*_4); // scope 2 at $DIR/array_index_is_temporary.rs:+3:25: +3:31 + StorageDead(_4); // scope 2 at $DIR/array_index_is_temporary.rs:+3:31: +3:32 + StorageLive(_5); // scope 3 at $DIR/array_index_is_temporary.rs:+4:12: +4:29 + StorageLive(_6); // scope 4 at $DIR/array_index_is_temporary.rs:+4:25: +4:26 + _6 = _3; // scope 4 at $DIR/array_index_is_temporary.rs:+4:25: +4:26 + _5 = foo(move _6) -> bb1; // scope 4 at $DIR/array_index_is_temporary.rs:+4:21: +4:27 // mir::Constant - // + span: $DIR/array-index-is-temporary.rs:16:21: 16:24 + // + span: $DIR/array_index_is_temporary.rs:16:21: 16:24 // + literal: Const { ty: unsafe fn(*mut usize) -> u32 {foo}, val: Value(<ZST>) } } bb1: { - StorageDead(_6); // scope 4 at $DIR/array-index-is-temporary.rs:+4:26: +4:27 - StorageLive(_7); // scope 3 at $DIR/array-index-is-temporary.rs:+4:7: +4:8 - _7 = _2; // scope 3 at $DIR/array-index-is-temporary.rs:+4:7: +4:8 - _8 = Len(_1); // scope 3 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 - _9 = Lt(_7, _8); // scope 3 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb2; // scope 3 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 + StorageDead(_6); // scope 4 at $DIR/array_index_is_temporary.rs:+4:26: +4:27 + StorageLive(_7); // scope 3 at $DIR/array_index_is_temporary.rs:+4:7: +4:8 + _7 = _2; // scope 3 at $DIR/array_index_is_temporary.rs:+4:7: +4:8 + _8 = Len(_1); // scope 3 at $DIR/array_index_is_temporary.rs:+4:5: +4:9 + _9 = Lt(_7, _8); // scope 3 at $DIR/array_index_is_temporary.rs:+4:5: +4:9 + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb2; // scope 3 at $DIR/array_index_is_temporary.rs:+4:5: +4:9 } bb2: { - _1[_7] = move _5; // scope 3 at $DIR/array-index-is-temporary.rs:+4:5: +4:29 - StorageDead(_5); // scope 3 at $DIR/array-index-is-temporary.rs:+4:28: +4:29 - StorageDead(_7); // scope 3 at $DIR/array-index-is-temporary.rs:+4:29: +4:30 - _0 = const (); // scope 0 at $DIR/array-index-is-temporary.rs:+0:11: +5:2 - StorageDead(_3); // scope 2 at $DIR/array-index-is-temporary.rs:+5:1: +5:2 - StorageDead(_2); // scope 1 at $DIR/array-index-is-temporary.rs:+5:1: +5:2 - StorageDead(_1); // scope 0 at $DIR/array-index-is-temporary.rs:+5:1: +5:2 - return; // scope 0 at $DIR/array-index-is-temporary.rs:+5:2: +5:2 + _1[_7] = move _5; // scope 3 at $DIR/array_index_is_temporary.rs:+4:5: +4:29 + StorageDead(_5); // scope 3 at $DIR/array_index_is_temporary.rs:+4:28: +4:29 + StorageDead(_7); // scope 3 at $DIR/array_index_is_temporary.rs:+4:29: +4:30 + _0 = const (); // scope 0 at $DIR/array_index_is_temporary.rs:+0:11: +5:2 + StorageDead(_3); // scope 2 at $DIR/array_index_is_temporary.rs:+5:1: +5:2 + StorageDead(_2); // scope 1 at $DIR/array_index_is_temporary.rs:+5:1: +5:2 + StorageDead(_1); // scope 0 at $DIR/array_index_is_temporary.rs:+5:1: +5:2 + return; // scope 0 at $DIR/array_index_is_temporary.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array_index_is_temporary.rs index e7bde81d4ca..e7bde81d4ca 100644 --- a/src/test/mir-opt/array-index-is-temporary.rs +++ b/src/test/mir-opt/array_index_is_temporary.rs diff --git a/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir new file mode 100644 index 00000000000..4a5ddde4081 --- /dev/null +++ b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir @@ -0,0 +1,14 @@ +// MIR for `immut_ref` after built + +fn immut_ref(_1: &i32) -> &i32 { + let mut _0: &i32; // return place in scope 0 at $DIR/references.rs:+0:30: +0:34 + let mut _2: *const i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _2 = &raw const (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:34 + Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:34 + _0 = &(*_2); // scope 0 at $DIR/references.rs:+0:1: +0:34 + Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:34 + return; // scope 0 at $DIR/references.rs:+0:1: +0:34 + } +} diff --git a/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir new file mode 100644 index 00000000000..ec8509f69d1 --- /dev/null +++ b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir @@ -0,0 +1,14 @@ +// MIR for `mut_ref` after built + +fn mut_ref(_1: &mut i32) -> &mut i32 { + let mut _0: &mut i32; // return place in scope 0 at $DIR/references.rs:+0:32: +0:40 + let mut _2: *mut i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _2 = &raw mut (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:40 + Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:40 + _0 = &mut (*_2); // scope 0 at $DIR/references.rs:+0:1: +0:40 + Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:40 + return; // scope 0 at $DIR/references.rs:+0:1: +0:40 + } +} diff --git a/src/test/mir-opt/building/custom/references.rs b/src/test/mir-opt/building/custom/references.rs new file mode 100644 index 00000000000..dee85722e86 --- /dev/null +++ b/src/test/mir-opt/building/custom/references.rs @@ -0,0 +1,43 @@ +#![feature(custom_mir, core_intrinsics)] + +extern crate core; +use core::intrinsics::mir::*; +use core::ptr::{addr_of, addr_of_mut}; + +// EMIT_MIR references.mut_ref.built.after.mir +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn mut_ref(x: &mut i32) -> &mut i32 { + mir!( + let t: *mut i32; + + { + t = addr_of_mut!(*x); + RetagRaw(t); + RET = &mut *t; + Retag(RET); + Return() + } + ) +} + +// EMIT_MIR references.immut_ref.built.after.mir +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn immut_ref(x: &i32) -> &i32 { + mir!( + let t: *const i32; + + { + t = addr_of!(*x); + RetagRaw(t); + RET = & *t; + Retag(RET); + Return() + } + ) +} + +fn main() { + let mut x = 5; + assert_eq!(*mut_ref(&mut x), 5); + assert_eq!(*immut_ref(&x), 5); +} diff --git a/src/test/mir-opt/building/custom/simple_assign.rs b/src/test/mir-opt/building/custom/simple_assign.rs new file mode 100644 index 00000000000..ec6dbe1d052 --- /dev/null +++ b/src/test/mir-opt/building/custom/simple_assign.rs @@ -0,0 +1,37 @@ +#![feature(custom_mir, core_intrinsics)] + +extern crate core; +use core::intrinsics::mir::*; + +// EMIT_MIR simple_assign.simple.built.after.mir +#[custom_mir(dialect = "built")] +pub fn simple(x: i32) -> i32 { + mir!( + let temp1: i32; + let temp2: _; + + { + temp1 = x; + Goto(exit) + } + + exit = { + temp2 = Move(temp1); + RET = temp2; + Return() + } + ) +} + +// EMIT_MIR simple_assign.simple_ref.built.after.mir +#[custom_mir(dialect = "built")] +pub fn simple_ref(x: &mut i32) -> &mut i32 { + mir!({ + RET = Move(x); + Return() + }) +} + +fn main() { + assert_eq!(5, simple(5)); +} diff --git a/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir b/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir new file mode 100644 index 00000000000..a5a2834c2e1 --- /dev/null +++ b/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir @@ -0,0 +1,18 @@ +// MIR for `simple` after built + +fn simple(_1: i32) -> i32 { + let mut _0: i32; // return place in scope 0 at $DIR/simple_assign.rs:+0:26: +0:29 + let mut _2: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _3: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _2 = _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + goto -> bb1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + } + + bb1: { + _3 = move _2; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + _0 = _3; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + } +} diff --git a/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir b/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir new file mode 100644 index 00000000000..6c90f0130a2 --- /dev/null +++ b/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir @@ -0,0 +1,10 @@ +// MIR for `simple_ref` after built + +fn simple_ref(_1: &mut i32) -> &mut i32 { + let mut _0: &mut i32; // return place in scope 0 at $DIR/simple_assign.rs:+0:35: +0:43 + + bb0: { + _0 = move _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43 + return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43 + } +} diff --git a/src/test/mir-opt/building/issue_101867.main.built.after.mir b/src/test/mir-opt/building/issue_101867.main.built.after.mir index 6834205b649..0ebd840cf2d 100644 --- a/src/test/mir-opt/building/issue_101867.main.built.after.mir +++ b/src/test/mir-opt/building/issue_101867.main.built.after.mir @@ -1,33 +1,33 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue-101867.rs:3:12: 3:22, inferred_ty: std::option::Option<u8> -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue-101867.rs:3:12: 3:22, inferred_ty: std::option::Option<u8> +| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue_101867.rs:3:12: 3:22, inferred_ty: std::option::Option<u8> +| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue_101867.rs:3:12: 3:22, inferred_ty: std::option::Option<u8> | fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-101867.rs:+0:11: +0:11 - let _1: std::option::Option<u8> as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/issue-101867.rs:+1:9: +1:10 - let mut _2: !; // in scope 0 at $DIR/issue-101867.rs:+2:26: +4:6 + let mut _0: (); // return place in scope 0 at $DIR/issue_101867.rs:+0:11: +0:11 + let _1: std::option::Option<u8> as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/issue_101867.rs:+1:9: +1:10 + let mut _2: !; // in scope 0 at $DIR/issue_101867.rs:+2:26: +4:6 let _3: (); // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL let mut _4: !; // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL - let mut _6: isize; // in scope 0 at $DIR/issue-101867.rs:+2:9: +2:16 + let mut _6: isize; // in scope 0 at $DIR/issue_101867.rs:+2:9: +2:16 scope 1 { - debug x => _1; // in scope 1 at $DIR/issue-101867.rs:+1:9: +1:10 - let _5: u8; // in scope 1 at $DIR/issue-101867.rs:+2:14: +2:15 + debug x => _1; // in scope 1 at $DIR/issue_101867.rs:+1:9: +1:10 + let _5: u8; // in scope 1 at $DIR/issue_101867.rs:+2:14: +2:15 scope 2 { - debug y => _5; // in scope 2 at $DIR/issue-101867.rs:+2:14: +2:15 + debug y => _5; // in scope 2 at $DIR/issue_101867.rs:+2:14: +2:15 } } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-101867.rs:+1:9: +1:10 - _1 = Option::<u8>::Some(const 1_u8); // scope 0 at $DIR/issue-101867.rs:+1:25: +1:32 - FakeRead(ForLet(None), _1); // scope 0 at $DIR/issue-101867.rs:+1:9: +1:10 - AscribeUserType(_1, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue-101867.rs:+1:12: +1:22 - StorageLive(_5); // scope 1 at $DIR/issue-101867.rs:+2:14: +2:15 - FakeRead(ForMatchedPlace(None), _1); // scope 1 at $DIR/issue-101867.rs:+2:19: +2:20 - _6 = discriminant(_1); // scope 1 at $DIR/issue-101867.rs:+2:19: +2:20 - switchInt(move _6) -> [1_isize: bb4, otherwise: bb3]; // scope 1 at $DIR/issue-101867.rs:+2:9: +2:16 + StorageLive(_1); // scope 0 at $DIR/issue_101867.rs:+1:9: +1:10 + _1 = Option::<u8>::Some(const 1_u8); // scope 0 at $DIR/issue_101867.rs:+1:25: +1:32 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/issue_101867.rs:+1:9: +1:10 + AscribeUserType(_1, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue_101867.rs:+1:12: +1:22 + StorageLive(_5); // scope 1 at $DIR/issue_101867.rs:+2:14: +2:15 + FakeRead(ForMatchedPlace(None), _1); // scope 1 at $DIR/issue_101867.rs:+2:19: +2:20 + _6 = discriminant(_1); // scope 1 at $DIR/issue_101867.rs:+2:19: +2:20 + switchInt(move _6) -> [1_isize: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_101867.rs:+2:9: +2:16 } bb1: { @@ -44,32 +44,32 @@ fn main() -> () { bb2: { StorageDead(_4); // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL - StorageDead(_3); // scope 1 at $DIR/issue-101867.rs:+3:16: +3:17 - unreachable; // scope 1 at $DIR/issue-101867.rs:+2:26: +4:6 + StorageDead(_3); // scope 1 at $DIR/issue_101867.rs:+3:16: +3:17 + unreachable; // scope 1 at $DIR/issue_101867.rs:+2:26: +4:6 } bb3: { - goto -> bb6; // scope 1 at $DIR/issue-101867.rs:+2:19: +2:20 + goto -> bb6; // scope 1 at $DIR/issue_101867.rs:+2:19: +2:20 } bb4: { - falseEdge -> [real: bb5, imaginary: bb3]; // scope 1 at $DIR/issue-101867.rs:+2:9: +2:16 + falseEdge -> [real: bb5, imaginary: bb3]; // scope 1 at $DIR/issue_101867.rs:+2:9: +2:16 } bb5: { - _5 = ((_1 as Some).0: u8); // scope 1 at $DIR/issue-101867.rs:+2:14: +2:15 - _0 = const (); // scope 0 at $DIR/issue-101867.rs:+0:11: +5:2 - StorageDead(_5); // scope 1 at $DIR/issue-101867.rs:+5:1: +5:2 - StorageDead(_1); // scope 0 at $DIR/issue-101867.rs:+5:1: +5:2 - return; // scope 0 at $DIR/issue-101867.rs:+5:2: +5:2 + _5 = ((_1 as Some).0: u8); // scope 1 at $DIR/issue_101867.rs:+2:14: +2:15 + _0 = const (); // scope 0 at $DIR/issue_101867.rs:+0:11: +5:2 + StorageDead(_5); // scope 1 at $DIR/issue_101867.rs:+5:1: +5:2 + StorageDead(_1); // scope 0 at $DIR/issue_101867.rs:+5:1: +5:2 + return; // scope 0 at $DIR/issue_101867.rs:+5:2: +5:2 } bb6: { - StorageDead(_5); // scope 1 at $DIR/issue-101867.rs:+5:1: +5:2 - goto -> bb1; // scope 0 at $DIR/issue-101867.rs:+0:11: +5:2 + StorageDead(_5); // scope 1 at $DIR/issue_101867.rs:+5:1: +5:2 + goto -> bb1; // scope 0 at $DIR/issue_101867.rs:+0:11: +5:2 } bb7 (cleanup): { - resume; // scope 0 at $DIR/issue-101867.rs:+0:1: +5:2 + resume; // scope 0 at $DIR/issue_101867.rs:+0:1: +5:2 } } diff --git a/src/test/mir-opt/building/issue-101867.rs b/src/test/mir-opt/building/issue_101867.rs index a32d8cb3714..a32d8cb3714 100644 --- a/src/test/mir-opt/building/issue-101867.rs +++ b/src/test/mir-opt/building/issue_101867.rs diff --git a/src/test/mir-opt/building/issue_49232.main.built.after.mir b/src/test/mir-opt/building/issue_49232.main.built.after.mir index b90f8c13589..9182bcaa21f 100644 --- a/src/test/mir-opt/building/issue_49232.main.built.after.mir +++ b/src/test/mir-opt/building/issue_49232.main.built.after.mir @@ -1,82 +1,82 @@ // MIR for `main` after built fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-49232.rs:+0:11: +0:11 - let mut _1: (); // in scope 0 at $DIR/issue-49232.rs:+0:1: +10:2 - let _2: i32; // in scope 0 at $DIR/issue-49232.rs:+2:13: +2:19 - let mut _3: bool; // in scope 0 at $DIR/issue-49232.rs:+3:19: +3:23 - let mut _4: !; // in scope 0 at $DIR/issue-49232.rs:+5:25: +5:30 - let _5: (); // in scope 0 at $DIR/issue-49232.rs:+8:9: +8:22 - let mut _6: &i32; // in scope 0 at $DIR/issue-49232.rs:+8:14: +8:21 + let mut _0: (); // return place in scope 0 at $DIR/issue_49232.rs:+0:11: +0:11 + let mut _1: (); // in scope 0 at $DIR/issue_49232.rs:+0:1: +10:2 + let _2: i32; // in scope 0 at $DIR/issue_49232.rs:+2:13: +2:19 + let mut _3: bool; // in scope 0 at $DIR/issue_49232.rs:+3:19: +3:23 + let mut _4: !; // in scope 0 at $DIR/issue_49232.rs:+5:25: +5:30 + let _5: (); // in scope 0 at $DIR/issue_49232.rs:+8:9: +8:22 + let mut _6: &i32; // in scope 0 at $DIR/issue_49232.rs:+8:14: +8:21 scope 1 { - debug beacon => _2; // in scope 1 at $DIR/issue-49232.rs:+2:13: +2:19 + debug beacon => _2; // in scope 1 at $DIR/issue_49232.rs:+2:13: +2:19 } bb0: { - goto -> bb1; // scope 0 at $DIR/issue-49232.rs:+1:5: +9:6 + goto -> bb1; // scope 0 at $DIR/issue_49232.rs:+1:5: +9:6 } bb1: { - falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/issue-49232.rs:+1:5: +9:6 + falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/issue_49232.rs:+1:5: +9:6 } bb2: { - StorageLive(_2); // scope 0 at $DIR/issue-49232.rs:+2:13: +2:19 - StorageLive(_3); // scope 0 at $DIR/issue-49232.rs:+3:19: +3:23 - _3 = const true; // scope 0 at $DIR/issue-49232.rs:+3:19: +3:23 - FakeRead(ForMatchedPlace(None), _3); // scope 0 at $DIR/issue-49232.rs:+3:19: +3:23 - switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/issue-49232.rs:+3:13: +3:23 + StorageLive(_2); // scope 0 at $DIR/issue_49232.rs:+2:13: +2:19 + StorageLive(_3); // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23 + _3 = const true; // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23 + FakeRead(ForMatchedPlace(None), _3); // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23 + switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/issue_49232.rs:+3:13: +3:23 } bb3: { - falseEdge -> [real: bb5, imaginary: bb4]; // scope 0 at $DIR/issue-49232.rs:+4:17: +4:22 + falseEdge -> [real: bb5, imaginary: bb4]; // scope 0 at $DIR/issue_49232.rs:+4:17: +4:22 } bb4: { - _0 = const (); // scope 0 at $DIR/issue-49232.rs:+5:25: +5:30 - goto -> bb10; // scope 0 at $DIR/issue-49232.rs:+5:25: +5:30 + _0 = const (); // scope 0 at $DIR/issue_49232.rs:+5:25: +5:30 + goto -> bb10; // scope 0 at $DIR/issue_49232.rs:+5:25: +5:30 } bb5: { - _2 = const 4_i32; // scope 0 at $DIR/issue-49232.rs:+4:26: +4:27 - goto -> bb8; // scope 0 at $DIR/issue-49232.rs:+4:26: +4:27 + _2 = const 4_i32; // scope 0 at $DIR/issue_49232.rs:+4:26: +4:27 + goto -> bb8; // scope 0 at $DIR/issue_49232.rs:+4:26: +4:27 } bb6: { - unreachable; // scope 0 at $DIR/issue-49232.rs:+5:25: +5:30 + unreachable; // scope 0 at $DIR/issue_49232.rs:+5:25: +5:30 } bb7: { - goto -> bb8; // scope 0 at $DIR/issue-49232.rs:+6:13: +6:14 + goto -> bb8; // scope 0 at $DIR/issue_49232.rs:+6:13: +6:14 } bb8: { - FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-49232.rs:+2:13: +2:19 - StorageDead(_3); // scope 0 at $DIR/issue-49232.rs:+7:10: +7:11 - StorageLive(_5); // scope 1 at $DIR/issue-49232.rs:+8:9: +8:22 - StorageLive(_6); // scope 1 at $DIR/issue-49232.rs:+8:14: +8:21 - _6 = &_2; // scope 1 at $DIR/issue-49232.rs:+8:14: +8:21 - _5 = std::mem::drop::<&i32>(move _6) -> [return: bb9, unwind: bb11]; // scope 1 at $DIR/issue-49232.rs:+8:9: +8:22 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue_49232.rs:+2:13: +2:19 + StorageDead(_3); // scope 0 at $DIR/issue_49232.rs:+7:10: +7:11 + StorageLive(_5); // scope 1 at $DIR/issue_49232.rs:+8:9: +8:22 + StorageLive(_6); // scope 1 at $DIR/issue_49232.rs:+8:14: +8:21 + _6 = &_2; // scope 1 at $DIR/issue_49232.rs:+8:14: +8:21 + _5 = std::mem::drop::<&i32>(move _6) -> [return: bb9, unwind: bb11]; // scope 1 at $DIR/issue_49232.rs:+8:9: +8:22 // mir::Constant - // + span: $DIR/issue-49232.rs:13:9: 13:13 + // + span: $DIR/issue_49232.rs:13:9: 13:13 // + literal: Const { ty: fn(&i32) {std::mem::drop::<&i32>}, val: Value(<ZST>) } } bb9: { - StorageDead(_6); // scope 1 at $DIR/issue-49232.rs:+8:21: +8:22 - StorageDead(_5); // scope 1 at $DIR/issue-49232.rs:+8:22: +8:23 - _1 = const (); // scope 0 at $DIR/issue-49232.rs:+1:10: +9:6 - StorageDead(_2); // scope 0 at $DIR/issue-49232.rs:+9:5: +9:6 - goto -> bb1; // scope 0 at $DIR/issue-49232.rs:+1:5: +9:6 + StorageDead(_6); // scope 1 at $DIR/issue_49232.rs:+8:21: +8:22 + StorageDead(_5); // scope 1 at $DIR/issue_49232.rs:+8:22: +8:23 + _1 = const (); // scope 0 at $DIR/issue_49232.rs:+1:10: +9:6 + StorageDead(_2); // scope 0 at $DIR/issue_49232.rs:+9:5: +9:6 + goto -> bb1; // scope 0 at $DIR/issue_49232.rs:+1:5: +9:6 } bb10: { - StorageDead(_3); // scope 0 at $DIR/issue-49232.rs:+7:10: +7:11 - StorageDead(_2); // scope 0 at $DIR/issue-49232.rs:+9:5: +9:6 - return; // scope 0 at $DIR/issue-49232.rs:+10:2: +10:2 + StorageDead(_3); // scope 0 at $DIR/issue_49232.rs:+7:10: +7:11 + StorageDead(_2); // scope 0 at $DIR/issue_49232.rs:+9:5: +9:6 + return; // scope 0 at $DIR/issue_49232.rs:+10:2: +10:2 } bb11 (cleanup): { - resume; // scope 0 at $DIR/issue-49232.rs:+0:1: +10:2 + resume; // scope 0 at $DIR/issue_49232.rs:+0:1: +10:2 } } diff --git a/src/test/mir-opt/building/issue-49232.rs b/src/test/mir-opt/building/issue_49232.rs index 7e9f0de81f7..7e9f0de81f7 100644 --- a/src/test/mir-opt/building/issue-49232.rs +++ b/src/test/mir-opt/building/issue_49232.rs diff --git a/src/test/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/src/test/mir-opt/building/receiver_ptr_mutability.main.built.after.mir index 0192bdc2d5e..41eb00363bd 100644 --- a/src/test/mir-opt/building/receiver_ptr_mutability.main.built.after.mir +++ b/src/test/mir-opt/building/receiver_ptr_mutability.main.built.after.mir @@ -1,96 +1,96 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut Test) }, span: $DIR/receiver-ptr-mutability.rs:14:14: 14:23, inferred_ty: *mut Test -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut Test) }, span: $DIR/receiver-ptr-mutability.rs:14:14: 14:23, inferred_ty: *mut Test -| 2: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], value: Ty(&&&&*mut Test) }, span: $DIR/receiver-ptr-mutability.rs:18:18: 18:31, inferred_ty: &&&&*mut Test -| 3: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], value: Ty(&&&&*mut Test) }, span: $DIR/receiver-ptr-mutability.rs:18:18: 18:31, inferred_ty: &&&&*mut Test +| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut Test) }, span: $DIR/receiver_ptr_mutability.rs:14:14: 14:23, inferred_ty: *mut Test +| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut Test) }, span: $DIR/receiver_ptr_mutability.rs:14:14: 14:23, inferred_ty: *mut Test +| 2: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], value: Ty(&&&&*mut Test) }, span: $DIR/receiver_ptr_mutability.rs:18:18: 18:31, inferred_ty: &&&&*mut Test +| 3: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], value: Ty(&&&&*mut Test) }, span: $DIR/receiver_ptr_mutability.rs:18:18: 18:31, inferred_ty: &&&&*mut Test | fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/receiver-ptr-mutability.rs:+0:11: +0:11 - let _1: *mut Test as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/receiver-ptr-mutability.rs:+1:9: +1:12 - let _2: (); // in scope 0 at $DIR/receiver-ptr-mutability.rs:+2:5: +2:12 - let mut _3: *const Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:+2:5: +2:12 - let mut _4: *mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:+2:5: +2:8 - let _6: &&&&*mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:+5:34: +5:41 - let _7: &&&*mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:+5:35: +5:41 - let _8: &&*mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:+5:36: +5:41 - let _9: &*mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:+5:37: +5:41 - let _10: (); // in scope 0 at $DIR/receiver-ptr-mutability.rs:+6:5: +6:16 - let mut _11: *const Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:+6:5: +6:16 - let mut _12: *mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:+6:5: +6:16 + let mut _0: (); // return place in scope 0 at $DIR/receiver_ptr_mutability.rs:+0:11: +0:11 + let _1: *mut Test as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/receiver_ptr_mutability.rs:+1:9: +1:12 + let _2: (); // in scope 0 at $DIR/receiver_ptr_mutability.rs:+2:5: +2:12 + let mut _3: *const Test; // in scope 0 at $DIR/receiver_ptr_mutability.rs:+2:5: +2:12 + let mut _4: *mut Test; // in scope 0 at $DIR/receiver_ptr_mutability.rs:+2:5: +2:8 + let _6: &&&&*mut Test; // in scope 0 at $DIR/receiver_ptr_mutability.rs:+5:34: +5:41 + let _7: &&&*mut Test; // in scope 0 at $DIR/receiver_ptr_mutability.rs:+5:35: +5:41 + let _8: &&*mut Test; // in scope 0 at $DIR/receiver_ptr_mutability.rs:+5:36: +5:41 + let _9: &*mut Test; // in scope 0 at $DIR/receiver_ptr_mutability.rs:+5:37: +5:41 + let _10: (); // in scope 0 at $DIR/receiver_ptr_mutability.rs:+6:5: +6:16 + let mut _11: *const Test; // in scope 0 at $DIR/receiver_ptr_mutability.rs:+6:5: +6:16 + let mut _12: *mut Test; // in scope 0 at $DIR/receiver_ptr_mutability.rs:+6:5: +6:16 scope 1 { - debug ptr => _1; // in scope 1 at $DIR/receiver-ptr-mutability.rs:+1:9: +1:12 - let _5: &&&&*mut Test as UserTypeProjection { base: UserType(2), projs: [] }; // in scope 1 at $DIR/receiver-ptr-mutability.rs:+5:9: +5:16 + debug ptr => _1; // in scope 1 at $DIR/receiver_ptr_mutability.rs:+1:9: +1:12 + let _5: &&&&*mut Test as UserTypeProjection { base: UserType(2), projs: [] }; // in scope 1 at $DIR/receiver_ptr_mutability.rs:+5:9: +5:16 scope 2 { - debug ptr_ref => _5; // in scope 2 at $DIR/receiver-ptr-mutability.rs:+5:9: +5:16 + debug ptr_ref => _5; // in scope 2 at $DIR/receiver_ptr_mutability.rs:+5:9: +5:16 } } bb0: { - StorageLive(_1); // scope 0 at $DIR/receiver-ptr-mutability.rs:+1:9: +1:12 - _1 = null_mut::<Test>() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/receiver-ptr-mutability.rs:+1:26: +1:46 + StorageLive(_1); // scope 0 at $DIR/receiver_ptr_mutability.rs:+1:9: +1:12 + _1 = null_mut::<Test>() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/receiver_ptr_mutability.rs:+1:26: +1:46 // mir::Constant - // + span: $DIR/receiver-ptr-mutability.rs:14:26: 14:44 + // + span: $DIR/receiver_ptr_mutability.rs:14:26: 14:44 // + literal: Const { ty: fn() -> *mut Test {null_mut::<Test>}, val: Value(<ZST>) } } bb1: { - FakeRead(ForLet(None), _1); // scope 0 at $DIR/receiver-ptr-mutability.rs:+1:9: +1:12 - AscribeUserType(_1, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/receiver-ptr-mutability.rs:+1:14: +1:23 - StorageLive(_2); // scope 1 at $DIR/receiver-ptr-mutability.rs:+2:5: +2:12 - StorageLive(_3); // scope 1 at $DIR/receiver-ptr-mutability.rs:+2:5: +2:12 - StorageLive(_4); // scope 1 at $DIR/receiver-ptr-mutability.rs:+2:5: +2:8 - _4 = _1; // scope 1 at $DIR/receiver-ptr-mutability.rs:+2:5: +2:8 - _3 = move _4 as *const Test (Pointer(MutToConstPointer)); // scope 1 at $DIR/receiver-ptr-mutability.rs:+2:5: +2:12 - StorageDead(_4); // scope 1 at $DIR/receiver-ptr-mutability.rs:+2:7: +2:8 - _2 = Test::x(move _3) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/receiver-ptr-mutability.rs:+2:5: +2:12 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/receiver_ptr_mutability.rs:+1:9: +1:12 + AscribeUserType(_1, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/receiver_ptr_mutability.rs:+1:14: +1:23 + StorageLive(_2); // scope 1 at $DIR/receiver_ptr_mutability.rs:+2:5: +2:12 + StorageLive(_3); // scope 1 at $DIR/receiver_ptr_mutability.rs:+2:5: +2:12 + StorageLive(_4); // scope 1 at $DIR/receiver_ptr_mutability.rs:+2:5: +2:8 + _4 = _1; // scope 1 at $DIR/receiver_ptr_mutability.rs:+2:5: +2:8 + _3 = move _4 as *const Test (Pointer(MutToConstPointer)); // scope 1 at $DIR/receiver_ptr_mutability.rs:+2:5: +2:12 + StorageDead(_4); // scope 1 at $DIR/receiver_ptr_mutability.rs:+2:7: +2:8 + _2 = Test::x(move _3) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/receiver_ptr_mutability.rs:+2:5: +2:12 // mir::Constant - // + span: $DIR/receiver-ptr-mutability.rs:15:9: 15:10 + // + span: $DIR/receiver_ptr_mutability.rs:15:9: 15:10 // + literal: Const { ty: fn(*const Test) {Test::x}, val: Value(<ZST>) } } bb2: { - StorageDead(_3); // scope 1 at $DIR/receiver-ptr-mutability.rs:+2:11: +2:12 - StorageDead(_2); // scope 1 at $DIR/receiver-ptr-mutability.rs:+2:12: +2:13 - StorageLive(_5); // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:9: +5:16 - StorageLive(_6); // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:34: +5:41 - StorageLive(_7); // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:35: +5:41 - StorageLive(_8); // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:36: +5:41 - StorageLive(_9); // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:37: +5:41 - _9 = &_1; // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:37: +5:41 - _8 = &_9; // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:36: +5:41 - _7 = &_8; // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:35: +5:41 - _6 = &_7; // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:34: +5:41 - _5 = &(*_6); // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:34: +5:41 - FakeRead(ForLet(None), _5); // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:9: +5:16 - AscribeUserType(_5, o, UserTypeProjection { base: UserType(3), projs: [] }); // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:18: +5:31 - StorageDead(_6); // scope 1 at $DIR/receiver-ptr-mutability.rs:+5:41: +5:42 - StorageLive(_10); // scope 2 at $DIR/receiver-ptr-mutability.rs:+6:5: +6:16 - StorageLive(_11); // scope 2 at $DIR/receiver-ptr-mutability.rs:+6:5: +6:16 - StorageLive(_12); // scope 2 at $DIR/receiver-ptr-mutability.rs:+6:5: +6:16 - _12 = (*(*(*(*_5)))); // scope 2 at $DIR/receiver-ptr-mutability.rs:+6:5: +6:16 - _11 = move _12 as *const Test (Pointer(MutToConstPointer)); // scope 2 at $DIR/receiver-ptr-mutability.rs:+6:5: +6:16 - StorageDead(_12); // scope 2 at $DIR/receiver-ptr-mutability.rs:+6:11: +6:12 - _10 = Test::x(move _11) -> [return: bb3, unwind: bb4]; // scope 2 at $DIR/receiver-ptr-mutability.rs:+6:5: +6:16 + StorageDead(_3); // scope 1 at $DIR/receiver_ptr_mutability.rs:+2:11: +2:12 + StorageDead(_2); // scope 1 at $DIR/receiver_ptr_mutability.rs:+2:12: +2:13 + StorageLive(_5); // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:9: +5:16 + StorageLive(_6); // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:34: +5:41 + StorageLive(_7); // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:35: +5:41 + StorageLive(_8); // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:36: +5:41 + StorageLive(_9); // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:37: +5:41 + _9 = &_1; // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:37: +5:41 + _8 = &_9; // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:36: +5:41 + _7 = &_8; // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:35: +5:41 + _6 = &_7; // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:34: +5:41 + _5 = &(*_6); // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:34: +5:41 + FakeRead(ForLet(None), _5); // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:9: +5:16 + AscribeUserType(_5, o, UserTypeProjection { base: UserType(3), projs: [] }); // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:18: +5:31 + StorageDead(_6); // scope 1 at $DIR/receiver_ptr_mutability.rs:+5:41: +5:42 + StorageLive(_10); // scope 2 at $DIR/receiver_ptr_mutability.rs:+6:5: +6:16 + StorageLive(_11); // scope 2 at $DIR/receiver_ptr_mutability.rs:+6:5: +6:16 + StorageLive(_12); // scope 2 at $DIR/receiver_ptr_mutability.rs:+6:5: +6:16 + _12 = (*(*(*(*_5)))); // scope 2 at $DIR/receiver_ptr_mutability.rs:+6:5: +6:16 + _11 = move _12 as *const Test (Pointer(MutToConstPointer)); // scope 2 at $DIR/receiver_ptr_mutability.rs:+6:5: +6:16 + StorageDead(_12); // scope 2 at $DIR/receiver_ptr_mutability.rs:+6:11: +6:12 + _10 = Test::x(move _11) -> [return: bb3, unwind: bb4]; // scope 2 at $DIR/receiver_ptr_mutability.rs:+6:5: +6:16 // mir::Constant - // + span: $DIR/receiver-ptr-mutability.rs:19:13: 19:14 + // + span: $DIR/receiver_ptr_mutability.rs:19:13: 19:14 // + literal: Const { ty: fn(*const Test) {Test::x}, val: Value(<ZST>) } } bb3: { - StorageDead(_11); // scope 2 at $DIR/receiver-ptr-mutability.rs:+6:15: +6:16 - StorageDead(_10); // scope 2 at $DIR/receiver-ptr-mutability.rs:+6:16: +6:17 - _0 = const (); // scope 0 at $DIR/receiver-ptr-mutability.rs:+0:11: +7:2 - StorageDead(_9); // scope 1 at $DIR/receiver-ptr-mutability.rs:+7:1: +7:2 - StorageDead(_8); // scope 1 at $DIR/receiver-ptr-mutability.rs:+7:1: +7:2 - StorageDead(_7); // scope 1 at $DIR/receiver-ptr-mutability.rs:+7:1: +7:2 - StorageDead(_5); // scope 1 at $DIR/receiver-ptr-mutability.rs:+7:1: +7:2 - StorageDead(_1); // scope 0 at $DIR/receiver-ptr-mutability.rs:+7:1: +7:2 - return; // scope 0 at $DIR/receiver-ptr-mutability.rs:+7:2: +7:2 + StorageDead(_11); // scope 2 at $DIR/receiver_ptr_mutability.rs:+6:15: +6:16 + StorageDead(_10); // scope 2 at $DIR/receiver_ptr_mutability.rs:+6:16: +6:17 + _0 = const (); // scope 0 at $DIR/receiver_ptr_mutability.rs:+0:11: +7:2 + StorageDead(_9); // scope 1 at $DIR/receiver_ptr_mutability.rs:+7:1: +7:2 + StorageDead(_8); // scope 1 at $DIR/receiver_ptr_mutability.rs:+7:1: +7:2 + StorageDead(_7); // scope 1 at $DIR/receiver_ptr_mutability.rs:+7:1: +7:2 + StorageDead(_5); // scope 1 at $DIR/receiver_ptr_mutability.rs:+7:1: +7:2 + StorageDead(_1); // scope 0 at $DIR/receiver_ptr_mutability.rs:+7:1: +7:2 + return; // scope 0 at $DIR/receiver_ptr_mutability.rs:+7:2: +7:2 } bb4 (cleanup): { - resume; // scope 0 at $DIR/receiver-ptr-mutability.rs:+0:1: +7:2 + resume; // scope 0 at $DIR/receiver_ptr_mutability.rs:+0:1: +7:2 } } diff --git a/src/test/mir-opt/building/receiver-ptr-mutability.rs b/src/test/mir-opt/building/receiver_ptr_mutability.rs index 668530968fe..668530968fe 100644 --- a/src/test/mir-opt/building/receiver-ptr-mutability.rs +++ b/src/test/mir-opt/building/receiver_ptr_mutability.rs diff --git a/src/test/mir-opt/building/simple_match.match_bool.built.after.mir b/src/test/mir-opt/building/simple_match.match_bool.built.after.mir index 5b101cbdee7..a4516026c3b 100644 --- a/src/test/mir-opt/building/simple_match.match_bool.built.after.mir +++ b/src/test/mir-opt/building/simple_match.match_bool.built.after.mir @@ -1,29 +1,29 @@ // MIR for `match_bool` after built fn match_bool(_1: bool) -> usize { - debug x => _1; // in scope 0 at $DIR/simple-match.rs:+0:15: +0:16 - let mut _0: usize; // return place in scope 0 at $DIR/simple-match.rs:+0:27: +0:32 + debug x => _1; // in scope 0 at $DIR/simple_match.rs:+0:15: +0:16 + let mut _0: usize; // return place in scope 0 at $DIR/simple_match.rs:+0:27: +0:32 bb0: { - FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple-match.rs:+1:11: +1:12 - switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:+1:5: +1:12 + FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple_match.rs:+1:11: +1:12 + switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple_match.rs:+1:5: +1:12 } bb1: { - falseEdge -> [real: bb3, imaginary: bb2]; // scope 0 at $DIR/simple-match.rs:+2:9: +2:13 + falseEdge -> [real: bb3, imaginary: bb2]; // scope 0 at $DIR/simple_match.rs:+2:9: +2:13 } bb2: { - _0 = const 20_usize; // scope 0 at $DIR/simple-match.rs:+3:14: +3:16 - goto -> bb4; // scope 0 at $DIR/simple-match.rs:+3:14: +3:16 + _0 = const 20_usize; // scope 0 at $DIR/simple_match.rs:+3:14: +3:16 + goto -> bb4; // scope 0 at $DIR/simple_match.rs:+3:14: +3:16 } bb3: { - _0 = const 10_usize; // scope 0 at $DIR/simple-match.rs:+2:17: +2:19 - goto -> bb4; // scope 0 at $DIR/simple-match.rs:+2:17: +2:19 + _0 = const 10_usize; // scope 0 at $DIR/simple_match.rs:+2:17: +2:19 + goto -> bb4; // scope 0 at $DIR/simple_match.rs:+2:17: +2:19 } bb4: { - return; // scope 0 at $DIR/simple-match.rs:+5:2: +5:2 + return; // scope 0 at $DIR/simple_match.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/building/simple-match.rs b/src/test/mir-opt/building/simple_match.rs index 0ef97dde636..0ef97dde636 100644 --- a/src/test/mir-opt/building/simple-match.rs +++ b/src/test/mir-opt/building/simple_match.rs diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 7650769de3b..028480bdc88 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -1,20 +1,20 @@ // MIR for `BAR::promoted[0]` after SimplifyCfg-elaborate-drops promoted[0] in BAR: &[&i32; 1] = { - let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 - let mut _1: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:35 - let mut _2: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:32: +0:34 - let mut _3: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:33: +0:34 + let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 + let mut _1: [&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:35 + let mut _2: &i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:34 + let mut _3: &i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:33: +0:34 bb0: { - _3 = const {alloc1: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:33: +0:34 + _3 = const {alloc1: &i32}; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:33: +0:34 // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 + // + span: $DIR/const_promotion_extern_static.rs:9:33: 9:34 // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } - _2 = &(*_3); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:32: +0:34 - _1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:35 - _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 + _2 = &(*_3); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:34 + _1 = [move _2]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:35 + _0 = &_1; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 + return; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 } } diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index f8a7c687e12..2ef4378115f 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -2,49 +2,49 @@ + // MIR for `BAR` after PromoteTemps static mut BAR: *const &i32 = { - let mut _0: *const &i32; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:+0:17: +0:28 - let mut _1: &[&i32]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 - let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 - let _3: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:35 - let mut _4: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:32: +0:34 - let _5: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:33: +0:34 -+ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 + let mut _0: *const &i32; // return place in scope 0 at $DIR/const_promotion_extern_static.rs:+0:17: +0:28 + let mut _1: &[&i32]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 + let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 + let _3: [&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:35 + let mut _4: &i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:34 + let _5: &i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:33: +0:34 ++ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 bb0: { - StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 - StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 -- StorageLive(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:35 -- StorageLive(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:32: +0:34 -- StorageLive(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:33: +0:34 -- _5 = const {alloc1: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:33: +0:34 -+ _6 = const _; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 + StorageLive(_1); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 + StorageLive(_2); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 +- StorageLive(_3); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:35 +- StorageLive(_4); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:34 +- StorageLive(_5); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:33: +0:34 +- _5 = const {alloc1: &i32}; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:33: +0:34 ++ _6 = const _; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 // mir::Constant -- // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 +- // + span: $DIR/const_promotion_extern_static.rs:9:33: 9:34 - // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } -- _4 = &(*_5); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:32: +0:34 -- _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:35 -- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 -+ // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:44 +- _4 = &(*_5); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:34 +- _3 = [move _4]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:35 +- _2 = &_3; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 ++ // + span: $DIR/const_promotion_extern_static.rs:9:31: 9:44 + // + literal: Const { ty: &[&i32; 1], val: Unevaluated(BAR, [], Some(promoted[0])) } -+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 - _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 -- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:34: +0:35 - StorageDead(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:34: +0:35 - _0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 ++ _2 = &(*_6); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 + _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 +- StorageDead(_4); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:34: +0:35 + StorageDead(_2); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:34: +0:35 + _0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:9:36: 9:42 + // + span: $DIR/const_promotion_extern_static.rs:9:36: 9:42 // + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) } } bb1: { -- StorageDead(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:43: +0:44 -- StorageDead(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:43: +0:44 - StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:43: +0:44 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:45 +- StorageDead(_5); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:43: +0:44 +- StorageDead(_3); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:43: +0:44 + StorageDead(_1); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:43: +0:44 + return; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:1: +0:45 } bb2 (cleanup): { - resume; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:45 + resume; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:1: +0:45 } - } - diff --git a/src/test/mir-opt/const_promotion_extern_static.BOP.built.after.mir b/src/test/mir-opt/const_promotion_extern_static.BOP.built.after.mir index 5bda86bbd4f..476fc49a1fe 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BOP.built.after.mir +++ b/src/test/mir-opt/const_promotion_extern_static.BOP.built.after.mir @@ -1,17 +1,17 @@ // MIR for `BOP` after built static BOP: &i32 = { - let mut _0: &i32; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:+0:13: +0:17 - let _1: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:20: +0:23 - let _2: i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:21: +0:23 + let mut _0: &i32; // return place in scope 0 at $DIR/const_promotion_extern_static.rs:+0:13: +0:17 + let _1: &i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:20: +0:23 + let _2: i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:21: +0:23 bb0: { - StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:20: +0:23 - StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:21: +0:23 - _2 = const 13_i32; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:21: +0:23 - _1 = &_2; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:20: +0:23 - _0 = &(*_1); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:20: +0:23 - StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:22: +0:23 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:24 + StorageLive(_1); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:20: +0:23 + StorageLive(_2); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:21: +0:23 + _2 = const 13_i32; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:21: +0:23 + _1 = &_2; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:20: +0:23 + _0 = &(*_1); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:20: +0:23 + StorageDead(_1); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:22: +0:23 + return; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:1: +0:24 } } diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 71827eab1c2..41657b53fc1 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -1,20 +1,20 @@ // MIR for `FOO::promoted[0]` after SimplifyCfg-elaborate-drops promoted[0] in FOO: &[&i32; 1] = { - let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 - let mut _1: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:46 - let mut _2: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:32: +0:45 - let mut _3: *const i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:42: +0:43 + let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 + let mut _1: [&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 + let mut _2: &i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:45 + let mut _3: *const i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 bb0: { - _3 = const {alloc3: *const i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:42: +0:43 + _3 = const {alloc3: *const i32}; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 + // + span: $DIR/const_promotion_extern_static.rs:13:42: 13:43 // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) } - _2 = &(*_3); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:41: +0:43 - _1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:46 - _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 + _2 = &(*_3); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:41: +0:43 + _1 = [move _2]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 + _0 = &_1; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 + return; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 } } diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index e938ca28af5..25ba0face6b 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -2,51 +2,51 @@ + // MIR for `FOO` after PromoteTemps static mut FOO: *const &i32 = { - let mut _0: *const &i32; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:+0:17: +0:28 - let mut _1: &[&i32]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 - let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 - let _3: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:46 - let mut _4: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:32: +0:45 - let _5: *const i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:42: +0:43 -+ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 + let mut _0: *const &i32; // return place in scope 0 at $DIR/const_promotion_extern_static.rs:+0:17: +0:28 + let mut _1: &[&i32]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 + let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 + let _3: [&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 + let mut _4: &i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:45 + let _5: *const i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 ++ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 scope 1 { } bb0: { - StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 - StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 -- StorageLive(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:46 -- StorageLive(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:32: +0:45 -- StorageLive(_5); // scope 1 at $DIR/const-promotion-extern-static.rs:+0:42: +0:43 -- _5 = const {alloc3: *const i32}; // scope 1 at $DIR/const-promotion-extern-static.rs:+0:42: +0:43 -+ _6 = const _; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 + StorageLive(_1); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 + StorageLive(_2); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 +- StorageLive(_3); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 +- StorageLive(_4); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:45 +- StorageLive(_5); // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 +- _5 = const {alloc3: *const i32}; // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 ++ _6 = const _; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 // mir::Constant -- // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 +- // + span: $DIR/const_promotion_extern_static.rs:13:42: 13:43 - // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) } -- _4 = &(*_5); // scope 1 at $DIR/const-promotion-extern-static.rs:+0:41: +0:43 -- _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:46 -- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 -+ // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:55 +- _4 = &(*_5); // scope 1 at $DIR/const_promotion_extern_static.rs:+0:41: +0:43 +- _3 = [move _4]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 +- _2 = &_3; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 ++ // + span: $DIR/const_promotion_extern_static.rs:13:31: 13:55 + // + literal: Const { ty: &[&i32; 1], val: Unevaluated(FOO, [], Some(promoted[0])) } -+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 - _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 -- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:45: +0:46 - StorageDead(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:45: +0:46 - _0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 ++ _2 = &(*_6); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 + _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 +- StorageDead(_4); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:45: +0:46 + StorageDead(_2); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:45: +0:46 + _0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:13:47: 13:53 + // + span: $DIR/const_promotion_extern_static.rs:13:47: 13:53 // + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) } } bb1: { -- StorageDead(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:54: +0:55 -- StorageDead(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:54: +0:55 - StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:+0:54: +0:55 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:56 +- StorageDead(_5); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:54: +0:55 +- StorageDead(_3); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:54: +0:55 + StorageDead(_1); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:54: +0:55 + return; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:1: +0:56 } bb2 (cleanup): { - resume; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:56 + resume; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:1: +0:56 } } - diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const_promotion_extern_static.rs index e4261cfe504..e4261cfe504 100644 --- a/src/test/mir-opt/const-promotion-extern-static.rs +++ b/src/test/mir-opt/const_promotion_extern_static.rs diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff index a07bdd99825..8b3b9d0a4c1 100644 --- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff +++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff @@ -2,15 +2,15 @@ + // MIR for `hello` after ConstProp fn hello() -> () { - let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:14: +0:14 - let mut _1: bool; // in scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 + let mut _0: (); // return place in scope 0 at $DIR/control_flow_simplification.rs:+0:14: +0:14 + let mut _1: bool; // in scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21 let mut _2: !; // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL bb0: { - StorageLive(_1); // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 - _1 = const _; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 -- switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 -+ switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 + StorageLive(_1); // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21 + _1 = const _; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21 +- switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21 ++ switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21 } bb1: { @@ -25,9 +25,9 @@ } bb2: { - nop; // scope 0 at $DIR/control-flow-simplification.rs:+3:6: +3:6 - StorageDead(_1); // scope 0 at $DIR/control-flow-simplification.rs:+3:5: +3:6 - return; // scope 0 at $DIR/control-flow-simplification.rs:+4:2: +4:2 + nop; // scope 0 at $DIR/control_flow_simplification.rs:+3:6: +3:6 + StorageDead(_1); // scope 0 at $DIR/control_flow_simplification.rs:+3:5: +3:6 + return; // scope 0 at $DIR/control_flow_simplification.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir b/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir index 70f97977511..9f7528f0ce1 100644 --- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir +++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir @@ -1,9 +1,9 @@ // MIR for `hello` before PreCodegen fn hello() -> () { - let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:14: +0:14 + let mut _0: (); // return place in scope 0 at $DIR/control_flow_simplification.rs:+0:14: +0:14 bb0: { - return; // scope 0 at $DIR/control-flow-simplification.rs:+4:2: +4:2 + return; // scope 0 at $DIR/control_flow_simplification.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/const_prop/control-flow-simplification.rs b/src/test/mir-opt/const_prop/control_flow_simplification.rs index 7dbe8e7344b..7dbe8e7344b 100644 --- a/src/test/mir-opt/const_prop/control-flow-simplification.rs +++ b/src/test/mir-opt/const_prop/control_flow_simplification.rs diff --git a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff index 9d541dcabbb..7d8e647cbce 100644 --- a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff @@ -2,32 +2,32 @@ + // MIR for `main` after ConstProp fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-66971.rs:+0:11: +0:11 - let _1: (); // in scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 - let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - let mut _3: (); // in scope 0 at $DIR/issue-66971.rs:+1:13: +1:15 + let mut _0: (); // return place in scope 0 at $DIR/issue_66971.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 + let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 + let mut _3: (); // in scope 0 at $DIR/issue_66971.rs:+1:13: +1:15 bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 - StorageLive(_2); // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - StorageLive(_3); // scope 0 at $DIR/issue-66971.rs:+1:13: +1:15 - nop; // scope 0 at $DIR/issue-66971.rs:+1:13: +1:15 - Deinit(_2); // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - nop; // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - StorageDead(_3); // scope 0 at $DIR/issue-66971.rs:+1:21: +1:22 - _1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 + StorageLive(_1); // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 + StorageLive(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 + StorageLive(_3); // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15 + nop; // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15 + Deinit(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 + nop; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 + (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 + (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 + StorageDead(_3); // scope 0 at $DIR/issue_66971.rs:+1:21: +1:22 + _1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 // mir::Constant - // + span: $DIR/issue-66971.rs:17:5: 17:11 + // + span: $DIR/issue_66971.rs:17:5: 17:11 // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value(<ZST>) } } bb1: { - StorageDead(_2); // scope 0 at $DIR/issue-66971.rs:+1:22: +1:23 - StorageDead(_1); // scope 0 at $DIR/issue-66971.rs:+1:23: +1:24 - nop; // scope 0 at $DIR/issue-66971.rs:+0:11: +2:2 - return; // scope 0 at $DIR/issue-66971.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/issue_66971.rs:+1:22: +1:23 + StorageDead(_1); // scope 0 at $DIR/issue_66971.rs:+1:23: +1:24 + nop; // scope 0 at $DIR/issue_66971.rs:+0:11: +2:2 + return; // scope 0 at $DIR/issue_66971.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_prop/issue-66971.rs b/src/test/mir-opt/const_prop/issue_66971.rs index 6ca03438ef3..6ca03438ef3 100644 --- a/src/test/mir-opt/const_prop/issue-66971.rs +++ b/src/test/mir-opt/const_prop/issue_66971.rs diff --git a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff index b79d814760d..79cd8bf4839 100644 --- a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff @@ -2,33 +2,33 @@ + // MIR for `main` after ConstProp fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-67019.rs:+0:11: +0:11 - let _1: (); // in scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 - let mut _2: ((u8, u8),); // in scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 - let mut _3: (u8, u8); // in scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 + let mut _0: (); // return place in scope 0 at $DIR/issue_67019.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/issue_67019.rs:+1:5: +1:20 + let mut _2: ((u8, u8),); // in scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 + let mut _3: (u8, u8); // in scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 - StorageLive(_2); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 - StorageLive(_3); // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 - Deinit(_3); // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 - (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 - (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 - Deinit(_2); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 -- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 -+ (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 - StorageDead(_3); // scope 0 at $DIR/issue-67019.rs:+1:18: +1:19 - _1 = test(move _2) -> bb1; // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 + StorageLive(_1); // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20 + StorageLive(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 + StorageLive(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 + Deinit(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 + (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 + (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 + Deinit(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 +- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 ++ (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 + StorageDead(_3); // scope 0 at $DIR/issue_67019.rs:+1:18: +1:19 + _1 = test(move _2) -> bb1; // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20 // mir::Constant - // + span: $DIR/issue-67019.rs:12:5: 12:9 + // + span: $DIR/issue_67019.rs:12:5: 12:9 // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value(<ZST>) } } bb1: { - StorageDead(_2); // scope 0 at $DIR/issue-67019.rs:+1:19: +1:20 - StorageDead(_1); // scope 0 at $DIR/issue-67019.rs:+1:20: +1:21 - nop; // scope 0 at $DIR/issue-67019.rs:+0:11: +2:2 - return; // scope 0 at $DIR/issue-67019.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/issue_67019.rs:+1:19: +1:20 + StorageDead(_1); // scope 0 at $DIR/issue_67019.rs:+1:20: +1:21 + nop; // scope 0 at $DIR/issue_67019.rs:+0:11: +2:2 + return; // scope 0 at $DIR/issue_67019.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_prop/issue-67019.rs b/src/test/mir-opt/const_prop/issue_67019.rs index ffc6fa1f290..ffc6fa1f290 100644 --- a/src/test/mir-opt/const_prop/issue-67019.rs +++ b/src/test/mir-opt/const_prop/issue_67019.rs diff --git a/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir index 96716a39a2b..08481777ed4 100644 --- a/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir @@ -1,83 +1,83 @@ // MIR for `match_tuple` after SimplifyCfg-initial fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 { - debug x => _1; // in scope 0 at $DIR/exponential-or.rs:+0:16: +0:17 - let mut _0: u32; // return place in scope 0 at $DIR/exponential-or.rs:+0:53: +0:56 - let mut _2: isize; // in scope 0 at $DIR/exponential-or.rs:+2:37: +2:48 - let mut _3: bool; // in scope 0 at $DIR/exponential-or.rs:+2:70: +2:77 - let mut _4: bool; // in scope 0 at $DIR/exponential-or.rs:+2:70: +2:77 - let mut _5: bool; // in scope 0 at $DIR/exponential-or.rs:+2:62: +2:67 - let mut _6: bool; // in scope 0 at $DIR/exponential-or.rs:+2:62: +2:67 - let _7: u32; // in scope 0 at $DIR/exponential-or.rs:+2:10: +2:11 - let _8: u32; // in scope 0 at $DIR/exponential-or.rs:+2:57: +2:58 - let mut _9: u32; // in scope 0 at $DIR/exponential-or.rs:+2:83: +2:84 - let mut _10: u32; // in scope 0 at $DIR/exponential-or.rs:+2:87: +2:88 + debug x => _1; // in scope 0 at $DIR/exponential_or.rs:+0:16: +0:17 + let mut _0: u32; // return place in scope 0 at $DIR/exponential_or.rs:+0:53: +0:56 + let mut _2: isize; // in scope 0 at $DIR/exponential_or.rs:+2:37: +2:48 + let mut _3: bool; // in scope 0 at $DIR/exponential_or.rs:+2:70: +2:77 + let mut _4: bool; // in scope 0 at $DIR/exponential_or.rs:+2:70: +2:77 + let mut _5: bool; // in scope 0 at $DIR/exponential_or.rs:+2:62: +2:67 + let mut _6: bool; // in scope 0 at $DIR/exponential_or.rs:+2:62: +2:67 + let _7: u32; // in scope 0 at $DIR/exponential_or.rs:+2:10: +2:11 + let _8: u32; // in scope 0 at $DIR/exponential_or.rs:+2:57: +2:58 + let mut _9: u32; // in scope 0 at $DIR/exponential_or.rs:+2:83: +2:84 + let mut _10: u32; // in scope 0 at $DIR/exponential_or.rs:+2:87: +2:88 scope 1 { - debug y => _7; // in scope 1 at $DIR/exponential-or.rs:+2:10: +2:11 - debug z => _8; // in scope 1 at $DIR/exponential-or.rs:+2:57: +2:58 + debug y => _7; // in scope 1 at $DIR/exponential_or.rs:+2:10: +2:11 + debug z => _8; // in scope 1 at $DIR/exponential_or.rs:+2:57: +2:58 } bb0: { - FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/exponential-or.rs:+1:11: +1:12 - switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:+2:15: +2:20 + FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/exponential_or.rs:+1:11: +1:12 + switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:15: +2:20 } bb1: { - _0 = const 0_u32; // scope 0 at $DIR/exponential-or.rs:+3:14: +3:15 - goto -> bb10; // scope 0 at $DIR/exponential-or.rs:+3:14: +3:15 + _0 = const 0_u32; // scope 0 at $DIR/exponential_or.rs:+3:14: +3:15 + goto -> bb10; // scope 0 at $DIR/exponential_or.rs:+3:14: +3:15 } bb2: { - _2 = discriminant((_1.2: std::option::Option<i32>)); // scope 0 at $DIR/exponential-or.rs:+2:37: +2:55 - switchInt(move _2) -> [0_isize: bb4, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:+2:37: +2:55 + _2 = discriminant((_1.2: std::option::Option<i32>)); // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55 + switchInt(move _2) -> [0_isize: bb4, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55 } bb3: { - switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1_i32: bb4, 8_i32: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:+2:37: +2:55 + switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1_i32: bb4, 8_i32: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55 } bb4: { - _5 = Le(const 6_u32, (_1.3: u32)); // scope 0 at $DIR/exponential-or.rs:+2:62: +2:67 - switchInt(move _5) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential-or.rs:+2:62: +2:67 + _5 = Le(const 6_u32, (_1.3: u32)); // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67 + switchInt(move _5) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67 } bb5: { - _6 = Le((_1.3: u32), const 9_u32); // scope 0 at $DIR/exponential-or.rs:+2:62: +2:67 - switchInt(move _6) -> [false: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential-or.rs:+2:62: +2:67 + _6 = Le((_1.3: u32), const 9_u32); // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67 + switchInt(move _6) -> [false: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67 } bb6: { - _3 = Le(const 13_u32, (_1.3: u32)); // scope 0 at $DIR/exponential-or.rs:+2:70: +2:77 - switchInt(move _3) -> [false: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential-or.rs:+2:70: +2:77 + _3 = Le(const 13_u32, (_1.3: u32)); // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77 + switchInt(move _3) -> [false: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77 } bb7: { - _4 = Le((_1.3: u32), const 16_u32); // scope 0 at $DIR/exponential-or.rs:+2:70: +2:77 - switchInt(move _4) -> [false: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential-or.rs:+2:70: +2:77 + _4 = Le((_1.3: u32), const 16_u32); // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77 + switchInt(move _4) -> [false: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77 } bb8: { - falseEdge -> [real: bb9, imaginary: bb1]; // scope 0 at $DIR/exponential-or.rs:+2:9: +2:79 + falseEdge -> [real: bb9, imaginary: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:9: +2:79 } bb9: { - StorageLive(_7); // scope 0 at $DIR/exponential-or.rs:+2:10: +2:11 - _7 = (_1.0: u32); // scope 0 at $DIR/exponential-or.rs:+2:10: +2:11 - StorageLive(_8); // scope 0 at $DIR/exponential-or.rs:+2:57: +2:58 - _8 = (_1.3: u32); // scope 0 at $DIR/exponential-or.rs:+2:57: +2:58 - StorageLive(_9); // scope 1 at $DIR/exponential-or.rs:+2:83: +2:84 - _9 = _7; // scope 1 at $DIR/exponential-or.rs:+2:83: +2:84 - StorageLive(_10); // scope 1 at $DIR/exponential-or.rs:+2:87: +2:88 - _10 = _8; // scope 1 at $DIR/exponential-or.rs:+2:87: +2:88 - _0 = BitXor(move _9, move _10); // scope 1 at $DIR/exponential-or.rs:+2:83: +2:88 - StorageDead(_10); // scope 1 at $DIR/exponential-or.rs:+2:87: +2:88 - StorageDead(_9); // scope 1 at $DIR/exponential-or.rs:+2:87: +2:88 - StorageDead(_8); // scope 0 at $DIR/exponential-or.rs:+2:87: +2:88 - StorageDead(_7); // scope 0 at $DIR/exponential-or.rs:+2:87: +2:88 - goto -> bb10; // scope 0 at $DIR/exponential-or.rs:+2:87: +2:88 + StorageLive(_7); // scope 0 at $DIR/exponential_or.rs:+2:10: +2:11 + _7 = (_1.0: u32); // scope 0 at $DIR/exponential_or.rs:+2:10: +2:11 + StorageLive(_8); // scope 0 at $DIR/exponential_or.rs:+2:57: +2:58 + _8 = (_1.3: u32); // scope 0 at $DIR/exponential_or.rs:+2:57: +2:58 + StorageLive(_9); // scope 1 at $DIR/exponential_or.rs:+2:83: +2:84 + _9 = _7; // scope 1 at $DIR/exponential_or.rs:+2:83: +2:84 + StorageLive(_10); // scope 1 at $DIR/exponential_or.rs:+2:87: +2:88 + _10 = _8; // scope 1 at $DIR/exponential_or.rs:+2:87: +2:88 + _0 = BitXor(move _9, move _10); // scope 1 at $DIR/exponential_or.rs:+2:83: +2:88 + StorageDead(_10); // scope 1 at $DIR/exponential_or.rs:+2:87: +2:88 + StorageDead(_9); // scope 1 at $DIR/exponential_or.rs:+2:87: +2:88 + StorageDead(_8); // scope 0 at $DIR/exponential_or.rs:+2:87: +2:88 + StorageDead(_7); // scope 0 at $DIR/exponential_or.rs:+2:87: +2:88 + goto -> bb10; // scope 0 at $DIR/exponential_or.rs:+2:87: +2:88 } bb10: { - return; // scope 0 at $DIR/exponential-or.rs:+5:2: +5:2 + return; // scope 0 at $DIR/exponential_or.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/exponential-or.rs b/src/test/mir-opt/exponential_or.rs index 0b8be8385dd..0b8be8385dd 100644 --- a/src/test/mir-opt/exponential-or.rs +++ b/src/test/mir-opt/exponential_or.rs diff --git a/src/test/mir-opt/fn-ptr-shim.rs b/src/test/mir-opt/fn_ptr_shim.rs index 64fbdc9ded1..64fbdc9ded1 100644 --- a/src/test/mir-opt/fn-ptr-shim.rs +++ b/src/test/mir-opt/fn_ptr_shim.rs diff --git a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir index c718138b6b3..c3b08bf0648 100644 --- a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir +++ b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir @@ -14,71 +14,71 @@ }, } */ -fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 10:17]) -> () { - let mut _0: (); // return place in scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 - let mut _2: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 - let _3: std::string::String; // in scope 0 at $DIR/generator-drop-cleanup.rs:+1:13: +1:15 - let _4: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:+2:9: +2:14 - let mut _5: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:+2:9: +2:14 - let mut _6: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:+0:18: +0:18 - let mut _7: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 - let mut _8: u32; // in scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 +fn main::{closure#0}(_1: *mut [generator@$DIR/generator_drop_cleanup.rs:10:15: 10:17]) -> () { + let mut _0: (); // return place in scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 + let mut _2: (); // in scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 + let _3: std::string::String; // in scope 0 at $DIR/generator_drop_cleanup.rs:+1:13: +1:15 + let _4: (); // in scope 0 at $DIR/generator_drop_cleanup.rs:+2:9: +2:14 + let mut _5: (); // in scope 0 at $DIR/generator_drop_cleanup.rs:+2:9: +2:14 + let mut _6: (); // in scope 0 at $DIR/generator_drop_cleanup.rs:+0:18: +0:18 + let mut _7: (); // in scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 + let mut _8: u32; // in scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 scope 1 { - debug _s => (((*_1) as variant#3).0: std::string::String); // in scope 1 at $DIR/generator-drop-cleanup.rs:+1:13: +1:15 + debug _s => (((*_1) as variant#3).0: std::string::String); // in scope 1 at $DIR/generator_drop_cleanup.rs:+1:13: +1:15 } bb0: { - _8 = discriminant((*_1)); // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 - switchInt(move _8) -> [0_u32: bb7, 3_u32: bb10, otherwise: bb11]; // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 + _8 = discriminant((*_1)); // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 + switchInt(move _8) -> [0_u32: bb7, 3_u32: bb10, otherwise: bb11]; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 } bb1: { - StorageDead(_5); // scope 1 at $DIR/generator-drop-cleanup.rs:+2:13: +2:14 - StorageDead(_4); // scope 1 at $DIR/generator-drop-cleanup.rs:+2:14: +2:15 - drop((((*_1) as variant#3).0: std::string::String)) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6 + StorageDead(_5); // scope 1 at $DIR/generator_drop_cleanup.rs:+2:13: +2:14 + StorageDead(_4); // scope 1 at $DIR/generator_drop_cleanup.rs:+2:14: +2:15 + drop((((*_1) as variant#3).0: std::string::String)) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/generator_drop_cleanup.rs:+3:5: +3:6 } bb2: { - nop; // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6 - goto -> bb8; // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6 + nop; // scope 0 at $DIR/generator_drop_cleanup.rs:+3:5: +3:6 + goto -> bb8; // scope 0 at $DIR/generator_drop_cleanup.rs:+3:5: +3:6 } bb3: { - return; // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 + return; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 } bb4 (cleanup): { - resume; // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 + resume; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 } bb5 (cleanup): { - nop; // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6 - goto -> bb4; // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6 + nop; // scope 0 at $DIR/generator_drop_cleanup.rs:+3:5: +3:6 + goto -> bb4; // scope 0 at $DIR/generator_drop_cleanup.rs:+3:5: +3:6 } bb6: { - return; // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 + return; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 } bb7: { - goto -> bb9; // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 + goto -> bb9; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 } bb8: { - goto -> bb3; // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6 + goto -> bb3; // scope 0 at $DIR/generator_drop_cleanup.rs:+3:5: +3:6 } bb9: { - goto -> bb6; // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 + goto -> bb6; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 } bb10: { - StorageLive(_4); // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 - StorageLive(_5); // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 - goto -> bb1; // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 + StorageLive(_4); // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 + StorageLive(_5); // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 + goto -> bb1; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 } bb11: { - return; // scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +3:6 + return; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6 } } diff --git a/src/test/mir-opt/generator-drop-cleanup.rs b/src/test/mir-opt/generator_drop_cleanup.rs index 82c1292cbd0..82c1292cbd0 100644 --- a/src/test/mir-opt/generator-drop-cleanup.rs +++ b/src/test/mir-opt/generator_drop_cleanup.rs diff --git a/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir b/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir index 3184343f207..cfbe0aaf252 100644 --- a/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir +++ b/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir @@ -1,124 +1,124 @@ // MIR for `main::{closure#0}` before StateTransform -fn main::{closure#0}(_1: [generator@$DIR/generator-storage-dead-unwind.rs:22:16: 22:18], _2: ()) -> () +fn main::{closure#0}(_1: [generator@$DIR/generator_storage_dead_unwind.rs:22:16: 22:18], _2: ()) -> () yields () { - let mut _0: (); // return place in scope 0 at $DIR/generator-storage-dead-unwind.rs:+0:19: +0:19 - let _3: Foo; // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+1:13: +1:14 - let _5: (); // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14 - let mut _6: (); // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14 - let _7: (); // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+4:9: +4:16 - let mut _8: Foo; // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+4:14: +4:15 - let _9: (); // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+5:9: +5:16 - let mut _10: Bar; // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+5:14: +5:15 + let mut _0: (); // return place in scope 0 at $DIR/generator_storage_dead_unwind.rs:+0:19: +0:19 + let _3: Foo; // in scope 0 at $DIR/generator_storage_dead_unwind.rs:+1:13: +1:14 + let _5: (); // in scope 0 at $DIR/generator_storage_dead_unwind.rs:+3:9: +3:14 + let mut _6: (); // in scope 0 at $DIR/generator_storage_dead_unwind.rs:+3:9: +3:14 + let _7: (); // in scope 0 at $DIR/generator_storage_dead_unwind.rs:+4:9: +4:16 + let mut _8: Foo; // in scope 0 at $DIR/generator_storage_dead_unwind.rs:+4:14: +4:15 + let _9: (); // in scope 0 at $DIR/generator_storage_dead_unwind.rs:+5:9: +5:16 + let mut _10: Bar; // in scope 0 at $DIR/generator_storage_dead_unwind.rs:+5:14: +5:15 scope 1 { - debug a => _3; // in scope 1 at $DIR/generator-storage-dead-unwind.rs:+1:13: +1:14 - let _4: Bar; // in scope 1 at $DIR/generator-storage-dead-unwind.rs:+2:13: +2:14 + debug a => _3; // in scope 1 at $DIR/generator_storage_dead_unwind.rs:+1:13: +1:14 + let _4: Bar; // in scope 1 at $DIR/generator_storage_dead_unwind.rs:+2:13: +2:14 scope 2 { - debug b => _4; // in scope 2 at $DIR/generator-storage-dead-unwind.rs:+2:13: +2:14 + debug b => _4; // in scope 2 at $DIR/generator_storage_dead_unwind.rs:+2:13: +2:14 } } bb0: { - StorageLive(_3); // scope 0 at $DIR/generator-storage-dead-unwind.rs:+1:13: +1:14 - _3 = Foo(const 5_i32); // scope 0 at $DIR/generator-storage-dead-unwind.rs:+1:17: +1:23 - StorageLive(_4); // scope 1 at $DIR/generator-storage-dead-unwind.rs:+2:13: +2:14 - _4 = Bar(const 6_i32); // scope 1 at $DIR/generator-storage-dead-unwind.rs:+2:17: +2:23 - StorageLive(_5); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14 - StorageLive(_6); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14 - _6 = (); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14 - _5 = yield(move _6) -> [resume: bb1, drop: bb6]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14 + StorageLive(_3); // scope 0 at $DIR/generator_storage_dead_unwind.rs:+1:13: +1:14 + _3 = Foo(const 5_i32); // scope 0 at $DIR/generator_storage_dead_unwind.rs:+1:17: +1:23 + StorageLive(_4); // scope 1 at $DIR/generator_storage_dead_unwind.rs:+2:13: +2:14 + _4 = Bar(const 6_i32); // scope 1 at $DIR/generator_storage_dead_unwind.rs:+2:17: +2:23 + StorageLive(_5); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+3:9: +3:14 + StorageLive(_6); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+3:9: +3:14 + _6 = (); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+3:9: +3:14 + _5 = yield(move _6) -> [resume: bb1, drop: bb6]; // scope 2 at $DIR/generator_storage_dead_unwind.rs:+3:9: +3:14 } bb1: { - StorageDead(_6); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:13: +3:14 - StorageDead(_5); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:14: +3:15 - StorageLive(_7); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:9: +4:16 - StorageLive(_8); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:14: +4:15 - _8 = move _3; // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:14: +4:15 - _7 = take::<Foo>(move _8) -> [return: bb2, unwind: bb10]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:9: +4:16 + StorageDead(_6); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+3:13: +3:14 + StorageDead(_5); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+3:14: +3:15 + StorageLive(_7); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+4:9: +4:16 + StorageLive(_8); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+4:14: +4:15 + _8 = move _3; // scope 2 at $DIR/generator_storage_dead_unwind.rs:+4:14: +4:15 + _7 = take::<Foo>(move _8) -> [return: bb2, unwind: bb10]; // scope 2 at $DIR/generator_storage_dead_unwind.rs:+4:9: +4:16 // mir::Constant - // + span: $DIR/generator-storage-dead-unwind.rs:26:9: 26:13 + // + span: $DIR/generator_storage_dead_unwind.rs:26:9: 26:13 // + literal: Const { ty: fn(Foo) {take::<Foo>}, val: Value(<ZST>) } } bb2: { - StorageDead(_8); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:15: +4:16 - StorageDead(_7); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:16: +4:17 - StorageLive(_9); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:9: +5:16 - StorageLive(_10); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:14: +5:15 - _10 = move _4; // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:14: +5:15 - _9 = take::<Bar>(move _10) -> [return: bb3, unwind: bb9]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:9: +5:16 + StorageDead(_8); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+4:15: +4:16 + StorageDead(_7); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+4:16: +4:17 + StorageLive(_9); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+5:9: +5:16 + StorageLive(_10); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+5:14: +5:15 + _10 = move _4; // scope 2 at $DIR/generator_storage_dead_unwind.rs:+5:14: +5:15 + _9 = take::<Bar>(move _10) -> [return: bb3, unwind: bb9]; // scope 2 at $DIR/generator_storage_dead_unwind.rs:+5:9: +5:16 // mir::Constant - // + span: $DIR/generator-storage-dead-unwind.rs:27:9: 27:13 + // + span: $DIR/generator_storage_dead_unwind.rs:27:9: 27:13 // + literal: Const { ty: fn(Bar) {take::<Bar>}, val: Value(<ZST>) } } bb3: { - StorageDead(_10); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:15: +5:16 - StorageDead(_9); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:16: +5:17 - _0 = const (); // scope 0 at $DIR/generator-storage-dead-unwind.rs:+0:19: +6:6 - StorageDead(_4); // scope 1 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 - goto -> bb4; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 + StorageDead(_10); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+5:15: +5:16 + StorageDead(_9); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+5:16: +5:17 + _0 = const (); // scope 0 at $DIR/generator_storage_dead_unwind.rs:+0:19: +6:6 + StorageDead(_4); // scope 1 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 + goto -> bb4; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 } bb4: { - StorageDead(_3); // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 - drop(_1) -> [return: bb5, unwind: bb14]; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 + StorageDead(_3); // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 + drop(_1) -> [return: bb5, unwind: bb14]; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 } bb5: { - return; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:6: +6:6 + return; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:6: +6:6 } bb6: { - StorageDead(_6); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:13: +3:14 - StorageDead(_5); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:14: +3:15 - StorageDead(_4); // scope 1 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 - drop(_3) -> [return: bb7, unwind: bb15]; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 + StorageDead(_6); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+3:13: +3:14 + StorageDead(_5); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+3:14: +3:15 + StorageDead(_4); // scope 1 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 + drop(_3) -> [return: bb7, unwind: bb15]; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 } bb7: { - StorageDead(_3); // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 - drop(_1) -> [return: bb8, unwind: bb14]; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 + StorageDead(_3); // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 + drop(_1) -> [return: bb8, unwind: bb14]; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 } bb8: { - generator_drop; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+0:16: +6:6 + generator_drop; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+0:16: +6:6 } bb9 (cleanup): { - StorageDead(_10); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:15: +5:16 - StorageDead(_9); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:16: +5:17 + StorageDead(_10); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+5:15: +5:16 + StorageDead(_9); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+5:16: +5:17 goto -> bb12; // scope 2 at no-location } bb10 (cleanup): { - goto -> bb11; // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:15: +4:16 + goto -> bb11; // scope 2 at $DIR/generator_storage_dead_unwind.rs:+4:15: +4:16 } bb11 (cleanup): { - StorageDead(_8); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:15: +4:16 - StorageDead(_7); // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:16: +4:17 + StorageDead(_8); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+4:15: +4:16 + StorageDead(_7); // scope 2 at $DIR/generator_storage_dead_unwind.rs:+4:16: +4:17 goto -> bb12; // scope 2 at no-location } bb12 (cleanup): { - StorageDead(_4); // scope 1 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 - goto -> bb13; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 + StorageDead(_4); // scope 1 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 + goto -> bb13; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 } bb13 (cleanup): { - StorageDead(_3); // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 - drop(_1) -> bb14; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 + StorageDead(_3); // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 + drop(_1) -> bb14; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 } bb14 (cleanup): { - resume; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+0:16: +6:6 + resume; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+0:16: +6:6 } bb15 (cleanup): { - StorageDead(_3); // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 - drop(_1) -> bb14; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6 + StorageDead(_3); // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 + drop(_1) -> bb14; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 } } diff --git a/src/test/mir-opt/generator-storage-dead-unwind.rs b/src/test/mir-opt/generator_storage_dead_unwind.rs index b72170adec3..b72170adec3 100644 --- a/src/test/mir-opt/generator-storage-dead-unwind.rs +++ b/src/test/mir-opt/generator_storage_dead_unwind.rs diff --git a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir index 07aeeaae012..fee6da2c635 100644 --- a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir +++ b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir @@ -14,71 +14,71 @@ }, } */ -fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 19:24]>, _2: u8) -> GeneratorState<(), ()> { - debug _x => _10; // in scope 0 at $DIR/generator-tiny.rs:+0:17: +0:19 - let mut _0: std::ops::GeneratorState<(), ()>; // return place in scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 - let _3: HasDrop; // in scope 0 at $DIR/generator-tiny.rs:+1:13: +1:15 - let mut _4: !; // in scope 0 at $DIR/generator-tiny.rs:+2:9: +5:10 - let mut _5: (); // in scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 - let _6: u8; // in scope 0 at $DIR/generator-tiny.rs:+3:13: +3:18 - let mut _7: (); // in scope 0 at $DIR/generator-tiny.rs:+3:13: +3:18 - let _8: (); // in scope 0 at $DIR/generator-tiny.rs:+4:13: +4:21 - let mut _9: (); // in scope 0 at $DIR/generator-tiny.rs:+0:25: +0:25 - let _10: u8; // in scope 0 at $DIR/generator-tiny.rs:+0:17: +0:19 - let mut _11: u32; // in scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 +fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]>, _2: u8) -> GeneratorState<(), ()> { + debug _x => _10; // in scope 0 at $DIR/generator_tiny.rs:+0:17: +0:19 + let mut _0: std::ops::GeneratorState<(), ()>; // return place in scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 + let _3: HasDrop; // in scope 0 at $DIR/generator_tiny.rs:+1:13: +1:15 + let mut _4: !; // in scope 0 at $DIR/generator_tiny.rs:+2:9: +5:10 + let mut _5: (); // in scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 + let _6: u8; // in scope 0 at $DIR/generator_tiny.rs:+3:13: +3:18 + let mut _7: (); // in scope 0 at $DIR/generator_tiny.rs:+3:13: +3:18 + let _8: (); // in scope 0 at $DIR/generator_tiny.rs:+4:13: +4:21 + let mut _9: (); // in scope 0 at $DIR/generator_tiny.rs:+0:25: +0:25 + let _10: u8; // in scope 0 at $DIR/generator_tiny.rs:+0:17: +0:19 + let mut _11: u32; // in scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 scope 1 { - debug _d => (((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop); // in scope 1 at $DIR/generator-tiny.rs:+1:13: +1:15 + debug _d => (((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop); // in scope 1 at $DIR/generator_tiny.rs:+1:13: +1:15 } bb0: { - _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24]))); // scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 - switchInt(move _11) -> [0_u32: bb1, 3_u32: bb5, otherwise: bb6]; // scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 + _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))); // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 + switchInt(move _11) -> [0_u32: bb1, 3_u32: bb5, otherwise: bb6]; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 } bb1: { - _10 = move _2; // scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 - nop; // scope 0 at $DIR/generator-tiny.rs:+1:13: +1:15 - (((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop) = HasDrop; // scope 0 at $DIR/generator-tiny.rs:+1:18: +1:25 - StorageLive(_4); // scope 1 at $DIR/generator-tiny.rs:+2:9: +5:10 - goto -> bb2; // scope 1 at $DIR/generator-tiny.rs:+2:9: +5:10 + _10 = move _2; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 + nop; // scope 0 at $DIR/generator_tiny.rs:+1:13: +1:15 + (((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop) = HasDrop; // scope 0 at $DIR/generator_tiny.rs:+1:18: +1:25 + StorageLive(_4); // scope 1 at $DIR/generator_tiny.rs:+2:9: +5:10 + goto -> bb2; // scope 1 at $DIR/generator_tiny.rs:+2:9: +5:10 } bb2: { - StorageLive(_6); // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18 - StorageLive(_7); // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18 - _7 = (); // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18 - Deinit(_0); // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18 - ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18 - discriminant(_0) = 0; // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18 - discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24]))) = 3; // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18 - return; // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18 + StorageLive(_6); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 + StorageLive(_7); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 + _7 = (); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 + Deinit(_0); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 + ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 + discriminant(_0) = 0; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 + discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))) = 3; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 + return; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 } bb3: { - StorageDead(_7); // scope 1 at $DIR/generator-tiny.rs:+3:17: +3:18 - StorageDead(_6); // scope 1 at $DIR/generator-tiny.rs:+3:18: +3:19 - StorageLive(_8); // scope 1 at $DIR/generator-tiny.rs:+4:13: +4:21 - _8 = callee() -> bb4; // scope 1 at $DIR/generator-tiny.rs:+4:13: +4:21 + StorageDead(_7); // scope 1 at $DIR/generator_tiny.rs:+3:17: +3:18 + StorageDead(_6); // scope 1 at $DIR/generator_tiny.rs:+3:18: +3:19 + StorageLive(_8); // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21 + _8 = callee() -> bb4; // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21 // mir::Constant - // + span: $DIR/generator-tiny.rs:23:13: 23:19 + // + span: $DIR/generator_tiny.rs:23:13: 23:19 // + literal: Const { ty: fn() {callee}, val: Value(<ZST>) } } bb4: { - StorageDead(_8); // scope 1 at $DIR/generator-tiny.rs:+4:21: +4:22 - _5 = const (); // scope 1 at $DIR/generator-tiny.rs:+2:14: +5:10 - goto -> bb2; // scope 1 at $DIR/generator-tiny.rs:+2:9: +5:10 + StorageDead(_8); // scope 1 at $DIR/generator_tiny.rs:+4:21: +4:22 + _5 = const (); // scope 1 at $DIR/generator_tiny.rs:+2:14: +5:10 + goto -> bb2; // scope 1 at $DIR/generator_tiny.rs:+2:9: +5:10 } bb5: { - StorageLive(_4); // scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 - StorageLive(_6); // scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 - StorageLive(_7); // scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 - _6 = move _2; // scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 - goto -> bb3; // scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 + StorageLive(_4); // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 + StorageLive(_6); // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 + StorageLive(_7); // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 + _6 = move _2; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 + goto -> bb3; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 } bb6: { - unreachable; // scope 0 at $DIR/generator-tiny.rs:+0:16: +6:6 + unreachable; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6 } } diff --git a/src/test/mir-opt/generator-tiny.rs b/src/test/mir-opt/generator_tiny.rs index 7dad63a61d6..7dad63a61d6 100644 --- a/src/test/mir-opt/generator-tiny.rs +++ b/src/test/mir-opt/generator_tiny.rs diff --git a/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff index 19b5ab44156..94180d20343 100644 --- a/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff @@ -2,29 +2,29 @@ + // MIR for `dont_opt_bool` after SimplifyComparisonIntegral fn dont_opt_bool(_1: bool) -> u32 { - debug x => _1; // in scope 0 at $DIR/if-condition-int.rs:+0:18: +0:19 - let mut _0: u32; // return place in scope 0 at $DIR/if-condition-int.rs:+0:30: +0:33 - let mut _2: bool; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 + debug x => _1; // in scope 0 at $DIR/if_condition_int.rs:+0:18: +0:19 + let mut _0: u32; // return place in scope 0 at $DIR/if_condition_int.rs:+0:30: +0:33 + let mut _2: bool; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 bb0: { - StorageLive(_2); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - _2 = _1; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 + StorageLive(_2); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + _2 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 } bb1: { - _0 = const 0_u32; // scope 0 at $DIR/if-condition-int.rs:+1:12: +1:13 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:26 + _0 = const 0_u32; // scope 0 at $DIR/if_condition_int.rs:+1:12: +1:13 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:26 } bb2: { - _0 = const 1_u32; // scope 0 at $DIR/if-condition-int.rs:+1:23: +1:24 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:26 + _0 = const 1_u32; // scope 0 at $DIR/if_condition_int.rs:+1:23: +1:24 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:26 } bb3: { - StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:+1:25: +1:26 - return; // scope 0 at $DIR/if-condition-int.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/if_condition_int.rs:+1:25: +1:26 + return; // scope 0 at $DIR/if_condition_int.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff index 256af7b94be..b22c7eac622 100644 --- a/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff @@ -2,33 +2,33 @@ + // MIR for `dont_opt_floats` after SimplifyComparisonIntegral fn dont_opt_floats(_1: f32) -> i32 { - debug a => _1; // in scope 0 at $DIR/if-condition-int.rs:+0:20: +0:21 - let mut _0: i32; // return place in scope 0 at $DIR/if-condition-int.rs:+0:31: +0:34 - let mut _2: bool; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:18 - let mut _3: f32; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 + debug a => _1; // in scope 0 at $DIR/if_condition_int.rs:+0:20: +0:21 + let mut _0: i32; // return place in scope 0 at $DIR/if_condition_int.rs:+0:31: +0:34 + let mut _2: bool; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18 + let mut _3: f32; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 bb0: { - StorageLive(_2); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:18 - StorageLive(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - _3 = _1; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - _2 = Eq(move _3, const -42f32); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:18 - StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:17: +1:18 - switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:18 + StorageLive(_2); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18 + StorageLive(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + _3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + _2 = Eq(move _3, const -42f32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18 + StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:17: +1:18 + switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18 } bb1: { - _0 = const 0_i32; // scope 0 at $DIR/if-condition-int.rs:+1:21: +1:22 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:35 + _0 = const 0_i32; // scope 0 at $DIR/if_condition_int.rs:+1:21: +1:22 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:35 } bb2: { - _0 = const 1_i32; // scope 0 at $DIR/if-condition-int.rs:+1:32: +1:33 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:35 + _0 = const 1_i32; // scope 0 at $DIR/if_condition_int.rs:+1:32: +1:33 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:35 } bb3: { - StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:+1:34: +1:35 - return; // scope 0 at $DIR/if-condition-int.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/if_condition_int.rs:+1:34: +1:35 + return; // scope 0 at $DIR/if_condition_int.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff index ed53c9a956c..cc0995f99cf 100644 --- a/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff @@ -2,57 +2,57 @@ + // MIR for `dont_remove_comparison` after SimplifyComparisonIntegral fn dont_remove_comparison(_1: i8) -> i32 { - debug a => _1; // in scope 0 at $DIR/if-condition-int.rs:+0:27: +0:28 - let mut _0: i32; // return place in scope 0 at $DIR/if-condition-int.rs:+0:37: +0:40 - let _2: bool; // in scope 0 at $DIR/if-condition-int.rs:+1:9: +1:10 - let mut _3: i8; // in scope 0 at $DIR/if-condition-int.rs:+1:13: +1:14 - let mut _4: i32; // in scope 0 at $DIR/if-condition-int.rs:+3:23: +3:31 - let mut _5: bool; // in scope 0 at $DIR/if-condition-int.rs:+3:23: +3:24 - let mut _6: i32; // in scope 0 at $DIR/if-condition-int.rs:+4:23: +4:31 - let mut _7: bool; // in scope 0 at $DIR/if-condition-int.rs:+4:23: +4:24 + debug a => _1; // in scope 0 at $DIR/if_condition_int.rs:+0:27: +0:28 + let mut _0: i32; // return place in scope 0 at $DIR/if_condition_int.rs:+0:37: +0:40 + let _2: bool; // in scope 0 at $DIR/if_condition_int.rs:+1:9: +1:10 + let mut _3: i8; // in scope 0 at $DIR/if_condition_int.rs:+1:13: +1:14 + let mut _4: i32; // in scope 0 at $DIR/if_condition_int.rs:+3:23: +3:31 + let mut _5: bool; // in scope 0 at $DIR/if_condition_int.rs:+3:23: +3:24 + let mut _6: i32; // in scope 0 at $DIR/if_condition_int.rs:+4:23: +4:31 + let mut _7: bool; // in scope 0 at $DIR/if_condition_int.rs:+4:23: +4:24 scope 1 { - debug b => _2; // in scope 1 at $DIR/if-condition-int.rs:+1:9: +1:10 + debug b => _2; // in scope 1 at $DIR/if_condition_int.rs:+1:9: +1:10 } bb0: { - StorageLive(_2); // scope 0 at $DIR/if-condition-int.rs:+1:9: +1:10 - StorageLive(_3); // scope 0 at $DIR/if-condition-int.rs:+1:13: +1:14 - _3 = _1; // scope 0 at $DIR/if-condition-int.rs:+1:13: +1:14 -- _2 = Eq(move _3, const 17_i8); // scope 0 at $DIR/if-condition-int.rs:+1:13: +1:20 -- StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:19: +1:20 -- switchInt(_2) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if-condition-int.rs:+2:5: +2:12 -+ _2 = Eq(_3, const 17_i8); // scope 0 at $DIR/if-condition-int.rs:+1:13: +1:20 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:19: +1:20 -+ switchInt(move _3) -> [17_i8: bb1, otherwise: bb2]; // scope 1 at $DIR/if-condition-int.rs:+2:5: +2:12 + StorageLive(_2); // scope 0 at $DIR/if_condition_int.rs:+1:9: +1:10 + StorageLive(_3); // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:14 + _3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:14 +- _2 = Eq(move _3, const 17_i8); // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:20 +- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20 +- switchInt(_2) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12 ++ _2 = Eq(_3, const 17_i8); // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:20 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20 ++ switchInt(move _3) -> [17_i8: bb1, otherwise: bb2]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12 } bb1: { -+ StorageDead(_3); // scope 1 at $DIR/if-condition-int.rs:+2:5: +2:12 - StorageLive(_6); // scope 1 at $DIR/if-condition-int.rs:+4:23: +4:31 - StorageLive(_7); // scope 1 at $DIR/if-condition-int.rs:+4:23: +4:24 - _7 = _2; // scope 1 at $DIR/if-condition-int.rs:+4:23: +4:24 - _6 = move _7 as i32 (IntToInt); // scope 1 at $DIR/if-condition-int.rs:+4:23: +4:31 - StorageDead(_7); // scope 1 at $DIR/if-condition-int.rs:+4:30: +4:31 - _0 = Add(const 100_i32, move _6); // scope 1 at $DIR/if-condition-int.rs:+4:17: +4:31 - StorageDead(_6); // scope 1 at $DIR/if-condition-int.rs:+4:30: +4:31 - goto -> bb3; // scope 1 at $DIR/if-condition-int.rs:+4:30: +4:31 ++ StorageDead(_3); // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12 + StorageLive(_6); // scope 1 at $DIR/if_condition_int.rs:+4:23: +4:31 + StorageLive(_7); // scope 1 at $DIR/if_condition_int.rs:+4:23: +4:24 + _7 = _2; // scope 1 at $DIR/if_condition_int.rs:+4:23: +4:24 + _6 = move _7 as i32 (IntToInt); // scope 1 at $DIR/if_condition_int.rs:+4:23: +4:31 + StorageDead(_7); // scope 1 at $DIR/if_condition_int.rs:+4:30: +4:31 + _0 = Add(const 100_i32, move _6); // scope 1 at $DIR/if_condition_int.rs:+4:17: +4:31 + StorageDead(_6); // scope 1 at $DIR/if_condition_int.rs:+4:30: +4:31 + goto -> bb3; // scope 1 at $DIR/if_condition_int.rs:+4:30: +4:31 } bb2: { -+ StorageDead(_3); // scope 1 at $DIR/if-condition-int.rs:+2:5: +2:12 - StorageLive(_4); // scope 1 at $DIR/if-condition-int.rs:+3:23: +3:31 - StorageLive(_5); // scope 1 at $DIR/if-condition-int.rs:+3:23: +3:24 - _5 = _2; // scope 1 at $DIR/if-condition-int.rs:+3:23: +3:24 - _4 = move _5 as i32 (IntToInt); // scope 1 at $DIR/if-condition-int.rs:+3:23: +3:31 - StorageDead(_5); // scope 1 at $DIR/if-condition-int.rs:+3:30: +3:31 - _0 = Add(const 10_i32, move _4); // scope 1 at $DIR/if-condition-int.rs:+3:18: +3:31 - StorageDead(_4); // scope 1 at $DIR/if-condition-int.rs:+3:30: +3:31 - goto -> bb3; // scope 1 at $DIR/if-condition-int.rs:+3:30: +3:31 ++ StorageDead(_3); // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12 + StorageLive(_4); // scope 1 at $DIR/if_condition_int.rs:+3:23: +3:31 + StorageLive(_5); // scope 1 at $DIR/if_condition_int.rs:+3:23: +3:24 + _5 = _2; // scope 1 at $DIR/if_condition_int.rs:+3:23: +3:24 + _4 = move _5 as i32 (IntToInt); // scope 1 at $DIR/if_condition_int.rs:+3:23: +3:31 + StorageDead(_5); // scope 1 at $DIR/if_condition_int.rs:+3:30: +3:31 + _0 = Add(const 10_i32, move _4); // scope 1 at $DIR/if_condition_int.rs:+3:18: +3:31 + StorageDead(_4); // scope 1 at $DIR/if_condition_int.rs:+3:30: +3:31 + goto -> bb3; // scope 1 at $DIR/if_condition_int.rs:+3:30: +3:31 } bb3: { - StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:+6:1: +6:2 - return; // scope 0 at $DIR/if-condition-int.rs:+6:2: +6:2 + StorageDead(_2); // scope 0 at $DIR/if_condition_int.rs:+6:1: +6:2 + return; // scope 0 at $DIR/if_condition_int.rs:+6:2: +6:2 } } diff --git a/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff index 9b64c379fee..801ea040203 100644 --- a/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff @@ -2,38 +2,38 @@ + // MIR for `opt_char` after SimplifyComparisonIntegral fn opt_char(_1: char) -> u32 { - debug x => _1; // in scope 0 at $DIR/if-condition-int.rs:+0:13: +0:14 - let mut _0: u32; // return place in scope 0 at $DIR/if-condition-int.rs:+0:25: +0:28 - let mut _2: bool; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 - let mut _3: char; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 + debug x => _1; // in scope 0 at $DIR/if_condition_int.rs:+0:13: +0:14 + let mut _0: u32; // return place in scope 0 at $DIR/if_condition_int.rs:+0:25: +0:28 + let mut _2: bool; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 + let mut _3: char; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 bb0: { - StorageLive(_2); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 - StorageLive(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - _3 = _1; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 -- _2 = Eq(move _3, const 'x'); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 -- StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:15: +1:16 -- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:15: +1:16 -+ switchInt(move _3) -> ['x': bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 + StorageLive(_2); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 + StorageLive(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + _3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 +- _2 = Eq(move _3, const 'x'); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 +- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16 +- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16 ++ switchInt(move _3) -> ['x': bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 } bb1: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 - _0 = const 0_u32; // scope 0 at $DIR/if-condition-int.rs:+1:19: +1:20 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:33 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 + _0 = const 0_u32; // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:33 } bb2: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 - _0 = const 1_u32; // scope 0 at $DIR/if-condition-int.rs:+1:30: +1:31 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:33 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 + _0 = const 1_u32; // scope 0 at $DIR/if_condition_int.rs:+1:30: +1:31 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:33 } bb3: { - StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:+1:32: +1:33 - return; // scope 0 at $DIR/if-condition-int.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/if_condition_int.rs:+1:32: +1:33 + return; // scope 0 at $DIR/if_condition_int.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff index 8042d63bb34..4297f4d6466 100644 --- a/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff @@ -2,38 +2,38 @@ + // MIR for `opt_i8` after SimplifyComparisonIntegral fn opt_i8(_1: i8) -> u32 { - debug x => _1; // in scope 0 at $DIR/if-condition-int.rs:+0:11: +0:12 - let mut _0: u32; // return place in scope 0 at $DIR/if-condition-int.rs:+0:21: +0:24 - let mut _2: bool; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - let mut _3: i8; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 + debug x => _1; // in scope 0 at $DIR/if_condition_int.rs:+0:11: +0:12 + let mut _0: u32; // return place in scope 0 at $DIR/if_condition_int.rs:+0:21: +0:24 + let mut _2: bool; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + let mut _3: i8; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 bb0: { - StorageLive(_2); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - StorageLive(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - _3 = _1; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 -- _2 = Eq(move _3, const 42_i8); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 -- StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:14: +1:15 -- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:14: +1:15 -+ switchInt(move _3) -> [42_i8: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 + StorageLive(_2); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + StorageLive(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + _3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 +- _2 = Eq(move _3, const 42_i8); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 +- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15 +- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15 ++ switchInt(move _3) -> [42_i8: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 } bb1: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - _0 = const 0_u32; // scope 0 at $DIR/if-condition-int.rs:+1:18: +1:19 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:32 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + _0 = const 0_u32; // scope 0 at $DIR/if_condition_int.rs:+1:18: +1:19 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:32 } bb2: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - _0 = const 1_u32; // scope 0 at $DIR/if-condition-int.rs:+1:29: +1:30 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:32 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + _0 = const 1_u32; // scope 0 at $DIR/if_condition_int.rs:+1:29: +1:30 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:32 } bb3: { - StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:+1:31: +1:32 - return; // scope 0 at $DIR/if-condition-int.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/if_condition_int.rs:+1:31: +1:32 + return; // scope 0 at $DIR/if_condition_int.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff index a408de1ef3e..8fb794abbd4 100644 --- a/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff @@ -2,64 +2,64 @@ + // MIR for `opt_multiple_ifs` after SimplifyComparisonIntegral fn opt_multiple_ifs(_1: u32) -> u32 { - debug x => _1; // in scope 0 at $DIR/if-condition-int.rs:+0:21: +0:22 - let mut _0: u32; // return place in scope 0 at $DIR/if-condition-int.rs:+0:32: +0:35 - let mut _2: bool; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - let mut _3: u32; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - let mut _4: bool; // in scope 0 at $DIR/if-condition-int.rs:+3:15: +3:22 - let mut _5: u32; // in scope 0 at $DIR/if-condition-int.rs:+3:15: +3:16 + debug x => _1; // in scope 0 at $DIR/if_condition_int.rs:+0:21: +0:22 + let mut _0: u32; // return place in scope 0 at $DIR/if_condition_int.rs:+0:32: +0:35 + let mut _2: bool; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + let mut _3: u32; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + let mut _4: bool; // in scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22 + let mut _5: u32; // in scope 0 at $DIR/if_condition_int.rs:+3:15: +3:16 bb0: { - StorageLive(_2); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - StorageLive(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - _3 = _1; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 -- _2 = Eq(move _3, const 42_u32); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 -- StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:14: +1:15 -- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:14: +1:15 -+ switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 + StorageLive(_2); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + StorageLive(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + _3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 +- _2 = Eq(move _3, const 42_u32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 +- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15 +- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15 ++ switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 } bb1: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - _0 = const 0_u32; // scope 0 at $DIR/if-condition-int.rs:+2:9: +2:10 - goto -> bb6; // scope 0 at $DIR/if-condition-int.rs:+1:5: +7:6 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + _0 = const 0_u32; // scope 0 at $DIR/if_condition_int.rs:+2:9: +2:10 + goto -> bb6; // scope 0 at $DIR/if_condition_int.rs:+1:5: +7:6 } bb2: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - StorageLive(_4); // scope 0 at $DIR/if-condition-int.rs:+3:15: +3:22 - StorageLive(_5); // scope 0 at $DIR/if-condition-int.rs:+3:15: +3:16 - _5 = _1; // scope 0 at $DIR/if-condition-int.rs:+3:15: +3:16 -- _4 = Ne(move _5, const 21_u32); // scope 0 at $DIR/if-condition-int.rs:+3:15: +3:22 -- StorageDead(_5); // scope 0 at $DIR/if-condition-int.rs:+3:21: +3:22 -- switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/if-condition-int.rs:+3:15: +3:22 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+3:15: +3:22 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+3:21: +3:22 -+ switchInt(move _5) -> [21_u32: bb4, otherwise: bb3]; // scope 0 at $DIR/if-condition-int.rs:+3:15: +3:22 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + StorageLive(_4); // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22 + StorageLive(_5); // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:16 + _5 = _1; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:16 +- _4 = Ne(move _5, const 21_u32); // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22 +- StorageDead(_5); // scope 0 at $DIR/if_condition_int.rs:+3:21: +3:22 +- switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+3:21: +3:22 ++ switchInt(move _5) -> [21_u32: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22 } bb3: { -+ StorageDead(_5); // scope 0 at $DIR/if-condition-int.rs:+3:15: +3:22 - _0 = const 1_u32; // scope 0 at $DIR/if-condition-int.rs:+4:9: +4:10 - goto -> bb5; // scope 0 at $DIR/if-condition-int.rs:+3:12: +7:6 ++ StorageDead(_5); // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22 + _0 = const 1_u32; // scope 0 at $DIR/if_condition_int.rs:+4:9: +4:10 + goto -> bb5; // scope 0 at $DIR/if_condition_int.rs:+3:12: +7:6 } bb4: { -+ StorageDead(_5); // scope 0 at $DIR/if-condition-int.rs:+3:15: +3:22 - _0 = const 2_u32; // scope 0 at $DIR/if-condition-int.rs:+6:9: +6:10 - goto -> bb5; // scope 0 at $DIR/if-condition-int.rs:+3:12: +7:6 ++ StorageDead(_5); // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22 + _0 = const 2_u32; // scope 0 at $DIR/if_condition_int.rs:+6:9: +6:10 + goto -> bb5; // scope 0 at $DIR/if_condition_int.rs:+3:12: +7:6 } bb5: { - StorageDead(_4); // scope 0 at $DIR/if-condition-int.rs:+7:5: +7:6 - goto -> bb6; // scope 0 at $DIR/if-condition-int.rs:+1:5: +7:6 + StorageDead(_4); // scope 0 at $DIR/if_condition_int.rs:+7:5: +7:6 + goto -> bb6; // scope 0 at $DIR/if_condition_int.rs:+1:5: +7:6 } bb6: { - StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:+7:5: +7:6 - return; // scope 0 at $DIR/if-condition-int.rs:+8:2: +8:2 + StorageDead(_2); // scope 0 at $DIR/if_condition_int.rs:+7:5: +7:6 + return; // scope 0 at $DIR/if_condition_int.rs:+8:2: +8:2 } } diff --git a/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff index 6802f89d927..992253ea780 100644 --- a/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff @@ -2,38 +2,38 @@ + // MIR for `opt_negative` after SimplifyComparisonIntegral fn opt_negative(_1: i32) -> u32 { - debug x => _1; // in scope 0 at $DIR/if-condition-int.rs:+0:17: +0:18 - let mut _0: u32; // return place in scope 0 at $DIR/if-condition-int.rs:+0:28: +0:31 - let mut _2: bool; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 - let mut _3: i32; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 + debug x => _1; // in scope 0 at $DIR/if_condition_int.rs:+0:17: +0:18 + let mut _0: u32; // return place in scope 0 at $DIR/if_condition_int.rs:+0:28: +0:31 + let mut _2: bool; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 + let mut _3: i32; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 bb0: { - StorageLive(_2); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 - StorageLive(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - _3 = _1; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 -- _2 = Eq(move _3, const -42_i32); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 -- StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:15: +1:16 -- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:15: +1:16 -+ switchInt(move _3) -> [-42_i32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 + StorageLive(_2); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 + StorageLive(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + _3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 +- _2 = Eq(move _3, const -42_i32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 +- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16 +- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16 ++ switchInt(move _3) -> [-42_i32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 } bb1: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 - _0 = const 0_u32; // scope 0 at $DIR/if-condition-int.rs:+1:19: +1:20 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:33 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 + _0 = const 0_u32; // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:33 } bb2: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:16 - _0 = const 1_u32; // scope 0 at $DIR/if-condition-int.rs:+1:30: +1:31 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:33 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16 + _0 = const 1_u32; // scope 0 at $DIR/if_condition_int.rs:+1:30: +1:31 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:33 } bb3: { - StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:+1:32: +1:33 - return; // scope 0 at $DIR/if-condition-int.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/if_condition_int.rs:+1:32: +1:33 + return; // scope 0 at $DIR/if_condition_int.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff index 96387771d06..7cea9472d3a 100644 --- a/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff @@ -2,38 +2,38 @@ + // MIR for `opt_u32` after SimplifyComparisonIntegral fn opt_u32(_1: u32) -> u32 { - debug x => _1; // in scope 0 at $DIR/if-condition-int.rs:+0:12: +0:13 - let mut _0: u32; // return place in scope 0 at $DIR/if-condition-int.rs:+0:23: +0:26 - let mut _2: bool; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - let mut _3: u32; // in scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 + debug x => _1; // in scope 0 at $DIR/if_condition_int.rs:+0:12: +0:13 + let mut _0: u32; // return place in scope 0 at $DIR/if_condition_int.rs:+0:23: +0:26 + let mut _2: bool; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + let mut _3: u32; // in scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 bb0: { - StorageLive(_2); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - StorageLive(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 - _3 = _1; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:9 -- _2 = Eq(move _3, const 42_u32); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 -- StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:14: +1:15 -- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 -+ nop; // scope 0 at $DIR/if-condition-int.rs:+1:14: +1:15 -+ switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 + StorageLive(_2); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + StorageLive(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 + _3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9 +- _2 = Eq(move _3, const 42_u32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 +- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15 +- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 ++ nop; // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15 ++ switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 } bb1: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - _0 = const 0_u32; // scope 0 at $DIR/if-condition-int.rs:+1:18: +1:19 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:32 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + _0 = const 0_u32; // scope 0 at $DIR/if_condition_int.rs:+1:18: +1:19 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:32 } bb2: { -+ StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:+1:8: +1:15 - _0 = const 1_u32; // scope 0 at $DIR/if-condition-int.rs:+1:29: +1:30 - goto -> bb3; // scope 0 at $DIR/if-condition-int.rs:+1:5: +1:32 ++ StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15 + _0 = const 1_u32; // scope 0 at $DIR/if_condition_int.rs:+1:29: +1:30 + goto -> bb3; // scope 0 at $DIR/if_condition_int.rs:+1:5: +1:32 } bb3: { - StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:+1:31: +1:32 - return; // scope 0 at $DIR/if-condition-int.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/if_condition_int.rs:+1:31: +1:32 + return; // scope 0 at $DIR/if_condition_int.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/if-condition-int.rs b/src/test/mir-opt/if_condition_int.rs index 398311e6bb8..398311e6bb8 100644 --- a/src/test/mir-opt/if-condition-int.rs +++ b/src/test/mir-opt/if_condition_int.rs diff --git a/src/test/mir-opt/inline/asm_unwind.main.Inline.diff b/src/test/mir-opt/inline/asm_unwind.main.Inline.diff index 57072fc0ad3..f1b62ac38ba 100644 --- a/src/test/mir-opt/inline/asm_unwind.main.Inline.diff +++ b/src/test/mir-opt/inline/asm_unwind.main.Inline.diff @@ -2,44 +2,44 @@ + // MIR for `main` after Inline fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/asm-unwind.rs:+0:15: +0:15 - let _1: (); // in scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10 -+ scope 1 (inlined foo) { // at $DIR/asm-unwind.rs:21:5: 21:10 -+ let _2: D; // in scope 1 at $DIR/asm-unwind.rs:15:9: 15:11 + let mut _0: (); // return place in scope 0 at $DIR/asm_unwind.rs:+0:15: +0:15 + let _1: (); // in scope 0 at $DIR/asm_unwind.rs:+1:5: +1:10 ++ scope 1 (inlined foo) { // at $DIR/asm_unwind.rs:21:5: 21:10 ++ let _2: D; // in scope 1 at $DIR/asm_unwind.rs:15:9: 15:11 + scope 2 { -+ debug _d => _2; // in scope 2 at $DIR/asm-unwind.rs:15:9: 15:11 ++ debug _d => _2; // in scope 2 at $DIR/asm_unwind.rs:15:9: 15:11 + scope 3 { + } + } + } bb0: { - StorageLive(_1); // scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10 -- _1 = foo() -> bb1; // scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10 + StorageLive(_1); // scope 0 at $DIR/asm_unwind.rs:+1:5: +1:10 +- _1 = foo() -> bb1; // scope 0 at $DIR/asm_unwind.rs:+1:5: +1:10 - // mir::Constant -- // + span: $DIR/asm-unwind.rs:21:5: 21:8 +- // + span: $DIR/asm_unwind.rs:21:5: 21:8 - // + literal: Const { ty: fn() {foo}, val: Value(<ZST>) } -+ StorageLive(_2); // scope 1 at $DIR/asm-unwind.rs:15:9: 15:11 -+ asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb3]; // scope 3 at $DIR/asm-unwind.rs:16:14: 16:54 ++ StorageLive(_2); // scope 1 at $DIR/asm_unwind.rs:15:9: 15:11 ++ asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb3]; // scope 3 at $DIR/asm_unwind.rs:16:14: 16:54 } bb1: { -+ drop(_2) -> bb2; // scope 1 at $DIR/asm-unwind.rs:17:1: 17:2 ++ drop(_2) -> bb2; // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2 + } + + bb2: { -+ StorageDead(_2); // scope 1 at $DIR/asm-unwind.rs:17:1: 17:2 - StorageDead(_1); // scope 0 at $DIR/asm-unwind.rs:+1:10: +1:11 - _0 = const (); // scope 0 at $DIR/asm-unwind.rs:+0:15: +2:2 - return; // scope 0 at $DIR/asm-unwind.rs:+2:2: +2:2 ++ StorageDead(_2); // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2 + StorageDead(_1); // scope 0 at $DIR/asm_unwind.rs:+1:10: +1:11 + _0 = const (); // scope 0 at $DIR/asm_unwind.rs:+0:15: +2:2 + return; // scope 0 at $DIR/asm_unwind.rs:+2:2: +2:2 + } + + bb3 (cleanup): { -+ drop(_2) -> bb4; // scope 1 at $DIR/asm-unwind.rs:17:1: 17:2 ++ drop(_2) -> bb4; // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2 + } + + bb4 (cleanup): { -+ resume; // scope 1 at $DIR/asm-unwind.rs:14:1: 17:2 ++ resume; // scope 1 at $DIR/asm_unwind.rs:14:1: 17:2 } } diff --git a/src/test/mir-opt/inline/asm-unwind.rs b/src/test/mir-opt/inline/asm_unwind.rs index c03feb43312..c03feb43312 100644 --- a/src/test/mir-opt/inline/asm-unwind.rs +++ b/src/test/mir-opt/inline/asm_unwind.rs diff --git a/src/test/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff b/src/test/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff index d7deb9c66cf..8b03006782b 100644 --- a/src/test/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff +++ b/src/test/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff @@ -2,32 +2,32 @@ + // MIR for `foo` after Inline fn foo() -> () { - let mut _0: (); // return place in scope 0 at $DIR/caller-with-trivial-bound.rs:+1:1: +1:1 - let mut _1: <IntFactory as Factory<T>>::Item; // in scope 0 at $DIR/caller-with-trivial-bound.rs:+4:9: +4:14 + let mut _0: (); // return place in scope 0 at $DIR/caller_with_trivial_bound.rs:+1:1: +1:1 + let mut _1: <IntFactory as Factory<T>>::Item; // in scope 0 at $DIR/caller_with_trivial_bound.rs:+4:9: +4:14 scope 1 { - debug x => _1; // in scope 1 at $DIR/caller-with-trivial-bound.rs:+4:9: +4:14 + debug x => _1; // in scope 1 at $DIR/caller_with_trivial_bound.rs:+4:9: +4:14 } bb0: { - StorageLive(_1); // scope 0 at $DIR/caller-with-trivial-bound.rs:+4:9: +4:14 - _1 = bar::<T>() -> bb1; // scope 0 at $DIR/caller-with-trivial-bound.rs:+4:51: +4:61 + StorageLive(_1); // scope 0 at $DIR/caller_with_trivial_bound.rs:+4:9: +4:14 + _1 = bar::<T>() -> bb1; // scope 0 at $DIR/caller_with_trivial_bound.rs:+4:51: +4:61 // mir::Constant - // + span: $DIR/caller-with-trivial-bound.rs:20:51: 20:59 + // + span: $DIR/caller_with_trivial_bound.rs:20:51: 20:59 // + literal: Const { ty: fn() -> <IntFactory as Factory<T>>::Item {bar::<T>}, val: Value(<ZST>) } } bb1: { - _0 = const (); // scope 0 at $DIR/caller-with-trivial-bound.rs:+3:1: +5:2 - drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/caller-with-trivial-bound.rs:+5:1: +5:2 + _0 = const (); // scope 0 at $DIR/caller_with_trivial_bound.rs:+3:1: +5:2 + drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/caller_with_trivial_bound.rs:+5:1: +5:2 } bb2: { - StorageDead(_1); // scope 0 at $DIR/caller-with-trivial-bound.rs:+5:1: +5:2 - return; // scope 0 at $DIR/caller-with-trivial-bound.rs:+5:2: +5:2 + StorageDead(_1); // scope 0 at $DIR/caller_with_trivial_bound.rs:+5:1: +5:2 + return; // scope 0 at $DIR/caller_with_trivial_bound.rs:+5:2: +5:2 } bb3 (cleanup): { - resume; // scope 0 at $DIR/caller-with-trivial-bound.rs:+0:1: +5:2 + resume; // scope 0 at $DIR/caller_with_trivial_bound.rs:+0:1: +5:2 } } diff --git a/src/test/mir-opt/inline/caller-with-trivial-bound.rs b/src/test/mir-opt/inline/caller_with_trivial_bound.rs index 8545db89414..8545db89414 100644 --- a/src/test/mir-opt/inline/caller-with-trivial-bound.rs +++ b/src/test/mir-opt/inline/caller_with_trivial_bound.rs diff --git a/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff index 1e95b5b29ff..284306a352d 100644 --- a/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff +++ b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff @@ -2,61 +2,61 @@ + // MIR for `get_query` after Inline fn get_query(_1: &T) -> () { - debug t => _1; // in scope 0 at $DIR/dyn-trait.rs:+0:31: +0:32 - let mut _0: (); // return place in scope 0 at $DIR/dyn-trait.rs:+0:38: +0:38 - let _2: &<Q as Query>::C; // in scope 0 at $DIR/dyn-trait.rs:+1:9: +1:10 - let mut _3: &T; // in scope 0 at $DIR/dyn-trait.rs:+1:22: +1:23 - let mut _4: &<Q as Query>::C; // in scope 0 at $DIR/dyn-trait.rs:+2:23: +2:24 + debug t => _1; // in scope 0 at $DIR/dyn_trait.rs:+0:31: +0:32 + let mut _0: (); // return place in scope 0 at $DIR/dyn_trait.rs:+0:38: +0:38 + let _2: &<Q as Query>::C; // in scope 0 at $DIR/dyn_trait.rs:+1:9: +1:10 + let mut _3: &T; // in scope 0 at $DIR/dyn_trait.rs:+1:22: +1:23 + let mut _4: &<Q as Query>::C; // in scope 0 at $DIR/dyn_trait.rs:+2:23: +2:24 scope 1 { - debug c => _2; // in scope 1 at $DIR/dyn-trait.rs:+1:9: +1:10 -+ scope 2 (inlined try_execute_query::<<Q as Query>::C>) { // at $DIR/dyn-trait.rs:34:5: 34:25 -+ debug c => _4; // in scope 2 at $DIR/dyn-trait.rs:26:36: 26:37 -+ let mut _5: &dyn Cache<V = <Q as Query>::V>; // in scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 -+ let mut _6: &<Q as Query>::C; // in scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 -+ scope 3 (inlined mk_cycle::<<Q as Query>::V>) { // at $DIR/dyn-trait.rs:27:5: 27:16 -+ debug c => _5; // in scope 3 at $DIR/dyn-trait.rs:20:27: 20:28 -+ let mut _7: &dyn Cache<V = <Q as Query>::V>; // in scope 3 at $DIR/dyn-trait.rs:21:5: 21:22 + debug c => _2; // in scope 1 at $DIR/dyn_trait.rs:+1:9: +1:10 ++ scope 2 (inlined try_execute_query::<<Q as Query>::C>) { // at $DIR/dyn_trait.rs:34:5: 34:25 ++ debug c => _4; // in scope 2 at $DIR/dyn_trait.rs:26:36: 26:37 ++ let mut _5: &dyn Cache<V = <Q as Query>::V>; // in scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ let mut _6: &<Q as Query>::C; // in scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ scope 3 (inlined mk_cycle::<<Q as Query>::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16 ++ debug c => _5; // in scope 3 at $DIR/dyn_trait.rs:20:27: 20:28 ++ let mut _7: &dyn Cache<V = <Q as Query>::V>; // in scope 3 at $DIR/dyn_trait.rs:21:5: 21:22 + } + } } bb0: { - StorageLive(_2); // scope 0 at $DIR/dyn-trait.rs:+1:9: +1:10 - StorageLive(_3); // scope 0 at $DIR/dyn-trait.rs:+1:22: +1:23 - _3 = &(*_1); // scope 0 at $DIR/dyn-trait.rs:+1:22: +1:23 - _2 = <Q as Query>::cache::<T>(move _3) -> bb1; // scope 0 at $DIR/dyn-trait.rs:+1:13: +1:24 + StorageLive(_2); // scope 0 at $DIR/dyn_trait.rs:+1:9: +1:10 + StorageLive(_3); // scope 0 at $DIR/dyn_trait.rs:+1:22: +1:23 + _3 = &(*_1); // scope 0 at $DIR/dyn_trait.rs:+1:22: +1:23 + _2 = <Q as Query>::cache::<T>(move _3) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:13: +1:24 // mir::Constant - // + span: $DIR/dyn-trait.rs:33:13: 33:21 + // + span: $DIR/dyn_trait.rs:33:13: 33:21 // + user_ty: UserType(0) // + literal: Const { ty: for<'a> fn(&'a T) -> &'a <Q as Query>::C {<Q as Query>::cache::<T>}, val: Value(<ZST>) } } bb1: { - StorageDead(_3); // scope 0 at $DIR/dyn-trait.rs:+1:23: +1:24 - StorageLive(_4); // scope 1 at $DIR/dyn-trait.rs:+2:23: +2:24 - _4 = &(*_2); // scope 1 at $DIR/dyn-trait.rs:+2:23: +2:24 -- _0 = try_execute_query::<<Q as Query>::C>(move _4) -> bb2; // scope 1 at $DIR/dyn-trait.rs:+2:5: +2:25 -+ StorageLive(_5); // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 -+ StorageLive(_6); // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 -+ _6 = _4; // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 -+ _5 = move _6 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 -+ StorageDead(_6); // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 -+ StorageLive(_7); // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22 -+ _7 = _5; // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22 -+ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _7) -> bb2; // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22 + StorageDead(_3); // scope 0 at $DIR/dyn_trait.rs:+1:23: +1:24 + StorageLive(_4); // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24 + _4 = &(*_2); // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24 +- _0 = try_execute_query::<<Q as Query>::C>(move _4) -> bb2; // scope 1 at $DIR/dyn_trait.rs:+2:5: +2:25 ++ StorageLive(_5); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ StorageLive(_6); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ _6 = _4; // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ _5 = move _6 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ StorageDead(_6); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ StorageLive(_7); // scope 3 at $DIR/dyn_trait.rs:21:5: 21:22 ++ _7 = _5; // scope 3 at $DIR/dyn_trait.rs:21:5: 21:22 ++ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _7) -> bb2; // scope 3 at $DIR/dyn_trait.rs:21:5: 21:22 // mir::Constant -- // + span: $DIR/dyn-trait.rs:34:5: 34:22 +- // + span: $DIR/dyn_trait.rs:34:5: 34:22 - // + literal: Const { ty: for<'a> fn(&'a <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) } -+ // + span: $DIR/dyn-trait.rs:21:7: 21:20 ++ // + span: $DIR/dyn_trait.rs:21:7: 21:20 + // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <Q as Query>::V>) {<dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache}, val: Value(<ZST>) } } bb2: { -+ StorageDead(_7); // scope 3 at $DIR/dyn-trait.rs:21:21: 21:22 -+ StorageDead(_5); // scope 2 at $DIR/dyn-trait.rs:27:15: 27:16 - StorageDead(_4); // scope 1 at $DIR/dyn-trait.rs:+2:24: +2:25 - StorageDead(_2); // scope 0 at $DIR/dyn-trait.rs:+3:1: +3:2 - return; // scope 0 at $DIR/dyn-trait.rs:+3:2: +3:2 ++ StorageDead(_7); // scope 3 at $DIR/dyn_trait.rs:21:21: 21:22 ++ StorageDead(_5); // scope 2 at $DIR/dyn_trait.rs:27:15: 27:16 + StorageDead(_4); // scope 1 at $DIR/dyn_trait.rs:+2:24: +2:25 + StorageDead(_2); // scope 0 at $DIR/dyn_trait.rs:+3:1: +3:2 + return; // scope 0 at $DIR/dyn_trait.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff b/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff index 7421db4d063..7653a5ded44 100644 --- a/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff +++ b/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff @@ -2,22 +2,22 @@ + // MIR for `mk_cycle` after Inline fn mk_cycle(_1: &dyn Cache<V = V>) -> () { - debug c => _1; // in scope 0 at $DIR/dyn-trait.rs:+0:27: +0:28 - let mut _0: (); // return place in scope 0 at $DIR/dyn-trait.rs:+0:49: +0:49 - let mut _2: &dyn Cache<V = V>; // in scope 0 at $DIR/dyn-trait.rs:+1:5: +1:22 + debug c => _1; // in scope 0 at $DIR/dyn_trait.rs:+0:27: +0:28 + let mut _0: (); // return place in scope 0 at $DIR/dyn_trait.rs:+0:49: +0:49 + let mut _2: &dyn Cache<V = V>; // in scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 bb0: { - StorageLive(_2); // scope 0 at $DIR/dyn-trait.rs:+1:5: +1:22 - _2 = &(*_1); // scope 0 at $DIR/dyn-trait.rs:+1:5: +1:22 - _0 = <dyn Cache<V = V> as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn-trait.rs:+1:5: +1:22 + StorageLive(_2); // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 + _2 = &(*_1); // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 + _0 = <dyn Cache<V = V> as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 // mir::Constant - // + span: $DIR/dyn-trait.rs:21:7: 21:20 + // + span: $DIR/dyn_trait.rs:21:7: 21:20 // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = V>) {<dyn Cache<V = V> as Cache>::store_nocache}, val: Value(<ZST>) } } bb1: { - StorageDead(_2); // scope 0 at $DIR/dyn-trait.rs:+1:21: +1:22 - return; // scope 0 at $DIR/dyn-trait.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/dyn_trait.rs:+1:21: +1:22 + return; // scope 0 at $DIR/dyn_trait.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/dyn-trait.rs b/src/test/mir-opt/inline/dyn_trait.rs index 6a46e1e07b1..6a46e1e07b1 100644 --- a/src/test/mir-opt/inline/dyn-trait.rs +++ b/src/test/mir-opt/inline/dyn_trait.rs diff --git a/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff index e6e78374422..0191045f3d1 100644 --- a/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff +++ b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff @@ -2,36 +2,36 @@ + // MIR for `try_execute_query` after Inline fn try_execute_query(_1: &C) -> () { - debug c => _1; // in scope 0 at $DIR/dyn-trait.rs:+0:36: +0:37 - let mut _0: (); // return place in scope 0 at $DIR/dyn-trait.rs:+0:43: +0:43 - let mut _2: &dyn Cache<V = <C as Cache>::V>; // in scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15 - let mut _3: &C; // in scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15 -+ scope 1 (inlined mk_cycle::<<C as Cache>::V>) { // at $DIR/dyn-trait.rs:27:5: 27:16 -+ debug c => _2; // in scope 1 at $DIR/dyn-trait.rs:20:27: 20:28 -+ let mut _4: &dyn Cache<V = <C as Cache>::V>; // in scope 1 at $DIR/dyn-trait.rs:21:5: 21:22 + debug c => _1; // in scope 0 at $DIR/dyn_trait.rs:+0:36: +0:37 + let mut _0: (); // return place in scope 0 at $DIR/dyn_trait.rs:+0:43: +0:43 + let mut _2: &dyn Cache<V = <C as Cache>::V>; // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + let mut _3: &C; // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 ++ scope 1 (inlined mk_cycle::<<C as Cache>::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16 ++ debug c => _2; // in scope 1 at $DIR/dyn_trait.rs:20:27: 20:28 ++ let mut _4: &dyn Cache<V = <C as Cache>::V>; // in scope 1 at $DIR/dyn_trait.rs:21:5: 21:22 + } bb0: { - StorageLive(_2); // scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15 - StorageLive(_3); // scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15 - _3 = &(*_1); // scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15 - _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (Pointer(Unsize)); // scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15 - StorageDead(_3); // scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15 -- _0 = mk_cycle::<<C as Cache>::V>(move _2) -> bb1; // scope 0 at $DIR/dyn-trait.rs:+1:5: +1:16 -+ StorageLive(_4); // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22 -+ _4 = _2; // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22 -+ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _4) -> bb1; // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22 + StorageLive(_2); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + StorageLive(_3); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + _3 = &(*_1); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (Pointer(Unsize)); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + StorageDead(_3); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 +- _0 = mk_cycle::<<C as Cache>::V>(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:16 ++ StorageLive(_4); // scope 1 at $DIR/dyn_trait.rs:21:5: 21:22 ++ _4 = _2; // scope 1 at $DIR/dyn_trait.rs:21:5: 21:22 ++ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _4) -> bb1; // scope 1 at $DIR/dyn_trait.rs:21:5: 21:22 // mir::Constant -- // + span: $DIR/dyn-trait.rs:27:5: 27:13 +- // + span: $DIR/dyn_trait.rs:27:5: 27:13 - // + literal: Const { ty: for<'a> fn(&'a (dyn Cache<V = <C as Cache>::V> + 'a)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) } -+ // + span: $DIR/dyn-trait.rs:21:7: 21:20 ++ // + span: $DIR/dyn_trait.rs:21:7: 21:20 + // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <C as Cache>::V>) {<dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache}, val: Value(<ZST>) } } bb1: { -+ StorageDead(_4); // scope 1 at $DIR/dyn-trait.rs:21:21: 21:22 - StorageDead(_2); // scope 0 at $DIR/dyn-trait.rs:+1:15: +1:16 - return; // scope 0 at $DIR/dyn-trait.rs:+2:2: +2:2 ++ StorageDead(_4); // scope 1 at $DIR/dyn_trait.rs:21:21: 21:22 + StorageDead(_2); // scope 0 at $DIR/dyn_trait.rs:+1:15: +1:16 + return; // scope 0 at $DIR/dyn_trait.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir index b27425fb18c..8956c80dcd2 100644 --- a/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir @@ -1,44 +1,44 @@ // MIR for `bar` after Inline fn bar() -> bool { - let mut _0: bool; // return place in scope 0 at $DIR/inline-any-operand.rs:+0:13: +0:17 - let _1: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline-any-operand.rs:+1:9: +1:10 - let mut _2: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline-any-operand.rs:+2:5: +2:6 - let mut _3: i32; // in scope 0 at $DIR/inline-any-operand.rs:+2:5: +2:13 - let mut _4: i32; // in scope 0 at $DIR/inline-any-operand.rs:+2:5: +2:13 + let mut _0: bool; // return place in scope 0 at $DIR/inline_any_operand.rs:+0:13: +0:17 + let _1: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline_any_operand.rs:+1:9: +1:10 + let mut _2: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline_any_operand.rs:+2:5: +2:6 + let mut _3: i32; // in scope 0 at $DIR/inline_any_operand.rs:+2:5: +2:13 + let mut _4: i32; // in scope 0 at $DIR/inline_any_operand.rs:+2:5: +2:13 scope 1 { - debug f => _1; // in scope 1 at $DIR/inline-any-operand.rs:+1:9: +1:10 - scope 2 (inlined foo) { // at $DIR/inline-any-operand.rs:12:5: 12:13 - debug x => _3; // in scope 2 at $DIR/inline-any-operand.rs:16:8: 16:9 - debug y => _4; // in scope 2 at $DIR/inline-any-operand.rs:16:16: 16:17 - let mut _5: i32; // in scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6 - let mut _6: i32; // in scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11 + debug f => _1; // in scope 1 at $DIR/inline_any_operand.rs:+1:9: +1:10 + scope 2 (inlined foo) { // at $DIR/inline_any_operand.rs:12:5: 12:13 + debug x => _3; // in scope 2 at $DIR/inline_any_operand.rs:16:8: 16:9 + debug y => _4; // in scope 2 at $DIR/inline_any_operand.rs:16:16: 16:17 + let mut _5: i32; // in scope 2 at $DIR/inline_any_operand.rs:17:5: 17:6 + let mut _6: i32; // in scope 2 at $DIR/inline_any_operand.rs:17:10: 17:11 } } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-any-operand.rs:+1:9: +1:10 - _1 = foo; // scope 0 at $DIR/inline-any-operand.rs:+1:13: +1:16 + StorageLive(_1); // scope 0 at $DIR/inline_any_operand.rs:+1:9: +1:10 + _1 = foo; // scope 0 at $DIR/inline_any_operand.rs:+1:13: +1:16 // mir::Constant - // + span: $DIR/inline-any-operand.rs:11:13: 11:16 + // + span: $DIR/inline_any_operand.rs:11:13: 11:16 // + literal: Const { ty: fn(i32, i32) -> bool {foo}, val: Value(<ZST>) } - StorageLive(_2); // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:6 - _2 = _1; // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:6 - StorageLive(_3); // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13 - _3 = const 1_i32; // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13 - StorageLive(_4); // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13 - _4 = const -1_i32; // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13 - StorageLive(_5); // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6 - _5 = _3; // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6 - StorageLive(_6); // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11 - _6 = _4; // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11 - _0 = Eq(move _5, move _6); // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:11 - StorageDead(_6); // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11 - StorageDead(_5); // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11 - StorageDead(_4); // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13 - StorageDead(_3); // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13 - StorageDead(_2); // scope 1 at $DIR/inline-any-operand.rs:+2:12: +2:13 - StorageDead(_1); // scope 0 at $DIR/inline-any-operand.rs:+3:1: +3:2 - return; // scope 0 at $DIR/inline-any-operand.rs:+3:2: +3:2 + StorageLive(_2); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:6 + _2 = _1; // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:6 + StorageLive(_3); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + _3 = const 1_i32; // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + StorageLive(_4); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + _4 = const -1_i32; // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + StorageLive(_5); // scope 2 at $DIR/inline_any_operand.rs:17:5: 17:6 + _5 = _3; // scope 2 at $DIR/inline_any_operand.rs:17:5: 17:6 + StorageLive(_6); // scope 2 at $DIR/inline_any_operand.rs:17:10: 17:11 + _6 = _4; // scope 2 at $DIR/inline_any_operand.rs:17:10: 17:11 + _0 = Eq(move _5, move _6); // scope 2 at $DIR/inline_any_operand.rs:17:5: 17:11 + StorageDead(_6); // scope 2 at $DIR/inline_any_operand.rs:17:10: 17:11 + StorageDead(_5); // scope 2 at $DIR/inline_any_operand.rs:17:10: 17:11 + StorageDead(_4); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + StorageDead(_3); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + StorageDead(_2); // scope 1 at $DIR/inline_any_operand.rs:+2:12: +2:13 + StorageDead(_1); // scope 0 at $DIR/inline_any_operand.rs:+3:1: +3:2 + return; // scope 0 at $DIR/inline_any_operand.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/inline/inline-any-operand.rs b/src/test/mir-opt/inline/inline_any_operand.rs index fb0de020f73..fb0de020f73 100644 --- a/src/test/mir-opt/inline/inline-any-operand.rs +++ b/src/test/mir-opt/inline/inline_any_operand.rs diff --git a/src/test/mir-opt/inline/inline-async.rs b/src/test/mir-opt/inline/inline_async.rs index 5c838159b98..5c838159b98 100644 --- a/src/test/mir-opt/inline/inline-async.rs +++ b/src/test/mir-opt/inline/inline_async.rs diff --git a/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir index 1fadd246479..9eb3a01eef9 100644 --- a/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir @@ -1,49 +1,49 @@ // MIR for `foo` after Inline fn foo(_1: T, _2: i32) -> i32 { - debug _t => _1; // in scope 0 at $DIR/inline-closure.rs:+0:17: +0:19 - debug q => _2; // in scope 0 at $DIR/inline-closure.rs:+0:24: +0:25 - let mut _0: i32; // return place in scope 0 at $DIR/inline-closure.rs:+0:35: +0:38 - let _3: [closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline-closure.rs:+1:9: +1:10 - let mut _4: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline-closure.rs:+2:5: +2:6 - let mut _5: (i32, i32); // in scope 0 at $DIR/inline-closure.rs:+2:5: +2:12 - let mut _6: i32; // in scope 0 at $DIR/inline-closure.rs:+2:7: +2:8 - let mut _7: i32; // in scope 0 at $DIR/inline-closure.rs:+2:10: +2:11 - let mut _8: i32; // in scope 0 at $DIR/inline-closure.rs:+2:5: +2:12 - let mut _9: i32; // in scope 0 at $DIR/inline-closure.rs:+2:5: +2:12 + debug _t => _1; // in scope 0 at $DIR/inline_closure.rs:+0:17: +0:19 + debug q => _2; // in scope 0 at $DIR/inline_closure.rs:+0:24: +0:25 + let mut _0: i32; // return place in scope 0 at $DIR/inline_closure.rs:+0:35: +0:38 + let _3: [closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure.rs:+1:9: +1:10 + let mut _4: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure.rs:+2:5: +2:6 + let mut _5: (i32, i32); // in scope 0 at $DIR/inline_closure.rs:+2:5: +2:12 + let mut _6: i32; // in scope 0 at $DIR/inline_closure.rs:+2:7: +2:8 + let mut _7: i32; // in scope 0 at $DIR/inline_closure.rs:+2:10: +2:11 + let mut _8: i32; // in scope 0 at $DIR/inline_closure.rs:+2:5: +2:12 + let mut _9: i32; // in scope 0 at $DIR/inline_closure.rs:+2:5: +2:12 scope 1 { - debug x => _3; // in scope 1 at $DIR/inline-closure.rs:+1:9: +1:10 - scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline-closure.rs:12:5: 12:12 - debug _t => _8; // in scope 2 at $DIR/inline-closure.rs:+1:14: +1:16 - debug _q => _9; // in scope 2 at $DIR/inline-closure.rs:+1:18: +1:20 + debug x => _3; // in scope 1 at $DIR/inline_closure.rs:+1:9: +1:10 + scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline_closure.rs:12:5: 12:12 + debug _t => _8; // in scope 2 at $DIR/inline_closure.rs:+1:14: +1:16 + debug _q => _9; // in scope 2 at $DIR/inline_closure.rs:+1:18: +1:20 } } bb0: { - StorageLive(_3); // scope 0 at $DIR/inline-closure.rs:+1:9: +1:10 - Deinit(_3); // scope 0 at $DIR/inline-closure.rs:+1:13: +1:24 - StorageLive(_4); // scope 1 at $DIR/inline-closure.rs:+2:5: +2:6 - _4 = &_3; // scope 1 at $DIR/inline-closure.rs:+2:5: +2:6 - StorageLive(_5); // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - StorageLive(_6); // scope 1 at $DIR/inline-closure.rs:+2:7: +2:8 - _6 = _2; // scope 1 at $DIR/inline-closure.rs:+2:7: +2:8 - StorageLive(_7); // scope 1 at $DIR/inline-closure.rs:+2:10: +2:11 - _7 = _2; // scope 1 at $DIR/inline-closure.rs:+2:10: +2:11 - Deinit(_5); // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - (_5.0: i32) = move _6; // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - (_5.1: i32) = move _7; // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - StorageLive(_8); // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - _8 = move (_5.0: i32); // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - StorageLive(_9); // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - _9 = move (_5.1: i32); // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - _0 = _8; // scope 2 at $DIR/inline-closure.rs:+1:22: +1:24 - StorageDead(_9); // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - StorageDead(_8); // scope 1 at $DIR/inline-closure.rs:+2:5: +2:12 - StorageDead(_7); // scope 1 at $DIR/inline-closure.rs:+2:11: +2:12 - StorageDead(_6); // scope 1 at $DIR/inline-closure.rs:+2:11: +2:12 - StorageDead(_5); // scope 1 at $DIR/inline-closure.rs:+2:11: +2:12 - StorageDead(_4); // scope 1 at $DIR/inline-closure.rs:+2:11: +2:12 - StorageDead(_3); // scope 0 at $DIR/inline-closure.rs:+3:1: +3:2 - return; // scope 0 at $DIR/inline-closure.rs:+3:2: +3:2 + StorageLive(_3); // scope 0 at $DIR/inline_closure.rs:+1:9: +1:10 + Deinit(_3); // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24 + StorageLive(_4); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6 + _4 = &_3; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6 + StorageLive(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageLive(_6); // scope 1 at $DIR/inline_closure.rs:+2:7: +2:8 + _6 = _2; // scope 1 at $DIR/inline_closure.rs:+2:7: +2:8 + StorageLive(_7); // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11 + _7 = _2; // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11 + Deinit(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + (_5.0: i32) = move _6; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + (_5.1: i32) = move _7; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageLive(_8); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + _8 = move (_5.0: i32); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageLive(_9); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + _9 = move (_5.1: i32); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + _0 = _8; // scope 2 at $DIR/inline_closure.rs:+1:22: +1:24 + StorageDead(_9); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageDead(_8); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageDead(_7); // scope 1 at $DIR/inline_closure.rs:+2:11: +2:12 + StorageDead(_6); // scope 1 at $DIR/inline_closure.rs:+2:11: +2:12 + StorageDead(_5); // scope 1 at $DIR/inline_closure.rs:+2:11: +2:12 + StorageDead(_4); // scope 1 at $DIR/inline_closure.rs:+2:11: +2:12 + StorageDead(_3); // scope 0 at $DIR/inline_closure.rs:+3:1: +3:2 + return; // scope 0 at $DIR/inline_closure.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/inline/inline-closure.rs b/src/test/mir-opt/inline/inline_closure.rs index 715fd0138a7..715fd0138a7 100644 --- a/src/test/mir-opt/inline/inline-closure.rs +++ b/src/test/mir-opt/inline/inline_closure.rs diff --git a/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir index 4069e9f89c8..e6275ac7f5d 100644 --- a/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir @@ -1,56 +1,56 @@ // MIR for `foo` after Inline fn foo(_1: T, _2: &i32) -> i32 { - debug _t => _1; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:+0:17: +0:19 - debug q => _2; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:+0:24: +0:25 - let mut _0: i32; // return place in scope 0 at $DIR/inline-closure-borrows-arg.rs:+0:36: +0:39 - let _3: [closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:+1:9: +1:10 - let mut _4: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:6 - let mut _5: (&i32, &i32); // in scope 0 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - let mut _6: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:+5:7: +5:8 - let mut _7: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:+5:10: +5:11 - let mut _8: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - let mut _9: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 + debug _t => _1; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+0:17: +0:19 + debug q => _2; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+0:24: +0:25 + let mut _0: i32; // return place in scope 0 at $DIR/inline_closure_borrows_arg.rs:+0:36: +0:39 + let _3: [closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10 + let mut _4: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6 + let mut _5: (&i32, &i32); // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + let mut _6: &i32; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8 + let mut _7: &i32; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11 + let mut _8: &i32; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + let mut _9: &i32; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 scope 1 { - debug x => _3; // in scope 1 at $DIR/inline-closure-borrows-arg.rs:+1:9: +1:10 - scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 - debug r => _8; // in scope 2 at $DIR/inline-closure-borrows-arg.rs:+1:14: +1:15 - debug _s => _9; // in scope 2 at $DIR/inline-closure-borrows-arg.rs:+1:23: +1:25 - let _10: &i32; // in scope 2 at $DIR/inline-closure-borrows-arg.rs:+2:13: +2:21 + debug x => _3; // in scope 1 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10 + scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline_closure_borrows_arg.rs:16:5: 16:12 + debug r => _8; // in scope 2 at $DIR/inline_closure_borrows_arg.rs:+1:14: +1:15 + debug _s => _9; // in scope 2 at $DIR/inline_closure_borrows_arg.rs:+1:23: +1:25 + let _10: &i32; // in scope 2 at $DIR/inline_closure_borrows_arg.rs:+2:13: +2:21 scope 3 { - debug variable => _10; // in scope 3 at $DIR/inline-closure-borrows-arg.rs:+2:13: +2:21 + debug variable => _10; // in scope 3 at $DIR/inline_closure_borrows_arg.rs:+2:13: +2:21 } } } bb0: { - StorageLive(_3); // scope 0 at $DIR/inline-closure-borrows-arg.rs:+1:9: +1:10 - Deinit(_3); // scope 0 at $DIR/inline-closure-borrows-arg.rs:+1:13: +4:6 - StorageLive(_4); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:6 - _4 = &_3; // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:6 - StorageLive(_5); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - StorageLive(_6); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:7: +5:8 - _6 = &(*_2); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:7: +5:8 - StorageLive(_7); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:10: +5:11 - _7 = &(*_2); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:10: +5:11 - Deinit(_5); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - (_5.0: &i32) = move _6; // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - (_5.1: &i32) = move _7; // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - StorageLive(_8); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - _8 = move (_5.0: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - StorageLive(_9); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - _9 = move (_5.1: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - StorageLive(_10); // scope 2 at $DIR/inline-closure-borrows-arg.rs:+2:13: +2:21 - _10 = _8; // scope 2 at $DIR/inline-closure-borrows-arg.rs:+2:24: +2:27 - _0 = (*_10); // scope 3 at $DIR/inline-closure-borrows-arg.rs:+3:9: +3:18 - StorageDead(_10); // scope 2 at $DIR/inline-closure-borrows-arg.rs:+4:5: +4:6 - StorageDead(_9); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - StorageDead(_8); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:5: +5:12 - StorageDead(_7); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:11: +5:12 - StorageDead(_6); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:11: +5:12 - StorageDead(_5); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:11: +5:12 - StorageDead(_4); // scope 1 at $DIR/inline-closure-borrows-arg.rs:+5:11: +5:12 - StorageDead(_3); // scope 0 at $DIR/inline-closure-borrows-arg.rs:+6:1: +6:2 - return; // scope 0 at $DIR/inline-closure-borrows-arg.rs:+6:2: +6:2 + StorageLive(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10 + Deinit(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6 + StorageLive(_4); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6 + _4 = &_3; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6 + StorageLive(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageLive(_6); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8 + _6 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8 + StorageLive(_7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11 + _7 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11 + Deinit(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + (_5.0: &i32) = move _6; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + (_5.1: &i32) = move _7; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageLive(_8); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + _8 = move (_5.0: &i32); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageLive(_9); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + _9 = move (_5.1: &i32); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageLive(_10); // scope 2 at $DIR/inline_closure_borrows_arg.rs:+2:13: +2:21 + _10 = _8; // scope 2 at $DIR/inline_closure_borrows_arg.rs:+2:24: +2:27 + _0 = (*_10); // scope 3 at $DIR/inline_closure_borrows_arg.rs:+3:9: +3:18 + StorageDead(_10); // scope 2 at $DIR/inline_closure_borrows_arg.rs:+4:5: +4:6 + StorageDead(_9); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageDead(_8); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageDead(_7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:11: +5:12 + StorageDead(_6); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:11: +5:12 + StorageDead(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:11: +5:12 + StorageDead(_4); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:11: +5:12 + StorageDead(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+6:1: +6:2 + return; // scope 0 at $DIR/inline_closure_borrows_arg.rs:+6:2: +6:2 } } diff --git a/src/test/mir-opt/inline/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline/inline_closure_borrows_arg.rs index d76bc33f52e..d76bc33f52e 100644 --- a/src/test/mir-opt/inline/inline-closure-borrows-arg.rs +++ b/src/test/mir-opt/inline/inline_closure_borrows_arg.rs diff --git a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index a2234e7c1ef..fd19c288666 100644 --- a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -1,65 +1,65 @@ // MIR for `foo` after Inline fn foo(_1: T, _2: i32) -> (i32, T) { - debug t => _1; // in scope 0 at $DIR/inline-closure-captures.rs:+0:17: +0:18 - debug q => _2; // in scope 0 at $DIR/inline-closure-captures.rs:+0:23: +0:24 - let mut _0: (i32, T); // return place in scope 0 at $DIR/inline-closure-captures.rs:+0:34: +0:42 - let _3: [closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline-closure-captures.rs:+1:9: +1:10 - let mut _4: &i32; // in scope 0 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - let mut _5: &T; // in scope 0 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - let mut _6: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline-closure-captures.rs:+2:5: +2:6 - let mut _7: (i32,); // in scope 0 at $DIR/inline-closure-captures.rs:+2:5: +2:9 - let mut _8: i32; // in scope 0 at $DIR/inline-closure-captures.rs:+2:7: +2:8 - let mut _9: i32; // in scope 0 at $DIR/inline-closure-captures.rs:+2:5: +2:9 + debug t => _1; // in scope 0 at $DIR/inline_closure_captures.rs:+0:17: +0:18 + debug q => _2; // in scope 0 at $DIR/inline_closure_captures.rs:+0:23: +0:24 + let mut _0: (i32, T); // return place in scope 0 at $DIR/inline_closure_captures.rs:+0:34: +0:42 + let _3: [closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure_captures.rs:+1:9: +1:10 + let mut _4: &i32; // in scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + let mut _5: &T; // in scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + let mut _6: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure_captures.rs:+2:5: +2:6 + let mut _7: (i32,); // in scope 0 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + let mut _8: i32; // in scope 0 at $DIR/inline_closure_captures.rs:+2:7: +2:8 + let mut _9: i32; // in scope 0 at $DIR/inline_closure_captures.rs:+2:5: +2:9 scope 1 { - debug x => _3; // in scope 1 at $DIR/inline-closure-captures.rs:+1:9: +1:10 - scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline-closure-captures.rs:12:5: 12:9 - debug _q => _9; // in scope 2 at $DIR/inline-closure-captures.rs:+1:14: +1:16 - debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline-closure-captures.rs:+0:23: +0:24 - debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline-closure-captures.rs:+0:17: +0:18 - let mut _10: i32; // in scope 2 at $DIR/inline-closure-captures.rs:+1:19: +1:20 - let mut _11: T; // in scope 2 at $DIR/inline-closure-captures.rs:+1:22: +1:23 - let mut _12: &i32; // in scope 2 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - let mut _13: &T; // in scope 2 at $DIR/inline-closure-captures.rs:+1:13: +1:24 + debug x => _3; // in scope 1 at $DIR/inline_closure_captures.rs:+1:9: +1:10 + scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline_closure_captures.rs:12:5: 12:9 + debug _q => _9; // in scope 2 at $DIR/inline_closure_captures.rs:+1:14: +1:16 + debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline_closure_captures.rs:+0:23: +0:24 + debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline_closure_captures.rs:+0:17: +0:18 + let mut _10: i32; // in scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20 + let mut _11: T; // in scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 + let mut _12: &i32; // in scope 2 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + let mut _13: &T; // in scope 2 at $DIR/inline_closure_captures.rs:+1:13: +1:24 } } bb0: { - StorageLive(_3); // scope 0 at $DIR/inline-closure-captures.rs:+1:9: +1:10 - StorageLive(_4); // scope 0 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - _4 = &_2; // scope 0 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - StorageLive(_5); // scope 0 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - _5 = &_1; // scope 0 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - Deinit(_3); // scope 0 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - (_3.0: &i32) = move _4; // scope 0 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - (_3.1: &T) = move _5; // scope 0 at $DIR/inline-closure-captures.rs:+1:13: +1:24 - StorageDead(_5); // scope 0 at $DIR/inline-closure-captures.rs:+1:16: +1:17 - StorageDead(_4); // scope 0 at $DIR/inline-closure-captures.rs:+1:16: +1:17 - StorageLive(_6); // scope 1 at $DIR/inline-closure-captures.rs:+2:5: +2:6 - _6 = &_3; // scope 1 at $DIR/inline-closure-captures.rs:+2:5: +2:6 - StorageLive(_7); // scope 1 at $DIR/inline-closure-captures.rs:+2:5: +2:9 - StorageLive(_8); // scope 1 at $DIR/inline-closure-captures.rs:+2:7: +2:8 - _8 = _2; // scope 1 at $DIR/inline-closure-captures.rs:+2:7: +2:8 - Deinit(_7); // scope 1 at $DIR/inline-closure-captures.rs:+2:5: +2:9 - (_7.0: i32) = move _8; // scope 1 at $DIR/inline-closure-captures.rs:+2:5: +2:9 - StorageLive(_9); // scope 1 at $DIR/inline-closure-captures.rs:+2:5: +2:9 - _9 = move (_7.0: i32); // scope 1 at $DIR/inline-closure-captures.rs:+2:5: +2:9 - StorageLive(_10); // scope 2 at $DIR/inline-closure-captures.rs:+1:19: +1:20 - _12 = deref_copy ((*_6).0: &i32); // scope 2 at $DIR/inline-closure-captures.rs:+1:19: +1:20 - _10 = (*_12); // scope 2 at $DIR/inline-closure-captures.rs:+1:19: +1:20 - StorageLive(_11); // scope 2 at $DIR/inline-closure-captures.rs:+1:22: +1:23 - _13 = deref_copy ((*_6).1: &T); // scope 2 at $DIR/inline-closure-captures.rs:+1:22: +1:23 - _11 = (*_13); // scope 2 at $DIR/inline-closure-captures.rs:+1:22: +1:23 - Deinit(_0); // scope 2 at $DIR/inline-closure-captures.rs:+1:18: +1:24 - (_0.0: i32) = move _10; // scope 2 at $DIR/inline-closure-captures.rs:+1:18: +1:24 - (_0.1: T) = move _11; // scope 2 at $DIR/inline-closure-captures.rs:+1:18: +1:24 - StorageDead(_11); // scope 2 at $DIR/inline-closure-captures.rs:+1:23: +1:24 - StorageDead(_10); // scope 2 at $DIR/inline-closure-captures.rs:+1:23: +1:24 - StorageDead(_9); // scope 1 at $DIR/inline-closure-captures.rs:+2:5: +2:9 - StorageDead(_8); // scope 1 at $DIR/inline-closure-captures.rs:+2:8: +2:9 - StorageDead(_7); // scope 1 at $DIR/inline-closure-captures.rs:+2:8: +2:9 - StorageDead(_6); // scope 1 at $DIR/inline-closure-captures.rs:+2:8: +2:9 - StorageDead(_3); // scope 0 at $DIR/inline-closure-captures.rs:+3:1: +3:2 - return; // scope 0 at $DIR/inline-closure-captures.rs:+3:2: +3:2 + StorageLive(_3); // scope 0 at $DIR/inline_closure_captures.rs:+1:9: +1:10 + StorageLive(_4); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + _4 = &_2; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + StorageLive(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + _5 = &_1; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + Deinit(_3); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + (_3.0: &i32) = move _4; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + (_3.1: &T) = move _5; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + StorageDead(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17 + StorageDead(_4); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17 + StorageLive(_6); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:6 + _6 = &_3; // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:6 + StorageLive(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + StorageLive(_8); // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8 + _8 = _2; // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8 + Deinit(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + (_7.0: i32) = move _8; // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + StorageLive(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + _9 = move (_7.0: i32); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + StorageLive(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20 + _12 = deref_copy ((*_6).0: &i32); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20 + _10 = (*_12); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20 + StorageLive(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 + _13 = deref_copy ((*_6).1: &T); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 + _11 = (*_13); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 + Deinit(_0); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 + (_0.0: i32) = move _10; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 + (_0.1: T) = move _11; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 + StorageDead(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24 + StorageDead(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24 + StorageDead(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + StorageDead(_8); // scope 1 at $DIR/inline_closure_captures.rs:+2:8: +2:9 + StorageDead(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:8: +2:9 + StorageDead(_6); // scope 1 at $DIR/inline_closure_captures.rs:+2:8: +2:9 + StorageDead(_3); // scope 0 at $DIR/inline_closure_captures.rs:+3:1: +3:2 + return; // scope 0 at $DIR/inline_closure_captures.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/inline/inline-closure-captures.rs b/src/test/mir-opt/inline/inline_closure_captures.rs index 52b6817e401..52b6817e401 100644 --- a/src/test/mir-opt/inline/inline-closure-captures.rs +++ b/src/test/mir-opt/inline/inline_closure_captures.rs diff --git a/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff index cf800ba1129..e30a5e116ea 100644 --- a/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff +++ b/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff @@ -2,23 +2,23 @@ + // MIR for `inlined_no_sanitize` after Inline fn inlined_no_sanitize() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-compatibility.rs:+0:37: +0:37 - let _1: (); // in scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:18 -+ scope 1 (inlined no_sanitize) { // at $DIR/inline-compatibility.rs:24:5: 24:18 + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:37: +0:37 + let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 ++ scope 1 (inlined no_sanitize) { // at $DIR/inline_compatibility.rs:24:5: 24:18 + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:18 -- _1 = no_sanitize() -> bb1; // scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:18 + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 +- _1 = no_sanitize() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 - // mir::Constant -- // + span: $DIR/inline-compatibility.rs:24:5: 24:16 +- // + span: $DIR/inline_compatibility.rs:24:5: 24:16 - // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(<ZST>) } - } - - bb1: { - StorageDead(_1); // scope 0 at $DIR/inline-compatibility.rs:+1:18: +1:19 - _0 = const (); // scope 0 at $DIR/inline-compatibility.rs:+0:37: +2:2 - return; // scope 0 at $DIR/inline-compatibility.rs:+2:2: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:18: +1:19 + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:37: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff index a45f959026d..c2b3c46a30c 100644 --- a/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff +++ b/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff @@ -2,23 +2,23 @@ + // MIR for `inlined_target_feature` after Inline fn inlined_target_feature() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-compatibility.rs:+0:40: +0:40 - let _1: (); // in scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:21 -+ scope 1 (inlined target_feature) { // at $DIR/inline-compatibility.rs:13:5: 13:21 + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:40: +0:40 + let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 ++ scope 1 (inlined target_feature) { // at $DIR/inline_compatibility.rs:13:5: 13:21 + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:21 -- _1 = target_feature() -> bb1; // scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:21 + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 +- _1 = target_feature() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 - // mir::Constant -- // + span: $DIR/inline-compatibility.rs:13:5: 13:19 +- // + span: $DIR/inline_compatibility.rs:13:5: 13:19 - // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(<ZST>) } - } - - bb1: { - StorageDead(_1); // scope 0 at $DIR/inline-compatibility.rs:+1:21: +1:22 - _0 = const (); // scope 0 at $DIR/inline-compatibility.rs:+0:40: +2:2 - return; // scope 0 at $DIR/inline-compatibility.rs:+2:2: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:21: +1:22 + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:40: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff index 49aea431e46..0ca5a5f70b7 100644 --- a/src/test/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff +++ b/src/test/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff @@ -2,24 +2,24 @@ + // MIR for `not_inlined_c_variadic` after Inline fn not_inlined_c_variadic() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-compatibility.rs:+0:40: +0:40 - let _1: u32; // in scope 0 at $DIR/inline-compatibility.rs:+1:9: +1:10 + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:40: +0:40 + let _1: u32; // in scope 0 at $DIR/inline_compatibility.rs:+1:9: +1:10 scope 1 { - debug s => _1; // in scope 1 at $DIR/inline-compatibility.rs:+1:9: +1:10 + debug s => _1; // in scope 1 at $DIR/inline_compatibility.rs:+1:9: +1:10 } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-compatibility.rs:+1:9: +1:10 - _1 = sum(const 4_u32, const 4_u32, const 30_u32, const 200_u32, const 1000_u32) -> bb1; // scope 0 at $DIR/inline-compatibility.rs:+1:13: +1:52 + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:9: +1:10 + _1 = sum(const 4_u32, const 4_u32, const 30_u32, const 200_u32, const 1000_u32) -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:13: +1:52 // mir::Constant - // + span: $DIR/inline-compatibility.rs:42:13: 42:16 + // + span: $DIR/inline_compatibility.rs:42:13: 42:16 // + literal: Const { ty: unsafe extern "C" fn(u32, ...) -> u32 {sum}, val: Value(<ZST>) } } bb1: { - _0 = const (); // scope 0 at $DIR/inline-compatibility.rs:+0:40: +2:2 - StorageDead(_1); // scope 0 at $DIR/inline-compatibility.rs:+2:1: +2:2 - return; // scope 0 at $DIR/inline-compatibility.rs:+2:2: +2:2 + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:40: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+2:1: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff index 94ce574a94d..00d405c77f9 100644 --- a/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff +++ b/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff @@ -2,21 +2,21 @@ + // MIR for `not_inlined_no_sanitize` after Inline fn not_inlined_no_sanitize() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-compatibility.rs:+0:41: +0:41 - let _1: (); // in scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:18 + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:41: +0:41 + let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:18 - _1 = no_sanitize() -> bb1; // scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:18 + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 + _1 = no_sanitize() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 // mir::Constant - // + span: $DIR/inline-compatibility.rs:29:5: 29:16 + // + span: $DIR/inline_compatibility.rs:29:5: 29:16 // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(<ZST>) } } bb1: { - StorageDead(_1); // scope 0 at $DIR/inline-compatibility.rs:+1:18: +1:19 - _0 = const (); // scope 0 at $DIR/inline-compatibility.rs:+0:41: +2:2 - return; // scope 0 at $DIR/inline-compatibility.rs:+2:2: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:18: +1:19 + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:41: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff index 8506e257b3f..8b9c86f5515 100644 --- a/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff +++ b/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff @@ -2,21 +2,21 @@ + // MIR for `not_inlined_target_feature` after Inline fn not_inlined_target_feature() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-compatibility.rs:+0:44: +0:44 - let _1: (); // in scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:21 + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:44: +0:44 + let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:21 - _1 = target_feature() -> bb1; // scope 0 at $DIR/inline-compatibility.rs:+1:5: +1:21 + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 + _1 = target_feature() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 // mir::Constant - // + span: $DIR/inline-compatibility.rs:18:5: 18:19 + // + span: $DIR/inline_compatibility.rs:18:5: 18:19 // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(<ZST>) } } bb1: { - StorageDead(_1); // scope 0 at $DIR/inline-compatibility.rs:+1:21: +1:22 - _0 = const (); // scope 0 at $DIR/inline-compatibility.rs:+0:44: +2:2 - return; // scope 0 at $DIR/inline-compatibility.rs:+2:2: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:21: +1:22 + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:44: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline-compatibility.rs b/src/test/mir-opt/inline/inline_compatibility.rs index 30aff0a64ef..30aff0a64ef 100644 --- a/src/test/mir-opt/inline/inline-compatibility.rs +++ b/src/test/mir-opt/inline/inline_compatibility.rs diff --git a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff index a4d706de0ba..5510cd7bc8c 100644 --- a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff @@ -2,29 +2,29 @@ + // MIR for `one` after Inline fn one() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-cycle.rs:+0:10: +0:10 - let _1: (); // in scope 0 at $DIR/inline-cycle.rs:+1:5: +1:24 -+ scope 1 (inlined <C as Call>::call) { // at $DIR/inline-cycle.rs:14:5: 14:24 -+ scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline-cycle.rs:43:9: 43:23 -+ scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline-cycle.rs:28:9: 28:31 + let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10 + let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 ++ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:14:5: 14:24 ++ scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23 ++ scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31 + } + } + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:24 -- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:24 -+ _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline-cycle.rs:36:9: 36:28 + StorageLive(_1); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 +- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 ++ _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28 // mir::Constant -- // + span: $DIR/inline-cycle.rs:14:5: 14:22 -+ // + span: $DIR/inline-cycle.rs:36:9: 36:26 +- // + span: $DIR/inline_cycle.rs:14:5: 14:22 ++ // + span: $DIR/inline_cycle.rs:36:9: 36:26 // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } } bb1: { - StorageDead(_1); // scope 0 at $DIR/inline-cycle.rs:+1:24: +1:25 - _0 = const (); // scope 0 at $DIR/inline-cycle.rs:+0:10: +2:2 - return; // scope 0 at $DIR/inline-cycle.rs:+2:2: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_cycle.rs:+1:24: +1:25 + _0 = const (); // scope 0 at $DIR/inline_cycle.rs:+0:10: +2:2 + return; // scope 0 at $DIR/inline_cycle.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline-cycle.rs b/src/test/mir-opt/inline/inline_cycle.rs index 63ad57de1d4..63ad57de1d4 100644 --- a/src/test/mir-opt/inline/inline-cycle.rs +++ b/src/test/mir-opt/inline/inline_cycle.rs diff --git a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff index b1a5b62ef1d..eceeb96f79f 100644 --- a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff @@ -2,54 +2,54 @@ + // MIR for `two` after Inline fn two() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-cycle.rs:+0:10: +0:10 - let _1: (); // in scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12 -+ let mut _2: fn() {f}; // in scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12 -+ scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline-cycle.rs:49:5: 49:12 -+ debug f => _2; // in scope 1 at $DIR/inline-cycle.rs:53:22: 53:23 -+ let _3: (); // in scope 1 at $DIR/inline-cycle.rs:54:5: 54:8 -+ let mut _4: fn() {f}; // in scope 1 at $DIR/inline-cycle.rs:54:5: 54:6 -+ let mut _5: (); // in scope 1 at $DIR/inline-cycle.rs:54:5: 54:8 -+ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline-cycle.rs:54:5: 54:8 + let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10 + let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 ++ let mut _2: fn() {f}; // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 ++ scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline_cycle.rs:49:5: 49:12 ++ debug f => _2; // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23 ++ let _3: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ let mut _4: fn() {f}; // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:6 ++ let mut _5: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8 + scope 3 (inlined f) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL -+ let _6: (); // in scope 3 at $DIR/inline-cycle.rs:59:5: 59:12 ++ let _6: (); // in scope 3 at $DIR/inline_cycle.rs:59:5: 59:12 + } + } + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12 -- _1 = call::<fn() {f}>(f) -> bb1; // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12 -+ StorageLive(_2); // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12 -+ _2 = f; // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12 + StorageLive(_1); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 +- _1 = call::<fn() {f}>(f) -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 ++ StorageLive(_2); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 ++ _2 = f; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 // mir::Constant -- // + span: $DIR/inline-cycle.rs:49:5: 49:9 -+ // + span: $DIR/inline-cycle.rs:49:10: 49:11 +- // + span: $DIR/inline_cycle.rs:49:5: 49:9 ++ // + span: $DIR/inline_cycle.rs:49:10: 49:11 + // + literal: Const { ty: fn() {f}, val: Value(<ZST>) } -+ StorageLive(_3); // scope 1 at $DIR/inline-cycle.rs:54:5: 54:8 -+ StorageLive(_4); // scope 1 at $DIR/inline-cycle.rs:54:5: 54:6 -+ _4 = move _2; // scope 1 at $DIR/inline-cycle.rs:54:5: 54:6 -+ StorageLive(_5); // scope 1 at $DIR/inline-cycle.rs:54:5: 54:8 -+ StorageLive(_6); // scope 3 at $DIR/inline-cycle.rs:59:5: 59:12 -+ _6 = call::<fn() {f}>(f) -> bb1; // scope 3 at $DIR/inline-cycle.rs:59:5: 59:12 ++ StorageLive(_3); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ StorageLive(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:6 ++ _4 = move _2; // scope 1 at $DIR/inline_cycle.rs:54:5: 54:6 ++ StorageLive(_5); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ StorageLive(_6); // scope 3 at $DIR/inline_cycle.rs:59:5: 59:12 ++ _6 = call::<fn() {f}>(f) -> bb1; // scope 3 at $DIR/inline_cycle.rs:59:5: 59:12 + // mir::Constant -+ // + span: $DIR/inline-cycle.rs:59:5: 59:9 ++ // + span: $DIR/inline_cycle.rs:59:5: 59:9 // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(<ZST>) } // mir::Constant -- // + span: $DIR/inline-cycle.rs:49:10: 49:11 -+ // + span: $DIR/inline-cycle.rs:59:10: 59:11 +- // + span: $DIR/inline_cycle.rs:49:10: 49:11 ++ // + span: $DIR/inline_cycle.rs:59:10: 59:11 // + literal: Const { ty: fn() {f}, val: Value(<ZST>) } } bb1: { -+ StorageDead(_6); // scope 3 at $DIR/inline-cycle.rs:59:12: 59:13 -+ StorageDead(_5); // scope 1 at $DIR/inline-cycle.rs:54:7: 54:8 -+ StorageDead(_4); // scope 1 at $DIR/inline-cycle.rs:54:7: 54:8 -+ StorageDead(_3); // scope 1 at $DIR/inline-cycle.rs:54:8: 54:9 -+ StorageDead(_2); // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12 - StorageDead(_1); // scope 0 at $DIR/inline-cycle.rs:+1:12: +1:13 - _0 = const (); // scope 0 at $DIR/inline-cycle.rs:+0:10: +2:2 - return; // scope 0 at $DIR/inline-cycle.rs:+2:2: +2:2 ++ StorageDead(_6); // scope 3 at $DIR/inline_cycle.rs:59:12: 59:13 ++ StorageDead(_5); // scope 1 at $DIR/inline_cycle.rs:54:7: 54:8 ++ StorageDead(_4); // scope 1 at $DIR/inline_cycle.rs:54:7: 54:8 ++ StorageDead(_3); // scope 1 at $DIR/inline_cycle.rs:54:8: 54:9 ++ StorageDead(_2); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 + StorageDead(_1); // scope 0 at $DIR/inline_cycle.rs:+1:12: +1:13 + _0 = const (); // scope 0 at $DIR/inline_cycle.rs:+0:10: +2:2 + return; // scope 0 at $DIR/inline_cycle.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff index fc5d57ce8bf..52debab4dd1 100644 --- a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff @@ -2,31 +2,31 @@ + // MIR for `main` after Inline fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-cycle-generic.rs:+0:11: +0:11 - let _1: (); // in scope 0 at $DIR/inline-cycle-generic.rs:+1:5: +1:24 -+ scope 1 (inlined <C as Call>::call) { // at $DIR/inline-cycle-generic.rs:9:5: 9:24 -+ scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline-cycle-generic.rs:38:9: 38:31 -+ scope 3 (inlined <A as Call>::call) { // at $DIR/inline-cycle-generic.rs:31:9: 31:28 -+ scope 4 (inlined <B<C> as Call>::call) { // at $DIR/inline-cycle-generic.rs:23:9: 23:31 + let mut _0: (); // return place in scope 0 at $DIR/inline_cycle_generic.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 ++ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24 ++ scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31 ++ scope 3 (inlined <A as Call>::call) { // at $DIR/inline_cycle_generic.rs:31:9: 31:28 ++ scope 4 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle_generic.rs:23:9: 23:31 + } + } + } + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-cycle-generic.rs:+1:5: +1:24 -- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle-generic.rs:+1:5: +1:24 -+ _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline-cycle-generic.rs:31:9: 31:28 + StorageLive(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 +- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 ++ _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline_cycle_generic.rs:31:9: 31:28 // mir::Constant -- // + span: $DIR/inline-cycle-generic.rs:9:5: 9:22 -+ // + span: $DIR/inline-cycle-generic.rs:31:9: 31:26 +- // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22 ++ // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26 // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } } bb1: { - StorageDead(_1); // scope 0 at $DIR/inline-cycle-generic.rs:+1:24: +1:25 - _0 = const (); // scope 0 at $DIR/inline-cycle-generic.rs:+0:11: +2:2 - return; // scope 0 at $DIR/inline-cycle-generic.rs:+2:2: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:24: +1:25 + _0 = const (); // scope 0 at $DIR/inline_cycle_generic.rs:+0:11: +2:2 + return; // scope 0 at $DIR/inline_cycle_generic.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline-cycle-generic.rs b/src/test/mir-opt/inline/inline_cycle_generic.rs index 24b4f37939a..24b4f37939a 100644 --- a/src/test/mir-opt/inline/inline-cycle-generic.rs +++ b/src/test/mir-opt/inline/inline_cycle_generic.rs diff --git a/src/test/mir-opt/inline/inline_diverging.f.Inline.diff b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff index cef4cfc67ab..b49191f495b 100644 --- a/src/test/mir-opt/inline/inline_diverging.f.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff @@ -2,23 +2,23 @@ + // MIR for `f` after Inline fn f() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:+0:12: +0:12 - let mut _1: !; // in scope 0 at $DIR/inline-diverging.rs:+0:12: +2:2 - let _2: !; // in scope 0 at $DIR/inline-diverging.rs:+1:5: +1:12 -+ scope 1 (inlined sleep) { // at $DIR/inline-diverging.rs:8:5: 8:12 + let mut _0: (); // return place in scope 0 at $DIR/inline_diverging.rs:+0:12: +0:12 + let mut _1: !; // in scope 0 at $DIR/inline_diverging.rs:+0:12: +2:2 + let _2: !; // in scope 0 at $DIR/inline_diverging.rs:+1:5: +1:12 ++ scope 1 (inlined sleep) { // at $DIR/inline_diverging.rs:8:5: 8:12 + } bb0: { - StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:+1:5: +1:12 -- _2 = sleep(); // scope 0 at $DIR/inline-diverging.rs:+1:5: +1:12 + StorageLive(_2); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:12 +- _2 = sleep(); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:12 - // mir::Constant -- // + span: $DIR/inline-diverging.rs:8:5: 8:10 +- // + span: $DIR/inline_diverging.rs:8:5: 8:10 - // + literal: Const { ty: fn() -> ! {sleep}, val: Value(<ZST>) } -+ goto -> bb1; // scope 0 at $DIR/inline-diverging.rs:+1:5: +1:12 ++ goto -> bb1; // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:12 + } + + bb1: { -+ goto -> bb1; // scope 1 at $DIR/inline-diverging.rs:39:5: 39:12 ++ goto -> bb1; // scope 1 at $DIR/inline_diverging.rs:39:5: 39:12 } } diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff index a71baad3e3e..1e703a8fd2b 100644 --- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff @@ -2,42 +2,42 @@ + // MIR for `g` after Inline fn g(_1: i32) -> u32 { - debug i => _1; // in scope 0 at $DIR/inline-diverging.rs:+0:10: +0:11 - let mut _0: u32; // return place in scope 0 at $DIR/inline-diverging.rs:+0:21: +0:24 - let mut _2: bool; // in scope 0 at $DIR/inline-diverging.rs:+1:8: +1:13 - let mut _3: i32; // in scope 0 at $DIR/inline-diverging.rs:+1:8: +1:9 - let mut _4: i32; // in scope 0 at $DIR/inline-diverging.rs:+2:9: +2:10 - let mut _5: !; // in scope 0 at $DIR/inline-diverging.rs:+3:12: +5:6 - let _6: !; // in scope 0 at $DIR/inline-diverging.rs:+4:9: +4:16 -+ scope 1 (inlined panic) { // at $DIR/inline-diverging.rs:16:9: 16:16 + debug i => _1; // in scope 0 at $DIR/inline_diverging.rs:+0:10: +0:11 + let mut _0: u32; // return place in scope 0 at $DIR/inline_diverging.rs:+0:21: +0:24 + let mut _2: bool; // in scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13 + let mut _3: i32; // in scope 0 at $DIR/inline_diverging.rs:+1:8: +1:9 + let mut _4: i32; // in scope 0 at $DIR/inline_diverging.rs:+2:9: +2:10 + let mut _5: !; // in scope 0 at $DIR/inline_diverging.rs:+3:12: +5:6 + let _6: !; // in scope 0 at $DIR/inline_diverging.rs:+4:9: +4:16 ++ scope 1 (inlined panic) { // at $DIR/inline_diverging.rs:16:9: 16:16 + let mut _7: !; // in scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL + } bb0: { - StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:+1:8: +1:13 - StorageLive(_3); // scope 0 at $DIR/inline-diverging.rs:+1:8: +1:9 - _3 = _1; // scope 0 at $DIR/inline-diverging.rs:+1:8: +1:9 - _2 = Gt(move _3, const 0_i32); // scope 0 at $DIR/inline-diverging.rs:+1:8: +1:13 - StorageDead(_3); // scope 0 at $DIR/inline-diverging.rs:+1:12: +1:13 - switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/inline-diverging.rs:+1:8: +1:13 + StorageLive(_2); // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13 + StorageLive(_3); // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:9 + _3 = _1; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:9 + _2 = Gt(move _3, const 0_i32); // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13 + StorageDead(_3); // scope 0 at $DIR/inline_diverging.rs:+1:12: +1:13 + switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13 } bb1: { - StorageLive(_4); // scope 0 at $DIR/inline-diverging.rs:+2:9: +2:10 - _4 = _1; // scope 0 at $DIR/inline-diverging.rs:+2:9: +2:10 - _0 = move _4 as u32 (IntToInt); // scope 0 at $DIR/inline-diverging.rs:+2:9: +2:17 - StorageDead(_4); // scope 0 at $DIR/inline-diverging.rs:+2:16: +2:17 - StorageDead(_2); // scope 0 at $DIR/inline-diverging.rs:+5:5: +5:6 - return; // scope 0 at $DIR/inline-diverging.rs:+6:2: +6:2 + StorageLive(_4); // scope 0 at $DIR/inline_diverging.rs:+2:9: +2:10 + _4 = _1; // scope 0 at $DIR/inline_diverging.rs:+2:9: +2:10 + _0 = move _4 as u32 (IntToInt); // scope 0 at $DIR/inline_diverging.rs:+2:9: +2:17 + StorageDead(_4); // scope 0 at $DIR/inline_diverging.rs:+2:16: +2:17 + StorageDead(_2); // scope 0 at $DIR/inline_diverging.rs:+5:5: +5:6 + return; // scope 0 at $DIR/inline_diverging.rs:+6:2: +6:2 } bb2: { - StorageLive(_6); // scope 0 at $DIR/inline-diverging.rs:+4:9: +4:16 -- _6 = panic(); // scope 0 at $DIR/inline-diverging.rs:+4:9: +4:16 + StorageLive(_6); // scope 0 at $DIR/inline_diverging.rs:+4:9: +4:16 +- _6 = panic(); // scope 0 at $DIR/inline_diverging.rs:+4:9: +4:16 + StorageLive(_7); // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL + _7 = begin_panic::<&str>(const "explicit panic"); // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL // mir::Constant -- // + span: $DIR/inline-diverging.rs:16:9: 16:14 +- // + span: $DIR/inline_diverging.rs:16:9: 16:14 - // + literal: Const { ty: fn() -> ! {panic}, val: Value(<ZST>) } + // + span: $SRC_DIR/std/src/panic.rs:LL:COL + // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(<ZST>) } diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff index 6569ab24c38..152153a813c 100644 --- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff @@ -2,55 +2,55 @@ + // MIR for `h` after Inline fn h() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:+0:12: +0:12 - let _1: (!, !); // in scope 0 at $DIR/inline-diverging.rs:+1:5: +1:22 -+ let mut _2: fn() -> ! {sleep}; // in scope 0 at $DIR/inline-diverging.rs:+1:5: +1:22 -+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22 -+ debug f => _2; // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37 -+ let _3: !; // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10 -+ let mut _4: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14 -+ let mut _5: (); // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:16 -+ let mut _7: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14 -+ let mut _8: (); // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:16 -+ let mut _9: !; // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7 -+ let mut _10: !; // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10 + let mut _0: (); // return place in scope 0 at $DIR/inline_diverging.rs:+0:12: +0:12 + let _1: (!, !); // in scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 ++ let mut _2: fn() -> ! {sleep}; // in scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 ++ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline_diverging.rs:22:5: 22:22 ++ debug f => _2; // in scope 1 at $DIR/inline_diverging.rs:26:36: 26:37 ++ let _3: !; // in scope 1 at $DIR/inline_diverging.rs:27:9: 27:10 ++ let mut _4: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 ++ let mut _5: (); // in scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 ++ let mut _7: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline_diverging.rs:28:13: 28:14 ++ let mut _8: (); // in scope 1 at $DIR/inline_diverging.rs:28:13: 28:16 ++ let mut _9: !; // in scope 1 at $DIR/inline_diverging.rs:29:6: 29:7 ++ let mut _10: !; // in scope 1 at $DIR/inline_diverging.rs:29:9: 29:10 + scope 2 { -+ debug a => _3; // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10 -+ let _6: !; // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10 ++ debug a => _3; // in scope 2 at $DIR/inline_diverging.rs:27:9: 27:10 ++ let _6: !; // in scope 2 at $DIR/inline_diverging.rs:28:9: 28:10 + scope 3 { -+ debug b => _6; // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10 ++ debug b => _6; // in scope 3 at $DIR/inline_diverging.rs:28:9: 28:10 + } -+ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:28:13: 28:16 ++ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:28:13: 28:16 + scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL + } + } + } -+ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:27:13: 27:16 ++ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:27:13: 27:16 + scope 5 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL + } + } + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-diverging.rs:+1:5: +1:22 -- _1 = call_twice::<!, fn() -> ! {sleep}>(sleep); // scope 0 at $DIR/inline-diverging.rs:+1:5: +1:22 -+ StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:+1:5: +1:22 -+ _2 = sleep; // scope 0 at $DIR/inline-diverging.rs:+1:5: +1:22 + StorageLive(_1); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 +- _1 = call_twice::<!, fn() -> ! {sleep}>(sleep); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 ++ StorageLive(_2); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 ++ _2 = sleep; // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 // mir::Constant -- // + span: $DIR/inline-diverging.rs:22:5: 22:15 +- // + span: $DIR/inline_diverging.rs:22:5: 22:15 - // + literal: Const { ty: fn(fn() -> ! {sleep}) -> (!, !) {call_twice::<!, fn() -> ! {sleep}>}, val: Value(<ZST>) } - // mir::Constant - // + span: $DIR/inline-diverging.rs:22:16: 22:21 + // + span: $DIR/inline_diverging.rs:22:16: 22:21 // + literal: Const { ty: fn() -> ! {sleep}, val: Value(<ZST>) } -+ StorageLive(_3); // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10 -+ StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14 -+ _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14 -+ StorageLive(_5); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16 -+ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12 ++ StorageLive(_3); // scope 1 at $DIR/inline_diverging.rs:27:9: 27:10 ++ StorageLive(_4); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 ++ _4 = &_2; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 ++ StorageLive(_5); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 ++ goto -> bb1; // scope 5 at $DIR/inline_diverging.rs:39:5: 39:12 + } + + bb1: { -+ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12 ++ goto -> bb1; // scope 5 at $DIR/inline_diverging.rs:39:5: 39:12 } } diff --git a/src/test/mir-opt/inline/inline-diverging.rs b/src/test/mir-opt/inline/inline_diverging.rs index ae6f814c290..ae6f814c290 100644 --- a/src/test/mir-opt/inline/inline-diverging.rs +++ b/src/test/mir-opt/inline/inline_diverging.rs diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index 3fd8aad7238..26202f2f40d 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -2,59 +2,59 @@ + // MIR for `main` after Inline fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-generator.rs:+0:11: +0:11 - let _1: std::ops::GeneratorState<i32, bool>; // in scope 0 at $DIR/inline-generator.rs:+1:9: +1:11 - let mut _2: std::pin::Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>; // in scope 0 at $DIR/inline-generator.rs:+1:14: +1:32 - let mut _3: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline-generator.rs:+1:23: +1:31 - let mut _4: [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline-generator.rs:+1:28: +1:31 -+ let mut _7: bool; // in scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 + let mut _0: (); // return place in scope 0 at $DIR/inline_generator.rs:+0:11: +0:11 + let _1: std::ops::GeneratorState<i32, bool>; // in scope 0 at $DIR/inline_generator.rs:+1:9: +1:11 + let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>; // in scope 0 at $DIR/inline_generator.rs:+1:14: +1:32 + let mut _3: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:23: +1:31 + let mut _4: [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:28: +1:31 ++ let mut _7: bool; // in scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 scope 1 { - debug _r => _1; // in scope 1 at $DIR/inline-generator.rs:+1:9: +1:11 + debug _r => _1; // in scope 1 at $DIR/inline_generator.rs:+1:9: +1:11 } -+ scope 2 (inlined g) { // at $DIR/inline-generator.rs:9:28: 9:31 ++ scope 2 (inlined g) { // at $DIR/inline_generator.rs:9:28: 9:31 + } -+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new) { // at $DIR/inline-generator.rs:9:14: 9:32 ++ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new) { // at $DIR/inline_generator.rs:9:14: 9:32 + debug pointer => _3; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL -+ let mut _5: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL ++ let mut _5: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL + scope 4 { -+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new_unchecked) { // at $SRC_DIR/core/src/pin.rs:LL:COL ++ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new_unchecked) { // at $SRC_DIR/core/src/pin.rs:LL:COL + debug pointer => _5; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL -+ let mut _6: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ let mut _6: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + } + } + } -+ scope 6 (inlined g::{closure#0}) { // at $DIR/inline-generator.rs:9:14: 9:46 -+ debug a => _11; // in scope 6 at $DIR/inline-generator.rs:15:6: 15:7 -+ let mut _8: i32; // in scope 6 at $DIR/inline-generator.rs:15:17: 15:39 -+ let mut _9: bool; // in scope 6 at $DIR/inline-generator.rs:15:20: 15:21 -+ let mut _10: bool; // in scope 6 at $DIR/inline-generator.rs:15:9: 15:9 -+ let _11: bool; // in scope 6 at $DIR/inline-generator.rs:15:6: 15:7 -+ let mut _12: u32; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ let mut _13: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ let mut _14: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ let mut _15: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ scope 6 (inlined g::{closure#0}) { // at $DIR/inline_generator.rs:9:14: 9:46 ++ debug a => _11; // in scope 6 at $DIR/inline_generator.rs:15:6: 15:7 ++ let mut _8: i32; // in scope 6 at $DIR/inline_generator.rs:15:17: 15:39 ++ let mut _9: bool; // in scope 6 at $DIR/inline_generator.rs:15:20: 15:21 ++ let mut _10: bool; // in scope 6 at $DIR/inline_generator.rs:15:9: 15:9 ++ let _11: bool; // in scope 6 at $DIR/inline_generator.rs:15:6: 15:7 ++ let mut _12: u32; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ let mut _13: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ let mut _14: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ let mut _15: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-generator.rs:+1:9: +1:11 - StorageLive(_2); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:32 - StorageLive(_3); // scope 0 at $DIR/inline-generator.rs:+1:23: +1:31 - StorageLive(_4); // scope 0 at $DIR/inline-generator.rs:+1:28: +1:31 -- _4 = g() -> bb1; // scope 0 at $DIR/inline-generator.rs:+1:28: +1:31 + StorageLive(_1); // scope 0 at $DIR/inline_generator.rs:+1:9: +1:11 + StorageLive(_2); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:32 + StorageLive(_3); // scope 0 at $DIR/inline_generator.rs:+1:23: +1:31 + StorageLive(_4); // scope 0 at $DIR/inline_generator.rs:+1:28: +1:31 +- _4 = g() -> bb1; // scope 0 at $DIR/inline_generator.rs:+1:28: +1:31 - // mir::Constant -- // + span: $DIR/inline-generator.rs:9:28: 9:29 +- // + span: $DIR/inline_generator.rs:9:28: 9:29 - // + literal: Const { ty: fn() -> impl Generator<bool> {g}, val: Value(<ZST>) } - } - - bb1: { -+ Deinit(_4); // scope 2 at $DIR/inline-generator.rs:15:5: 15:41 -+ discriminant(_4) = 0; // scope 2 at $DIR/inline-generator.rs:15:5: 15:41 - _3 = &mut _4; // scope 0 at $DIR/inline-generator.rs:+1:23: +1:31 -- _2 = Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:32 ++ Deinit(_4); // scope 2 at $DIR/inline_generator.rs:15:5: 15:41 ++ discriminant(_4) = 0; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41 + _3 = &mut _4; // scope 0 at $DIR/inline_generator.rs:+1:23: +1:31 +- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:32 - // mir::Constant -- // + span: $DIR/inline-generator.rs:9:14: 9:22 +- // + span: $DIR/inline_generator.rs:9:14: 9:22 - // + user_ty: UserType(0) -- // + literal: Const { ty: fn(&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]) -> Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]> {Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new}, val: Value(<ZST>) } +- // + literal: Const { ty: fn(&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]) -> Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> {Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new}, val: Value(<ZST>) } - } - - bb2: { @@ -63,86 +63,86 @@ + StorageLive(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + _6 = move _5; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + Deinit(_2); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL -+ (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]) = move _6; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]) = move _6; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageDead(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageDead(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL - StorageDead(_3); // scope 0 at $DIR/inline-generator.rs:+1:31: +1:32 -- _1 = <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 + StorageDead(_3); // scope 0 at $DIR/inline_generator.rs:+1:31: +1:32 +- _1 = <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 - // mir::Constant -- // + span: $DIR/inline-generator.rs:9:33: 9:39 -- // + literal: Const { ty: for<'a> fn(Pin<&'a mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator<bool>>::Yield, <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator<bool>>::Return> {<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator<bool>>::resume}, val: Value(<ZST>) } -+ StorageLive(_7); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 -+ _7 = const false; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 -+ StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 -+ StorageLive(_11); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 -+ _13 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ _12 = discriminant((*_13)); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 +- // + span: $DIR/inline_generator.rs:9:33: 9:39 +- // + literal: Const { ty: for<'a> fn(Pin<&'a mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Yield, <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Return> {<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::resume}, val: Value(<ZST>) } ++ StorageLive(_7); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ _7 = const false; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ StorageLive(_10); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ StorageLive(_11); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ _13 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ _12 = discriminant((*_13)); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 } - bb3: { + bb1: { -+ StorageDead(_11); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 -+ StorageDead(_10); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 -+ StorageDead(_7); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 - StorageDead(_2); // scope 0 at $DIR/inline-generator.rs:+1:45: +1:46 - StorageDead(_4); // scope 0 at $DIR/inline-generator.rs:+1:46: +1:47 - _0 = const (); // scope 0 at $DIR/inline-generator.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/inline-generator.rs:+2:1: +2:2 - return; // scope 0 at $DIR/inline-generator.rs:+2:2: +2:2 ++ StorageDead(_11); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ StorageDead(_10); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ StorageDead(_7); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 + StorageDead(_2); // scope 0 at $DIR/inline_generator.rs:+1:45: +1:46 + StorageDead(_4); // scope 0 at $DIR/inline_generator.rs:+1:46: +1:47 + _0 = const (); // scope 0 at $DIR/inline_generator.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_generator.rs:+2:1: +2:2 + return; // scope 0 at $DIR/inline_generator.rs:+2:2: +2:2 } - bb4 (cleanup): { + bb2 (cleanup): { - resume; // scope 0 at $DIR/inline-generator.rs:+0:1: +2:2 + resume; // scope 0 at $DIR/inline_generator.rs:+0:1: +2:2 + } + + bb3: { -+ _11 = move _7; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ StorageLive(_8); // scope 6 at $DIR/inline-generator.rs:15:17: 15:39 -+ StorageLive(_9); // scope 6 at $DIR/inline-generator.rs:15:20: 15:21 -+ _9 = _11; // scope 6 at $DIR/inline-generator.rs:15:20: 15:21 -+ switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline-generator.rs:15:20: 15:21 ++ _11 = move _7; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:17: 15:39 ++ StorageLive(_9); // scope 6 at $DIR/inline_generator.rs:15:20: 15:21 ++ _9 = _11; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21 ++ switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21 + } + + bb4: { -+ _8 = const 7_i32; // scope 6 at $DIR/inline-generator.rs:15:24: 15:25 -+ goto -> bb6; // scope 6 at $DIR/inline-generator.rs:15:17: 15:39 ++ _8 = const 7_i32; // scope 6 at $DIR/inline_generator.rs:15:24: 15:25 ++ goto -> bb6; // scope 6 at $DIR/inline_generator.rs:15:17: 15:39 + } + + bb5: { -+ _8 = const 13_i32; // scope 6 at $DIR/inline-generator.rs:15:35: 15:37 -+ goto -> bb6; // scope 6 at $DIR/inline-generator.rs:15:17: 15:39 ++ _8 = const 13_i32; // scope 6 at $DIR/inline_generator.rs:15:35: 15:37 ++ goto -> bb6; // scope 6 at $DIR/inline_generator.rs:15:17: 15:39 + } + + bb6: { -+ StorageDead(_9); // scope 6 at $DIR/inline-generator.rs:15:38: 15:39 -+ Deinit(_1); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 -+ ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 -+ discriminant(_1) = 0; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 -+ _14 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 -+ discriminant((*_14)) = 3; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 -+ goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:11: 15:39 ++ StorageDead(_9); // scope 6 at $DIR/inline_generator.rs:15:38: 15:39 ++ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ discriminant(_1) = 0; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ _14 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ discriminant((*_14)) = 3; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:11: 15:39 + } + + bb7: { -+ StorageLive(_8); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ _10 = move _7; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ StorageDead(_8); // scope 6 at $DIR/inline-generator.rs:15:38: 15:39 -+ Deinit(_1); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ discriminant(_1) = 1; // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ _15 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ discriminant((*_15)) = 1; // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:41: 15:41 ++ StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ _10 = move _7; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ StorageDead(_8); // scope 6 at $DIR/inline_generator.rs:15:38: 15:39 ++ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ discriminant(_1) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ _15 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ discriminant((*_15)) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:41: 15:41 + } + + bb8: { -+ assert(const false, "generator resumed after completion") -> [success: bb8, unwind: bb2]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ assert(const false, "generator resumed after completion") -> [success: bb8, unwind: bb2]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 + } + + bb9: { -+ unreachable; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ unreachable; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 } } diff --git a/src/test/mir-opt/inline/inline-generator.rs b/src/test/mir-opt/inline/inline_generator.rs index d11b3e548f7..d11b3e548f7 100644 --- a/src/test/mir-opt/inline/inline-generator.rs +++ b/src/test/mir-opt/inline/inline_generator.rs diff --git a/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff b/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff index 076509df349..e421428dcdf 100644 --- a/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff +++ b/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff @@ -2,43 +2,43 @@ + // MIR for `default` after Inline fn default() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-instruction-set.rs:+0:18: +0:18 - let _1: (); // in scope 0 at $DIR/inline-instruction-set.rs:+1:5: +1:26 - let _2: (); // in scope 0 at $DIR/inline-instruction-set.rs:+2:5: +2:26 - let _3: (); // in scope 0 at $DIR/inline-instruction-set.rs:+3:5: +3:30 -+ scope 1 (inlined instruction_set_default) { // at $DIR/inline-instruction-set.rs:53:5: 53:30 + let mut _0: (); // return place in scope 0 at $DIR/inline_instruction_set.rs:+0:18: +0:18 + let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 + let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 ++ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:53:5: 53:30 + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-instruction-set.rs:+1:5: +1:26 - _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline-instruction-set.rs:+1:5: +1:26 + StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 // mir::Constant - // + span: $DIR/inline-instruction-set.rs:51:5: 51:24 + // + span: $DIR/inline_instruction_set.rs:51:5: 51:24 // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) } } bb1: { - StorageDead(_1); // scope 0 at $DIR/inline-instruction-set.rs:+1:26: +1:27 - StorageLive(_2); // scope 0 at $DIR/inline-instruction-set.rs:+2:5: +2:26 - _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline-instruction-set.rs:+2:5: +2:26 + StorageDead(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27 + StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 + _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 // mir::Constant - // + span: $DIR/inline-instruction-set.rs:52:5: 52:24 + // + span: $DIR/inline_instruction_set.rs:52:5: 52:24 // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) } } bb2: { - StorageDead(_2); // scope 0 at $DIR/inline-instruction-set.rs:+2:26: +2:27 - StorageLive(_3); // scope 0 at $DIR/inline-instruction-set.rs:+3:5: +3:30 -- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline-instruction-set.rs:+3:5: +3:30 + StorageDead(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27 + StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 +- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 - // mir::Constant -- // + span: $DIR/inline-instruction-set.rs:53:5: 53:28 +- // + span: $DIR/inline_instruction_set.rs:53:5: 53:28 - // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) } - } - - bb3: { - StorageDead(_3); // scope 0 at $DIR/inline-instruction-set.rs:+3:30: +3:31 - _0 = const (); // scope 0 at $DIR/inline-instruction-set.rs:+0:18: +4:2 - return; // scope 0 at $DIR/inline-instruction-set.rs:+4:2: +4:2 + StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31 + _0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +4:2 + return; // scope 0 at $DIR/inline_instruction_set.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/inline/inline-instruction-set.rs b/src/test/mir-opt/inline/inline_instruction_set.rs index be36ff50c7e..be36ff50c7e 100644 --- a/src/test/mir-opt/inline/inline-instruction-set.rs +++ b/src/test/mir-opt/inline/inline_instruction_set.rs diff --git a/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff b/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff index b275d08e05f..1ea2b87e53a 100644 --- a/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff +++ b/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff @@ -2,45 +2,45 @@ + // MIR for `t32` after Inline fn t32() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-instruction-set.rs:+0:14: +0:14 - let _1: (); // in scope 0 at $DIR/inline-instruction-set.rs:+1:5: +1:26 - let _2: (); // in scope 0 at $DIR/inline-instruction-set.rs:+2:5: +2:26 - let _3: (); // in scope 0 at $DIR/inline-instruction-set.rs:+5:5: +5:30 -+ scope 1 (inlined instruction_set_t32) { // at $DIR/inline-instruction-set.rs:43:5: 43:26 + let mut _0: (); // return place in scope 0 at $DIR/inline_instruction_set.rs:+0:14: +0:14 + let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 + let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30 ++ scope 1 (inlined instruction_set_t32) { // at $DIR/inline_instruction_set.rs:43:5: 43:26 + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-instruction-set.rs:+1:5: +1:26 - _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline-instruction-set.rs:+1:5: +1:26 + StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 // mir::Constant - // + span: $DIR/inline-instruction-set.rs:42:5: 42:24 + // + span: $DIR/inline_instruction_set.rs:42:5: 42:24 // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) } } bb1: { - StorageDead(_1); // scope 0 at $DIR/inline-instruction-set.rs:+1:26: +1:27 - StorageLive(_2); // scope 0 at $DIR/inline-instruction-set.rs:+2:5: +2:26 -- _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline-instruction-set.rs:+2:5: +2:26 + StorageDead(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27 + StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 +- _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 - // mir::Constant -- // + span: $DIR/inline-instruction-set.rs:43:5: 43:24 +- // + span: $DIR/inline_instruction_set.rs:43:5: 43:24 - // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) } - } - - bb2: { - StorageDead(_2); // scope 0 at $DIR/inline-instruction-set.rs:+2:26: +2:27 - StorageLive(_3); // scope 0 at $DIR/inline-instruction-set.rs:+5:5: +5:30 -- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline-instruction-set.rs:+5:5: +5:30 -+ _3 = instruction_set_default() -> bb2; // scope 0 at $DIR/inline-instruction-set.rs:+5:5: +5:30 + StorageDead(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27 + StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30 +- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30 ++ _3 = instruction_set_default() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30 // mir::Constant - // + span: $DIR/inline-instruction-set.rs:46:5: 46:28 + // + span: $DIR/inline_instruction_set.rs:46:5: 46:28 // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) } } - bb3: { + bb2: { - StorageDead(_3); // scope 0 at $DIR/inline-instruction-set.rs:+5:30: +5:31 - _0 = const (); // scope 0 at $DIR/inline-instruction-set.rs:+0:14: +6:2 - return; // scope 0 at $DIR/inline-instruction-set.rs:+6:2: +6:2 + StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+5:30: +5:31 + _0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:14: +6:2 + return; // scope 0 at $DIR/inline_instruction_set.rs:+6:2: +6:2 } } diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff index 7e017373b44..2a4dc9e3e80 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff @@ -2,45 +2,45 @@ + // MIR for `main` after Inline fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-into-box-place.rs:+0:11: +0:11 - let _1: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:9: +1:11 - let mut _2: usize; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _3: usize; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _4: *mut u8; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _5: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 - let mut _7: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 -+ let mut _8: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 + let mut _0: (); // return place in scope 0 at $DIR/inline_into_box_place.rs:+0:11: +0:11 + let _1: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:9: +1:11 + let mut _2: usize; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + let mut _3: usize; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + let mut _4: *mut u8; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + let mut _5: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + let mut _6: (); // in scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 + let mut _7: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 ++ let mut _8: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 scope 1 { - debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:+1:9: +1:11 + debug _x => _1; // in scope 1 at $DIR/inline_into_box_place.rs:+1:9: +1:11 } scope 2 { } -+ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline_into_box_place.rs:8:33: 8:43 + let mut _9: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:+1:9: +1:11 - _2 = SizeOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - _3 = AlignOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:+1:29: +1:43 + StorageLive(_1); // scope 0 at $DIR/inline_into_box_place.rs:+1:9: +1:11 + _2 = SizeOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + _3 = AlignOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline_into_box_place.rs:+1:29: +1:43 // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:29: 8:43 + // + span: $DIR/inline_into_box_place.rs:8:29: 8:43 // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(<ZST>) } } bb1: { - StorageLive(_5); // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - _5 = ShallowInitBox(move _4, std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - _7 = (((_5.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -- (*_7) = Vec::<u32>::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ StorageLive(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ _8 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 + StorageLive(_5); // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + _5 = ShallowInitBox(move _4, std::vec::Vec<u32>); // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + _7 = (((_5.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 +- (*_7) = Vec::<u32>::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ StorageLive(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ _8 = &mut (*_7); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 + StorageLive(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + _9 = const _; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL // mir::Constant -- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 +- // + span: $DIR/inline_into_box_place.rs:8:33: 8:41 - // + user_ty: UserType(1) - // + literal: Const { ty: fn() -> Vec<u32> {Vec::<u32>::new}, val: Value(<ZST>) } - } @@ -53,29 +53,29 @@ + ((*_8).0: alloc::raw_vec::RawVec<u32>) = move _9; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ((*_8).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + StorageDead(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ StorageDead(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 - _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 - _0 = const (); // scope 0 at $DIR/inline-into-box-place.rs:+0:11: +2:2 -- drop(_1) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:+2:1: +2:2 -+ drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:+2:1: +2:2 ++ StorageDead(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 + _1 = move _5; // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + StorageDead(_5); // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 + _0 = const (); // scope 0 at $DIR/inline_into_box_place.rs:+0:11: +2:2 +- drop(_1) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2 ++ drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2 } - bb3: { + bb2: { - StorageDead(_1); // scope 0 at $DIR/inline-into-box-place.rs:+2:1: +2:2 - return; // scope 0 at $DIR/inline-into-box-place.rs:+2:2: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2 + return; // scope 0 at $DIR/inline_into_box_place.rs:+2:2: +2:2 } - bb4 (cleanup): { + bb3 (cleanup): { - resume; // scope 0 at $DIR/inline-into-box-place.rs:+0:1: +2:2 + resume; // scope 0 at $DIR/inline_into_box_place.rs:+0:1: +2:2 - } - - bb5 (cleanup): { -- _6 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 +- _6 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 - // mir::Constant -- // + span: $DIR/inline-into-box-place.rs:8:42: 8:43 +- // + span: $DIR/inline_into_box_place.rs:8:42: 8:43 - // + literal: Const { ty: unsafe fn(Unique<Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>}, val: Value(<ZST>) } } } diff --git a/src/test/mir-opt/inline/inline-into-box-place.rs b/src/test/mir-opt/inline/inline_into_box_place.rs index 232bcc7b27d..232bcc7b27d 100644 --- a/src/test/mir-opt/inline/inline-into-box-place.rs +++ b/src/test/mir-opt/inline/inline_into_box_place.rs diff --git a/src/test/mir-opt/inline/inline_options.main.Inline.after.mir b/src/test/mir-opt/inline/inline_options.main.Inline.after.mir index 361b0271526..1c590be945c 100644 --- a/src/test/mir-opt/inline/inline_options.main.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_options.main.Inline.after.mir @@ -1,55 +1,55 @@ // MIR for `main` after Inline fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-options.rs:+0:11: +0:11 - let _1: (); // in scope 0 at $DIR/inline-options.rs:+1:5: +1:18 - let _2: (); // in scope 0 at $DIR/inline-options.rs:+2:5: +2:21 - scope 1 (inlined inlined::<u32>) { // at $DIR/inline-options.rs:10:5: 10:21 - let _3: (); // in scope 1 at $DIR/inline-options.rs:16:23: 16:26 - let _4: (); // in scope 1 at $DIR/inline-options.rs:16:28: 16:31 - let _5: (); // in scope 1 at $DIR/inline-options.rs:16:33: 16:36 + let mut _0: (); // return place in scope 0 at $DIR/inline_options.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/inline_options.rs:+1:5: +1:18 + let _2: (); // in scope 0 at $DIR/inline_options.rs:+2:5: +2:21 + scope 1 (inlined inlined::<u32>) { // at $DIR/inline_options.rs:10:5: 10:21 + let _3: (); // in scope 1 at $DIR/inline_options.rs:16:23: 16:26 + let _4: (); // in scope 1 at $DIR/inline_options.rs:16:28: 16:31 + let _5: (); // in scope 1 at $DIR/inline_options.rs:16:33: 16:36 } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-options.rs:+1:5: +1:18 - _1 = not_inlined() -> bb1; // scope 0 at $DIR/inline-options.rs:+1:5: +1:18 + StorageLive(_1); // scope 0 at $DIR/inline_options.rs:+1:5: +1:18 + _1 = not_inlined() -> bb1; // scope 0 at $DIR/inline_options.rs:+1:5: +1:18 // mir::Constant - // + span: $DIR/inline-options.rs:9:5: 9:16 + // + span: $DIR/inline_options.rs:9:5: 9:16 // + literal: Const { ty: fn() {not_inlined}, val: Value(<ZST>) } } bb1: { - StorageDead(_1); // scope 0 at $DIR/inline-options.rs:+1:18: +1:19 - StorageLive(_2); // scope 0 at $DIR/inline-options.rs:+2:5: +2:21 - StorageLive(_3); // scope 1 at $DIR/inline-options.rs:16:23: 16:26 - _3 = g() -> bb2; // scope 1 at $DIR/inline-options.rs:16:23: 16:26 + StorageDead(_1); // scope 0 at $DIR/inline_options.rs:+1:18: +1:19 + StorageLive(_2); // scope 0 at $DIR/inline_options.rs:+2:5: +2:21 + StorageLive(_3); // scope 1 at $DIR/inline_options.rs:16:23: 16:26 + _3 = g() -> bb2; // scope 1 at $DIR/inline_options.rs:16:23: 16:26 // mir::Constant - // + span: $DIR/inline-options.rs:16:23: 16:24 + // + span: $DIR/inline_options.rs:16:23: 16:24 // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } } bb2: { - StorageDead(_3); // scope 1 at $DIR/inline-options.rs:16:26: 16:27 - StorageLive(_4); // scope 1 at $DIR/inline-options.rs:16:28: 16:31 - _4 = g() -> bb3; // scope 1 at $DIR/inline-options.rs:16:28: 16:31 + StorageDead(_3); // scope 1 at $DIR/inline_options.rs:16:26: 16:27 + StorageLive(_4); // scope 1 at $DIR/inline_options.rs:16:28: 16:31 + _4 = g() -> bb3; // scope 1 at $DIR/inline_options.rs:16:28: 16:31 // mir::Constant - // + span: $DIR/inline-options.rs:16:28: 16:29 + // + span: $DIR/inline_options.rs:16:28: 16:29 // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } } bb3: { - StorageDead(_4); // scope 1 at $DIR/inline-options.rs:16:31: 16:32 - StorageLive(_5); // scope 1 at $DIR/inline-options.rs:16:33: 16:36 - _5 = g() -> bb4; // scope 1 at $DIR/inline-options.rs:16:33: 16:36 + StorageDead(_4); // scope 1 at $DIR/inline_options.rs:16:31: 16:32 + StorageLive(_5); // scope 1 at $DIR/inline_options.rs:16:33: 16:36 + _5 = g() -> bb4; // scope 1 at $DIR/inline_options.rs:16:33: 16:36 // mir::Constant - // + span: $DIR/inline-options.rs:16:33: 16:34 + // + span: $DIR/inline_options.rs:16:33: 16:34 // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } } bb4: { - StorageDead(_5); // scope 1 at $DIR/inline-options.rs:16:36: 16:37 - StorageDead(_2); // scope 0 at $DIR/inline-options.rs:+2:21: +2:22 - _0 = const (); // scope 0 at $DIR/inline-options.rs:+0:11: +3:2 - return; // scope 0 at $DIR/inline-options.rs:+3:2: +3:2 + StorageDead(_5); // scope 1 at $DIR/inline_options.rs:16:36: 16:37 + StorageDead(_2); // scope 0 at $DIR/inline_options.rs:+2:21: +2:22 + _0 = const (); // scope 0 at $DIR/inline_options.rs:+0:11: +3:2 + return; // scope 0 at $DIR/inline_options.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/inline/inline-options.rs b/src/test/mir-opt/inline/inline_options.rs index 477f050b69e..477f050b69e 100644 --- a/src/test/mir-opt/inline/inline-options.rs +++ b/src/test/mir-opt/inline/inline_options.rs diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir index 169e7f5c5d9..75af20d482d 100644 --- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -1,72 +1,72 @@ // MIR for `bar` after Inline fn bar() -> bool { - let mut _0: bool; // return place in scope 0 at $DIR/inline-retag.rs:+0:13: +0:17 - let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+1:9: +1:10 - let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+2:5: +2:6 - let mut _3: &i32; // in scope 0 at $DIR/inline-retag.rs:+2:7: +2:9 - let _4: &i32; // in scope 0 at $DIR/inline-retag.rs:+2:7: +2:9 - let _5: i32; // in scope 0 at $DIR/inline-retag.rs:+2:8: +2:9 - let mut _6: &i32; // in scope 0 at $DIR/inline-retag.rs:+2:11: +2:14 - let _7: &i32; // in scope 0 at $DIR/inline-retag.rs:+2:11: +2:14 - let _8: i32; // in scope 0 at $DIR/inline-retag.rs:+2:12: +2:14 + let mut _0: bool; // return place in scope 0 at $DIR/inline_retag.rs:+0:13: +0:17 + let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline_retag.rs:+1:9: +1:10 + let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline_retag.rs:+2:5: +2:6 + let mut _3: &i32; // in scope 0 at $DIR/inline_retag.rs:+2:7: +2:9 + let _4: &i32; // in scope 0 at $DIR/inline_retag.rs:+2:7: +2:9 + let _5: i32; // in scope 0 at $DIR/inline_retag.rs:+2:8: +2:9 + let mut _6: &i32; // in scope 0 at $DIR/inline_retag.rs:+2:11: +2:14 + let _7: &i32; // in scope 0 at $DIR/inline_retag.rs:+2:11: +2:14 + let _8: i32; // in scope 0 at $DIR/inline_retag.rs:+2:12: +2:14 scope 1 { - debug f => _1; // in scope 1 at $DIR/inline-retag.rs:+1:9: +1:10 - let mut _9: &i32; // in scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 - let mut _10: &i32; // in scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 - scope 2 (inlined foo) { // at $DIR/inline-retag.rs:12:5: 12:15 - debug x => _3; // in scope 2 at $DIR/inline-retag.rs:16:8: 16:9 - debug y => _6; // in scope 2 at $DIR/inline-retag.rs:16:17: 16:18 - let mut _11: i32; // in scope 2 at $DIR/inline-retag.rs:17:5: 17:7 - let mut _12: i32; // in scope 2 at $DIR/inline-retag.rs:17:11: 17:13 + debug f => _1; // in scope 1 at $DIR/inline_retag.rs:+1:9: +1:10 + let mut _9: &i32; // in scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + let mut _10: &i32; // in scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + scope 2 (inlined foo) { // at $DIR/inline_retag.rs:12:5: 12:15 + debug x => _3; // in scope 2 at $DIR/inline_retag.rs:16:8: 16:9 + debug y => _6; // in scope 2 at $DIR/inline_retag.rs:16:17: 16:18 + let mut _11: i32; // in scope 2 at $DIR/inline_retag.rs:17:5: 17:7 + let mut _12: i32; // in scope 2 at $DIR/inline_retag.rs:17:11: 17:13 } } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-retag.rs:+1:9: +1:10 - _1 = foo; // scope 0 at $DIR/inline-retag.rs:+1:13: +1:16 + StorageLive(_1); // scope 0 at $DIR/inline_retag.rs:+1:9: +1:10 + _1 = foo; // scope 0 at $DIR/inline_retag.rs:+1:13: +1:16 // mir::Constant - // + span: $DIR/inline-retag.rs:11:13: 11:16 + // + span: $DIR/inline_retag.rs:11:13: 11:16 // + literal: Const { ty: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}, val: Value(<ZST>) } - StorageLive(_2); // scope 1 at $DIR/inline-retag.rs:+2:5: +2:6 - _2 = _1; // scope 1 at $DIR/inline-retag.rs:+2:5: +2:6 - StorageLive(_3); // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 - StorageLive(_4); // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 - _10 = const _; // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 + StorageLive(_2); // scope 1 at $DIR/inline_retag.rs:+2:5: +2:6 + _2 = _1; // scope 1 at $DIR/inline_retag.rs:+2:5: +2:6 + StorageLive(_3); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + StorageLive(_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + _10 = const _; // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 // mir::Constant - // + span: $DIR/inline-retag.rs:12:7: 12:9 + // + span: $DIR/inline_retag.rs:12:7: 12:9 // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) } - Retag(_10); // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 - _4 = &(*_10); // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 - Retag(_4); // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 - _3 = &(*_4); // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 - Retag(_3); // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 - StorageLive(_6); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 - StorageLive(_7); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 - _9 = const _; // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 + Retag(_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + _4 = &(*_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + Retag(_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + _3 = &(*_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + Retag(_3); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + StorageLive(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + StorageLive(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + _9 = const _; // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 // mir::Constant - // + span: $DIR/inline-retag.rs:12:11: 12:14 + // + span: $DIR/inline_retag.rs:12:11: 12:14 // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) } - Retag(_9); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 - _7 = &(*_9); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 - Retag(_7); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 - _6 = &(*_7); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 - Retag(_6); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 - Retag(_3); // scope 2 at $DIR/inline-retag.rs:16:8: 16:9 - Retag(_6); // scope 2 at $DIR/inline-retag.rs:16:17: 16:18 - StorageLive(_11); // scope 2 at $DIR/inline-retag.rs:17:5: 17:7 - _11 = (*_3); // scope 2 at $DIR/inline-retag.rs:17:5: 17:7 - StorageLive(_12); // scope 2 at $DIR/inline-retag.rs:17:11: 17:13 - _12 = (*_6); // scope 2 at $DIR/inline-retag.rs:17:11: 17:13 - _0 = Eq(move _11, move _12); // scope 2 at $DIR/inline-retag.rs:17:5: 17:13 - StorageDead(_12); // scope 2 at $DIR/inline-retag.rs:17:12: 17:13 - StorageDead(_11); // scope 2 at $DIR/inline-retag.rs:17:12: 17:13 - StorageDead(_6); // scope 1 at $DIR/inline-retag.rs:+2:14: +2:15 - StorageDead(_3); // scope 1 at $DIR/inline-retag.rs:+2:14: +2:15 - StorageDead(_2); // scope 1 at $DIR/inline-retag.rs:+2:14: +2:15 - StorageDead(_1); // scope 0 at $DIR/inline-retag.rs:+3:1: +3:2 - StorageDead(_7); // scope 0 at $DIR/inline-retag.rs:+3:1: +3:2 - StorageDead(_4); // scope 0 at $DIR/inline-retag.rs:+3:1: +3:2 - return; // scope 0 at $DIR/inline-retag.rs:+3:2: +3:2 + Retag(_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + _7 = &(*_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + Retag(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + _6 = &(*_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + Retag(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + Retag(_3); // scope 2 at $DIR/inline_retag.rs:16:8: 16:9 + Retag(_6); // scope 2 at $DIR/inline_retag.rs:16:17: 16:18 + StorageLive(_11); // scope 2 at $DIR/inline_retag.rs:17:5: 17:7 + _11 = (*_3); // scope 2 at $DIR/inline_retag.rs:17:5: 17:7 + StorageLive(_12); // scope 2 at $DIR/inline_retag.rs:17:11: 17:13 + _12 = (*_6); // scope 2 at $DIR/inline_retag.rs:17:11: 17:13 + _0 = Eq(move _11, move _12); // scope 2 at $DIR/inline_retag.rs:17:5: 17:13 + StorageDead(_12); // scope 2 at $DIR/inline_retag.rs:17:12: 17:13 + StorageDead(_11); // scope 2 at $DIR/inline_retag.rs:17:12: 17:13 + StorageDead(_6); // scope 1 at $DIR/inline_retag.rs:+2:14: +2:15 + StorageDead(_3); // scope 1 at $DIR/inline_retag.rs:+2:14: +2:15 + StorageDead(_2); // scope 1 at $DIR/inline_retag.rs:+2:14: +2:15 + StorageDead(_1); // scope 0 at $DIR/inline_retag.rs:+3:1: +3:2 + StorageDead(_7); // scope 0 at $DIR/inline_retag.rs:+3:1: +3:2 + StorageDead(_4); // scope 0 at $DIR/inline_retag.rs:+3:1: +3:2 + return; // scope 0 at $DIR/inline_retag.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/inline/inline-retag.rs b/src/test/mir-opt/inline/inline_retag.rs index c6950f26925..c6950f26925 100644 --- a/src/test/mir-opt/inline/inline-retag.rs +++ b/src/test/mir-opt/inline/inline_retag.rs diff --git a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff index d691e90b7da..969573ba325 100644 --- a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff +++ b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff @@ -2,25 +2,25 @@ + // MIR for `clone` after Inline fn clone(_1: fn(A, B)) -> fn(A, B) { - debug f => _1; // in scope 0 at $DIR/inline-shims.rs:+0:20: +0:21 - let mut _0: fn(A, B); // return place in scope 0 at $DIR/inline-shims.rs:+0:36: +0:44 - let mut _2: &fn(A, B); // in scope 0 at $DIR/inline-shims.rs:+1:5: +1:14 -+ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) { // at $DIR/inline-shims.rs:6:5: 6:14 + debug f => _1; // in scope 0 at $DIR/inline_shims.rs:+0:20: +0:21 + let mut _0: fn(A, B); // return place in scope 0 at $DIR/inline_shims.rs:+0:36: +0:44 + let mut _2: &fn(A, B); // in scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 ++ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) { // at $DIR/inline_shims.rs:6:5: 6:14 + } bb0: { - StorageLive(_2); // scope 0 at $DIR/inline-shims.rs:+1:5: +1:14 - _2 = &_1; // scope 0 at $DIR/inline-shims.rs:+1:5: +1:14 -- _0 = <fn(A, B) as Clone>::clone(move _2) -> bb1; // scope 0 at $DIR/inline-shims.rs:+1:5: +1:14 + StorageLive(_2); // scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 + _2 = &_1; // scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 +- _0 = <fn(A, B) as Clone>::clone(move _2) -> bb1; // scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 - // mir::Constant -- // + span: $DIR/inline-shims.rs:6:7: 6:12 +- // + span: $DIR/inline_shims.rs:6:7: 6:12 - // + literal: Const { ty: for<'a> fn(&'a fn(A, B)) -> fn(A, B) {<fn(A, B) as Clone>::clone}, val: Value(<ZST>) } - } - - bb1: { + _0 = (*_2); // scope 1 at $SRC_DIR/core/src/clone.rs:LL:COL - StorageDead(_2); // scope 0 at $DIR/inline-shims.rs:+1:13: +1:14 - return; // scope 0 at $DIR/inline-shims.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/inline_shims.rs:+1:13: +1:14 + return; // scope 0 at $DIR/inline_shims.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline_shims.drop.Inline.diff b/src/test/mir-opt/inline/inline_shims.drop.Inline.diff index f7b1cde80bd..7a54beca233 100644 --- a/src/test/mir-opt/inline/inline_shims.drop.Inline.diff +++ b/src/test/mir-opt/inline/inline_shims.drop.Inline.diff @@ -2,51 +2,51 @@ + // MIR for `drop` after Inline fn drop(_1: *mut Vec<A>, _2: *mut Option<B>) -> () { - debug a => _1; // in scope 0 at $DIR/inline-shims.rs:+0:19: +0:20 - debug b => _2; // in scope 0 at $DIR/inline-shims.rs:+0:35: +0:36 - let mut _0: (); // return place in scope 0 at $DIR/inline-shims.rs:+0:54: +0:54 - let _3: (); // in scope 0 at $DIR/inline-shims.rs:+1:14: +1:40 - let mut _4: *mut std::vec::Vec<A>; // in scope 0 at $DIR/inline-shims.rs:+1:38: +1:39 - let mut _5: *mut std::option::Option<B>; // in scope 0 at $DIR/inline-shims.rs:+2:38: +2:39 + debug a => _1; // in scope 0 at $DIR/inline_shims.rs:+0:19: +0:20 + debug b => _2; // in scope 0 at $DIR/inline_shims.rs:+0:35: +0:36 + let mut _0: (); // return place in scope 0 at $DIR/inline_shims.rs:+0:54: +0:54 + let _3: (); // in scope 0 at $DIR/inline_shims.rs:+1:14: +1:40 + let mut _4: *mut std::vec::Vec<A>; // in scope 0 at $DIR/inline_shims.rs:+1:38: +1:39 + let mut _5: *mut std::option::Option<B>; // in scope 0 at $DIR/inline_shims.rs:+2:38: +2:39 scope 1 { } scope 2 { -+ scope 3 (inlined std::ptr::drop_in_place::<Option<B>> - shim(Some(Option<B>))) { // at $DIR/inline-shims.rs:12:14: 12:40 ++ scope 3 (inlined std::ptr::drop_in_place::<Option<B>> - shim(Some(Option<B>))) { // at $DIR/inline_shims.rs:12:14: 12:40 + let mut _6: isize; // in scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + let mut _7: isize; // in scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + } } bb0: { - StorageLive(_3); // scope 0 at $DIR/inline-shims.rs:+1:5: +1:42 - StorageLive(_4); // scope 1 at $DIR/inline-shims.rs:+1:38: +1:39 - _4 = _1; // scope 1 at $DIR/inline-shims.rs:+1:38: +1:39 - _3 = std::ptr::drop_in_place::<Vec<A>>(move _4) -> bb1; // scope 1 at $DIR/inline-shims.rs:+1:14: +1:40 + StorageLive(_3); // scope 0 at $DIR/inline_shims.rs:+1:5: +1:42 + StorageLive(_4); // scope 1 at $DIR/inline_shims.rs:+1:38: +1:39 + _4 = _1; // scope 1 at $DIR/inline_shims.rs:+1:38: +1:39 + _3 = std::ptr::drop_in_place::<Vec<A>>(move _4) -> bb1; // scope 1 at $DIR/inline_shims.rs:+1:14: +1:40 // mir::Constant - // + span: $DIR/inline-shims.rs:11:14: 11:37 + // + span: $DIR/inline_shims.rs:11:14: 11:37 // + literal: Const { ty: unsafe fn(*mut Vec<A>) {std::ptr::drop_in_place::<Vec<A>>}, val: Value(<ZST>) } } bb1: { - StorageDead(_4); // scope 1 at $DIR/inline-shims.rs:+1:39: +1:40 - StorageDead(_3); // scope 0 at $DIR/inline-shims.rs:+1:41: +1:42 - StorageLive(_5); // scope 2 at $DIR/inline-shims.rs:+2:38: +2:39 - _5 = _2; // scope 2 at $DIR/inline-shims.rs:+2:38: +2:39 -- _0 = std::ptr::drop_in_place::<Option<B>>(move _5) -> bb2; // scope 2 at $DIR/inline-shims.rs:+2:14: +2:40 + StorageDead(_4); // scope 1 at $DIR/inline_shims.rs:+1:39: +1:40 + StorageDead(_3); // scope 0 at $DIR/inline_shims.rs:+1:41: +1:42 + StorageLive(_5); // scope 2 at $DIR/inline_shims.rs:+2:38: +2:39 + _5 = _2; // scope 2 at $DIR/inline_shims.rs:+2:38: +2:39 +- _0 = std::ptr::drop_in_place::<Option<B>>(move _5) -> bb2; // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 - // mir::Constant -- // + span: $DIR/inline-shims.rs:12:14: 12:37 +- // + span: $DIR/inline_shims.rs:12:14: 12:37 - // + literal: Const { ty: unsafe fn(*mut Option<B>) {std::ptr::drop_in_place::<Option<B>>}, val: Value(<ZST>) } -+ StorageLive(_6); // scope 2 at $DIR/inline-shims.rs:+2:14: +2:40 -+ StorageLive(_7); // scope 2 at $DIR/inline-shims.rs:+2:14: +2:40 ++ StorageLive(_6); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 ++ StorageLive(_7); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 + _6 = discriminant((*_5)); // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + switchInt(move _6) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL } bb2: { -+ StorageDead(_7); // scope 2 at $DIR/inline-shims.rs:+2:14: +2:40 -+ StorageDead(_6); // scope 2 at $DIR/inline-shims.rs:+2:14: +2:40 - StorageDead(_5); // scope 2 at $DIR/inline-shims.rs:+2:39: +2:40 - return; // scope 0 at $DIR/inline-shims.rs:+3:2: +3:2 ++ StorageDead(_7); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 ++ StorageDead(_6); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 + StorageDead(_5); // scope 2 at $DIR/inline_shims.rs:+2:39: +2:40 + return; // scope 0 at $DIR/inline_shims.rs:+3:2: +3:2 + } + + bb3: { diff --git a/src/test/mir-opt/inline/inline-shims.rs b/src/test/mir-opt/inline/inline_shims.rs index 7c8618f71e5..7c8618f71e5 100644 --- a/src/test/mir-opt/inline/inline-shims.rs +++ b/src/test/mir-opt/inline/inline_shims.rs diff --git a/src/test/mir-opt/inline/inline_specialization.main.Inline.diff b/src/test/mir-opt/inline/inline_specialization.main.Inline.diff index fdf2a1e1ff9..af08296edea 100644 --- a/src/test/mir-opt/inline/inline_specialization.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_specialization.main.Inline.diff @@ -2,27 +2,27 @@ + // MIR for `main` after Inline fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-specialization.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/inline-specialization.rs:+1:9: +1:10 + let mut _0: (); // return place in scope 0 at $DIR/inline_specialization.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/inline_specialization.rs:+1:9: +1:10 scope 1 { - debug x => _1; // in scope 1 at $DIR/inline-specialization.rs:+1:9: +1:10 + debug x => _1; // in scope 1 at $DIR/inline_specialization.rs:+1:9: +1:10 } -+ scope 2 (inlined <Vec<()> as Foo>::bar) { // at $DIR/inline-specialization.rs:5:13: 5:38 ++ scope 2 (inlined <Vec<()> as Foo>::bar) { // at $DIR/inline_specialization.rs:5:13: 5:38 + } bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-specialization.rs:+1:9: +1:10 -- _1 = <Vec<()> as Foo>::bar() -> bb1; // scope 0 at $DIR/inline-specialization.rs:+1:13: +1:38 + StorageLive(_1); // scope 0 at $DIR/inline_specialization.rs:+1:9: +1:10 +- _1 = <Vec<()> as Foo>::bar() -> bb1; // scope 0 at $DIR/inline_specialization.rs:+1:13: +1:38 - // mir::Constant -- // + span: $DIR/inline-specialization.rs:5:13: 5:36 +- // + span: $DIR/inline_specialization.rs:5:13: 5:36 - // + literal: Const { ty: fn() -> u32 {<Vec<()> as Foo>::bar}, val: Value(<ZST>) } - } - - bb1: { -+ _1 = const 123_u32; // scope 2 at $DIR/inline-specialization.rs:14:31: 14:34 - _0 = const (); // scope 0 at $DIR/inline-specialization.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/inline-specialization.rs:+2:1: +2:2 - return; // scope 0 at $DIR/inline-specialization.rs:+2:2: +2:2 ++ _1 = const 123_u32; // scope 2 at $DIR/inline_specialization.rs:14:31: 14:34 + _0 = const (); // scope 0 at $DIR/inline_specialization.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_specialization.rs:+2:1: +2:2 + return; // scope 0 at $DIR/inline_specialization.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline-specialization.rs b/src/test/mir-opt/inline/inline_specialization.rs index 87275b4e514..87275b4e514 100644 --- a/src/test/mir-opt/inline/inline-specialization.rs +++ b/src/test/mir-opt/inline/inline_specialization.rs diff --git a/src/test/mir-opt/inline/inline-trait-method.rs b/src/test/mir-opt/inline/inline_trait_method.rs index 74be53f5512..74be53f5512 100644 --- a/src/test/mir-opt/inline/inline-trait-method.rs +++ b/src/test/mir-opt/inline/inline_trait_method.rs diff --git a/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir index 89eefc29269..637bf282a65 100644 --- a/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir @@ -1,21 +1,21 @@ // MIR for `test` after Inline fn test(_1: &dyn X) -> u32 { - debug x => _1; // in scope 0 at $DIR/inline-trait-method.rs:+0:9: +0:10 - let mut _0: u32; // return place in scope 0 at $DIR/inline-trait-method.rs:+0:23: +0:26 - let mut _2: &dyn X; // in scope 0 at $DIR/inline-trait-method.rs:+1:5: +1:10 + debug x => _1; // in scope 0 at $DIR/inline_trait_method.rs:+0:9: +0:10 + let mut _0: u32; // return place in scope 0 at $DIR/inline_trait_method.rs:+0:23: +0:26 + let mut _2: &dyn X; // in scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 bb0: { - StorageLive(_2); // scope 0 at $DIR/inline-trait-method.rs:+1:5: +1:10 - _2 = &(*_1); // scope 0 at $DIR/inline-trait-method.rs:+1:5: +1:10 - _0 = <dyn X as X>::y(move _2) -> bb1; // scope 0 at $DIR/inline-trait-method.rs:+1:5: +1:10 + StorageLive(_2); // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 + _2 = &(*_1); // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 + _0 = <dyn X as X>::y(move _2) -> bb1; // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 // mir::Constant - // + span: $DIR/inline-trait-method.rs:9:7: 9:8 + // + span: $DIR/inline_trait_method.rs:9:7: 9:8 // + literal: Const { ty: for<'a> fn(&'a dyn X) -> u32 {<dyn X as X>::y}, val: Value(<ZST>) } } bb1: { - StorageDead(_2); // scope 0 at $DIR/inline-trait-method.rs:+1:9: +1:10 - return; // scope 0 at $DIR/inline-trait-method.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/inline_trait_method.rs:+1:9: +1:10 + return; // scope 0 at $DIR/inline_trait_method.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/inline-trait-method_2.rs b/src/test/mir-opt/inline/inline_trait_method_2.rs index 378e71a2567..378e71a2567 100644 --- a/src/test/mir-opt/inline/inline-trait-method_2.rs +++ b/src/test/mir-opt/inline/inline_trait_method_2.rs diff --git a/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir index 3d05869fa51..dab8bb9a0c6 100644 --- a/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir @@ -1,32 +1,32 @@ // MIR for `test2` after Inline fn test2(_1: &dyn X) -> bool { - debug x => _1; // in scope 0 at $DIR/inline-trait-method_2.rs:+0:10: +0:11 - let mut _0: bool; // return place in scope 0 at $DIR/inline-trait-method_2.rs:+0:24: +0:28 - let mut _2: &dyn X; // in scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11 - let mut _3: &dyn X; // in scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11 - scope 1 (inlined test) { // at $DIR/inline-trait-method_2.rs:5:5: 5:12 - debug x => _2; // in scope 1 at $DIR/inline-trait-method_2.rs:9:9: 9:10 - let mut _4: &dyn X; // in scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10 + debug x => _1; // in scope 0 at $DIR/inline_trait_method_2.rs:+0:10: +0:11 + let mut _0: bool; // return place in scope 0 at $DIR/inline_trait_method_2.rs:+0:24: +0:28 + let mut _2: &dyn X; // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + let mut _3: &dyn X; // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + scope 1 (inlined test) { // at $DIR/inline_trait_method_2.rs:5:5: 5:12 + debug x => _2; // in scope 1 at $DIR/inline_trait_method_2.rs:9:9: 9:10 + let mut _4: &dyn X; // in scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10 } bb0: { - StorageLive(_2); // scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11 - StorageLive(_3); // scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11 - _3 = &(*_1); // scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11 - _2 = move _3 as &dyn X (Pointer(Unsize)); // scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11 - StorageDead(_3); // scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11 - StorageLive(_4); // scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10 - _4 = _2; // scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10 - _0 = <dyn X as X>::y(move _4) -> bb1; // scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10 + StorageLive(_2); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + StorageLive(_3); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + _3 = &(*_1); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + _2 = move _3 as &dyn X (Pointer(Unsize)); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + StorageDead(_3); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + StorageLive(_4); // scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10 + _4 = _2; // scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10 + _0 = <dyn X as X>::y(move _4) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10 // mir::Constant - // + span: $DIR/inline-trait-method_2.rs:10:7: 10:8 + // + span: $DIR/inline_trait_method_2.rs:10:7: 10:8 // + literal: Const { ty: for<'a> fn(&'a dyn X) -> bool {<dyn X as X>::y}, val: Value(<ZST>) } } bb1: { - StorageDead(_4); // scope 1 at $DIR/inline-trait-method_2.rs:10:9: 10:10 - StorageDead(_2); // scope 0 at $DIR/inline-trait-method_2.rs:+1:11: +1:12 - return; // scope 0 at $DIR/inline-trait-method_2.rs:+2:2: +2:2 + StorageDead(_4); // scope 1 at $DIR/inline_trait_method_2.rs:10:9: 10:10 + StorageDead(_2); // scope 0 at $DIR/inline_trait_method_2.rs:+1:11: +1:12 + return; // scope 0 at $DIR/inline_trait_method_2.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir index 5168ae031f0..777681e1ce7 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir @@ -1,30 +1,30 @@ // MIR for `a` after Inline fn a(_1: &mut [T]) -> &mut [T] { - debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+0:13: +0:14 - let mut _0: &mut [T]; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+0:29: +0:37 - let mut _2: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - let mut _3: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - let mut _4: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 + debug x => _1; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:13: +0:14 + let mut _0: &mut [T]; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:29: +0:37 + let mut _2: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _3: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _4: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:3:5: 3:15 debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL let mut _5: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - _4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 + StorageLive(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _4 = &mut (*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 StorageLive(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL _5 = &mut (*_4); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL _3 = &mut (*_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL StorageDead(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - _2 = &mut (*_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageDead(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:14: +1:15 - _0 = &mut (*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:1: +2:2 - StorageDead(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:1: +2:2 - return; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:2: +2:2 + _2 = &mut (*_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 + _0 = &mut (*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + StorageDead(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 06d442ae88b..83545c99100 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -1,12 +1,12 @@ // MIR for `b` after Inline fn b(_1: &mut Box<T>) -> &mut T { - debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+0:13: +0:14 - let mut _0: &mut T; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+0:32: +0:38 - let mut _2: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - let mut _3: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + debug x => _1; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:13: +0:14 + let mut _0: &mut T; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:32: +0:38 + let mut _2: &mut T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _3: &mut T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:5: 8:15 debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL @@ -15,10 +15,10 @@ fn b(_1: &mut Box<T>) -> &mut T { } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - _4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 + StorageLive(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _4 = &mut (*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageLive(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _7 = deref_copy (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL @@ -28,11 +28,11 @@ fn b(_1: &mut Box<T>) -> &mut T { _3 = &mut (*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageDead(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageDead(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _2 = &mut (*_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageDead(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:14: +1:15 - _0 = &mut (*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:1: +2:2 - StorageDead(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:1: +2:2 - return; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:2: +2:2 + _2 = &mut (*_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 + _0 = &mut (*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + StorageDead(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir index c7f20ff98ff..ed4e9927ce9 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir @@ -1,22 +1,22 @@ // MIR for `c` after Inline fn c(_1: &[T]) -> &[T] { - debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+0:13: +0:14 - let mut _0: &[T]; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+0:25: +0:29 - let _2: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - let mut _3: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - scope 1 (inlined <[T] as AsRef<[T]>>::as_ref) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 + debug x => _1; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:13: +0:14 + let mut _0: &[T]; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:25: +0:29 + let _2: &[T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _3: &[T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + scope 1 (inlined <[T] as AsRef<[T]>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:13:5: 13:15 debug self => _3; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - _3 = &(*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 + StorageLive(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _3 = &(*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 _2 = _3; // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - _0 = &(*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:14: +1:15 - StorageDead(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:1: +2:2 - return; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:2: +2:2 + _0 = &(*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 + StorageDead(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index d5f06c54a57..18a2670be21 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -1,26 +1,26 @@ // MIR for `d` after Inline fn d(_1: &Box<T>) -> &T { - debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+0:13: +0:14 - let mut _0: &T; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+0:28: +0:30 - let _2: &T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - let mut _3: &std::boxed::Box<T>; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 + debug x => _1; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:13: +0:14 + let mut _0: &T; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:28: +0:30 + let _2: &T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _3: &std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:18:5: 18:15 debug self => _3; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _4: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _5: *const T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - _3 = &(*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 + StorageLive(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _3 = &(*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 _4 = deref_copy (*_3); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _5 = (((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _2 = &(*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _0 = &(*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:5: +1:15 - StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+1:14: +1:15 - StorageDead(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:1: +2:2 - return; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:+2:2: +2:2 + _0 = &(*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 + StorageDead(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs index 94f926d3964..94f926d3964 100644 --- a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs diff --git a/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir index fca53a72f88..d99ae1a6c7c 100644 --- a/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir @@ -1,42 +1,42 @@ // MIR for `main` after Inline fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+0:11: +0:11 - let _1: [closure@$DIR/issue-76997-inline-scopes-parenting.rs:5:13: 5:16]; // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+1:9: +1:10 - let mut _2: &[closure@$DIR/issue-76997-inline-scopes-parenting.rs:5:13: 5:16]; // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:6 - let mut _3: ((),); // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:10 - let mut _4: (); // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:7: +2:9 - let mut _5: (); // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:10 + let mut _0: (); // return place in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+0:11: +0:11 + let _1: [closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10 + let mut _2: &[closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6 + let mut _3: ((),); // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + let mut _4: (); // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9 + let mut _5: (); // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 scope 1 { - debug f => _1; // in scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+1:9: +1:10 - scope 2 (inlined main::{closure#0}) { // at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10 - debug x => _5; // in scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:+1:14: +1:15 - let _6: (); // in scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:+1:23: +1:24 + debug f => _1; // in scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10 + scope 2 (inlined main::{closure#0}) { // at $DIR/issue_76997_inline_scopes_parenting.rs:6:5: 6:10 + debug x => _5; // in scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:14: +1:15 + let _6: (); // in scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24 scope 3 { - debug y => _6; // in scope 3 at $DIR/issue-76997-inline-scopes-parenting.rs:+1:23: +1:24 + debug y => _6; // in scope 3 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24 } } } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+1:9: +1:10 - Deinit(_1); // scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+1:13: +1:33 - StorageLive(_2); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:6 - _2 = &_1; // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:6 - StorageLive(_3); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:10 - StorageLive(_4); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:7: +2:9 - Deinit(_4); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:7: +2:9 - Deinit(_3); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:10 - (_3.0: ()) = move _4; // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:10 - StorageLive(_5); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:10 - _5 = move (_3.0: ()); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:10 - StorageLive(_6); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:+1:23: +1:24 - StorageDead(_6); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:+1:32: +1:33 - StorageDead(_5); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:5: +2:10 - StorageDead(_4); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:9: +2:10 - StorageDead(_3); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:9: +2:10 - StorageDead(_2); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:+2:9: +2:10 - StorageDead(_1); // scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+3:1: +3:2 - return; // scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:+3:2: +3:2 + StorageLive(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10 + Deinit(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33 + StorageLive(_2); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6 + _2 = &_1; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6 + StorageLive(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + StorageLive(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9 + Deinit(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9 + Deinit(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + (_3.0: ()) = move _4; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + StorageLive(_5); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + _5 = move (_3.0: ()); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + StorageLive(_6); // scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24 + StorageDead(_6); // scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:32: +1:33 + StorageDead(_5); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + StorageDead(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:9: +2:10 + StorageDead(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:9: +2:10 + StorageDead(_2); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:9: +2:10 + StorageDead(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+3:1: +3:2 + return; // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/inline/issue-76997-inline-scopes-parenting.rs b/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.rs index 76d806acc63..76d806acc63 100644 --- a/src/test/mir-opt/inline/issue-76997-inline-scopes-parenting.rs +++ b/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.rs diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff index 4186650dfab..51a98465fd9 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff @@ -2,67 +2,67 @@ + // MIR for `bar` after Inline fn bar(_1: P) -> () { - debug _baz => _1; // in scope 0 at $DIR/issue-78442.rs:+2:5: +2:9 - let mut _0: (); // return place in scope 0 at $DIR/issue-78442.rs:+3:3: +3:3 - let _2: (); // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 - let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 - let _4: fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 - let mut _5: (); // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 -+ scope 1 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) { // at $DIR/issue-78442.rs:11:5: 11:17 + debug _baz => _1; // in scope 0 at $DIR/issue_78442.rs:+2:5: +2:9 + let mut _0: (); // return place in scope 0 at $DIR/issue_78442.rs:+3:3: +3:3 + let _2: (); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + let _4: fn() {foo}; // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + let mut _5: (); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 ++ scope 1 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) { // at $DIR/issue_78442.rs:11:5: 11:17 + } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 - StorageLive(_3); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 - StorageLive(_4); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 -- _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 -+ _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 + StorageLive(_2); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + StorageLive(_3); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + StorageLive(_4); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 +- _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 ++ _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 // mir::Constant - // + span: $DIR/issue-78442.rs:11:5: 11:13 + // + span: $DIR/issue_78442.rs:11:5: 11:13 // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(<ZST>) } } bb1: { - _3 = &_4; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 - StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 - Deinit(_5); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 -- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 + _3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 +- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 - // mir::Constant -- // + span: $DIR/issue-78442.rs:11:5: 11:15 +- // + span: $DIR/issue_78442.rs:11:5: 11:15 - // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {foo}, ()) -> <fn() {foo} as FnOnce<()>>::Output {<fn() {foo} as Fn<()>>::call}, val: Value(<ZST>) } + _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb2: { -- StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 -- StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 -- StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 -- StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 -- _0 = const (); // scope 0 at $DIR/issue-78442.rs:+3:3: +5:2 -- drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 -+ return; // scope 0 at $DIR/issue-78442.rs:+5:2: +5:2 +- StorageDead(_5); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 +- StorageDead(_3); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 +- StorageDead(_4); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 +- StorageDead(_2); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 +- _0 = const (); // scope 0 at $DIR/issue_78442.rs:+3:3: +5:2 +- drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 ++ return; // scope 0 at $DIR/issue_78442.rs:+5:2: +5:2 } - bb3: { -- return; // scope 0 at $DIR/issue-78442.rs:+5:2: +5:2 +- return; // scope 0 at $DIR/issue_78442.rs:+5:2: +5:2 + bb3 (cleanup): { -+ drop(_1) -> bb4; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 ++ drop(_1) -> bb4; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 } bb4 (cleanup): { -- drop(_1) -> bb5; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 -+ resume; // scope 0 at $DIR/issue-78442.rs:+0:1: +5:2 +- drop(_1) -> bb5; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 ++ resume; // scope 0 at $DIR/issue_78442.rs:+0:1: +5:2 } - bb5 (cleanup): { -- resume; // scope 0 at $DIR/issue-78442.rs:+0:1: +5:2 +- resume; // scope 0 at $DIR/issue_78442.rs:+0:1: +5:2 + bb5: { -+ StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 -+ StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 -+ StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 -+ StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 -+ _0 = const (); // scope 0 at $DIR/issue-78442.rs:+3:3: +5:2 -+ drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 ++ StorageDead(_5); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 ++ StorageDead(_3); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 ++ StorageDead(_4); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 ++ StorageDead(_2); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 ++ _0 = const (); // scope 0 at $DIR/issue_78442.rs:+3:3: +5:2 ++ drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 } } diff --git a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff index 24e9a3df15a..e47466c5e80 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -2,56 +2,56 @@ + // MIR for `bar` after RevealAll fn bar(_1: P) -> () { - debug _baz => _1; // in scope 0 at $DIR/issue-78442.rs:+2:5: +2:9 - let mut _0: (); // return place in scope 0 at $DIR/issue-78442.rs:+3:3: +3:3 - let _2: (); // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 -- let mut _3: &impl Fn(); // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 -- let _4: impl Fn(); // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 -+ let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 -+ let _4: fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 - let mut _5: (); // in scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 + debug _baz => _1; // in scope 0 at $DIR/issue_78442.rs:+2:5: +2:9 + let mut _0: (); // return place in scope 0 at $DIR/issue_78442.rs:+3:3: +3:3 + let _2: (); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 +- let mut _3: &impl Fn(); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 +- let _4: impl Fn(); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 ++ let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 ++ let _4: fn() {foo}; // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + let mut _5: (); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 - StorageLive(_3); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 - StorageLive(_4); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 - _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 + StorageLive(_2); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + StorageLive(_3); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + StorageLive(_4); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 // mir::Constant - // + span: $DIR/issue-78442.rs:11:5: 11:13 + // + span: $DIR/issue_78442.rs:11:5: 11:13 // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(<ZST>) } } bb1: { - _3 = &_4; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:15 - StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 - Deinit(_5); // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 -- _2 = <impl Fn() as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 -+ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 + _3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 +- _2 = <impl Fn() as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 ++ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 // mir::Constant - // + span: $DIR/issue-78442.rs:11:5: 11:15 + // + span: $DIR/issue_78442.rs:11:5: 11:15 - // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(), ()) -> <impl Fn() as FnOnce<()>>::Output {<impl Fn() as Fn<()>>::call}, val: Value(<ZST>) } + // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {foo}, ()) -> <fn() {foo} as FnOnce<()>>::Output {<fn() {foo} as Fn<()>>::call}, val: Value(<ZST>) } } bb2: { - StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 - StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:+4:16: +4:17 - StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 - StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:+4:17: +4:18 - _0 = const (); // scope 0 at $DIR/issue-78442.rs:+3:3: +5:2 - drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 + StorageDead(_5); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 + StorageDead(_3); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 + StorageDead(_4); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 + StorageDead(_2); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 + _0 = const (); // scope 0 at $DIR/issue_78442.rs:+3:3: +5:2 + drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 } bb3: { - return; // scope 0 at $DIR/issue-78442.rs:+5:2: +5:2 + return; // scope 0 at $DIR/issue_78442.rs:+5:2: +5:2 } bb4 (cleanup): { - drop(_1) -> bb5; // scope 0 at $DIR/issue-78442.rs:+5:1: +5:2 + drop(_1) -> bb5; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 } bb5 (cleanup): { - resume; // scope 0 at $DIR/issue-78442.rs:+0:1: +5:2 + resume; // scope 0 at $DIR/issue_78442.rs:+0:1: +5:2 } } diff --git a/src/test/mir-opt/inline/issue-78442.rs b/src/test/mir-opt/inline/issue_78442.rs index aa8ede2df9e..aa8ede2df9e 100644 --- a/src/test/mir-opt/inline/issue-78442.rs +++ b/src/test/mir-opt/inline/issue_78442.rs diff --git a/src/test/mir-opt/inline/polymorphic-recursion.rs b/src/test/mir-opt/inline/polymorphic_recursion.rs index 7388722b776..7388722b776 100644 --- a/src/test/mir-opt/inline/polymorphic-recursion.rs +++ b/src/test/mir-opt/inline/polymorphic_recursion.rs diff --git a/src/test/mir-opt/issue_101973.inner.ConstProp.diff b/src/test/mir-opt/issue_101973.inner.ConstProp.diff index 281afe4be17..c24abedae92 100644 --- a/src/test/mir-opt/issue_101973.inner.ConstProp.diff +++ b/src/test/mir-opt/issue_101973.inner.ConstProp.diff @@ -2,29 +2,29 @@ + // MIR for `inner` after ConstProp fn inner(_1: u32) -> i64 { - debug fields => _1; // in scope 0 at $DIR/issue-101973.rs:+0:14: +0:20 - let mut _0: i64; // return place in scope 0 at $DIR/issue-101973.rs:+0:30: +0:33 - let mut _2: i32; // in scope 0 at $DIR/issue-101973.rs:+1:5: +1:65 - let mut _3: u32; // in scope 0 at $DIR/issue-101973.rs:+1:5: +1:58 - let mut _4: u32; // in scope 0 at $DIR/issue-101973.rs:+1:5: +1:17 - let mut _5: u32; // in scope 0 at $DIR/issue-101973.rs:+1:10: +1:16 - let mut _6: u32; // in scope 0 at $DIR/issue-101973.rs:+1:31: +1:57 - let mut _7: u32; // in scope 0 at $DIR/issue-101973.rs:+1:31: +1:52 - let mut _8: u32; // in scope 0 at $DIR/issue-101973.rs:+1:32: +1:45 - let mut _9: u32; // in scope 0 at $DIR/issue-101973.rs:+1:33: +1:39 - let mut _10: (u32, bool); // in scope 0 at $DIR/issue-101973.rs:+1:32: +1:45 - let mut _11: (u32, bool); // in scope 0 at $DIR/issue-101973.rs:+1:31: +1:57 - scope 1 (inlined imm8) { // at $DIR/issue-101973.rs:14:5: 14:17 - debug x => _5; // in scope 1 at $DIR/issue-101973.rs:5:13: 5:14 - let mut _12: u32; // in scope 1 at $DIR/issue-101973.rs:7:12: 7:27 - let mut _13: u32; // in scope 1 at $DIR/issue-101973.rs:7:12: 7:20 - let mut _14: u32; // in scope 1 at $DIR/issue-101973.rs:7:13: 7:14 - let mut _15: (u32, bool); // in scope 1 at $DIR/issue-101973.rs:7:12: 7:20 + debug fields => _1; // in scope 0 at $DIR/issue_101973.rs:+0:14: +0:20 + let mut _0: i64; // return place in scope 0 at $DIR/issue_101973.rs:+0:30: +0:33 + let mut _2: i32; // in scope 0 at $DIR/issue_101973.rs:+1:5: +1:65 + let mut _3: u32; // in scope 0 at $DIR/issue_101973.rs:+1:5: +1:58 + let mut _4: u32; // in scope 0 at $DIR/issue_101973.rs:+1:5: +1:17 + let mut _5: u32; // in scope 0 at $DIR/issue_101973.rs:+1:10: +1:16 + let mut _6: u32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 + let mut _7: u32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 + let mut _8: u32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 + let mut _9: u32; // in scope 0 at $DIR/issue_101973.rs:+1:33: +1:39 + let mut _10: (u32, bool); // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 + let mut _11: (u32, bool); // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 + scope 1 (inlined imm8) { // at $DIR/issue_101973.rs:14:5: 14:17 + debug x => _5; // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14 + let mut _12: u32; // in scope 1 at $DIR/issue_101973.rs:7:12: 7:27 + let mut _13: u32; // in scope 1 at $DIR/issue_101973.rs:7:12: 7:20 + let mut _14: u32; // in scope 1 at $DIR/issue_101973.rs:7:13: 7:14 + let mut _15: (u32, bool); // in scope 1 at $DIR/issue_101973.rs:7:12: 7:20 scope 2 { - debug out => _4; // in scope 2 at $DIR/issue-101973.rs:6:9: 6:16 + debug out => _4; // in scope 2 at $DIR/issue_101973.rs:6:9: 6:16 } } - scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue-101973.rs:14:5: 14:58 + scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:14:5: 14:58 debug self => _4; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL debug n => _6; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL let mut _16: u32; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL @@ -32,32 +32,32 @@ } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-101973.rs:+1:5: +1:65 - StorageLive(_3); // scope 0 at $DIR/issue-101973.rs:+1:5: +1:58 - StorageLive(_4); // scope 0 at $DIR/issue-101973.rs:+1:5: +1:17 - StorageLive(_5); // scope 0 at $DIR/issue-101973.rs:+1:10: +1:16 - _5 = _1; // scope 0 at $DIR/issue-101973.rs:+1:10: +1:16 - _4 = const 0_u32; // scope 1 at $DIR/issue-101973.rs:6:19: 6:23 - StorageLive(_12); // scope 2 at $DIR/issue-101973.rs:7:12: 7:27 - StorageLive(_13); // scope 2 at $DIR/issue-101973.rs:7:12: 7:20 - StorageLive(_14); // scope 2 at $DIR/issue-101973.rs:7:13: 7:14 - _14 = _5; // scope 2 at $DIR/issue-101973.rs:7:13: 7:14 - _15 = CheckedShr(_14, const 0_i32); // scope 2 at $DIR/issue-101973.rs:7:12: 7:20 - assert(!move (_15.1: bool), "attempt to shift right by `{}`, which would overflow", const 0_i32) -> bb3; // scope 2 at $DIR/issue-101973.rs:7:12: 7:20 + StorageLive(_2); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65 + StorageLive(_3); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:58 + StorageLive(_4); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17 + StorageLive(_5); // scope 0 at $DIR/issue_101973.rs:+1:10: +1:16 + _5 = _1; // scope 0 at $DIR/issue_101973.rs:+1:10: +1:16 + _4 = const 0_u32; // scope 1 at $DIR/issue_101973.rs:6:19: 6:23 + StorageLive(_12); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27 + StorageLive(_13); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20 + StorageLive(_14); // scope 2 at $DIR/issue_101973.rs:7:13: 7:14 + _14 = _5; // scope 2 at $DIR/issue_101973.rs:7:13: 7:14 + _15 = CheckedShr(_14, const 0_i32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20 + assert(!move (_15.1: bool), "attempt to shift right by `{}`, which would overflow", const 0_i32) -> bb3; // scope 2 at $DIR/issue_101973.rs:7:12: 7:20 } bb1: { - _8 = move (_10.0: u32); // scope 0 at $DIR/issue-101973.rs:+1:32: +1:45 - StorageDead(_9); // scope 0 at $DIR/issue-101973.rs:+1:44: +1:45 - _7 = BitAnd(move _8, const 15_u32); // scope 0 at $DIR/issue-101973.rs:+1:31: +1:52 - StorageDead(_8); // scope 0 at $DIR/issue-101973.rs:+1:51: +1:52 - _11 = CheckedShl(_7, const 1_i32); // scope 0 at $DIR/issue-101973.rs:+1:31: +1:57 - assert(!move (_11.1: bool), "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue-101973.rs:+1:31: +1:57 + _8 = move (_10.0: u32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 + StorageDead(_9); // scope 0 at $DIR/issue_101973.rs:+1:44: +1:45 + _7 = BitAnd(move _8, const 15_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 + StorageDead(_8); // scope 0 at $DIR/issue_101973.rs:+1:51: +1:52 + _11 = CheckedShl(_7, const 1_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 + assert(!move (_11.1: bool), "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 } bb2: { - _6 = move (_11.0: u32); // scope 0 at $DIR/issue-101973.rs:+1:31: +1:57 - StorageDead(_7); // scope 0 at $DIR/issue-101973.rs:+1:56: +1:57 + _6 = move (_11.0: u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 + StorageDead(_7); // scope 0 at $DIR/issue_101973.rs:+1:56: +1:57 StorageLive(_16); // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL _16 = _4; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL StorageLive(_17); // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL @@ -69,32 +69,32 @@ } bb3: { - _13 = move (_15.0: u32); // scope 2 at $DIR/issue-101973.rs:7:12: 7:20 - StorageDead(_14); // scope 2 at $DIR/issue-101973.rs:7:19: 7:20 - _12 = BitAnd(move _13, const 255_u32); // scope 2 at $DIR/issue-101973.rs:7:12: 7:27 - StorageDead(_13); // scope 2 at $DIR/issue-101973.rs:7:26: 7:27 - _4 = BitOr(_4, move _12); // scope 2 at $DIR/issue-101973.rs:7:5: 7:27 - StorageDead(_12); // scope 2 at $DIR/issue-101973.rs:7:26: 7:27 - StorageDead(_5); // scope 0 at $DIR/issue-101973.rs:+1:16: +1:17 - StorageLive(_6); // scope 0 at $DIR/issue-101973.rs:+1:31: +1:57 - StorageLive(_7); // scope 0 at $DIR/issue-101973.rs:+1:31: +1:52 - StorageLive(_8); // scope 0 at $DIR/issue-101973.rs:+1:32: +1:45 - StorageLive(_9); // scope 0 at $DIR/issue-101973.rs:+1:33: +1:39 - _9 = _1; // scope 0 at $DIR/issue-101973.rs:+1:33: +1:39 - _10 = CheckedShr(_9, const 8_i32); // scope 0 at $DIR/issue-101973.rs:+1:32: +1:45 - assert(!move (_10.1: bool), "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue-101973.rs:+1:32: +1:45 + _13 = move (_15.0: u32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20 + StorageDead(_14); // scope 2 at $DIR/issue_101973.rs:7:19: 7:20 + _12 = BitAnd(move _13, const 255_u32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27 + StorageDead(_13); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27 + _4 = BitOr(_4, move _12); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27 + StorageDead(_12); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27 + StorageDead(_5); // scope 0 at $DIR/issue_101973.rs:+1:16: +1:17 + StorageLive(_6); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 + StorageLive(_7); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 + StorageLive(_8); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 + StorageLive(_9); // scope 0 at $DIR/issue_101973.rs:+1:33: +1:39 + _9 = _1; // scope 0 at $DIR/issue_101973.rs:+1:33: +1:39 + _10 = CheckedShr(_9, const 8_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 + assert(!move (_10.1: bool), "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 } bb4: { StorageDead(_17); // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL StorageDead(_16); // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - StorageDead(_6); // scope 0 at $DIR/issue-101973.rs:+1:57: +1:58 - StorageDead(_4); // scope 0 at $DIR/issue-101973.rs:+1:57: +1:58 - _2 = move _3 as i32 (IntToInt); // scope 0 at $DIR/issue-101973.rs:+1:5: +1:65 - StorageDead(_3); // scope 0 at $DIR/issue-101973.rs:+1:64: +1:65 - _0 = move _2 as i64 (IntToInt); // scope 0 at $DIR/issue-101973.rs:+1:5: +1:72 - StorageDead(_2); // scope 0 at $DIR/issue-101973.rs:+1:71: +1:72 - return; // scope 0 at $DIR/issue-101973.rs:+2:2: +2:2 + StorageDead(_6); // scope 0 at $DIR/issue_101973.rs:+1:57: +1:58 + StorageDead(_4); // scope 0 at $DIR/issue_101973.rs:+1:57: +1:58 + _2 = move _3 as i32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65 + StorageDead(_3); // scope 0 at $DIR/issue_101973.rs:+1:64: +1:65 + _0 = move _2 as i64 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:72 + StorageDead(_2); // scope 0 at $DIR/issue_101973.rs:+1:71: +1:72 + return; // scope 0 at $DIR/issue_101973.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/issue-101973.rs b/src/test/mir-opt/issue_101973.rs index 216659a235e..216659a235e 100644 --- a/src/test/mir-opt/issue-101973.rs +++ b/src/test/mir-opt/issue_101973.rs diff --git a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir index b13987f7360..82210081832 100644 --- a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir @@ -1,52 +1,52 @@ // MIR for `main` after SimplifyCfg-initial fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-38669.rs:+0:11: +0:11 - let mut _1: bool; // in scope 0 at $DIR/issue-38669.rs:+1:9: +1:25 - let mut _2: (); // in scope 0 at $DIR/issue-38669.rs:+0:1: +8:2 - let _3: (); // in scope 0 at $DIR/issue-38669.rs:+3:9: +5:10 - let mut _4: bool; // in scope 0 at $DIR/issue-38669.rs:+3:12: +3:24 - let mut _5: !; // in scope 0 at $DIR/issue-38669.rs:+3:25: +5:10 + let mut _0: (); // return place in scope 0 at $DIR/issue_38669.rs:+0:11: +0:11 + let mut _1: bool; // in scope 0 at $DIR/issue_38669.rs:+1:9: +1:25 + let mut _2: (); // in scope 0 at $DIR/issue_38669.rs:+0:1: +8:2 + let _3: (); // in scope 0 at $DIR/issue_38669.rs:+3:9: +5:10 + let mut _4: bool; // in scope 0 at $DIR/issue_38669.rs:+3:12: +3:24 + let mut _5: !; // in scope 0 at $DIR/issue_38669.rs:+3:25: +5:10 scope 1 { - debug should_break => _1; // in scope 1 at $DIR/issue-38669.rs:+1:9: +1:25 + debug should_break => _1; // in scope 1 at $DIR/issue_38669.rs:+1:9: +1:25 } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-38669.rs:+1:9: +1:25 - _1 = const false; // scope 0 at $DIR/issue-38669.rs:+1:28: +1:33 - FakeRead(ForLet(None), _1); // scope 0 at $DIR/issue-38669.rs:+1:9: +1:25 - goto -> bb1; // scope 1 at $DIR/issue-38669.rs:+2:5: +7:6 + StorageLive(_1); // scope 0 at $DIR/issue_38669.rs:+1:9: +1:25 + _1 = const false; // scope 0 at $DIR/issue_38669.rs:+1:28: +1:33 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/issue_38669.rs:+1:9: +1:25 + goto -> bb1; // scope 1 at $DIR/issue_38669.rs:+2:5: +7:6 } bb1: { - falseUnwind -> [real: bb2, cleanup: bb5]; // scope 1 at $DIR/issue-38669.rs:+2:5: +7:6 + falseUnwind -> [real: bb2, cleanup: bb5]; // scope 1 at $DIR/issue_38669.rs:+2:5: +7:6 } bb2: { - StorageLive(_3); // scope 1 at $DIR/issue-38669.rs:+3:9: +5:10 - StorageLive(_4); // scope 1 at $DIR/issue-38669.rs:+3:12: +3:24 - _4 = _1; // scope 1 at $DIR/issue-38669.rs:+3:12: +3:24 - switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/issue-38669.rs:+3:12: +3:24 + StorageLive(_3); // scope 1 at $DIR/issue_38669.rs:+3:9: +5:10 + StorageLive(_4); // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24 + _4 = _1; // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24 + switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24 } bb3: { - _0 = const (); // scope 1 at $DIR/issue-38669.rs:+4:13: +4:18 - StorageDead(_4); // scope 1 at $DIR/issue-38669.rs:+5:9: +5:10 - StorageDead(_3); // scope 1 at $DIR/issue-38669.rs:+5:9: +5:10 - StorageDead(_1); // scope 0 at $DIR/issue-38669.rs:+8:1: +8:2 - return; // scope 0 at $DIR/issue-38669.rs:+8:2: +8:2 + _0 = const (); // scope 1 at $DIR/issue_38669.rs:+4:13: +4:18 + StorageDead(_4); // scope 1 at $DIR/issue_38669.rs:+5:9: +5:10 + StorageDead(_3); // scope 1 at $DIR/issue_38669.rs:+5:9: +5:10 + StorageDead(_1); // scope 0 at $DIR/issue_38669.rs:+8:1: +8:2 + return; // scope 0 at $DIR/issue_38669.rs:+8:2: +8:2 } bb4: { - _3 = const (); // scope 1 at $DIR/issue-38669.rs:+5:10: +5:10 - StorageDead(_4); // scope 1 at $DIR/issue-38669.rs:+5:9: +5:10 - StorageDead(_3); // scope 1 at $DIR/issue-38669.rs:+5:9: +5:10 - _1 = const true; // scope 1 at $DIR/issue-38669.rs:+6:9: +6:28 - _2 = const (); // scope 1 at $DIR/issue-38669.rs:+2:10: +7:6 - goto -> bb1; // scope 1 at $DIR/issue-38669.rs:+2:5: +7:6 + _3 = const (); // scope 1 at $DIR/issue_38669.rs:+5:10: +5:10 + StorageDead(_4); // scope 1 at $DIR/issue_38669.rs:+5:9: +5:10 + StorageDead(_3); // scope 1 at $DIR/issue_38669.rs:+5:9: +5:10 + _1 = const true; // scope 1 at $DIR/issue_38669.rs:+6:9: +6:28 + _2 = const (); // scope 1 at $DIR/issue_38669.rs:+2:10: +7:6 + goto -> bb1; // scope 1 at $DIR/issue_38669.rs:+2:5: +7:6 } bb5 (cleanup): { - resume; // scope 0 at $DIR/issue-38669.rs:+0:1: +8:2 + resume; // scope 0 at $DIR/issue_38669.rs:+0:1: +8:2 } } diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue_38669.rs index db3f89472c9..db3f89472c9 100644 --- a/src/test/mir-opt/issue-38669.rs +++ b/src/test/mir-opt/issue_38669.rs diff --git a/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir index 1d7cb91d6a7..c573ad5a8e4 100644 --- a/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir +++ b/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir @@ -1,70 +1,70 @@ // MIR for `main` after ElaborateDrops fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-41110.rs:+0:11: +0:11 - let _1: (); // in scope 0 at $DIR/issue-41110.rs:+1:9: +1:10 - let mut _2: S; // in scope 0 at $DIR/issue-41110.rs:+1:13: +1:14 - let mut _3: S; // in scope 0 at $DIR/issue-41110.rs:+1:21: +1:27 - let mut _4: S; // in scope 0 at $DIR/issue-41110.rs:+1:21: +1:22 - let mut _5: bool; // in scope 0 at $DIR/issue-41110.rs:+1:27: +1:28 + let mut _0: (); // return place in scope 0 at $DIR/issue_41110.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/issue_41110.rs:+1:9: +1:10 + let mut _2: S; // in scope 0 at $DIR/issue_41110.rs:+1:13: +1:14 + let mut _3: S; // in scope 0 at $DIR/issue_41110.rs:+1:21: +1:27 + let mut _4: S; // in scope 0 at $DIR/issue_41110.rs:+1:21: +1:22 + let mut _5: bool; // in scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 scope 1 { - debug x => _1; // in scope 1 at $DIR/issue-41110.rs:+1:9: +1:10 + debug x => _1; // in scope 1 at $DIR/issue_41110.rs:+1:9: +1:10 } bb0: { - _5 = const false; // scope 0 at $DIR/issue-41110.rs:+1:9: +1:10 - StorageLive(_1); // scope 0 at $DIR/issue-41110.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/issue-41110.rs:+1:13: +1:14 - _5 = const true; // scope 0 at $DIR/issue-41110.rs:+1:13: +1:14 - _2 = S; // scope 0 at $DIR/issue-41110.rs:+1:13: +1:14 - StorageLive(_3); // scope 0 at $DIR/issue-41110.rs:+1:21: +1:27 - StorageLive(_4); // scope 0 at $DIR/issue-41110.rs:+1:21: +1:22 - _4 = S; // scope 0 at $DIR/issue-41110.rs:+1:21: +1:22 - _3 = S::id(move _4) -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-41110.rs:+1:21: +1:27 + _5 = const false; // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10 + StorageLive(_1); // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14 + _5 = const true; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14 + _2 = S; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14 + StorageLive(_3); // scope 0 at $DIR/issue_41110.rs:+1:21: +1:27 + StorageLive(_4); // scope 0 at $DIR/issue_41110.rs:+1:21: +1:22 + _4 = S; // scope 0 at $DIR/issue_41110.rs:+1:21: +1:22 + _3 = S::id(move _4) -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue_41110.rs:+1:21: +1:27 // mir::Constant - // + span: $DIR/issue-41110.rs:8:23: 8:25 + // + span: $DIR/issue_41110.rs:8:23: 8:25 // + literal: Const { ty: fn(S) -> S {S::id}, val: Value(<ZST>) } } bb1: { - StorageDead(_4); // scope 0 at $DIR/issue-41110.rs:+1:26: +1:27 - _5 = const false; // scope 0 at $DIR/issue-41110.rs:+1:13: +1:28 - _1 = S::other(move _2, move _3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/issue-41110.rs:+1:13: +1:28 + StorageDead(_4); // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27 + _5 = const false; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:28 + _1 = S::other(move _2, move _3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:28 // mir::Constant - // + span: $DIR/issue-41110.rs:8:15: 8:20 + // + span: $DIR/issue_41110.rs:8:15: 8:20 // + literal: Const { ty: fn(S, S) {S::other}, val: Value(<ZST>) } } bb2: { - StorageDead(_3); // scope 0 at $DIR/issue-41110.rs:+1:27: +1:28 - _5 = const false; // scope 0 at $DIR/issue-41110.rs:+1:27: +1:28 - StorageDead(_2); // scope 0 at $DIR/issue-41110.rs:+1:27: +1:28 - _0 = const (); // scope 0 at $DIR/issue-41110.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/issue-41110.rs:+2:1: +2:2 - return; // scope 0 at $DIR/issue-41110.rs:+2:2: +2:2 + StorageDead(_3); // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 + _5 = const false; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 + StorageDead(_2); // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 + _0 = const (); // scope 0 at $DIR/issue_41110.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/issue_41110.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_41110.rs:+2:2: +2:2 } bb3 (cleanup): { - goto -> bb5; // scope 0 at $DIR/issue-41110.rs:+1:27: +1:28 + goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 } bb4 (cleanup): { - goto -> bb5; // scope 0 at $DIR/issue-41110.rs:+1:26: +1:27 + goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27 } bb5 (cleanup): { - goto -> bb8; // scope 0 at $DIR/issue-41110.rs:+1:27: +1:28 + goto -> bb8; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 } bb6 (cleanup): { - resume; // scope 0 at $DIR/issue-41110.rs:+0:1: +2:2 + resume; // scope 0 at $DIR/issue_41110.rs:+0:1: +2:2 } bb7 (cleanup): { - drop(_2) -> bb6; // scope 0 at $DIR/issue-41110.rs:+1:27: +1:28 + drop(_2) -> bb6; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 } bb8 (cleanup): { - switchInt(_5) -> [false: bb6, otherwise: bb7]; // scope 0 at $DIR/issue-41110.rs:+1:27: +1:28 + switchInt(_5) -> [false: bb6, otherwise: bb7]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 } } diff --git a/src/test/mir-opt/issue-41110.rs b/src/test/mir-opt/issue_41110.rs index 638dc601ec8..638dc601ec8 100644 --- a/src/test/mir-opt/issue-41110.rs +++ b/src/test/mir-opt/issue_41110.rs diff --git a/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir index b0e3496b2c8..470b0323281 100644 --- a/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir +++ b/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir @@ -1,101 +1,101 @@ // MIR for `test` after ElaborateDrops fn test() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-41110.rs:+0:15: +0:15 - let _1: S; // in scope 0 at $DIR/issue-41110.rs:+1:9: +1:10 - let _3: (); // in scope 0 at $DIR/issue-41110.rs:+3:5: +3:12 - let mut _4: S; // in scope 0 at $DIR/issue-41110.rs:+3:10: +3:11 - let mut _5: S; // in scope 0 at $DIR/issue-41110.rs:+4:9: +4:10 - let mut _6: bool; // in scope 0 at $DIR/issue-41110.rs:+5:1: +5:2 + let mut _0: (); // return place in scope 0 at $DIR/issue_41110.rs:+0:15: +0:15 + let _1: S; // in scope 0 at $DIR/issue_41110.rs:+1:9: +1:10 + let _3: (); // in scope 0 at $DIR/issue_41110.rs:+3:5: +3:12 + let mut _4: S; // in scope 0 at $DIR/issue_41110.rs:+3:10: +3:11 + let mut _5: S; // in scope 0 at $DIR/issue_41110.rs:+4:9: +4:10 + let mut _6: bool; // in scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 scope 1 { - debug u => _1; // in scope 1 at $DIR/issue-41110.rs:+1:9: +1:10 - let mut _2: S; // in scope 1 at $DIR/issue-41110.rs:+2:9: +2:14 + debug u => _1; // in scope 1 at $DIR/issue_41110.rs:+1:9: +1:10 + let mut _2: S; // in scope 1 at $DIR/issue_41110.rs:+2:9: +2:14 scope 2 { - debug v => _2; // in scope 2 at $DIR/issue-41110.rs:+2:9: +2:14 + debug v => _2; // in scope 2 at $DIR/issue_41110.rs:+2:9: +2:14 } } bb0: { - _6 = const false; // scope 0 at $DIR/issue-41110.rs:+1:9: +1:10 - StorageLive(_1); // scope 0 at $DIR/issue-41110.rs:+1:9: +1:10 - _6 = const true; // scope 0 at $DIR/issue-41110.rs:+1:13: +1:14 - _1 = S; // scope 0 at $DIR/issue-41110.rs:+1:13: +1:14 - StorageLive(_2); // scope 1 at $DIR/issue-41110.rs:+2:9: +2:14 - _2 = S; // scope 1 at $DIR/issue-41110.rs:+2:17: +2:18 - StorageLive(_3); // scope 2 at $DIR/issue-41110.rs:+3:5: +3:12 - StorageLive(_4); // scope 2 at $DIR/issue-41110.rs:+3:10: +3:11 - _4 = move _2; // scope 2 at $DIR/issue-41110.rs:+3:10: +3:11 - _3 = std::mem::drop::<S>(move _4) -> [return: bb1, unwind: bb7]; // scope 2 at $DIR/issue-41110.rs:+3:5: +3:12 + _6 = const false; // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10 + StorageLive(_1); // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10 + _6 = const true; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14 + _1 = S; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14 + StorageLive(_2); // scope 1 at $DIR/issue_41110.rs:+2:9: +2:14 + _2 = S; // scope 1 at $DIR/issue_41110.rs:+2:17: +2:18 + StorageLive(_3); // scope 2 at $DIR/issue_41110.rs:+3:5: +3:12 + StorageLive(_4); // scope 2 at $DIR/issue_41110.rs:+3:10: +3:11 + _4 = move _2; // scope 2 at $DIR/issue_41110.rs:+3:10: +3:11 + _3 = std::mem::drop::<S>(move _4) -> [return: bb1, unwind: bb7]; // scope 2 at $DIR/issue_41110.rs:+3:5: +3:12 // mir::Constant - // + span: $DIR/issue-41110.rs:17:5: 17:9 + // + span: $DIR/issue_41110.rs:17:5: 17:9 // + literal: Const { ty: fn(S) {std::mem::drop::<S>}, val: Value(<ZST>) } } bb1: { - StorageDead(_4); // scope 2 at $DIR/issue-41110.rs:+3:11: +3:12 - StorageDead(_3); // scope 2 at $DIR/issue-41110.rs:+3:12: +3:13 - StorageLive(_5); // scope 2 at $DIR/issue-41110.rs:+4:9: +4:10 - _6 = const false; // scope 2 at $DIR/issue-41110.rs:+4:9: +4:10 - _5 = move _1; // scope 2 at $DIR/issue-41110.rs:+4:9: +4:10 - goto -> bb12; // scope 2 at $DIR/issue-41110.rs:+4:5: +4:6 + StorageDead(_4); // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12 + StorageDead(_3); // scope 2 at $DIR/issue_41110.rs:+3:12: +3:13 + StorageLive(_5); // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10 + _6 = const false; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10 + _5 = move _1; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10 + goto -> bb12; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6 } bb2: { - goto -> bb3; // scope 2 at $DIR/issue-41110.rs:+4:9: +4:10 + goto -> bb3; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10 } bb3: { - StorageDead(_5); // scope 2 at $DIR/issue-41110.rs:+4:9: +4:10 - _0 = const (); // scope 0 at $DIR/issue-41110.rs:+0:15: +5:2 - drop(_2) -> [return: bb4, unwind: bb9]; // scope 1 at $DIR/issue-41110.rs:+5:1: +5:2 + StorageDead(_5); // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10 + _0 = const (); // scope 0 at $DIR/issue_41110.rs:+0:15: +5:2 + drop(_2) -> [return: bb4, unwind: bb9]; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2 } bb4: { - StorageDead(_2); // scope 1 at $DIR/issue-41110.rs:+5:1: +5:2 - goto -> bb5; // scope 0 at $DIR/issue-41110.rs:+5:1: +5:2 + StorageDead(_2); // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2 + goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 } bb5: { - _6 = const false; // scope 0 at $DIR/issue-41110.rs:+5:1: +5:2 - StorageDead(_1); // scope 0 at $DIR/issue-41110.rs:+5:1: +5:2 - return; // scope 0 at $DIR/issue-41110.rs:+5:2: +5:2 + _6 = const false; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 + StorageDead(_1); // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 + return; // scope 0 at $DIR/issue_41110.rs:+5:2: +5:2 } bb6 (cleanup): { - goto -> bb8; // scope 2 at $DIR/issue-41110.rs:+4:9: +4:10 + goto -> bb8; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10 } bb7 (cleanup): { - goto -> bb8; // scope 2 at $DIR/issue-41110.rs:+3:11: +3:12 + goto -> bb8; // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12 } bb8 (cleanup): { - goto -> bb9; // scope 1 at $DIR/issue-41110.rs:+5:1: +5:2 + goto -> bb9; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2 } bb9 (cleanup): { - goto -> bb14; // scope 0 at $DIR/issue-41110.rs:+5:1: +5:2 + goto -> bb14; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 } bb10 (cleanup): { - resume; // scope 0 at $DIR/issue-41110.rs:+0:1: +5:2 + resume; // scope 0 at $DIR/issue_41110.rs:+0:1: +5:2 } bb11 (cleanup): { - _2 = move _5; // scope 2 at $DIR/issue-41110.rs:+4:5: +4:6 - goto -> bb6; // scope 2 at $DIR/issue-41110.rs:+4:5: +4:6 + _2 = move _5; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6 + goto -> bb6; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6 } bb12: { - _2 = move _5; // scope 2 at $DIR/issue-41110.rs:+4:5: +4:6 - goto -> bb2; // scope 2 at $DIR/issue-41110.rs:+4:5: +4:6 + _2 = move _5; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6 + goto -> bb2; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6 } bb13 (cleanup): { - drop(_1) -> bb10; // scope 0 at $DIR/issue-41110.rs:+5:1: +5:2 + drop(_1) -> bb10; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 } bb14 (cleanup): { - switchInt(_6) -> [false: bb10, otherwise: bb13]; // scope 0 at $DIR/issue-41110.rs:+5:1: +5:2 + switchInt(_6) -> [false: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 } } diff --git a/src/test/mir-opt/issue-41697.rs b/src/test/mir-opt/issue_41697.rs index cbd8633a345..cbd8633a345 100644 --- a/src/test/mir-opt/issue-41697.rs +++ b/src/test/mir-opt/issue_41697.rs diff --git a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir b/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir index 047b24db466..8af087d84f1 100644 --- a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir +++ b/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir @@ -1,20 +1,20 @@ -// MIR for `<impl at $DIR/issue-41697.rs:18:1: 18:23>::{constant#0}` after SimplifyCfg-promote-consts +// MIR for `<impl at $DIR/issue_41697.rs:18:1: 18:23>::{constant#0}` after SimplifyCfg-promote-consts -<impl at $DIR/issue-41697.rs:18:1: 18:23>::{constant#0}: usize = { - let mut _0: usize; // return place in scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - let mut _1: (usize, bool); // in scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 +<impl at $DIR/issue_41697.rs:18:1: 18:23>::{constant#0}: usize = { + let mut _0: usize; // return place in scope 0 at $DIR/issue_41697.rs:+0:19: +0:22 + let mut _1: (usize, bool); // in scope 0 at $DIR/issue_41697.rs:+0:19: +0:22 bb0: { - _1 = CheckedAdd(const 1_usize, const 1_usize); // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_usize, const 1_usize) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 + _1 = CheckedAdd(const 1_usize, const 1_usize); // scope 0 at $DIR/issue_41697.rs:+0:19: +0:22 + assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_usize, const 1_usize) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue_41697.rs:+0:19: +0:22 } bb1: { - _0 = move (_1.0: usize); // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - return; // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 + _0 = move (_1.0: usize); // scope 0 at $DIR/issue_41697.rs:+0:19: +0:22 + return; // scope 0 at $DIR/issue_41697.rs:+0:19: +0:22 } bb2 (cleanup): { - resume; // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 + resume; // scope 0 at $DIR/issue_41697.rs:+0:19: +0:22 } } diff --git a/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir index f95a0a1c013..73372c97bea 100644 --- a/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir +++ b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir @@ -1,152 +1,152 @@ // MIR for `main` after ElaborateDrops fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-41888.rs:+0:11: +0:11 - let _1: E; // in scope 0 at $DIR/issue-41888.rs:+1:9: +1:10 - let mut _2: bool; // in scope 0 at $DIR/issue-41888.rs:+2:8: +2:14 - let mut _3: E; // in scope 0 at $DIR/issue-41888.rs:+3:13: +3:20 - let mut _4: K; // in scope 0 at $DIR/issue-41888.rs:+3:18: +3:19 - let mut _5: isize; // in scope 0 at $DIR/issue-41888.rs:+4:16: +4:24 - let mut _7: bool; // in scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - let mut _8: bool; // in scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - let mut _9: bool; // in scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - let mut _10: isize; // in scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - let mut _11: isize; // in scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + let mut _0: (); // return place in scope 0 at $DIR/issue_41888.rs:+0:11: +0:11 + let _1: E; // in scope 0 at $DIR/issue_41888.rs:+1:9: +1:10 + let mut _2: bool; // in scope 0 at $DIR/issue_41888.rs:+2:8: +2:14 + let mut _3: E; // in scope 0 at $DIR/issue_41888.rs:+3:13: +3:20 + let mut _4: K; // in scope 0 at $DIR/issue_41888.rs:+3:18: +3:19 + let mut _5: isize; // in scope 0 at $DIR/issue_41888.rs:+4:16: +4:24 + let mut _7: bool; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + let mut _8: bool; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + let mut _9: bool; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + let mut _10: isize; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + let mut _11: isize; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 scope 1 { - debug e => _1; // in scope 1 at $DIR/issue-41888.rs:+1:9: +1:10 + debug e => _1; // in scope 1 at $DIR/issue_41888.rs:+1:9: +1:10 scope 2 { - debug _k => _6; // in scope 2 at $DIR/issue-41888.rs:+4:21: +4:23 - let _6: K; // in scope 2 at $DIR/issue-41888.rs:+4:21: +4:23 + debug _k => _6; // in scope 2 at $DIR/issue_41888.rs:+4:21: +4:23 + let _6: K; // in scope 2 at $DIR/issue_41888.rs:+4:21: +4:23 } } bb0: { - _9 = const false; // scope 0 at $DIR/issue-41888.rs:+1:9: +1:10 - _7 = const false; // scope 0 at $DIR/issue-41888.rs:+1:9: +1:10 - _8 = const false; // scope 0 at $DIR/issue-41888.rs:+1:9: +1:10 - StorageLive(_1); // scope 0 at $DIR/issue-41888.rs:+1:9: +1:10 - StorageLive(_2); // scope 1 at $DIR/issue-41888.rs:+2:8: +2:14 - _2 = cond() -> [return: bb1, unwind: bb11]; // scope 1 at $DIR/issue-41888.rs:+2:8: +2:14 + _9 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10 + _7 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10 + _8 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10 + StorageLive(_1); // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10 + StorageLive(_2); // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14 + _2 = cond() -> [return: bb1, unwind: bb11]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14 // mir::Constant - // + span: $DIR/issue-41888.rs:8:8: 8:12 + // + span: $DIR/issue_41888.rs:8:8: 8:12 // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) } } bb1: { - switchInt(move _2) -> [false: bb7, otherwise: bb2]; // scope 1 at $DIR/issue-41888.rs:+2:8: +2:14 + switchInt(move _2) -> [false: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14 } bb2: { - StorageLive(_3); // scope 1 at $DIR/issue-41888.rs:+3:13: +3:20 - StorageLive(_4); // scope 1 at $DIR/issue-41888.rs:+3:18: +3:19 - _4 = K; // scope 1 at $DIR/issue-41888.rs:+3:18: +3:19 - _3 = E::F(move _4); // scope 1 at $DIR/issue-41888.rs:+3:13: +3:20 - StorageDead(_4); // scope 1 at $DIR/issue-41888.rs:+3:19: +3:20 - goto -> bb14; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 + StorageLive(_3); // scope 1 at $DIR/issue_41888.rs:+3:13: +3:20 + StorageLive(_4); // scope 1 at $DIR/issue_41888.rs:+3:18: +3:19 + _4 = K; // scope 1 at $DIR/issue_41888.rs:+3:18: +3:19 + _3 = E::F(move _4); // scope 1 at $DIR/issue_41888.rs:+3:13: +3:20 + StorageDead(_4); // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20 + goto -> bb14; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 } bb3: { - goto -> bb4; // scope 1 at $DIR/issue-41888.rs:+3:19: +3:20 + goto -> bb4; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20 } bb4: { - StorageDead(_3); // scope 1 at $DIR/issue-41888.rs:+3:19: +3:20 - _5 = discriminant(_1); // scope 2 at $DIR/issue-41888.rs:+4:16: +4:24 - switchInt(move _5) -> [0_isize: bb5, otherwise: bb6]; // scope 2 at $DIR/issue-41888.rs:+4:16: +4:24 + StorageDead(_3); // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20 + _5 = discriminant(_1); // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24 + switchInt(move _5) -> [0_isize: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24 } bb5: { - StorageLive(_6); // scope 2 at $DIR/issue-41888.rs:+4:21: +4:23 - _9 = const false; // scope 2 at $DIR/issue-41888.rs:+4:21: +4:23 - _6 = move ((_1 as F).0: K); // scope 2 at $DIR/issue-41888.rs:+4:21: +4:23 - _0 = const (); // scope 2 at $DIR/issue-41888.rs:+4:29: +7:10 - StorageDead(_6); // scope 1 at $DIR/issue-41888.rs:+7:9: +7:10 - goto -> bb8; // scope 1 at $DIR/issue-41888.rs:+4:9: +7:10 + StorageLive(_6); // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23 + _9 = const false; // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23 + _6 = move ((_1 as F).0: K); // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23 + _0 = const (); // scope 2 at $DIR/issue_41888.rs:+4:29: +7:10 + StorageDead(_6); // scope 1 at $DIR/issue_41888.rs:+7:9: +7:10 + goto -> bb8; // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10 } bb6: { - _0 = const (); // scope 1 at $DIR/issue-41888.rs:+7:10: +7:10 - goto -> bb8; // scope 1 at $DIR/issue-41888.rs:+4:9: +7:10 + _0 = const (); // scope 1 at $DIR/issue_41888.rs:+7:10: +7:10 + goto -> bb8; // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10 } bb7: { - _0 = const (); // scope 1 at $DIR/issue-41888.rs:+8:6: +8:6 - goto -> bb8; // scope 1 at $DIR/issue-41888.rs:+2:5: +8:6 + _0 = const (); // scope 1 at $DIR/issue_41888.rs:+8:6: +8:6 + goto -> bb8; // scope 1 at $DIR/issue_41888.rs:+2:5: +8:6 } bb8: { - StorageDead(_2); // scope 1 at $DIR/issue-41888.rs:+8:5: +8:6 - goto -> bb20; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + StorageDead(_2); // scope 1 at $DIR/issue_41888.rs:+8:5: +8:6 + goto -> bb20; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb9: { - _7 = const false; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - _8 = const false; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - _9 = const false; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - StorageDead(_1); // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - return; // scope 0 at $DIR/issue-41888.rs:+9:2: +9:2 + _7 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + _8 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + _9 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + StorageDead(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + return; // scope 0 at $DIR/issue_41888.rs:+9:2: +9:2 } bb10 (cleanup): { - goto -> bb11; // scope 1 at $DIR/issue-41888.rs:+3:19: +3:20 + goto -> bb11; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20 } bb11 (cleanup): { - goto -> bb12; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + goto -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb12 (cleanup): { - resume; // scope 0 at $DIR/issue-41888.rs:+0:1: +9:2 + resume; // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2 } bb13 (cleanup): { - _7 = const true; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 - _8 = const true; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 - _9 = const true; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 - _1 = move _3; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 - goto -> bb10; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 + _7 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 + _8 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 + _9 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 + _1 = move _3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 + goto -> bb10; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 } bb14: { - _7 = const true; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 - _8 = const true; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 - _9 = const true; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 - _1 = move _3; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 - goto -> bb3; // scope 1 at $DIR/issue-41888.rs:+3:9: +3:10 + _7 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 + _8 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 + _9 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 + _1 = move _3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 + goto -> bb3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 } bb15: { - _7 = const false; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - goto -> bb9; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + _7 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + goto -> bb9; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb16 (cleanup): { - goto -> bb12; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + goto -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb17: { - drop(_1) -> [return: bb15, unwind: bb12]; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + drop(_1) -> [return: bb15, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb18 (cleanup): { - drop(_1) -> bb12; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + drop(_1) -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb19: { - _10 = discriminant(_1); // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - switchInt(move _10) -> [0_isize: bb15, otherwise: bb17]; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + _10 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + switchInt(move _10) -> [0_isize: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb20: { - switchInt(_7) -> [false: bb15, otherwise: bb19]; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + switchInt(_7) -> [false: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb21 (cleanup): { - _11 = discriminant(_1); // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 - switchInt(move _11) -> [0_isize: bb16, otherwise: bb18]; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + _11 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + switchInt(move _11) -> [0_isize: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb22 (cleanup): { - switchInt(_7) -> [false: bb12, otherwise: bb21]; // scope 0 at $DIR/issue-41888.rs:+9:1: +9:2 + switchInt(_7) -> [false: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } } diff --git a/src/test/mir-opt/issue-41888.rs b/src/test/mir-opt/issue_41888.rs index c1046c14dbf..c1046c14dbf 100644 --- a/src/test/mir-opt/issue-41888.rs +++ b/src/test/mir-opt/issue_41888.rs diff --git a/src/test/mir-opt/issue-62289.rs b/src/test/mir-opt/issue_62289.rs index 37e3390d5fc..37e3390d5fc 100644 --- a/src/test/mir-opt/issue-62289.rs +++ b/src/test/mir-opt/issue_62289.rs diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir index 72603dc5dbe..6969a66ac19 100644 --- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -1,122 +1,122 @@ // MIR for `test` before ElaborateDrops fn test() -> Option<Box<u32>> { - let mut _0: std::option::Option<std::boxed::Box<u32>>; // return place in scope 0 at $DIR/issue-62289.rs:+0:14: +0:30 - let mut _1: std::boxed::Box<u32>; // in scope 0 at $DIR/issue-62289.rs:+1:10: +1:21 - let mut _2: usize; // in scope 0 at $DIR/issue-62289.rs:+1:10: +1:21 - let mut _3: usize; // in scope 0 at $DIR/issue-62289.rs:+1:10: +1:21 - let mut _4: *mut u8; // in scope 0 at $DIR/issue-62289.rs:+1:10: +1:21 - let mut _5: std::boxed::Box<u32>; // in scope 0 at $DIR/issue-62289.rs:+1:10: +1:21 - let mut _6: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>; // in scope 0 at $DIR/issue-62289.rs:+1:15: +1:20 - let mut _7: std::option::Option<u32>; // in scope 0 at $DIR/issue-62289.rs:+1:15: +1:19 - let mut _8: isize; // in scope 0 at $DIR/issue-62289.rs:+1:19: +1:20 - let _9: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:+1:19: +1:20 - let mut _10: !; // in scope 0 at $DIR/issue-62289.rs:+1:19: +1:20 - let mut _11: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:+1:19: +1:20 - let _12: u32; // in scope 0 at $DIR/issue-62289.rs:+1:15: +1:20 + let mut _0: std::option::Option<std::boxed::Box<u32>>; // return place in scope 0 at $DIR/issue_62289.rs:+0:14: +0:30 + let mut _1: std::boxed::Box<u32>; // in scope 0 at $DIR/issue_62289.rs:+1:10: +1:21 + let mut _2: usize; // in scope 0 at $DIR/issue_62289.rs:+1:10: +1:21 + let mut _3: usize; // in scope 0 at $DIR/issue_62289.rs:+1:10: +1:21 + let mut _4: *mut u8; // in scope 0 at $DIR/issue_62289.rs:+1:10: +1:21 + let mut _5: std::boxed::Box<u32>; // in scope 0 at $DIR/issue_62289.rs:+1:10: +1:21 + let mut _6: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>; // in scope 0 at $DIR/issue_62289.rs:+1:15: +1:20 + let mut _7: std::option::Option<u32>; // in scope 0 at $DIR/issue_62289.rs:+1:15: +1:19 + let mut _8: isize; // in scope 0 at $DIR/issue_62289.rs:+1:19: +1:20 + let _9: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue_62289.rs:+1:19: +1:20 + let mut _10: !; // in scope 0 at $DIR/issue_62289.rs:+1:19: +1:20 + let mut _11: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue_62289.rs:+1:19: +1:20 + let _12: u32; // in scope 0 at $DIR/issue_62289.rs:+1:15: +1:20 scope 1 { } scope 2 { - debug residual => _9; // in scope 2 at $DIR/issue-62289.rs:+1:19: +1:20 + debug residual => _9; // in scope 2 at $DIR/issue_62289.rs:+1:19: +1:20 scope 3 { } } scope 4 { - debug val => _12; // in scope 4 at $DIR/issue-62289.rs:+1:15: +1:20 + debug val => _12; // in scope 4 at $DIR/issue_62289.rs:+1:15: +1:20 scope 5 { } } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-62289.rs:+1:10: +1:21 - _2 = SizeOf(u32); // scope 1 at $DIR/issue-62289.rs:+1:10: +1:21 - _3 = AlignOf(u32); // scope 1 at $DIR/issue-62289.rs:+1:10: +1:21 - _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 1 at $DIR/issue-62289.rs:+1:10: +1:21 + StorageLive(_1); // scope 0 at $DIR/issue_62289.rs:+1:10: +1:21 + _2 = SizeOf(u32); // scope 1 at $DIR/issue_62289.rs:+1:10: +1:21 + _3 = AlignOf(u32); // scope 1 at $DIR/issue_62289.rs:+1:10: +1:21 + _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 1 at $DIR/issue_62289.rs:+1:10: +1:21 // mir::Constant - // + span: $DIR/issue-62289.rs:9:10: 9:21 + // + span: $DIR/issue_62289.rs:9:10: 9:21 // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(<ZST>) } } bb1: { - StorageLive(_5); // scope 0 at $DIR/issue-62289.rs:+1:10: +1:21 - _5 = ShallowInitBox(move _4, u32); // scope 0 at $DIR/issue-62289.rs:+1:10: +1:21 - StorageLive(_6); // scope 0 at $DIR/issue-62289.rs:+1:15: +1:20 - StorageLive(_7); // scope 0 at $DIR/issue-62289.rs:+1:15: +1:19 - _7 = Option::<u32>::None; // scope 0 at $DIR/issue-62289.rs:+1:15: +1:19 - _6 = <Option<u32> as Try>::branch(move _7) -> [return: bb2, unwind: bb12]; // scope 0 at $DIR/issue-62289.rs:+1:15: +1:20 + StorageLive(_5); // scope 0 at $DIR/issue_62289.rs:+1:10: +1:21 + _5 = ShallowInitBox(move _4, u32); // scope 0 at $DIR/issue_62289.rs:+1:10: +1:21 + StorageLive(_6); // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20 + StorageLive(_7); // scope 0 at $DIR/issue_62289.rs:+1:15: +1:19 + _7 = Option::<u32>::None; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:19 + _6 = <Option<u32> as Try>::branch(move _7) -> [return: bb2, unwind: bb12]; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20 // mir::Constant - // + span: $DIR/issue-62289.rs:9:15: 9:20 + // + span: $DIR/issue_62289.rs:9:15: 9:20 // + literal: Const { ty: fn(Option<u32>) -> ControlFlow<<Option<u32> as Try>::Residual, <Option<u32> as Try>::Output> {<Option<u32> as Try>::branch}, val: Value(<ZST>) } } bb2: { - StorageDead(_7); // scope 0 at $DIR/issue-62289.rs:+1:19: +1:20 - _8 = discriminant(_6); // scope 0 at $DIR/issue-62289.rs:+1:15: +1:20 - switchInt(move _8) -> [0_isize: bb3, 1_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/issue-62289.rs:+1:15: +1:20 + StorageDead(_7); // scope 0 at $DIR/issue_62289.rs:+1:19: +1:20 + _8 = discriminant(_6); // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20 + switchInt(move _8) -> [0_isize: bb3, 1_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20 } bb3: { - StorageLive(_12); // scope 0 at $DIR/issue-62289.rs:+1:15: +1:20 - _12 = ((_6 as Continue).0: u32); // scope 0 at $DIR/issue-62289.rs:+1:15: +1:20 - (*_5) = _12; // scope 5 at $DIR/issue-62289.rs:+1:15: +1:20 - StorageDead(_12); // scope 0 at $DIR/issue-62289.rs:+1:19: +1:20 - _1 = move _5; // scope 0 at $DIR/issue-62289.rs:+1:10: +1:21 - drop(_5) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:+1:20: +1:21 + StorageLive(_12); // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20 + _12 = ((_6 as Continue).0: u32); // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20 + (*_5) = _12; // scope 5 at $DIR/issue_62289.rs:+1:15: +1:20 + StorageDead(_12); // scope 0 at $DIR/issue_62289.rs:+1:19: +1:20 + _1 = move _5; // scope 0 at $DIR/issue_62289.rs:+1:10: +1:21 + drop(_5) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/issue_62289.rs:+1:20: +1:21 } bb4: { - unreachable; // scope 0 at $DIR/issue-62289.rs:+1:15: +1:20 + unreachable; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20 } bb5: { - StorageLive(_9); // scope 0 at $DIR/issue-62289.rs:+1:19: +1:20 - _9 = ((_6 as Break).0: std::option::Option<std::convert::Infallible>); // scope 0 at $DIR/issue-62289.rs:+1:19: +1:20 - StorageLive(_11); // scope 3 at $DIR/issue-62289.rs:+1:19: +1:20 - _11 = _9; // scope 3 at $DIR/issue-62289.rs:+1:19: +1:20 - _0 = <Option<Box<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _11) -> [return: bb6, unwind: bb12]; // scope 3 at $DIR/issue-62289.rs:+1:15: +1:20 + StorageLive(_9); // scope 0 at $DIR/issue_62289.rs:+1:19: +1:20 + _9 = ((_6 as Break).0: std::option::Option<std::convert::Infallible>); // scope 0 at $DIR/issue_62289.rs:+1:19: +1:20 + StorageLive(_11); // scope 3 at $DIR/issue_62289.rs:+1:19: +1:20 + _11 = _9; // scope 3 at $DIR/issue_62289.rs:+1:19: +1:20 + _0 = <Option<Box<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _11) -> [return: bb6, unwind: bb12]; // scope 3 at $DIR/issue_62289.rs:+1:15: +1:20 // mir::Constant - // + span: $DIR/issue-62289.rs:9:19: 9:20 + // + span: $DIR/issue_62289.rs:9:19: 9:20 // + literal: Const { ty: fn(Option<Infallible>) -> Option<Box<u32>> {<Option<Box<u32>> as FromResidual<Option<Infallible>>>::from_residual}, val: Value(<ZST>) } } bb6: { - StorageDead(_11); // scope 3 at $DIR/issue-62289.rs:+1:19: +1:20 - StorageDead(_9); // scope 0 at $DIR/issue-62289.rs:+1:19: +1:20 - drop(_5) -> bb9; // scope 0 at $DIR/issue-62289.rs:+1:20: +1:21 + StorageDead(_11); // scope 3 at $DIR/issue_62289.rs:+1:19: +1:20 + StorageDead(_9); // scope 0 at $DIR/issue_62289.rs:+1:19: +1:20 + drop(_5) -> bb9; // scope 0 at $DIR/issue_62289.rs:+1:20: +1:21 } bb7: { - StorageDead(_5); // scope 0 at $DIR/issue-62289.rs:+1:20: +1:21 - _0 = Option::<Box<u32>>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:+1:5: +1:22 - drop(_1) -> bb8; // scope 0 at $DIR/issue-62289.rs:+1:21: +1:22 + StorageDead(_5); // scope 0 at $DIR/issue_62289.rs:+1:20: +1:21 + _0 = Option::<Box<u32>>::Some(move _1); // scope 0 at $DIR/issue_62289.rs:+1:5: +1:22 + drop(_1) -> bb8; // scope 0 at $DIR/issue_62289.rs:+1:21: +1:22 } bb8: { - StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:+1:21: +1:22 - StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:+2:1: +2:2 - goto -> bb10; // scope 0 at $DIR/issue-62289.rs:+2:2: +2:2 + StorageDead(_1); // scope 0 at $DIR/issue_62289.rs:+1:21: +1:22 + StorageDead(_6); // scope 0 at $DIR/issue_62289.rs:+2:1: +2:2 + goto -> bb10; // scope 0 at $DIR/issue_62289.rs:+2:2: +2:2 } bb9: { - StorageDead(_5); // scope 0 at $DIR/issue-62289.rs:+1:20: +1:21 - StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:+1:21: +1:22 - StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:+2:1: +2:2 - goto -> bb10; // scope 0 at $DIR/issue-62289.rs:+2:2: +2:2 + StorageDead(_5); // scope 0 at $DIR/issue_62289.rs:+1:20: +1:21 + StorageDead(_1); // scope 0 at $DIR/issue_62289.rs:+1:21: +1:22 + StorageDead(_6); // scope 0 at $DIR/issue_62289.rs:+2:1: +2:2 + goto -> bb10; // scope 0 at $DIR/issue_62289.rs:+2:2: +2:2 } bb10: { - return; // scope 0 at $DIR/issue-62289.rs:+2:2: +2:2 + return; // scope 0 at $DIR/issue_62289.rs:+2:2: +2:2 } bb11 (cleanup): { - drop(_1) -> bb13; // scope 0 at $DIR/issue-62289.rs:+1:21: +1:22 + drop(_1) -> bb13; // scope 0 at $DIR/issue_62289.rs:+1:21: +1:22 } bb12 (cleanup): { - drop(_5) -> bb13; // scope 0 at $DIR/issue-62289.rs:+1:20: +1:21 + drop(_5) -> bb13; // scope 0 at $DIR/issue_62289.rs:+1:20: +1:21 } bb13 (cleanup): { - resume; // scope 0 at $DIR/issue-62289.rs:+0:1: +2:2 + resume; // scope 0 at $DIR/issue_62289.rs:+0:1: +2:2 } } diff --git a/src/test/mir-opt/issue_72181.bar.built.after.mir b/src/test/mir-opt/issue_72181.bar.built.after.mir index aa9c9986aac..ebee89001b9 100644 --- a/src/test/mir-opt/issue_72181.bar.built.after.mir +++ b/src/test/mir-opt/issue_72181.bar.built.after.mir @@ -1,17 +1,17 @@ // MIR for `bar` after built fn bar(_1: [(Never, u32); 1]) -> u32 { - let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:+0:40: +0:43 - let _2: u32; // in scope 0 at $DIR/issue-72181.rs:+0:13: +0:14 + let mut _0: u32; // return place in scope 0 at $DIR/issue_72181.rs:+0:40: +0:43 + let _2: u32; // in scope 0 at $DIR/issue_72181.rs:+0:13: +0:14 scope 1 { - debug x => _2; // in scope 1 at $DIR/issue-72181.rs:+0:13: +0:14 + debug x => _2; // in scope 1 at $DIR/issue_72181.rs:+0:13: +0:14 } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:+0:13: +0:14 - _2 = (_1[0 of 1].1: u32); // scope 0 at $DIR/issue-72181.rs:+0:13: +0:14 - _0 = _2; // scope 1 at $DIR/issue-72181.rs:+0:46: +0:47 - StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:+0:48: +0:49 - return; // scope 0 at $DIR/issue-72181.rs:+0:49: +0:49 + StorageLive(_2); // scope 0 at $DIR/issue_72181.rs:+0:13: +0:14 + _2 = (_1[0 of 1].1: u32); // scope 0 at $DIR/issue_72181.rs:+0:13: +0:14 + _0 = _2; // scope 1 at $DIR/issue_72181.rs:+0:46: +0:47 + StorageDead(_2); // scope 0 at $DIR/issue_72181.rs:+0:48: +0:49 + return; // scope 0 at $DIR/issue_72181.rs:+0:49: +0:49 } } diff --git a/src/test/mir-opt/issue_72181.foo.built.after.mir b/src/test/mir-opt/issue_72181.foo.built.after.mir index 1d771ad3656..90c9785202a 100644 --- a/src/test/mir-opt/issue_72181.foo.built.after.mir +++ b/src/test/mir-opt/issue_72181.foo.built.after.mir @@ -1,27 +1,27 @@ // MIR for `foo` after built fn foo(_1: [(Never, u32); 1]) -> u32 { - debug xs => _1; // in scope 0 at $DIR/issue-72181.rs:+0:8: +0:10 - let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:+0:34: +0:37 - let _2: usize; // in scope 0 at $DIR/issue-72181.rs:+0:43: +0:44 - let mut _3: usize; // in scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 - let mut _4: bool; // in scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 + debug xs => _1; // in scope 0 at $DIR/issue_72181.rs:+0:8: +0:10 + let mut _0: u32; // return place in scope 0 at $DIR/issue_72181.rs:+0:34: +0:37 + let _2: usize; // in scope 0 at $DIR/issue_72181.rs:+0:43: +0:44 + let mut _3: usize; // in scope 0 at $DIR/issue_72181.rs:+0:40: +0:45 + let mut _4: bool; // in scope 0 at $DIR/issue_72181.rs:+0:40: +0:45 bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:+0:43: +0:44 - _2 = const 0_usize; // scope 0 at $DIR/issue-72181.rs:+0:43: +0:44 - _3 = Len(_1); // scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 - _4 = Lt(_2, _3); // scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 - assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 + StorageLive(_2); // scope 0 at $DIR/issue_72181.rs:+0:43: +0:44 + _2 = const 0_usize; // scope 0 at $DIR/issue_72181.rs:+0:43: +0:44 + _3 = Len(_1); // scope 0 at $DIR/issue_72181.rs:+0:40: +0:45 + _4 = Lt(_2, _3); // scope 0 at $DIR/issue_72181.rs:+0:40: +0:45 + assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue_72181.rs:+0:40: +0:45 } bb1: { - _0 = (_1[_2].1: u32); // scope 0 at $DIR/issue-72181.rs:+0:40: +0:47 - StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:+0:48: +0:49 - return; // scope 0 at $DIR/issue-72181.rs:+0:49: +0:49 + _0 = (_1[_2].1: u32); // scope 0 at $DIR/issue_72181.rs:+0:40: +0:47 + StorageDead(_2); // scope 0 at $DIR/issue_72181.rs:+0:48: +0:49 + return; // scope 0 at $DIR/issue_72181.rs:+0:49: +0:49 } bb2 (cleanup): { - resume; // scope 0 at $DIR/issue-72181.rs:+0:1: +0:49 + resume; // scope 0 at $DIR/issue_72181.rs:+0:1: +0:49 } } diff --git a/src/test/mir-opt/issue_72181.main.built.after.mir b/src/test/mir-opt/issue_72181.main.built.after.mir index afa09b16fe9..e8683692770 100644 --- a/src/test/mir-opt/issue_72181.main.built.after.mir +++ b/src/test/mir-opt/issue_72181.main.built.after.mir @@ -1,18 +1,18 @@ // MIR for `main` after built fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-72181.rs:+0:11: +0:11 - let mut _1: usize; // in scope 0 at $DIR/issue-72181.rs:+1:13: +1:34 - let mut _3: Foo; // in scope 0 at $DIR/issue-72181.rs:+3:14: +3:27 - let mut _4: Foo; // in scope 0 at $DIR/issue-72181.rs:+3:29: +3:42 - let mut _5: u64; // in scope 0 at $DIR/issue-72181.rs:+4:13: +4:30 - let _6: usize; // in scope 0 at $DIR/issue-72181.rs:+4:24: +4:25 - let mut _7: usize; // in scope 0 at $DIR/issue-72181.rs:+4:22: +4:26 - let mut _8: bool; // in scope 0 at $DIR/issue-72181.rs:+4:22: +4:26 + let mut _0: (); // return place in scope 0 at $DIR/issue_72181.rs:+0:11: +0:11 + let mut _1: usize; // in scope 0 at $DIR/issue_72181.rs:+1:13: +1:34 + let mut _3: Foo; // in scope 0 at $DIR/issue_72181.rs:+3:14: +3:27 + let mut _4: Foo; // in scope 0 at $DIR/issue_72181.rs:+3:29: +3:42 + let mut _5: u64; // in scope 0 at $DIR/issue_72181.rs:+4:13: +4:30 + let _6: usize; // in scope 0 at $DIR/issue_72181.rs:+4:24: +4:25 + let mut _7: usize; // in scope 0 at $DIR/issue_72181.rs:+4:22: +4:26 + let mut _8: bool; // in scope 0 at $DIR/issue_72181.rs:+4:22: +4:26 scope 1 { - let _2: [Foo; 2]; // in scope 1 at $DIR/issue-72181.rs:+3:9: +3:10 + let _2: [Foo; 2]; // in scope 1 at $DIR/issue_72181.rs:+3:9: +3:10 scope 2 { - debug f => _2; // in scope 2 at $DIR/issue-72181.rs:+3:9: +3:10 + debug f => _2; // in scope 2 at $DIR/issue_72181.rs:+3:9: +3:10 scope 3 { } scope 4 { @@ -21,42 +21,42 @@ fn main() -> () { } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-72181.rs:+1:13: +1:34 - _1 = std::mem::size_of::<Foo>() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-72181.rs:+1:13: +1:34 + StorageLive(_1); // scope 0 at $DIR/issue_72181.rs:+1:13: +1:34 + _1 = std::mem::size_of::<Foo>() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue_72181.rs:+1:13: +1:34 // mir::Constant - // + span: $DIR/issue-72181.rs:24:13: 24:32 + // + span: $DIR/issue_72181.rs:24:13: 24:32 // + literal: Const { ty: fn() -> usize {std::mem::size_of::<Foo>}, val: Value(<ZST>) } } bb1: { - StorageDead(_1); // scope 0 at $DIR/issue-72181.rs:+1:34: +1:35 - StorageLive(_2); // scope 1 at $DIR/issue-72181.rs:+3:9: +3:10 - StorageLive(_3); // scope 1 at $DIR/issue-72181.rs:+3:14: +3:27 - _3 = Foo { a: const 42_u64 }; // scope 1 at $DIR/issue-72181.rs:+3:14: +3:27 - StorageLive(_4); // scope 1 at $DIR/issue-72181.rs:+3:29: +3:42 - _4 = Foo { a: const 10_u64 }; // scope 1 at $DIR/issue-72181.rs:+3:29: +3:42 - _2 = [move _3, move _4]; // scope 1 at $DIR/issue-72181.rs:+3:13: +3:43 - StorageDead(_4); // scope 1 at $DIR/issue-72181.rs:+3:42: +3:43 - StorageDead(_3); // scope 1 at $DIR/issue-72181.rs:+3:42: +3:43 - FakeRead(ForLet(None), _2); // scope 1 at $DIR/issue-72181.rs:+3:9: +3:10 - StorageLive(_5); // scope 2 at $DIR/issue-72181.rs:+4:13: +4:30 - StorageLive(_6); // scope 4 at $DIR/issue-72181.rs:+4:24: +4:25 - _6 = const 0_usize; // scope 4 at $DIR/issue-72181.rs:+4:24: +4:25 - _7 = Len(_2); // scope 4 at $DIR/issue-72181.rs:+4:22: +4:26 - _8 = Lt(_6, _7); // scope 4 at $DIR/issue-72181.rs:+4:22: +4:26 - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb2, unwind: bb3]; // scope 4 at $DIR/issue-72181.rs:+4:22: +4:26 + StorageDead(_1); // scope 0 at $DIR/issue_72181.rs:+1:34: +1:35 + StorageLive(_2); // scope 1 at $DIR/issue_72181.rs:+3:9: +3:10 + StorageLive(_3); // scope 1 at $DIR/issue_72181.rs:+3:14: +3:27 + _3 = Foo { a: const 42_u64 }; // scope 1 at $DIR/issue_72181.rs:+3:14: +3:27 + StorageLive(_4); // scope 1 at $DIR/issue_72181.rs:+3:29: +3:42 + _4 = Foo { a: const 10_u64 }; // scope 1 at $DIR/issue_72181.rs:+3:29: +3:42 + _2 = [move _3, move _4]; // scope 1 at $DIR/issue_72181.rs:+3:13: +3:43 + StorageDead(_4); // scope 1 at $DIR/issue_72181.rs:+3:42: +3:43 + StorageDead(_3); // scope 1 at $DIR/issue_72181.rs:+3:42: +3:43 + FakeRead(ForLet(None), _2); // scope 1 at $DIR/issue_72181.rs:+3:9: +3:10 + StorageLive(_5); // scope 2 at $DIR/issue_72181.rs:+4:13: +4:30 + StorageLive(_6); // scope 4 at $DIR/issue_72181.rs:+4:24: +4:25 + _6 = const 0_usize; // scope 4 at $DIR/issue_72181.rs:+4:24: +4:25 + _7 = Len(_2); // scope 4 at $DIR/issue_72181.rs:+4:22: +4:26 + _8 = Lt(_6, _7); // scope 4 at $DIR/issue_72181.rs:+4:22: +4:26 + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb2, unwind: bb3]; // scope 4 at $DIR/issue_72181.rs:+4:22: +4:26 } bb2: { - _5 = (_2[_6].0: u64); // scope 4 at $DIR/issue-72181.rs:+4:22: +4:28 - StorageDead(_6); // scope 2 at $DIR/issue-72181.rs:+4:30: +4:31 - StorageDead(_5); // scope 2 at $DIR/issue-72181.rs:+4:30: +4:31 - _0 = const (); // scope 0 at $DIR/issue-72181.rs:+0:11: +5:2 - StorageDead(_2); // scope 1 at $DIR/issue-72181.rs:+5:1: +5:2 - return; // scope 0 at $DIR/issue-72181.rs:+5:2: +5:2 + _5 = (_2[_6].0: u64); // scope 4 at $DIR/issue_72181.rs:+4:22: +4:28 + StorageDead(_6); // scope 2 at $DIR/issue_72181.rs:+4:30: +4:31 + StorageDead(_5); // scope 2 at $DIR/issue_72181.rs:+4:30: +4:31 + _0 = const (); // scope 0 at $DIR/issue_72181.rs:+0:11: +5:2 + StorageDead(_2); // scope 1 at $DIR/issue_72181.rs:+5:1: +5:2 + return; // scope 0 at $DIR/issue_72181.rs:+5:2: +5:2 } bb3 (cleanup): { - resume; // scope 0 at $DIR/issue-72181.rs:+0:1: +5:2 + resume; // scope 0 at $DIR/issue_72181.rs:+0:1: +5:2 } } diff --git a/src/test/mir-opt/issue-72181.rs b/src/test/mir-opt/issue_72181.rs index 6a32d4bbee2..6a32d4bbee2 100644 --- a/src/test/mir-opt/issue-72181.rs +++ b/src/test/mir-opt/issue_72181.rs diff --git a/src/test/mir-opt/issue_72181_1.f.built.after.mir b/src/test/mir-opt/issue_72181_1.f.built.after.mir index 31e997f9b33..4086da52011 100644 --- a/src/test/mir-opt/issue_72181_1.f.built.after.mir +++ b/src/test/mir-opt/issue_72181_1.f.built.after.mir @@ -1,29 +1,29 @@ // MIR for `f` after built fn f(_1: Void) -> ! { - debug v => _1; // in scope 0 at $DIR/issue-72181-1.rs:+0:6: +0:7 - let mut _0: !; // return place in scope 0 at $DIR/issue-72181-1.rs:+0:18: +0:19 - let mut _2: !; // in scope 0 at $DIR/issue-72181-1.rs:+0:20: +2:2 - let mut _3: !; // in scope 0 at $DIR/issue-72181-1.rs:+1:5: +1:15 + debug v => _1; // in scope 0 at $DIR/issue_72181_1.rs:+0:6: +0:7 + let mut _0: !; // return place in scope 0 at $DIR/issue_72181_1.rs:+0:18: +0:19 + let mut _2: !; // in scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2 + let mut _3: !; // in scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15 bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-72181-1.rs:+0:20: +2:2 - StorageLive(_3); // scope 0 at $DIR/issue-72181-1.rs:+1:5: +1:15 - FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/issue-72181-1.rs:+1:11: +1:12 - unreachable; // scope 0 at $DIR/issue-72181-1.rs:+1:11: +1:12 + StorageLive(_2); // scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2 + StorageLive(_3); // scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15 + FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/issue_72181_1.rs:+1:11: +1:12 + unreachable; // scope 0 at $DIR/issue_72181_1.rs:+1:11: +1:12 } bb1: { - unreachable; // scope 0 at $DIR/issue-72181-1.rs:+1:5: +1:15 + unreachable; // scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15 } bb2: { - StorageDead(_3); // scope 0 at $DIR/issue-72181-1.rs:+1:14: +1:15 - unreachable; // scope 0 at $DIR/issue-72181-1.rs:+0:20: +2:2 + StorageDead(_3); // scope 0 at $DIR/issue_72181_1.rs:+1:14: +1:15 + unreachable; // scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2 } bb3: { - StorageDead(_2); // scope 0 at $DIR/issue-72181-1.rs:+2:1: +2:2 - return; // scope 0 at $DIR/issue-72181-1.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/issue_72181_1.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_72181_1.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/issue_72181_1.main.built.after.mir b/src/test/mir-opt/issue_72181_1.main.built.after.mir index 65177a81b03..2172f3aa9e2 100644 --- a/src/test/mir-opt/issue_72181_1.main.built.after.mir +++ b/src/test/mir-opt/issue_72181_1.main.built.after.mir @@ -1,57 +1,57 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(Void) }, span: $DIR/issue-72181-1.rs:16:12: 16:16, inferred_ty: Void -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(Void) }, span: $DIR/issue-72181-1.rs:16:12: 16:16, inferred_ty: Void +| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(Void) }, span: $DIR/issue_72181_1.rs:16:12: 16:16, inferred_ty: Void +| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(Void) }, span: $DIR/issue_72181_1.rs:16:12: 16:16, inferred_ty: Void | fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-72181-1.rs:+0:11: +0:11 - let mut _1: !; // in scope 0 at $DIR/issue-72181-1.rs:+0:11: +6:2 - let _2: Void as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/issue-72181-1.rs:+1:9: +1:10 - let mut _3: (); // in scope 0 at $DIR/issue-72181-1.rs:+2:41: +2:43 - let _4: !; // in scope 0 at $DIR/issue-72181-1.rs:+5:5: +5:9 - let mut _5: Void; // in scope 0 at $DIR/issue-72181-1.rs:+5:7: +5:8 + let mut _0: (); // return place in scope 0 at $DIR/issue_72181_1.rs:+0:11: +0:11 + let mut _1: !; // in scope 0 at $DIR/issue_72181_1.rs:+0:11: +6:2 + let _2: Void as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/issue_72181_1.rs:+1:9: +1:10 + let mut _3: (); // in scope 0 at $DIR/issue_72181_1.rs:+2:41: +2:43 + let _4: !; // in scope 0 at $DIR/issue_72181_1.rs:+5:5: +5:9 + let mut _5: Void; // in scope 0 at $DIR/issue_72181_1.rs:+5:7: +5:8 scope 1 { - debug v => _2; // in scope 1 at $DIR/issue-72181-1.rs:+1:9: +1:10 + debug v => _2; // in scope 1 at $DIR/issue_72181_1.rs:+1:9: +1:10 } scope 2 { } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-72181-1.rs:+1:9: +1:10 - StorageLive(_3); // scope 2 at $DIR/issue-72181-1.rs:+2:41: +2:43 - _3 = (); // scope 2 at $DIR/issue-72181-1.rs:+2:41: +2:43 - _2 = transmute::<(), Void>(move _3) -> bb4; // scope 2 at $DIR/issue-72181-1.rs:+2:9: +2:44 + StorageLive(_2); // scope 0 at $DIR/issue_72181_1.rs:+1:9: +1:10 + StorageLive(_3); // scope 2 at $DIR/issue_72181_1.rs:+2:41: +2:43 + _3 = (); // scope 2 at $DIR/issue_72181_1.rs:+2:41: +2:43 + _2 = transmute::<(), Void>(move _3) -> bb4; // scope 2 at $DIR/issue_72181_1.rs:+2:9: +2:44 // mir::Constant - // + span: $DIR/issue-72181-1.rs:17:9: 17:40 + // + span: $DIR/issue_72181_1.rs:17:9: 17:40 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {transmute::<(), Void>}, val: Value(<ZST>) } } bb1: { - StorageDead(_3); // scope 2 at $DIR/issue-72181-1.rs:+2:43: +2:44 - FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-72181-1.rs:+1:9: +1:10 - AscribeUserType(_2, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue-72181-1.rs:+1:12: +1:16 - StorageLive(_4); // scope 1 at $DIR/issue-72181-1.rs:+5:5: +5:9 - StorageLive(_5); // scope 1 at $DIR/issue-72181-1.rs:+5:7: +5:8 - _5 = move _2; // scope 1 at $DIR/issue-72181-1.rs:+5:7: +5:8 - _4 = f(move _5) -> bb4; // scope 1 at $DIR/issue-72181-1.rs:+5:5: +5:9 + StorageDead(_3); // scope 2 at $DIR/issue_72181_1.rs:+2:43: +2:44 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue_72181_1.rs:+1:9: +1:10 + AscribeUserType(_2, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue_72181_1.rs:+1:12: +1:16 + StorageLive(_4); // scope 1 at $DIR/issue_72181_1.rs:+5:5: +5:9 + StorageLive(_5); // scope 1 at $DIR/issue_72181_1.rs:+5:7: +5:8 + _5 = move _2; // scope 1 at $DIR/issue_72181_1.rs:+5:7: +5:8 + _4 = f(move _5) -> bb4; // scope 1 at $DIR/issue_72181_1.rs:+5:5: +5:9 // mir::Constant - // + span: $DIR/issue-72181-1.rs:20:5: 20:6 + // + span: $DIR/issue_72181_1.rs:20:5: 20:6 // + literal: Const { ty: fn(Void) -> ! {f}, val: Value(<ZST>) } } bb2: { - StorageDead(_5); // scope 1 at $DIR/issue-72181-1.rs:+5:8: +5:9 - StorageDead(_4); // scope 1 at $DIR/issue-72181-1.rs:+5:9: +5:10 - StorageDead(_2); // scope 0 at $DIR/issue-72181-1.rs:+6:1: +6:2 - unreachable; // scope 0 at $DIR/issue-72181-1.rs:+0:11: +6:2 + StorageDead(_5); // scope 1 at $DIR/issue_72181_1.rs:+5:8: +5:9 + StorageDead(_4); // scope 1 at $DIR/issue_72181_1.rs:+5:9: +5:10 + StorageDead(_2); // scope 0 at $DIR/issue_72181_1.rs:+6:1: +6:2 + unreachable; // scope 0 at $DIR/issue_72181_1.rs:+0:11: +6:2 } bb3: { - return; // scope 0 at $DIR/issue-72181-1.rs:+6:2: +6:2 + return; // scope 0 at $DIR/issue_72181_1.rs:+6:2: +6:2 } bb4 (cleanup): { - resume; // scope 0 at $DIR/issue-72181-1.rs:+0:1: +6:2 + resume; // scope 0 at $DIR/issue_72181_1.rs:+0:1: +6:2 } } diff --git a/src/test/mir-opt/issue-72181-1.rs b/src/test/mir-opt/issue_72181_1.rs index 8ae2599ec73..8ae2599ec73 100644 --- a/src/test/mir-opt/issue-72181-1.rs +++ b/src/test/mir-opt/issue_72181_1.rs diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index 269e4e32617..c9a9511586d 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff @@ -2,18 +2,18 @@ + // MIR for `main` after SimplifyArmIdentity fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - let mut _3: isize; // in scope 0 at $DIR/issue-73223.rs:+2:9: +2:16 - let _4: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - let mut _5: !; // in scope 0 at $DIR/issue-73223.rs:+3:17: +3:23 - let mut _7: i32; // in scope 0 at $DIR/issue-73223.rs:+6:22: +6:27 + let mut _0: (); // return place in scope 0 at $DIR/issue_73223.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/issue_73223.rs:+1:9: +1:14 + let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 + let mut _3: isize; // in scope 0 at $DIR/issue_73223.rs:+2:9: +2:16 + let _4: i32; // in scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 + let mut _5: !; // in scope 0 at $DIR/issue_73223.rs:+3:17: +3:23 + let mut _7: i32; // in scope 0 at $DIR/issue_73223.rs:+6:22: +6:27 let _8: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _9: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _10: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _11: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _12: i32; // in scope 0 at $DIR/issue-73223.rs:+7:23: +7:24 + let _12: i32; // in scope 0 at $DIR/issue_73223.rs:+7:23: +7:24 let mut _15: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _16: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _17: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -27,10 +27,10 @@ let _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _27: std::option::Option<std::fmt::Arguments<'_>>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { - debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14 - let _6: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 + debug split => _1; // in scope 1 at $DIR/issue_73223.rs:+1:9: +1:14 + let _6: std::option::Option<i32>; // in scope 1 at $DIR/issue_73223.rs:+6:9: +6:14 scope 3 { - debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14 + debug _prev => _6; // in scope 3 at $DIR/issue_73223.rs:+6:9: +6:14 let _13: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _14: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _28: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -45,43 +45,43 @@ } } scope 2 { - debug v => _4; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15 + debug v => _4; // in scope 2 at $DIR/issue_73223.rs:+2:14: +2:15 } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - _3 = const 1_isize; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - goto -> bb3; // scope 0 at $DIR/issue-73223.rs:+1:17: +1:30 + StorageLive(_1); // scope 0 at $DIR/issue_73223.rs:+1:9: +1:14 + StorageLive(_2); // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 + Deinit(_2); // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 + ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 + discriminant(_2) = 1; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 + _3 = const 1_isize; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 + goto -> bb3; // scope 0 at $DIR/issue_73223.rs:+1:17: +1:30 } bb1: { - nop; // scope 0 at $DIR/issue-73223.rs:+3:17: +3:23 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 - return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 + nop; // scope 0 at $DIR/issue_73223.rs:+3:17: +3:23 + StorageDead(_2); // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7 + StorageDead(_1); // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2 + return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 } bb2: { - unreachable; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + unreachable; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 } bb3: { - StorageLive(_4); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _1 = _4; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_4); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 - StorageLive(_6); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - StorageLive(_7); // scope 1 at $DIR/issue-73223.rs:+6:22: +6:27 - _7 = _1; // scope 1 at $DIR/issue-73223.rs:+6:22: +6:27 - Deinit(_6); // scope 1 at $DIR/issue-73223.rs:+6:17: +6:28 - ((_6 as Some).0: i32) = move _7; // scope 1 at $DIR/issue-73223.rs:+6:17: +6:28 - discriminant(_6) = 1; // scope 1 at $DIR/issue-73223.rs:+6:17: +6:28 - StorageDead(_7); // scope 1 at $DIR/issue-73223.rs:+6:27: +6:28 + StorageLive(_4); // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 + _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 + _1 = _4; // scope 2 at $DIR/issue_73223.rs:+2:20: +2:21 + StorageDead(_4); // scope 0 at $DIR/issue_73223.rs:+2:20: +2:21 + StorageDead(_2); // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7 + StorageLive(_6); // scope 1 at $DIR/issue_73223.rs:+6:9: +6:14 + StorageLive(_7); // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27 + _7 = _1; // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27 + Deinit(_6); // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 + ((_6 as Some).0: i32) = move _7; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 + discriminant(_6) = 1; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 + StorageDead(_7); // scope 1 at $DIR/issue_73223.rs:+6:27: +6:28 StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -152,10 +152,10 @@ StorageDead(_13); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - nop; // scope 0 at $DIR/issue-73223.rs:+0:11: +8:2 - StorageDead(_6); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 - return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 + nop; // scope 0 at $DIR/issue_73223.rs:+0:11: +8:2 + StorageDead(_6); // scope 1 at $DIR/issue_73223.rs:+8:1: +8:2 + StorageDead(_1); // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2 + return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 } } diff --git a/src/test/mir-opt/issue-73223.rs b/src/test/mir-opt/issue_73223.rs index be114cab719..be114cab719 100644 --- a/src/test/mir-opt/issue-73223.rs +++ b/src/test/mir-opt/issue_73223.rs diff --git a/src/test/mir-opt/issue_78192.f.InstCombine.diff b/src/test/mir-opt/issue_78192.f.InstCombine.diff index 8ec94d65fda..116ca304c99 100644 --- a/src/test/mir-opt/issue_78192.f.InstCombine.diff +++ b/src/test/mir-opt/issue_78192.f.InstCombine.diff @@ -2,28 +2,28 @@ + // MIR for `f` after InstCombine fn f(_1: &T) -> *const T { - debug a => _1; // in scope 0 at $DIR/issue-78192.rs:+0:13: +0:14 - let mut _0: *const T; // return place in scope 0 at $DIR/issue-78192.rs:+0:23: +0:31 - let _2: &*const T; // in scope 0 at $DIR/issue-78192.rs:+1:9: +1:10 - let _3: &*const T; // in scope 0 at $DIR/issue-78192.rs:+1:24: +1:40 - let _4: *const T; // in scope 0 at $DIR/issue-78192.rs:+1:25: +1:40 + debug a => _1; // in scope 0 at $DIR/issue_78192.rs:+0:13: +0:14 + let mut _0: *const T; // return place in scope 0 at $DIR/issue_78192.rs:+0:23: +0:31 + let _2: &*const T; // in scope 0 at $DIR/issue_78192.rs:+1:9: +1:10 + let _3: &*const T; // in scope 0 at $DIR/issue_78192.rs:+1:24: +1:40 + let _4: *const T; // in scope 0 at $DIR/issue_78192.rs:+1:25: +1:40 scope 1 { - debug b => _2; // in scope 1 at $DIR/issue-78192.rs:+1:9: +1:10 + debug b => _2; // in scope 1 at $DIR/issue_78192.rs:+1:9: +1:10 } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-78192.rs:+1:9: +1:10 - StorageLive(_3); // scope 0 at $DIR/issue-78192.rs:+1:24: +1:40 - StorageLive(_4); // scope 0 at $DIR/issue-78192.rs:+1:25: +1:40 - _4 = &raw const (*_1); // scope 0 at $DIR/issue-78192.rs:+1:26: +1:27 - _3 = &_4; // scope 0 at $DIR/issue-78192.rs:+1:24: +1:40 -- _2 = &(*_3); // scope 0 at $DIR/issue-78192.rs:+1:24: +1:40 -+ _2 = _3; // scope 0 at $DIR/issue-78192.rs:+1:24: +1:40 - StorageDead(_3); // scope 0 at $DIR/issue-78192.rs:+1:40: +1:41 - _0 = (*_2); // scope 1 at $DIR/issue-78192.rs:+2:5: +2:7 - StorageDead(_4); // scope 0 at $DIR/issue-78192.rs:+3:1: +3:2 - StorageDead(_2); // scope 0 at $DIR/issue-78192.rs:+3:1: +3:2 - return; // scope 0 at $DIR/issue-78192.rs:+3:2: +3:2 + StorageLive(_2); // scope 0 at $DIR/issue_78192.rs:+1:9: +1:10 + StorageLive(_3); // scope 0 at $DIR/issue_78192.rs:+1:24: +1:40 + StorageLive(_4); // scope 0 at $DIR/issue_78192.rs:+1:25: +1:40 + _4 = &raw const (*_1); // scope 0 at $DIR/issue_78192.rs:+1:26: +1:27 + _3 = &_4; // scope 0 at $DIR/issue_78192.rs:+1:24: +1:40 +- _2 = &(*_3); // scope 0 at $DIR/issue_78192.rs:+1:24: +1:40 ++ _2 = _3; // scope 0 at $DIR/issue_78192.rs:+1:24: +1:40 + StorageDead(_3); // scope 0 at $DIR/issue_78192.rs:+1:40: +1:41 + _0 = (*_2); // scope 1 at $DIR/issue_78192.rs:+2:5: +2:7 + StorageDead(_4); // scope 0 at $DIR/issue_78192.rs:+3:1: +3:2 + StorageDead(_2); // scope 0 at $DIR/issue_78192.rs:+3:1: +3:2 + return; // scope 0 at $DIR/issue_78192.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/issue-78192.rs b/src/test/mir-opt/issue_78192.rs index 39f665402b0..39f665402b0 100644 --- a/src/test/mir-opt/issue-78192.rs +++ b/src/test/mir-opt/issue_78192.rs diff --git a/src/test/mir-opt/issue_91633.bar.built.after.mir b/src/test/mir-opt/issue_91633.bar.built.after.mir index 19b1b6fe12b..c3fb90e8402 100644 --- a/src/test/mir-opt/issue_91633.bar.built.after.mir +++ b/src/test/mir-opt/issue_91633.bar.built.after.mir @@ -1,39 +1,39 @@ // MIR for `bar` after built fn bar(_1: Box<[T]>) -> () { - debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14 - let mut _0: (); // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2 - let mut _2: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 - let mut _3: &[T]; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:16 + debug it => _1; // in scope 0 at $DIR/issue_91633.rs:+0:12: +0:14 + let mut _0: (); // return place in scope 0 at $DIR/issue_91633.rs:+1:2: +1:2 + let mut _2: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue_91633.rs:+4:14: +4:19 + let mut _3: &[T]; // in scope 0 at $DIR/issue_91633.rs:+4:14: +4:16 scope 1 { } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 - StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16 - _3 = &(*_1); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16 - _2 = <[T] as Index<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 + StorageLive(_2); // scope 0 at $DIR/issue_91633.rs:+4:14: +4:19 + StorageLive(_3); // scope 0 at $DIR/issue_91633.rs:+4:14: +4:16 + _3 = &(*_1); // scope 0 at $DIR/issue_91633.rs:+4:14: +4:16 + _2 = <[T] as Index<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue_91633.rs:+4:14: +4:19 // mir::Constant - // + span: $DIR/issue-91633.rs:15:14: 15:19 + // + span: $DIR/issue_91633.rs:15:14: 15:19 // + literal: Const { ty: for<'a> fn(&'a [T], usize) -> &'a <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) } } bb1: { - StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+4:18: +4:19 - StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20 - _0 = const (); // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3 - drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3 + StorageDead(_3); // scope 0 at $DIR/issue_91633.rs:+4:18: +4:19 + StorageDead(_2); // scope 0 at $DIR/issue_91633.rs:+4:19: +4:20 + _0 = const (); // scope 0 at $DIR/issue_91633.rs:+3:2: +5:3 + drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3 } bb2: { - return; // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3 + return; // scope 0 at $DIR/issue_91633.rs:+5:3: +5:3 } bb3 (cleanup): { - drop(_1) -> bb4; // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3 + drop(_1) -> bb4; // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3 } bb4 (cleanup): { - resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3 + resume; // scope 0 at $DIR/issue_91633.rs:+0:1: +5:3 } } diff --git a/src/test/mir-opt/issue_91633.foo.built.after.mir b/src/test/mir-opt/issue_91633.foo.built.after.mir index 1a6eee93d36..4e3dd365e92 100644 --- a/src/test/mir-opt/issue_91633.foo.built.after.mir +++ b/src/test/mir-opt/issue_91633.foo.built.after.mir @@ -1,57 +1,57 @@ // MIR for `foo` after built fn foo(_1: Box<[T]>) -> T { - debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:19: +0:21 - let mut _0: T; // return place in scope 0 at $DIR/issue-91633.rs:+0:36: +0:37 - let _2: T; // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 - let mut _3: &T; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 - let _4: usize; // in scope 0 at $DIR/issue-91633.rs:+2:17: +2:18 - let mut _5: usize; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 - let mut _6: bool; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + debug it => _1; // in scope 0 at $DIR/issue_91633.rs:+0:19: +0:21 + let mut _0: T; // return place in scope 0 at $DIR/issue_91633.rs:+0:36: +0:37 + let _2: T; // in scope 0 at $DIR/issue_91633.rs:+2:10: +2:11 + let mut _3: &T; // in scope 0 at $DIR/issue_91633.rs:+2:14: +2:27 + let _4: usize; // in scope 0 at $DIR/issue_91633.rs:+2:17: +2:18 + let mut _5: usize; // in scope 0 at $DIR/issue_91633.rs:+2:14: +2:19 + let mut _6: bool; // in scope 0 at $DIR/issue_91633.rs:+2:14: +2:19 scope 1 { - debug f => _2; // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11 + debug f => _2; // in scope 1 at $DIR/issue_91633.rs:+2:10: +2:11 } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 - StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 - StorageLive(_4); // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18 - _4 = const 0_usize; // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18 - _5 = Len((*_1)); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 - _6 = Lt(_4, _5); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + StorageLive(_2); // scope 0 at $DIR/issue_91633.rs:+2:10: +2:11 + StorageLive(_3); // scope 0 at $DIR/issue_91633.rs:+2:14: +2:27 + StorageLive(_4); // scope 0 at $DIR/issue_91633.rs:+2:17: +2:18 + _4 = const 0_usize; // scope 0 at $DIR/issue_91633.rs:+2:17: +2:18 + _5 = Len((*_1)); // scope 0 at $DIR/issue_91633.rs:+2:14: +2:19 + _6 = Lt(_4, _5); // scope 0 at $DIR/issue_91633.rs:+2:14: +2:19 + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind: bb5]; // scope 0 at $DIR/issue_91633.rs:+2:14: +2:19 } bb1: { - _3 = &(*_1)[_4]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 - _2 = <T as Clone>::clone(move _3) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 + _3 = &(*_1)[_4]; // scope 0 at $DIR/issue_91633.rs:+2:14: +2:27 + _2 = <T as Clone>::clone(move _3) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue_91633.rs:+2:14: +2:27 // mir::Constant - // + span: $DIR/issue-91633.rs:28:20: 28:25 + // + span: $DIR/issue_91633.rs:28:20: 28:25 // + literal: Const { ty: for<'a> fn(&'a T) -> T {<T as Clone>::clone}, val: Value(<ZST>) } } bb2: { - StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+2:26: +2:27 - FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 - StorageDead(_4); // scope 0 at $DIR/issue-91633.rs:+2:27: +2:28 - _0 = move _2; // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7 - drop(_2) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + StorageDead(_3); // scope 0 at $DIR/issue_91633.rs:+2:26: +2:27 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue_91633.rs:+2:10: +2:11 + StorageDead(_4); // scope 0 at $DIR/issue_91633.rs:+2:27: +2:28 + _0 = move _2; // scope 1 at $DIR/issue_91633.rs:+3:6: +3:7 + drop(_2) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3 } bb3: { - StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 - drop(_1) -> [return: bb4, unwind: bb6]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + StorageDead(_2); // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3 + drop(_1) -> [return: bb4, unwind: bb6]; // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3 } bb4: { - return; // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3 + return; // scope 0 at $DIR/issue_91633.rs:+4:3: +4:3 } bb5 (cleanup): { - drop(_1) -> bb6; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + drop(_1) -> bb6; // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3 } bb6 (cleanup): { - resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3 + resume; // scope 0 at $DIR/issue_91633.rs:+0:1: +4:3 } } diff --git a/src/test/mir-opt/issue_91633.fun.built.after.mir b/src/test/mir-opt/issue_91633.fun.built.after.mir index b3eea600330..42486d3a50e 100644 --- a/src/test/mir-opt/issue_91633.fun.built.after.mir +++ b/src/test/mir-opt/issue_91633.fun.built.after.mir @@ -1,35 +1,35 @@ // MIR for `fun` after built fn fun(_1: &[T]) -> &T { - debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14 - let mut _0: &T; // return place in scope 0 at $DIR/issue-91633.rs:+0:25: +0:27 - let _2: &T; // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 - let _3: usize; // in scope 0 at $DIR/issue-91633.rs:+2:18: +2:19 - let mut _4: usize; // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 - let mut _5: bool; // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + debug it => _1; // in scope 0 at $DIR/issue_91633.rs:+0:12: +0:14 + let mut _0: &T; // return place in scope 0 at $DIR/issue_91633.rs:+0:25: +0:27 + let _2: &T; // in scope 0 at $DIR/issue_91633.rs:+2:10: +2:11 + let _3: usize; // in scope 0 at $DIR/issue_91633.rs:+2:18: +2:19 + let mut _4: usize; // in scope 0 at $DIR/issue_91633.rs:+2:15: +2:20 + let mut _5: bool; // in scope 0 at $DIR/issue_91633.rs:+2:15: +2:20 scope 1 { - debug f => _2; // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11 + debug f => _2; // in scope 1 at $DIR/issue_91633.rs:+2:10: +2:11 } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 - StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19 - _3 = const 0_usize; // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19 - _4 = Len((*_1)); // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 - _5 = Lt(_3, _4); // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + StorageLive(_2); // scope 0 at $DIR/issue_91633.rs:+2:10: +2:11 + StorageLive(_3); // scope 0 at $DIR/issue_91633.rs:+2:18: +2:19 + _3 = const 0_usize; // scope 0 at $DIR/issue_91633.rs:+2:18: +2:19 + _4 = Len((*_1)); // scope 0 at $DIR/issue_91633.rs:+2:15: +2:20 + _5 = Lt(_3, _4); // scope 0 at $DIR/issue_91633.rs:+2:15: +2:20 + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue_91633.rs:+2:15: +2:20 } bb1: { - _2 = &(*_1)[_3]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:20 - FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 - _0 = &(*_2); // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7 - StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 - StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 - return; // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3 + _2 = &(*_1)[_3]; // scope 0 at $DIR/issue_91633.rs:+2:14: +2:20 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue_91633.rs:+2:10: +2:11 + _0 = &(*_2); // scope 1 at $DIR/issue_91633.rs:+3:6: +3:7 + StorageDead(_3); // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3 + StorageDead(_2); // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3 + return; // scope 0 at $DIR/issue_91633.rs:+4:3: +4:3 } bb2 (cleanup): { - resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3 + resume; // scope 0 at $DIR/issue_91633.rs:+0:1: +4:3 } } diff --git a/src/test/mir-opt/issue_91633.hey.built.after.mir b/src/test/mir-opt/issue_91633.hey.built.after.mir index e7e31ad33c1..ccb06dd5983 100644 --- a/src/test/mir-opt/issue_91633.hey.built.after.mir +++ b/src/test/mir-opt/issue_91633.hey.built.after.mir @@ -1,35 +1,35 @@ // MIR for `hey` after built fn hey(_1: &[T]) -> () { - debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14 - let mut _0: (); // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2 - let mut _2: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:20 - let _3: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 - let mut _4: &[T]; // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:17 + debug it => _1; // in scope 0 at $DIR/issue_91633.rs:+0:12: +0:14 + let mut _0: (); // return place in scope 0 at $DIR/issue_91633.rs:+1:2: +1:2 + let mut _2: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue_91633.rs:+4:14: +4:20 + let _3: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue_91633.rs:+4:15: +4:20 + let mut _4: &[T]; // in scope 0 at $DIR/issue_91633.rs:+4:15: +4:17 scope 1 { } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20 - StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 - StorageLive(_4); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17 - _4 = &(*_1); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17 - _3 = <[T] as Index<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 + StorageLive(_2); // scope 0 at $DIR/issue_91633.rs:+4:14: +4:20 + StorageLive(_3); // scope 0 at $DIR/issue_91633.rs:+4:15: +4:20 + StorageLive(_4); // scope 0 at $DIR/issue_91633.rs:+4:15: +4:17 + _4 = &(*_1); // scope 0 at $DIR/issue_91633.rs:+4:15: +4:17 + _3 = <[T] as Index<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/issue_91633.rs:+4:15: +4:20 // mir::Constant - // + span: $DIR/issue-91633.rs:7:15: 7:20 + // + span: $DIR/issue_91633.rs:7:15: 7:20 // + literal: Const { ty: for<'a> fn(&'a [T], usize) -> &'a <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) } } bb1: { - StorageDead(_4); // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20 - _2 = &(*_3); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20 - StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:20: +4:21 - _0 = const (); // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3 - StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3 - return; // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3 + StorageDead(_4); // scope 0 at $DIR/issue_91633.rs:+4:19: +4:20 + _2 = &(*_3); // scope 0 at $DIR/issue_91633.rs:+4:14: +4:20 + StorageDead(_2); // scope 0 at $DIR/issue_91633.rs:+4:20: +4:21 + _0 = const (); // scope 0 at $DIR/issue_91633.rs:+3:2: +5:3 + StorageDead(_3); // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3 + return; // scope 0 at $DIR/issue_91633.rs:+5:3: +5:3 } bb2 (cleanup): { - resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3 + resume; // scope 0 at $DIR/issue_91633.rs:+0:1: +5:3 } } diff --git a/src/test/mir-opt/issue-91633.rs b/src/test/mir-opt/issue_91633.rs index 9127cacc97c..9127cacc97c 100644 --- a/src/test/mir-opt/issue-91633.rs +++ b/src/test/mir-opt/issue_91633.rs diff --git a/src/test/mir-opt/issue_99325.main.built.after.mir b/src/test/mir-opt/issue_99325.main.built.after.mir index f588f06b7e4..3db40412b2e 100644 --- a/src/test/mir-opt/issue_99325.main.built.after.mir +++ b/src/test/mir-opt/issue_99325.main.built.after.mir @@ -1,18 +1,18 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }) }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }) }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-99325.rs:+0:15: +0:15 + let mut _0: (); // return place in scope 0 at $DIR/issue_99325.rs:+0:15: +0:15 let _1: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _2: (&&[u8], &&[u8; 4]); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _3: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _4: &[u8]; // in scope 0 at $DIR/issue-99325.rs:+1:16: +1:48 + let _4: &[u8]; // in scope 0 at $DIR/issue_99325.rs:+1:16: +1:48 let mut _5: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _6: &[u8; 4]; // in scope 0 at $DIR/issue-99325.rs:+1:50: +1:75 - let _7: [u8; 4]; // in scope 0 at $DIR/issue-99325.rs:+1:51: +1:75 + let _6: &[u8; 4]; // in scope 0 at $DIR/issue_99325.rs:+1:50: +1:75 + let _7: [u8; 4]; // in scope 0 at $DIR/issue_99325.rs:+1:51: +1:75 let _8: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _9: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -30,9 +30,9 @@ fn main() -> () { let _23: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _24: (&&[u8], &&[u8; 4]); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _25: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _26: &[u8]; // in scope 0 at $DIR/issue-99325.rs:+2:16: +2:70 + let _26: &[u8]; // in scope 0 at $DIR/issue_99325.rs:+2:16: +2:70 let mut _27: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _28: &[u8; 4]; // in scope 0 at $DIR/issue-99325.rs:+2:72: +2:79 + let _28: &[u8; 4]; // in scope 0 at $DIR/issue_99325.rs:+2:72: +2:79 let _29: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _30: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _31: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -68,10 +68,10 @@ fn main() -> () { StorageLive(_1); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_3); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_4); // scope 0 at $DIR/issue-99325.rs:+1:16: +1:48 - _4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb19]; // scope 0 at $DIR/issue-99325.rs:+1:16: +1:48 + StorageLive(_4); // scope 0 at $DIR/issue_99325.rs:+1:16: +1:48 + _4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb19]; // scope 0 at $DIR/issue_99325.rs:+1:16: +1:48 // mir::Constant - // + span: $DIR/issue-99325.rs:10:16: 10:46 + // + span: $DIR/issue_99325.rs:10:16: 10:46 // + user_ty: UserType(0) // + literal: Const { ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}, val: Value(<ZST>) } } @@ -79,10 +79,10 @@ fn main() -> () { bb1: { _3 = &_4; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_5); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_6); // scope 0 at $DIR/issue-99325.rs:+1:50: +1:75 - StorageLive(_7); // scope 0 at $DIR/issue-99325.rs:+1:51: +1:75 - _7 = [const 65_u8, const 65_u8, const 65_u8, const 65_u8]; // scope 0 at $DIR/issue-99325.rs:+1:51: +1:75 - _6 = &_7; // scope 0 at $DIR/issue-99325.rs:+1:50: +1:75 + StorageLive(_6); // scope 0 at $DIR/issue_99325.rs:+1:50: +1:75 + StorageLive(_7); // scope 0 at $DIR/issue_99325.rs:+1:51: +1:75 + _7 = [const 65_u8, const 65_u8, const 65_u8, const 65_u8]; // scope 0 at $DIR/issue_99325.rs:+1:51: +1:75 + _6 = &_7; // scope 0 at $DIR/issue_99325.rs:+1:50: +1:75 _5 = &_6; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _2 = (move _3, move _5); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_5); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -176,10 +176,10 @@ fn main() -> () { StorageLive(_23); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_24); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_25); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_26); // scope 0 at $DIR/issue-99325.rs:+2:16: +2:70 - _26 = function_with_bytes::<&*b"AAAA">() -> [return: bb10, unwind: bb19]; // scope 0 at $DIR/issue-99325.rs:+2:16: +2:70 + StorageLive(_26); // scope 0 at $DIR/issue_99325.rs:+2:16: +2:70 + _26 = function_with_bytes::<&*b"AAAA">() -> [return: bb10, unwind: bb19]; // scope 0 at $DIR/issue_99325.rs:+2:16: +2:70 // mir::Constant - // + span: $DIR/issue-99325.rs:11:16: 11:68 + // + span: $DIR/issue_99325.rs:11:16: 11:68 // + user_ty: UserType(1) // + literal: Const { ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}, val: Value(<ZST>) } } @@ -187,10 +187,10 @@ fn main() -> () { bb10: { _25 = &_26; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_27); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_28); // scope 0 at $DIR/issue-99325.rs:+2:72: +2:79 - _28 = const b"AAAA"; // scope 0 at $DIR/issue-99325.rs:+2:72: +2:79 + StorageLive(_28); // scope 0 at $DIR/issue_99325.rs:+2:72: +2:79 + _28 = const b"AAAA"; // scope 0 at $DIR/issue_99325.rs:+2:72: +2:79 // mir::Constant - // + span: $DIR/issue-99325.rs:11:72: 11:79 + // + span: $DIR/issue_99325.rs:11:72: 11:79 // + literal: Const { ty: &[u8; 4], val: Value(Scalar(alloc4)) } _27 = &_28; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _24 = (move _25, move _27); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -281,12 +281,12 @@ fn main() -> () { StorageDead(_26); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_24); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_23); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _0 = const (); // scope 0 at $DIR/issue-99325.rs:+0:15: +3:2 - return; // scope 0 at $DIR/issue-99325.rs:+3:2: +3:2 + _0 = const (); // scope 0 at $DIR/issue_99325.rs:+0:15: +3:2 + return; // scope 0 at $DIR/issue_99325.rs:+3:2: +3:2 } bb19 (cleanup): { - resume; // scope 0 at $DIR/issue-99325.rs:+0:1: +3:2 + resume; // scope 0 at $DIR/issue_99325.rs:+0:1: +3:2 } } diff --git a/src/test/mir-opt/issue-99325.rs b/src/test/mir-opt/issue_99325.rs index fe819cddb2c..fe819cddb2c 100644 --- a/src/test/mir-opt/issue-99325.rs +++ b/src/test/mir-opt/issue_99325.rs diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index f46c10711f6..1cfa41b4daa 100644 --- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -1,14 +1,14 @@ // MIR for `num_to_digit` after PreCodegen fn num_to_digit(_1: char) -> u32 { - debug num => _1; // in scope 0 at $DIR/issue-59352.rs:+0:21: +0:24 - let mut _0: u32; // return place in scope 0 at $DIR/issue-59352.rs:+0:35: +0:38 - let mut _2: char; // in scope 0 at $DIR/issue-59352.rs:+2:8: +2:11 - let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:+2:26: +2:41 - let mut _4: char; // in scope 0 at $DIR/issue-59352.rs:+2:26: +2:29 - let mut _5: u32; // in scope 0 at $DIR/issue-59352.rs:+2:8: +2:23 + debug num => _1; // in scope 0 at $DIR/issue_59352.rs:+0:21: +0:24 + let mut _0: u32; // return place in scope 0 at $DIR/issue_59352.rs:+0:35: +0:38 + let mut _2: char; // in scope 0 at $DIR/issue_59352.rs:+2:8: +2:11 + let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41 + let mut _4: char; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:29 + let mut _5: u32; // in scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 let mut _12: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue-59352.rs:14:8: 14:23 + scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:14:8: 14:23 debug self => _2; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL debug radix => _5; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL let mut _6: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL @@ -19,7 +19,7 @@ fn num_to_digit(_1: char) -> u32 { let mut _9: isize; // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL } } - scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue-59352.rs:14:26: 14:50 + scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:14:26: 14:50 debug self => _3; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL let mut _10: isize; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL let mut _11: !; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL @@ -29,9 +29,9 @@ fn num_to_digit(_1: char) -> u32 { } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-59352.rs:+2:8: +2:11 - _2 = _1; // scope 0 at $DIR/issue-59352.rs:+2:8: +2:11 - StorageLive(_5); // scope 0 at $DIR/issue-59352.rs:+2:8: +2:23 + StorageLive(_2); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:11 + _2 = _1; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:11 + StorageLive(_5); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 StorageLive(_6); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL StorageLive(_7); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL StorageLive(_8); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL @@ -43,30 +43,30 @@ fn num_to_digit(_1: char) -> u32 { } bb1: { - StorageDead(_12); // scope 0 at $DIR/issue-59352.rs:+2:8: +2:23 - StorageLive(_3); // scope 0 at $DIR/issue-59352.rs:+2:26: +2:41 - StorageLive(_4); // scope 0 at $DIR/issue-59352.rs:+2:26: +2:29 - _4 = _1; // scope 0 at $DIR/issue-59352.rs:+2:26: +2:29 - _3 = char::methods::<impl char>::to_digit(move _4, const 8_u32) -> bb2; // scope 0 at $DIR/issue-59352.rs:+2:26: +2:41 + StorageDead(_12); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 + StorageLive(_3); // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41 + StorageLive(_4); // scope 0 at $DIR/issue_59352.rs:+2:26: +2:29 + _4 = _1; // scope 0 at $DIR/issue_59352.rs:+2:26: +2:29 + _3 = char::methods::<impl char>::to_digit(move _4, const 8_u32) -> bb2; // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41 // mir::Constant - // + span: $DIR/issue-59352.rs:14:30: 14:38 + // + span: $DIR/issue_59352.rs:14:30: 14:38 // + literal: Const { ty: fn(char, u32) -> Option<u32> {char::methods::<impl char>::to_digit}, val: Value(<ZST>) } } bb2: { - StorageDead(_4); // scope 0 at $DIR/issue-59352.rs:+2:40: +2:41 + StorageDead(_4); // scope 0 at $DIR/issue_59352.rs:+2:40: +2:41 _10 = discriminant(_3); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL switchInt(move _10) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL } bb3: { - StorageDead(_12); // scope 0 at $DIR/issue-59352.rs:+2:8: +2:23 - _0 = const 0_u32; // scope 0 at $DIR/issue-59352.rs:+2:60: +2:61 - goto -> bb4; // scope 0 at $DIR/issue-59352.rs:+2:5: +2:63 + StorageDead(_12); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 + _0 = const 0_u32; // scope 0 at $DIR/issue_59352.rs:+2:60: +2:61 + goto -> bb4; // scope 0 at $DIR/issue_59352.rs:+2:5: +2:63 } bb4: { - return; // scope 0 at $DIR/issue-59352.rs:+3:2: +3:2 + return; // scope 0 at $DIR/issue_59352.rs:+3:2: +3:2 } bb5: { @@ -77,9 +77,9 @@ fn num_to_digit(_1: char) -> u32 { _12 = move _9; // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_6); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL StorageDead(_7); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL - StorageDead(_5); // scope 0 at $DIR/issue-59352.rs:+2:8: +2:23 - StorageDead(_2); // scope 0 at $DIR/issue-59352.rs:+2:22: +2:23 - switchInt(move _12) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/issue-59352.rs:+2:8: +2:23 + StorageDead(_5); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 + StorageDead(_2); // scope 0 at $DIR/issue_59352.rs:+2:22: +2:23 + switchInt(move _12) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 } bb6: { @@ -99,7 +99,7 @@ fn num_to_digit(_1: char) -> u32 { bb8: { _0 = move ((_3 as Some).0: u32); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL - StorageDead(_3); // scope 0 at $DIR/issue-59352.rs:+2:49: +2:50 - goto -> bb4; // scope 0 at $DIR/issue-59352.rs:+2:5: +2:63 + StorageDead(_3); // scope 0 at $DIR/issue_59352.rs:+2:49: +2:50 + goto -> bb4; // scope 0 at $DIR/issue_59352.rs:+2:5: +2:63 } } diff --git a/src/test/mir-opt/issues/issue-59352.rs b/src/test/mir-opt/issues/issue_59352.rs index 1e0045555ab..1e0045555ab 100644 --- a/src/test/mir-opt/issues/issue-59352.rs +++ b/src/test/mir-opt/issues/issue_59352.rs diff --git a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index 2ee4332ad38..87066cc62c0 100644 --- a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -2,17 +2,17 @@ + // MIR for `foo` after MatchBranchSimplification fn foo(_1: [u8; 16]) -> Option<[u8; 4]> { - debug bytes => _1; // in scope 0 at $DIR/issue-75439.rs:+0:12: +0:17 - let mut _0: std::option::Option<[u8; 4]>; // return place in scope 0 at $DIR/issue-75439.rs:+0:32: +0:47 - let _2: [u32; 4]; // in scope 0 at $DIR/issue-75439.rs:+2:9: +2:15 - let mut _3: [u8; 16]; // in scope 0 at $DIR/issue-75439.rs:+2:47: +2:52 - let mut _5: [u8; 4]; // in scope 0 at $DIR/issue-75439.rs:+5:14: +5:38 - let mut _6: u32; // in scope 0 at $DIR/issue-75439.rs:+5:33: +5:35 + debug bytes => _1; // in scope 0 at $DIR/issue_75439.rs:+0:12: +0:17 + let mut _0: std::option::Option<[u8; 4]>; // return place in scope 0 at $DIR/issue_75439.rs:+0:32: +0:47 + let _2: [u32; 4]; // in scope 0 at $DIR/issue_75439.rs:+2:9: +2:15 + let mut _3: [u8; 16]; // in scope 0 at $DIR/issue_75439.rs:+2:47: +2:52 + let mut _5: [u8; 4]; // in scope 0 at $DIR/issue_75439.rs:+5:14: +5:38 + let mut _6: u32; // in scope 0 at $DIR/issue_75439.rs:+5:33: +5:35 scope 1 { - debug dwords => _2; // in scope 1 at $DIR/issue-75439.rs:+2:9: +2:15 + debug dwords => _2; // in scope 1 at $DIR/issue_75439.rs:+2:9: +2:15 scope 3 { - debug ip => _4; // in scope 3 at $DIR/issue-75439.rs:+4:27: +4:29 - let _4: u32; // in scope 3 at $DIR/issue-75439.rs:+4:27: +4:29 + debug ip => _4; // in scope 3 at $DIR/issue_75439.rs:+4:27: +4:29 + let _4: u32; // in scope 3 at $DIR/issue_75439.rs:+4:27: +4:29 scope 4 { } } @@ -21,69 +21,69 @@ } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-75439.rs:+2:9: +2:15 - StorageLive(_3); // scope 2 at $DIR/issue-75439.rs:+2:47: +2:52 - _3 = _1; // scope 2 at $DIR/issue-75439.rs:+2:47: +2:52 - _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue-75439.rs:+2:37: +2:53 + StorageLive(_2); // scope 0 at $DIR/issue_75439.rs:+2:9: +2:15 + StorageLive(_3); // scope 2 at $DIR/issue_75439.rs:+2:47: +2:52 + _3 = _1; // scope 2 at $DIR/issue_75439.rs:+2:47: +2:52 + _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue_75439.rs:+2:37: +2:53 // mir::Constant - // + span: $DIR/issue-75439.rs:7:37: 7:46 + // + span: $DIR/issue_75439.rs:7:37: 7:46 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {transmute::<[u8; 16], [u32; 4]>}, val: Value(<ZST>) } } bb1: { - StorageDead(_3); // scope 2 at $DIR/issue-75439.rs:+2:52: +2:53 - switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb8]; // scope 3 at $DIR/issue-75439.rs:+4:12: +4:30 + StorageDead(_3); // scope 2 at $DIR/issue_75439.rs:+2:52: +2:53 + switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30 } bb2: { - switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb8]; // scope 3 at $DIR/issue-75439.rs:+4:12: +4:30 + switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30 } bb3: { - switchInt(_2[2 of 4]) -> [0_u32: bb5, 4294901760_u32: bb6, otherwise: bb8]; // scope 3 at $DIR/issue-75439.rs:+4:12: +4:30 + switchInt(_2[2 of 4]) -> [0_u32: bb5, 4294901760_u32: bb6, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30 } bb4: { - StorageLive(_5); // scope 3 at $DIR/issue-75439.rs:+5:14: +5:38 - StorageLive(_6); // scope 4 at $DIR/issue-75439.rs:+5:33: +5:35 - _6 = _4; // scope 4 at $DIR/issue-75439.rs:+5:33: +5:35 - _5 = transmute::<u32, [u8; 4]>(move _6) -> bb7; // scope 4 at $DIR/issue-75439.rs:+5:23: +5:36 + StorageLive(_5); // scope 3 at $DIR/issue_75439.rs:+5:14: +5:38 + StorageLive(_6); // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35 + _6 = _4; // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35 + _5 = transmute::<u32, [u8; 4]>(move _6) -> bb7; // scope 4 at $DIR/issue_75439.rs:+5:23: +5:36 // mir::Constant - // + span: $DIR/issue-75439.rs:10:23: 10:32 + // + span: $DIR/issue_75439.rs:10:23: 10:32 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {transmute::<u32, [u8; 4]>}, val: Value(<ZST>) } } bb5: { - StorageLive(_4); // scope 3 at $DIR/issue-75439.rs:+4:27: +4:29 - _4 = _2[3 of 4]; // scope 3 at $DIR/issue-75439.rs:+4:27: +4:29 - goto -> bb4; // scope 3 at $DIR/issue-75439.rs:+4:12: +4:30 + StorageLive(_4); // scope 3 at $DIR/issue_75439.rs:+4:27: +4:29 + _4 = _2[3 of 4]; // scope 3 at $DIR/issue_75439.rs:+4:27: +4:29 + goto -> bb4; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30 } bb6: { - StorageLive(_4); // scope 3 at $DIR/issue-75439.rs:+4:27: +4:29 - _4 = _2[3 of 4]; // scope 3 at $DIR/issue-75439.rs:+4:27: +4:29 - goto -> bb4; // scope 3 at $DIR/issue-75439.rs:+4:12: +4:30 + StorageLive(_4); // scope 3 at $DIR/issue_75439.rs:+4:27: +4:29 + _4 = _2[3 of 4]; // scope 3 at $DIR/issue_75439.rs:+4:27: +4:29 + goto -> bb4; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30 } bb7: { - StorageDead(_6); // scope 4 at $DIR/issue-75439.rs:+5:35: +5:36 - Deinit(_0); // scope 3 at $DIR/issue-75439.rs:+5:9: +5:39 - ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue-75439.rs:+5:9: +5:39 - discriminant(_0) = 1; // scope 3 at $DIR/issue-75439.rs:+5:9: +5:39 - StorageDead(_5); // scope 3 at $DIR/issue-75439.rs:+5:38: +5:39 - StorageDead(_4); // scope 1 at $DIR/issue-75439.rs:+6:5: +6:6 - goto -> bb9; // scope 1 at $DIR/issue-75439.rs:+4:5: +8:6 + StorageDead(_6); // scope 4 at $DIR/issue_75439.rs:+5:35: +5:36 + Deinit(_0); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39 + ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39 + discriminant(_0) = 1; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39 + StorageDead(_5); // scope 3 at $DIR/issue_75439.rs:+5:38: +5:39 + StorageDead(_4); // scope 1 at $DIR/issue_75439.rs:+6:5: +6:6 + goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6 } bb8: { - Deinit(_0); // scope 1 at $DIR/issue-75439.rs:+7:9: +7:13 - discriminant(_0) = 0; // scope 1 at $DIR/issue-75439.rs:+7:9: +7:13 - goto -> bb9; // scope 1 at $DIR/issue-75439.rs:+4:5: +8:6 + Deinit(_0); // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13 + discriminant(_0) = 0; // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13 + goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6 } bb9: { - StorageDead(_2); // scope 0 at $DIR/issue-75439.rs:+9:1: +9:2 - return; // scope 0 at $DIR/issue-75439.rs:+9:2: +9:2 + StorageDead(_2); // scope 0 at $DIR/issue_75439.rs:+9:1: +9:2 + return; // scope 0 at $DIR/issue_75439.rs:+9:2: +9:2 } } diff --git a/src/test/mir-opt/issues/issue-75439.rs b/src/test/mir-opt/issues/issue_75439.rs index ae2e036312e..ae2e036312e 100644 --- a/src/test/mir-opt/issues/issue-75439.rs +++ b/src/test/mir-opt/issues/issue_75439.rs diff --git a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 25ab0c9f7f4..d3db3b18271 100644 --- a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -2,271 +2,271 @@ + // MIR for `complicated_match` after ElaborateDrops fn complicated_match(_1: bool, _2: (bool, bool, String)) -> i32 { - debug cond => _1; // in scope 0 at $DIR/match-arm-scopes.rs:+0:22: +0:26 - debug items => _2; // in scope 0 at $DIR/match-arm-scopes.rs:+0:34: +0:39 - let mut _0: i32; // return place in scope 0 at $DIR/match-arm-scopes.rs:+0:66: +0:69 - let mut _3: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:+1:11: +1:16 - let mut _4: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:+1:11: +1:16 - let _5: bool; // in scope 0 at $DIR/match-arm-scopes.rs:+2:17: +2:18 - let _6: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:+2:17: +2:18 - let _7: std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:+2:20: +2:21 - let _8: &std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:+2:20: +2:21 - let mut _9: bool; // in scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 - let mut _10: bool; // in scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 - let mut _11: !; // in scope 0 at $DIR/match-arm-scopes.rs:+2:52: +2:60 - let mut _12: bool; // in scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 - let mut _13: bool; // in scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 - let mut _14: !; // in scope 0 at $DIR/match-arm-scopes.rs:+2:52: +2:60 - let _15: bool; // in scope 0 at $DIR/match-arm-scopes.rs:+3:16: +3:17 - let _16: std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:+3:19: +3:20 + debug cond => _1; // in scope 0 at $DIR/match_arm_scopes.rs:+0:22: +0:26 + debug items => _2; // in scope 0 at $DIR/match_arm_scopes.rs:+0:34: +0:39 + let mut _0: i32; // return place in scope 0 at $DIR/match_arm_scopes.rs:+0:66: +0:69 + let mut _3: &bool; // in scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16 + let mut _4: &bool; // in scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16 + let _5: bool; // in scope 0 at $DIR/match_arm_scopes.rs:+2:17: +2:18 + let _6: &bool; // in scope 0 at $DIR/match_arm_scopes.rs:+2:17: +2:18 + let _7: std::string::String; // in scope 0 at $DIR/match_arm_scopes.rs:+2:20: +2:21 + let _8: &std::string::String; // in scope 0 at $DIR/match_arm_scopes.rs:+2:20: +2:21 + let mut _9: bool; // in scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 + let mut _10: bool; // in scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 + let mut _11: !; // in scope 0 at $DIR/match_arm_scopes.rs:+2:52: +2:60 + let mut _12: bool; // in scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 + let mut _13: bool; // in scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 + let mut _14: !; // in scope 0 at $DIR/match_arm_scopes.rs:+2:52: +2:60 + let _15: bool; // in scope 0 at $DIR/match_arm_scopes.rs:+3:16: +3:17 + let _16: std::string::String; // in scope 0 at $DIR/match_arm_scopes.rs:+3:19: +3:20 scope 1 { - debug a => _5; // in scope 1 at $DIR/match-arm-scopes.rs:+2:17: +2:18 - debug a => _6; // in scope 1 at $DIR/match-arm-scopes.rs:+2:17: +2:18 - debug s => _7; // in scope 1 at $DIR/match-arm-scopes.rs:+2:20: +2:21 - debug s => _8; // in scope 1 at $DIR/match-arm-scopes.rs:+2:20: +2:21 + debug a => _5; // in scope 1 at $DIR/match_arm_scopes.rs:+2:17: +2:18 + debug a => _6; // in scope 1 at $DIR/match_arm_scopes.rs:+2:17: +2:18 + debug s => _7; // in scope 1 at $DIR/match_arm_scopes.rs:+2:20: +2:21 + debug s => _8; // in scope 1 at $DIR/match_arm_scopes.rs:+2:20: +2:21 } scope 2 { - debug b => _15; // in scope 2 at $DIR/match-arm-scopes.rs:+3:16: +3:17 - debug t => _16; // in scope 2 at $DIR/match-arm-scopes.rs:+3:19: +3:20 + debug b => _15; // in scope 2 at $DIR/match_arm_scopes.rs:+3:16: +3:17 + debug t => _16; // in scope 2 at $DIR/match_arm_scopes.rs:+3:19: +3:20 } bb0: { -- FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match-arm-scopes.rs:+1:11: +1:16 -- switchInt((_2.0: bool)) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +1:16 -+ switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +1:16 +- FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16 +- switchInt((_2.0: bool)) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16 ++ switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16 } bb1: { -- falseEdge -> [real: bb8, imaginary: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:+2:9: +2:22 -+ switchInt((_2.1: bool)) -> [false: bb10, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +1:16 +- falseEdge -> [real: bb8, imaginary: bb3]; // scope 0 at $DIR/match_arm_scopes.rs:+2:9: +2:22 ++ switchInt((_2.1: bool)) -> [false: bb10, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16 } bb2: { -- switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +1:16 -+ switchInt((_2.0: bool)) -> [false: bb3, otherwise: bb17]; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +1:16 +- switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16 ++ switchInt((_2.0: bool)) -> [false: bb3, otherwise: bb17]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16 } bb3: { -- falseEdge -> [real: bb13, imaginary: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:+2:25: +2:38 +- falseEdge -> [real: bb13, imaginary: bb5]; // scope 0 at $DIR/match_arm_scopes.rs:+2:25: +2:38 - } - - bb4: { -- switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +1:16 +- switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16 - } - - bb5: { -- falseEdge -> [real: bb20, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:+3:9: +3:21 +- falseEdge -> [real: bb20, imaginary: bb6]; // scope 0 at $DIR/match_arm_scopes.rs:+3:9: +3:21 - } - - bb6: { - StorageLive(_15); // scope 0 at $DIR/match-arm-scopes.rs:+3:32: +3:33 - _15 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:+3:32: +3:33 - StorageLive(_16); // scope 0 at $DIR/match-arm-scopes.rs:+3:35: +3:36 - _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:+3:35: +3:36 -- goto -> bb19; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +4:6 -+ goto -> bb16; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +4:6 + StorageLive(_15); // scope 0 at $DIR/match_arm_scopes.rs:+3:32: +3:33 + _15 = (_2.1: bool); // scope 0 at $DIR/match_arm_scopes.rs:+3:32: +3:33 + StorageLive(_16); // scope 0 at $DIR/match_arm_scopes.rs:+3:35: +3:36 + _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match_arm_scopes.rs:+3:35: +3:36 +- goto -> bb19; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +4:6 ++ goto -> bb16; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +4:6 } - bb7: { + bb4: { - _0 = const 1_i32; // scope 1 at $DIR/match-arm-scopes.rs:+2:77: +2:78 -- drop(_7) -> [return: bb18, unwind: bb25]; // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 -+ drop(_7) -> [return: bb15, unwind: bb22]; // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 + _0 = const 1_i32; // scope 1 at $DIR/match_arm_scopes.rs:+2:77: +2:78 +- drop(_7) -> [return: bb18, unwind: bb25]; // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 ++ drop(_7) -> [return: bb15, unwind: bb22]; // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 } - bb8: { + bb5: { - StorageLive(_6); // scope 0 at $DIR/match-arm-scopes.rs:+2:17: +2:18 - _6 = &(_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:+2:17: +2:18 - StorageLive(_8); // scope 0 at $DIR/match-arm-scopes.rs:+2:20: +2:21 - _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:+2:20: +2:21 -- _3 = &shallow (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:+1:11: +1:16 -- _4 = &shallow (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:+1:11: +1:16 - StorageLive(_9); // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 - StorageLive(_10); // scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 - _10 = _1; // scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 -- switchInt(move _10) -> [false: bb10, otherwise: bb9]; // scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 -+ switchInt(move _10) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 + StorageLive(_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:17: +2:18 + _6 = &(_2.1: bool); // scope 0 at $DIR/match_arm_scopes.rs:+2:17: +2:18 + StorageLive(_8); // scope 0 at $DIR/match_arm_scopes.rs:+2:20: +2:21 + _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match_arm_scopes.rs:+2:20: +2:21 +- _3 = &shallow (_2.0: bool); // scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16 +- _4 = &shallow (_2.1: bool); // scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16 + StorageLive(_9); // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 + StorageLive(_10); // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 + _10 = _1; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 +- switchInt(move _10) -> [false: bb10, otherwise: bb9]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 ++ switchInt(move _10) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 } - bb9: { + bb6: { - _0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:+2:59: +2:60 - StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 + _0 = const 3_i32; // scope 0 at $DIR/match_arm_scopes.rs:+2:59: +2:60 + StorageDead(_10); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageDead(_9); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 - goto -> bb23; // scope 0 at no-location + goto -> bb20; // scope 0 at no-location } - bb10: { + bb7: { - _9 = (*_6); // scope 0 at $DIR/match-arm-scopes.rs:+2:70: +2:71 -- switchInt(move _9) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 -+ switchInt(move _9) -> [false: bb9, otherwise: bb8]; // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 + _9 = (*_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:70: +2:71 +- switchInt(move _9) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 ++ switchInt(move _9) -> [false: bb9, otherwise: bb8]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 } - bb11: { + bb8: { - StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 -- FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 -- FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 -- FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 -- FakeRead(ForGuardBinding, _8); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageLive(_5); // scope 0 at $DIR/match-arm-scopes.rs:+2:17: +2:18 - _5 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:+2:17: +2:18 - StorageLive(_7); // scope 0 at $DIR/match-arm-scopes.rs:+2:20: +2:21 - _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:+2:20: +2:21 -- goto -> bb7; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +4:6 -+ goto -> bb4; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +4:6 + StorageDead(_10); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageDead(_9); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 +- FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 +- FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 +- FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 +- FakeRead(ForGuardBinding, _8); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageLive(_5); // scope 0 at $DIR/match_arm_scopes.rs:+2:17: +2:18 + _5 = (_2.1: bool); // scope 0 at $DIR/match_arm_scopes.rs:+2:17: +2:18 + StorageLive(_7); // scope 0 at $DIR/match_arm_scopes.rs:+2:20: +2:21 + _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match_arm_scopes.rs:+2:20: +2:21 +- goto -> bb7; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +4:6 ++ goto -> bb4; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +4:6 } - bb12: { + bb9: { - StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 -- falseEdge -> [real: bb2, imaginary: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 -+ goto -> bb1; // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 + StorageDead(_10); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageDead(_9); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageDead(_8); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 + StorageDead(_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 +- falseEdge -> [real: bb2, imaginary: bb3]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 ++ goto -> bb1; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 } - bb13: { + bb10: { - StorageLive(_6); // scope 0 at $DIR/match-arm-scopes.rs:+2:26: +2:27 - _6 = &(_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:+2:26: +2:27 - StorageLive(_8); // scope 0 at $DIR/match-arm-scopes.rs:+2:36: +2:37 - _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:+2:36: +2:37 -- _3 = &shallow (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:+1:11: +1:16 -- _4 = &shallow (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:+1:11: +1:16 - StorageLive(_12); // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 - StorageLive(_13); // scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 - _13 = _1; // scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 -- switchInt(move _13) -> [false: bb15, otherwise: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 -+ switchInt(move _13) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:+2:45: +2:49 + StorageLive(_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:26: +2:27 + _6 = &(_2.0: bool); // scope 0 at $DIR/match_arm_scopes.rs:+2:26: +2:27 + StorageLive(_8); // scope 0 at $DIR/match_arm_scopes.rs:+2:36: +2:37 + _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match_arm_scopes.rs:+2:36: +2:37 +- _3 = &shallow (_2.0: bool); // scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16 +- _4 = &shallow (_2.1: bool); // scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16 + StorageLive(_12); // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 + StorageLive(_13); // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 + _13 = _1; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 +- switchInt(move _13) -> [false: bb15, otherwise: bb14]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 ++ switchInt(move _13) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49 } - bb14: { + bb11: { - _0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:+2:59: +2:60 - StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 + _0 = const 3_i32; // scope 0 at $DIR/match_arm_scopes.rs:+2:59: +2:60 + StorageDead(_13); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageDead(_12); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 - goto -> bb23; // scope 0 at no-location + goto -> bb20; // scope 0 at no-location } - bb15: { + bb12: { - _12 = (*_6); // scope 0 at $DIR/match-arm-scopes.rs:+2:70: +2:71 -- switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 -+ switchInt(move _12) -> [false: bb14, otherwise: bb13]; // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 + _12 = (*_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:70: +2:71 +- switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 ++ switchInt(move _12) -> [false: bb14, otherwise: bb13]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 } - bb16: { + bb13: { - StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 -- FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 -- FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 -- FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 -- FakeRead(ForGuardBinding, _8); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageLive(_5); // scope 0 at $DIR/match-arm-scopes.rs:+2:26: +2:27 - _5 = (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:+2:26: +2:27 - StorageLive(_7); // scope 0 at $DIR/match-arm-scopes.rs:+2:36: +2:37 - _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:+2:36: +2:37 -- goto -> bb7; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +4:6 -+ goto -> bb4; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +4:6 + StorageDead(_13); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageDead(_12); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 +- FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 +- FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 +- FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 +- FakeRead(ForGuardBinding, _8); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageLive(_5); // scope 0 at $DIR/match_arm_scopes.rs:+2:26: +2:27 + _5 = (_2.0: bool); // scope 0 at $DIR/match_arm_scopes.rs:+2:26: +2:27 + StorageLive(_7); // scope 0 at $DIR/match_arm_scopes.rs:+2:36: +2:37 + _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match_arm_scopes.rs:+2:36: +2:37 +- goto -> bb7; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +4:6 ++ goto -> bb4; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +4:6 } - bb17: { + bb14: { - StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:+2:72: +2:73 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 -- falseEdge -> [real: bb4, imaginary: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 -+ goto -> bb2; // scope 0 at $DIR/match-arm-scopes.rs:+2:42: +2:73 + StorageDead(_13); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageDead(_12); // scope 0 at $DIR/match_arm_scopes.rs:+2:72: +2:73 + StorageDead(_8); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 + StorageDead(_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 +- falseEdge -> [real: bb4, imaginary: bb5]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 ++ goto -> bb2; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73 } - bb18: { + bb15: { - StorageDead(_7); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 - StorageDead(_5); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 -- goto -> bb22; // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 -+ goto -> bb19; // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 + StorageDead(_7); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 + StorageDead(_5); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 + StorageDead(_8); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 + StorageDead(_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 +- goto -> bb22; // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 ++ goto -> bb19; // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 } - bb19: { + bb16: { - _0 = const 2_i32; // scope 2 at $DIR/match-arm-scopes.rs:+3:41: +3:42 -- drop(_16) -> [return: bb21, unwind: bb25]; // scope 0 at $DIR/match-arm-scopes.rs:+3:41: +3:42 -+ drop(_16) -> [return: bb18, unwind: bb22]; // scope 0 at $DIR/match-arm-scopes.rs:+3:41: +3:42 + _0 = const 2_i32; // scope 2 at $DIR/match_arm_scopes.rs:+3:41: +3:42 +- drop(_16) -> [return: bb21, unwind: bb25]; // scope 0 at $DIR/match_arm_scopes.rs:+3:41: +3:42 ++ drop(_16) -> [return: bb18, unwind: bb22]; // scope 0 at $DIR/match_arm_scopes.rs:+3:41: +3:42 } - bb20: { + bb17: { - StorageLive(_15); // scope 0 at $DIR/match-arm-scopes.rs:+3:16: +3:17 - _15 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:+3:16: +3:17 - StorageLive(_16); // scope 0 at $DIR/match-arm-scopes.rs:+3:19: +3:20 - _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:+3:19: +3:20 -- goto -> bb19; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +4:6 -+ goto -> bb16; // scope 0 at $DIR/match-arm-scopes.rs:+1:5: +4:6 + StorageLive(_15); // scope 0 at $DIR/match_arm_scopes.rs:+3:16: +3:17 + _15 = (_2.1: bool); // scope 0 at $DIR/match_arm_scopes.rs:+3:16: +3:17 + StorageLive(_16); // scope 0 at $DIR/match_arm_scopes.rs:+3:19: +3:20 + _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match_arm_scopes.rs:+3:19: +3:20 +- goto -> bb19; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +4:6 ++ goto -> bb16; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +4:6 } - bb21: { + bb18: { - StorageDead(_16); // scope 0 at $DIR/match-arm-scopes.rs:+3:41: +3:42 - StorageDead(_15); // scope 0 at $DIR/match-arm-scopes.rs:+3:41: +3:42 -- goto -> bb22; // scope 0 at $DIR/match-arm-scopes.rs:+3:41: +3:42 -+ goto -> bb19; // scope 0 at $DIR/match-arm-scopes.rs:+3:41: +3:42 + StorageDead(_16); // scope 0 at $DIR/match_arm_scopes.rs:+3:41: +3:42 + StorageDead(_15); // scope 0 at $DIR/match_arm_scopes.rs:+3:41: +3:42 +- goto -> bb22; // scope 0 at $DIR/match_arm_scopes.rs:+3:41: +3:42 ++ goto -> bb19; // scope 0 at $DIR/match_arm_scopes.rs:+3:41: +3:42 } - bb22: { -- drop(_2) -> [return: bb24, unwind: bb26]; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 +- drop(_2) -> [return: bb24, unwind: bb26]; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 + bb19: { -+ goto -> bb26; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 ++ goto -> bb26; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 } - bb23: { + bb20: { - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:+2:77: +2:78 -- drop(_2) -> [return: bb24, unwind: bb26]; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 -+ drop(_2) -> [return: bb21, unwind: bb23]; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 + StorageDead(_8); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 + StorageDead(_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:77: +2:78 +- drop(_2) -> [return: bb24, unwind: bb26]; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 ++ drop(_2) -> [return: bb21, unwind: bb23]; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 } - bb24: { + bb21: { - return; // scope 0 at $DIR/match-arm-scopes.rs:+5:2: +5:2 + return; // scope 0 at $DIR/match_arm_scopes.rs:+5:2: +5:2 } - bb25 (cleanup): { -- drop(_2) -> bb26; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 +- drop(_2) -> bb26; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 + bb22 (cleanup): { -+ goto -> bb27; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 ++ goto -> bb27; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 } - bb26 (cleanup): { + bb23 (cleanup): { - resume; // scope 0 at $DIR/match-arm-scopes.rs:+0:1: +5:2 + resume; // scope 0 at $DIR/match_arm_scopes.rs:+0:1: +5:2 + } + + bb24: { -+ goto -> bb21; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 ++ goto -> bb21; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 + } + + bb25 (cleanup): { -+ goto -> bb23; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 ++ goto -> bb23; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 + } + + bb26: { -+ goto -> bb24; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 ++ goto -> bb24; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 + } + + bb27 (cleanup): { -+ goto -> bb23; // scope 0 at $DIR/match-arm-scopes.rs:+5:1: +5:2 ++ goto -> bb23; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 } } diff --git a/src/test/mir-opt/match-arm-scopes.rs b/src/test/mir-opt/match_arm_scopes.rs index 7b7de7788c2..7b7de7788c2 100644 --- a/src/test/mir-opt/match-arm-scopes.rs +++ b/src/test/mir-opt/match_arm_scopes.rs diff --git a/src/test/mir-opt/nll/named-lifetimes-basic.rs b/src/test/mir-opt/nll/named_lifetimes_basic.rs index 843716033ca..843716033ca 100644 --- a/src/test/mir-opt/nll/named-lifetimes-basic.rs +++ b/src/test/mir-opt/nll/named_lifetimes_basic.rs diff --git a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir index 0ab9d712d9f..6cd6d8b7795 100644 --- a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir +++ b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir @@ -24,24 +24,24 @@ | '_#2r live at {bb0[0..=1]} | '_#3r live at {bb0[0..=1]} | '_#4r live at {bb0[0..=1]} -| '_#1r: '_#5r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0) -| '_#1r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0) -| '_#2r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0) -| '_#3r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0) -| '_#5r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0) -| '_#6r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0) -| '_#7r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0) -| '_#8r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0) +| '_#1r: '_#5r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:26: 12:27) ($DIR/named_lifetimes_basic.rs:12:26: 12:27 (#0) +| '_#1r: '_#7r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:54: 12:55) ($DIR/named_lifetimes_basic.rs:12:54: 12:55 (#0) +| '_#2r: '_#6r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:42: 12:43) ($DIR/named_lifetimes_basic.rs:12:42: 12:43 (#0) +| '_#3r: '_#8r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:66: 12:67) ($DIR/named_lifetimes_basic.rs:12:66: 12:67 (#0) +| '_#5r: '_#1r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:26: 12:27) ($DIR/named_lifetimes_basic.rs:12:26: 12:27 (#0) +| '_#6r: '_#2r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:42: 12:43) ($DIR/named_lifetimes_basic.rs:12:42: 12:43 (#0) +| '_#7r: '_#1r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:54: 12:55) ($DIR/named_lifetimes_basic.rs:12:54: 12:55 (#0) +| '_#8r: '_#3r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:66: 12:67) ($DIR/named_lifetimes_basic.rs:12:66: 12:67 (#0) | fn use_x(_1: &'_#5r mut i32, _2: &'_#6r u32, _3: &'_#7r u32, _4: &'_#8r u32) -> bool { - debug w => _1; // in scope 0 at $DIR/named-lifetimes-basic.rs:+0:26: +0:27 - debug x => _2; // in scope 0 at $DIR/named-lifetimes-basic.rs:+0:42: +0:43 - debug y => _3; // in scope 0 at $DIR/named-lifetimes-basic.rs:+0:54: +0:55 - debug z => _4; // in scope 0 at $DIR/named-lifetimes-basic.rs:+0:66: +0:67 - let mut _0: bool; // return place in scope 0 at $DIR/named-lifetimes-basic.rs:+0:81: +0:85 + debug w => _1; // in scope 0 at $DIR/named_lifetimes_basic.rs:+0:26: +0:27 + debug x => _2; // in scope 0 at $DIR/named_lifetimes_basic.rs:+0:42: +0:43 + debug y => _3; // in scope 0 at $DIR/named_lifetimes_basic.rs:+0:54: +0:55 + debug z => _4; // in scope 0 at $DIR/named_lifetimes_basic.rs:+0:66: +0:67 + let mut _0: bool; // return place in scope 0 at $DIR/named_lifetimes_basic.rs:+0:81: +0:85 bb0: { - _0 = const ConstValue(Scalar(0x01): bool); // bb0[0]: scope 0 at $DIR/named-lifetimes-basic.rs:+0:88: +0:92 - return; // bb0[1]: scope 0 at $DIR/named-lifetimes-basic.rs:+0:94: +0:94 + _0 = const ConstValue(Scalar(0x01): bool); // bb0[0]: scope 0 at $DIR/named_lifetimes_basic.rs:+0:88: +0:92 + return; // bb0[1]: scope 0 at $DIR/named_lifetimes_basic.rs:+0:94: +0:94 } } diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index 36705d18e01..3e3fda6141a 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -17,95 +17,95 @@ | '_#2r live at {bb1[0]} | '_#3r live at {bb1[1..=3]} | '_#4r live at {bb1[4..=7], bb2[0..=2]} -| '_#2r: '_#3r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0) -| '_#3r: '_#4r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0) +| '_#2r: '_#3r due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:18:13: 18:18 (#0) +| '_#3r: '_#4r due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:19:13: 19:14 (#0) | fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:+0:11: +0:11 - let mut _1: [usize; Const { ty: usize, kind: Value(Leaf(0x00000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:+1:9: +1:14 - let _3: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:+2:16: +2:17 - let mut _4: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 - let mut _5: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 - let mut _7: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:+4:8: +4:12 - let _8: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:+5:9: +5:18 - let mut _9: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:+5:15: +5:17 - let _10: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:+7:9: +7:18 + let mut _0: (); // return place in scope 0 at $DIR/region_subtyping_basic.rs:+0:11: +0:11 + let mut _1: [usize; Const { ty: usize, kind: Value(Leaf(0x00000003)) }]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 + let _3: usize; // in scope 0 at $DIR/region_subtyping_basic.rs:+2:16: +2:17 + let mut _4: usize; // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 + let mut _5: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 + let mut _7: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+4:8: +4:12 + let _8: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+5:9: +5:18 + let mut _9: usize; // in scope 0 at $DIR/region_subtyping_basic.rs:+5:15: +5:17 + let _10: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+7:9: +7:18 scope 1 { - debug v => _1; // in scope 1 at $DIR/region-subtyping-basic.rs:+1:9: +1:14 - let _2: &'_#3r usize; // in scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10 + debug v => _1; // in scope 1 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 + let _2: &'_#3r usize; // in scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 scope 2 { - debug p => _2; // in scope 2 at $DIR/region-subtyping-basic.rs:+2:9: +2:10 - let _6: &'_#4r usize; // in scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10 + debug p => _2; // in scope 2 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 + let _6: &'_#4r usize; // in scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 scope 3 { - debug q => _6; // in scope 3 at $DIR/region-subtyping-basic.rs:+3:9: +3:10 + debug q => _6; // in scope 3 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 } } } bb0: { - StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:+1:9: +1:14 - _1 = [const ConstValue(Scalar(0x00000001): usize), const ConstValue(Scalar(0x00000002): usize), const ConstValue(Scalar(0x00000003): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:+1:17: +1:26 - FakeRead(ForLet(None), _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:+1:9: +1:14 - StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10 - StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:+2:16: +2:17 - _3 = const ConstValue(Scalar(0x00000000): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:+2:16: +2:17 - _4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 - _5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 + StorageLive(_1); // bb0[0]: scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 + _1 = [const ConstValue(Scalar(0x00000001): usize), const ConstValue(Scalar(0x00000002): usize), const ConstValue(Scalar(0x00000003): usize)]; // bb0[1]: scope 0 at $DIR/region_subtyping_basic.rs:+1:17: +1:26 + FakeRead(ForLet(None), _1); // bb0[2]: scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 + StorageLive(_2); // bb0[3]: scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 + StorageLive(_3); // bb0[4]: scope 1 at $DIR/region_subtyping_basic.rs:+2:16: +2:17 + _3 = const ConstValue(Scalar(0x00000000): usize); // bb0[5]: scope 1 at $DIR/region_subtyping_basic.rs:+2:16: +2:17 + _4 = Len(_1); // bb0[6]: scope 1 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 + _5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; // bb0[8]: scope 1 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 } bb1: { - _2 = &'_#2r _1[_3]; // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:+2:13: +2:18 - FakeRead(ForLet(None), _2); // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10 - StorageLive(_6); // bb1[2]: scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10 - _6 = _2; // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:+3:13: +3:14 - FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10 - StorageLive(_7); // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:+4:8: +4:12 - _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:+4:8: +4:12 - switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:+4:8: +4:12 + _2 = &'_#2r _1[_3]; // bb1[0]: scope 1 at $DIR/region_subtyping_basic.rs:+2:13: +2:18 + FakeRead(ForLet(None), _2); // bb1[1]: scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 + StorageLive(_6); // bb1[2]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 + _6 = _2; // bb1[3]: scope 2 at $DIR/region_subtyping_basic.rs:+3:13: +3:14 + FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 + StorageLive(_7); // bb1[5]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12 + _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12 + switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12 } bb2: { - StorageLive(_8); // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:+5:9: +5:18 - StorageLive(_9); // bb2[1]: scope 3 at $DIR/region-subtyping-basic.rs:+5:15: +5:17 - _9 = (*_6); // bb2[2]: scope 3 at $DIR/region-subtyping-basic.rs:+5:15: +5:17 - _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:+5:9: +5:18 + StorageLive(_8); // bb2[0]: scope 3 at $DIR/region_subtyping_basic.rs:+5:9: +5:18 + StorageLive(_9); // bb2[1]: scope 3 at $DIR/region_subtyping_basic.rs:+5:15: +5:17 + _9 = (*_6); // bb2[2]: scope 3 at $DIR/region_subtyping_basic.rs:+5:15: +5:17 + _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region_subtyping_basic.rs:+5:9: +5:18 // mir::Constant - // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14 + // + span: $DIR/region_subtyping_basic.rs:21:9: 21:14 // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(<ZST>) } } bb3: { - StorageDead(_9); // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:+5:17: +5:18 - StorageDead(_8); // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:+5:18: +5:19 - _0 = const ConstValue(ZeroSized: ()); // bb3[2]: scope 3 at $DIR/region-subtyping-basic.rs:+4:13: +6:6 - goto -> bb6; // bb3[3]: scope 3 at $DIR/region-subtyping-basic.rs:+4:5: +8:6 + StorageDead(_9); // bb3[0]: scope 3 at $DIR/region_subtyping_basic.rs:+5:17: +5:18 + StorageDead(_8); // bb3[1]: scope 3 at $DIR/region_subtyping_basic.rs:+5:18: +5:19 + _0 = const ConstValue(ZeroSized: ()); // bb3[2]: scope 3 at $DIR/region_subtyping_basic.rs:+4:13: +6:6 + goto -> bb6; // bb3[3]: scope 3 at $DIR/region_subtyping_basic.rs:+4:5: +8:6 } bb4: { - StorageLive(_10); // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:+7:9: +7:18 - _10 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x00000016): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:+7:9: +7:18 + StorageLive(_10); // bb4[0]: scope 3 at $DIR/region_subtyping_basic.rs:+7:9: +7:18 + _10 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x00000016): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region_subtyping_basic.rs:+7:9: +7:18 // mir::Constant - // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14 + // + span: $DIR/region_subtyping_basic.rs:23:9: 23:14 // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(<ZST>) } } bb5: { - StorageDead(_10); // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:+7:18: +7:19 - _0 = const ConstValue(ZeroSized: ()); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:+6:12: +8:6 - goto -> bb6; // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:+4:5: +8:6 + StorageDead(_10); // bb5[0]: scope 3 at $DIR/region_subtyping_basic.rs:+7:18: +7:19 + _0 = const ConstValue(ZeroSized: ()); // bb5[1]: scope 3 at $DIR/region_subtyping_basic.rs:+6:12: +8:6 + goto -> bb6; // bb5[2]: scope 3 at $DIR/region_subtyping_basic.rs:+4:5: +8:6 } bb6: { - StorageDead(_7); // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:+8:5: +8:6 - StorageDead(_6); // bb6[1]: scope 2 at $DIR/region-subtyping-basic.rs:+9:1: +9:2 - StorageDead(_3); // bb6[2]: scope 1 at $DIR/region-subtyping-basic.rs:+9:1: +9:2 - StorageDead(_2); // bb6[3]: scope 1 at $DIR/region-subtyping-basic.rs:+9:1: +9:2 - StorageDead(_1); // bb6[4]: scope 0 at $DIR/region-subtyping-basic.rs:+9:1: +9:2 - return; // bb6[5]: scope 0 at $DIR/region-subtyping-basic.rs:+9:2: +9:2 + StorageDead(_7); // bb6[0]: scope 3 at $DIR/region_subtyping_basic.rs:+8:5: +8:6 + StorageDead(_6); // bb6[1]: scope 2 at $DIR/region_subtyping_basic.rs:+9:1: +9:2 + StorageDead(_3); // bb6[2]: scope 1 at $DIR/region_subtyping_basic.rs:+9:1: +9:2 + StorageDead(_2); // bb6[3]: scope 1 at $DIR/region_subtyping_basic.rs:+9:1: +9:2 + StorageDead(_1); // bb6[4]: scope 0 at $DIR/region_subtyping_basic.rs:+9:1: +9:2 + return; // bb6[5]: scope 0 at $DIR/region_subtyping_basic.rs:+9:2: +9:2 } bb7 (cleanup): { - resume; // bb7[0]: scope 0 at $DIR/region-subtyping-basic.rs:+0:1: +9:2 + resume; // bb7[0]: scope 0 at $DIR/region_subtyping_basic.rs:+0:1: +9:2 } } diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index 4f6256a67f4..39a53702a4c 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -17,95 +17,95 @@ | '_#2r live at {bb1[0]} | '_#3r live at {bb1[1..=3]} | '_#4r live at {bb1[4..=7], bb2[0..=2]} -| '_#2r: '_#3r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0) -| '_#3r: '_#4r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0) +| '_#2r: '_#3r due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:18:13: 18:18 (#0) +| '_#3r: '_#4r due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:19:13: 19:14 (#0) | fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:+0:11: +0:11 - let mut _1: [usize; Const { ty: usize, kind: Value(Leaf(0x0000000000000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:+1:9: +1:14 - let _3: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:+2:16: +2:17 - let mut _4: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 - let mut _5: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 - let mut _7: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:+4:8: +4:12 - let _8: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:+5:9: +5:18 - let mut _9: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:+5:15: +5:17 - let _10: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:+7:9: +7:18 + let mut _0: (); // return place in scope 0 at $DIR/region_subtyping_basic.rs:+0:11: +0:11 + let mut _1: [usize; Const { ty: usize, kind: Value(Leaf(0x0000000000000003)) }]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 + let _3: usize; // in scope 0 at $DIR/region_subtyping_basic.rs:+2:16: +2:17 + let mut _4: usize; // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 + let mut _5: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 + let mut _7: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+4:8: +4:12 + let _8: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+5:9: +5:18 + let mut _9: usize; // in scope 0 at $DIR/region_subtyping_basic.rs:+5:15: +5:17 + let _10: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+7:9: +7:18 scope 1 { - debug v => _1; // in scope 1 at $DIR/region-subtyping-basic.rs:+1:9: +1:14 - let _2: &'_#3r usize; // in scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10 + debug v => _1; // in scope 1 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 + let _2: &'_#3r usize; // in scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 scope 2 { - debug p => _2; // in scope 2 at $DIR/region-subtyping-basic.rs:+2:9: +2:10 - let _6: &'_#4r usize; // in scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10 + debug p => _2; // in scope 2 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 + let _6: &'_#4r usize; // in scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 scope 3 { - debug q => _6; // in scope 3 at $DIR/region-subtyping-basic.rs:+3:9: +3:10 + debug q => _6; // in scope 3 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 } } } bb0: { - StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:+1:9: +1:14 - _1 = [const ConstValue(Scalar(0x0000000000000001): usize), const ConstValue(Scalar(0x0000000000000002): usize), const ConstValue(Scalar(0x0000000000000003): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:+1:17: +1:26 - FakeRead(ForLet(None), _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:+1:9: +1:14 - StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10 - StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:+2:16: +2:17 - _3 = const ConstValue(Scalar(0x0000000000000000): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:+2:16: +2:17 - _4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 - _5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:+2:14: +2:18 + StorageLive(_1); // bb0[0]: scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 + _1 = [const ConstValue(Scalar(0x0000000000000001): usize), const ConstValue(Scalar(0x0000000000000002): usize), const ConstValue(Scalar(0x0000000000000003): usize)]; // bb0[1]: scope 0 at $DIR/region_subtyping_basic.rs:+1:17: +1:26 + FakeRead(ForLet(None), _1); // bb0[2]: scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 + StorageLive(_2); // bb0[3]: scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 + StorageLive(_3); // bb0[4]: scope 1 at $DIR/region_subtyping_basic.rs:+2:16: +2:17 + _3 = const ConstValue(Scalar(0x0000000000000000): usize); // bb0[5]: scope 1 at $DIR/region_subtyping_basic.rs:+2:16: +2:17 + _4 = Len(_1); // bb0[6]: scope 1 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 + _5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; // bb0[8]: scope 1 at $DIR/region_subtyping_basic.rs:+2:14: +2:18 } bb1: { - _2 = &'_#2r _1[_3]; // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:+2:13: +2:18 - FakeRead(ForLet(None), _2); // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10 - StorageLive(_6); // bb1[2]: scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10 - _6 = _2; // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:+3:13: +3:14 - FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10 - StorageLive(_7); // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:+4:8: +4:12 - _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:+4:8: +4:12 - switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:+4:8: +4:12 + _2 = &'_#2r _1[_3]; // bb1[0]: scope 1 at $DIR/region_subtyping_basic.rs:+2:13: +2:18 + FakeRead(ForLet(None), _2); // bb1[1]: scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 + StorageLive(_6); // bb1[2]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 + _6 = _2; // bb1[3]: scope 2 at $DIR/region_subtyping_basic.rs:+3:13: +3:14 + FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 + StorageLive(_7); // bb1[5]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12 + _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12 + switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12 } bb2: { - StorageLive(_8); // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:+5:9: +5:18 - StorageLive(_9); // bb2[1]: scope 3 at $DIR/region-subtyping-basic.rs:+5:15: +5:17 - _9 = (*_6); // bb2[2]: scope 3 at $DIR/region-subtyping-basic.rs:+5:15: +5:17 - _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:+5:9: +5:18 + StorageLive(_8); // bb2[0]: scope 3 at $DIR/region_subtyping_basic.rs:+5:9: +5:18 + StorageLive(_9); // bb2[1]: scope 3 at $DIR/region_subtyping_basic.rs:+5:15: +5:17 + _9 = (*_6); // bb2[2]: scope 3 at $DIR/region_subtyping_basic.rs:+5:15: +5:17 + _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region_subtyping_basic.rs:+5:9: +5:18 // mir::Constant - // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14 + // + span: $DIR/region_subtyping_basic.rs:21:9: 21:14 // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(<ZST>) } } bb3: { - StorageDead(_9); // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:+5:17: +5:18 - StorageDead(_8); // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:+5:18: +5:19 - _0 = const ConstValue(ZeroSized: ()); // bb3[2]: scope 3 at $DIR/region-subtyping-basic.rs:+4:13: +6:6 - goto -> bb6; // bb3[3]: scope 3 at $DIR/region-subtyping-basic.rs:+4:5: +8:6 + StorageDead(_9); // bb3[0]: scope 3 at $DIR/region_subtyping_basic.rs:+5:17: +5:18 + StorageDead(_8); // bb3[1]: scope 3 at $DIR/region_subtyping_basic.rs:+5:18: +5:19 + _0 = const ConstValue(ZeroSized: ()); // bb3[2]: scope 3 at $DIR/region_subtyping_basic.rs:+4:13: +6:6 + goto -> bb6; // bb3[3]: scope 3 at $DIR/region_subtyping_basic.rs:+4:5: +8:6 } bb4: { - StorageLive(_10); // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:+7:9: +7:18 - _10 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x0000000000000016): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:+7:9: +7:18 + StorageLive(_10); // bb4[0]: scope 3 at $DIR/region_subtyping_basic.rs:+7:9: +7:18 + _10 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x0000000000000016): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region_subtyping_basic.rs:+7:9: +7:18 // mir::Constant - // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14 + // + span: $DIR/region_subtyping_basic.rs:23:9: 23:14 // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(<ZST>) } } bb5: { - StorageDead(_10); // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:+7:18: +7:19 - _0 = const ConstValue(ZeroSized: ()); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:+6:12: +8:6 - goto -> bb6; // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:+4:5: +8:6 + StorageDead(_10); // bb5[0]: scope 3 at $DIR/region_subtyping_basic.rs:+7:18: +7:19 + _0 = const ConstValue(ZeroSized: ()); // bb5[1]: scope 3 at $DIR/region_subtyping_basic.rs:+6:12: +8:6 + goto -> bb6; // bb5[2]: scope 3 at $DIR/region_subtyping_basic.rs:+4:5: +8:6 } bb6: { - StorageDead(_7); // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:+8:5: +8:6 - StorageDead(_6); // bb6[1]: scope 2 at $DIR/region-subtyping-basic.rs:+9:1: +9:2 - StorageDead(_3); // bb6[2]: scope 1 at $DIR/region-subtyping-basic.rs:+9:1: +9:2 - StorageDead(_2); // bb6[3]: scope 1 at $DIR/region-subtyping-basic.rs:+9:1: +9:2 - StorageDead(_1); // bb6[4]: scope 0 at $DIR/region-subtyping-basic.rs:+9:1: +9:2 - return; // bb6[5]: scope 0 at $DIR/region-subtyping-basic.rs:+9:2: +9:2 + StorageDead(_7); // bb6[0]: scope 3 at $DIR/region_subtyping_basic.rs:+8:5: +8:6 + StorageDead(_6); // bb6[1]: scope 2 at $DIR/region_subtyping_basic.rs:+9:1: +9:2 + StorageDead(_3); // bb6[2]: scope 1 at $DIR/region_subtyping_basic.rs:+9:1: +9:2 + StorageDead(_2); // bb6[3]: scope 1 at $DIR/region_subtyping_basic.rs:+9:1: +9:2 + StorageDead(_1); // bb6[4]: scope 0 at $DIR/region_subtyping_basic.rs:+9:1: +9:2 + return; // bb6[5]: scope 0 at $DIR/region_subtyping_basic.rs:+9:2: +9:2 } bb7 (cleanup): { - resume; // bb7[0]: scope 0 at $DIR/region-subtyping-basic.rs:+0:1: +9:2 + resume; // bb7[0]: scope 0 at $DIR/region_subtyping_basic.rs:+0:1: +9:2 } } diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region_subtyping_basic.rs index 64332f302e8..64332f302e8 100644 --- a/src/test/mir-opt/nll/region-subtyping-basic.rs +++ b/src/test/mir-opt/nll/region_subtyping_basic.rs diff --git a/src/test/mir-opt/no-drop-for-inactive-variant.rs b/src/test/mir-opt/no_drop_for_inactive_variant.rs index 34e2b1a134f..34e2b1a134f 100644 --- a/src/test/mir-opt/no-drop-for-inactive-variant.rs +++ b/src/test/mir-opt/no_drop_for_inactive_variant.rs diff --git a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir index 50fd98ff13a..e708255cea4 100644 --- a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir @@ -1,21 +1,21 @@ // MIR for `unwrap` after SimplifyCfg-elaborate-drops fn unwrap(_1: Option<T>) -> T { - debug opt => _1; // in scope 0 at $DIR/no-drop-for-inactive-variant.rs:+0:14: +0:17 - let mut _0: T; // return place in scope 0 at $DIR/no-drop-for-inactive-variant.rs:+0:33: +0:34 - let mut _2: isize; // in scope 0 at $DIR/no-drop-for-inactive-variant.rs:+2:9: +2:16 - let _3: T; // in scope 0 at $DIR/no-drop-for-inactive-variant.rs:+2:14: +2:15 + debug opt => _1; // in scope 0 at $DIR/no_drop_for_inactive_variant.rs:+0:14: +0:17 + let mut _0: T; // return place in scope 0 at $DIR/no_drop_for_inactive_variant.rs:+0:33: +0:34 + let mut _2: isize; // in scope 0 at $DIR/no_drop_for_inactive_variant.rs:+2:9: +2:16 + let _3: T; // in scope 0 at $DIR/no_drop_for_inactive_variant.rs:+2:14: +2:15 let mut _4: !; // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL - let mut _5: isize; // in scope 0 at $DIR/no-drop-for-inactive-variant.rs:+5:1: +5:2 - let mut _6: isize; // in scope 0 at $DIR/no-drop-for-inactive-variant.rs:+5:1: +5:2 - let mut _7: isize; // in scope 0 at $DIR/no-drop-for-inactive-variant.rs:+5:1: +5:2 + let mut _5: isize; // in scope 0 at $DIR/no_drop_for_inactive_variant.rs:+5:1: +5:2 + let mut _6: isize; // in scope 0 at $DIR/no_drop_for_inactive_variant.rs:+5:1: +5:2 + let mut _7: isize; // in scope 0 at $DIR/no_drop_for_inactive_variant.rs:+5:1: +5:2 scope 1 { - debug x => _3; // in scope 1 at $DIR/no-drop-for-inactive-variant.rs:+2:14: +2:15 + debug x => _3; // in scope 1 at $DIR/no_drop_for_inactive_variant.rs:+2:14: +2:15 } bb0: { - _2 = discriminant(_1); // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+1:11: +1:14 - switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+1:5: +1:14 + _2 = discriminant(_1); // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:11: +1:14 + switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:5: +1:14 } bb1: { @@ -30,20 +30,20 @@ fn unwrap(_1: Option<T>) -> T { } bb2: { - unreachable; // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+1:11: +1:14 + unreachable; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:11: +1:14 } bb3: { - StorageLive(_3); // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+2:14: +2:15 - _3 = move ((_1 as Some).0: T); // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+2:14: +2:15 - _0 = move _3; // scope 1 at $DIR/no-drop-for-inactive-variant.rs:+2:20: +2:21 - StorageDead(_3); // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+2:20: +2:21 - _5 = discriminant(_1); // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+5:1: +5:2 - return; // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+5:2: +5:2 + StorageLive(_3); // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+2:14: +2:15 + _3 = move ((_1 as Some).0: T); // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+2:14: +2:15 + _0 = move _3; // scope 1 at $DIR/no_drop_for_inactive_variant.rs:+2:20: +2:21 + StorageDead(_3); // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+2:20: +2:21 + _5 = discriminant(_1); // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+5:1: +5:2 + return; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+5:2: +5:2 } bb4 (cleanup): { - _7 = discriminant(_1); // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+5:1: +5:2 - resume; // scope 0 at $DIR/no-drop-for-inactive-variant.rs:+0:1: +5:2 + _7 = discriminant(_1); // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+5:1: +5:2 + resume; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+0:1: +5:2 } } diff --git a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir index 963e7cde656..0cb34a2f274 100644 --- a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir @@ -1,49 +1,49 @@ // MIR for `main` before ElaborateDrops fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/no-spurious-drop-after-call.rs:+0:11: +0:11 - let _1: (); // in scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:5: +1:35 - let mut _2: std::string::String; // in scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:34 - let mut _3: &str; // in scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:34 - let _4: &str; // in scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:22 + let mut _0: (); // return place in scope 0 at $DIR/no_spurious_drop_after_call.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:5: +1:35 + let mut _2: std::string::String; // in scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:20: +1:34 + let mut _3: &str; // in scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:20: +1:34 + let _4: &str; // in scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:20: +1:22 bb0: { - StorageLive(_1); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:5: +1:35 - StorageLive(_2); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:34 - StorageLive(_3); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:34 - StorageLive(_4); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:22 - _4 = const ""; // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:22 + StorageLive(_1); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:5: +1:35 + StorageLive(_2); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:20: +1:34 + StorageLive(_3); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:20: +1:34 + StorageLive(_4); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:20: +1:22 + _4 = const ""; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:20: +1:22 // mir::Constant - // + span: $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 + // + span: $DIR/no_spurious_drop_after_call.rs:9:20: 9:22 // + literal: Const { ty: &str, val: Value(Slice(..)) } - _3 = &(*_4); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:34 - _2 = <str as ToString>::to_string(move _3) -> bb1; // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:34 + _3 = &(*_4); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:20: +1:34 + _2 = <str as ToString>::to_string(move _3) -> bb1; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:20: +1:34 // mir::Constant - // + span: $DIR/no-spurious-drop-after-call.rs:9:23: 9:32 + // + span: $DIR/no_spurious_drop_after_call.rs:9:23: 9:32 // + literal: Const { ty: for<'a> fn(&'a str) -> String {<str as ToString>::to_string}, val: Value(<ZST>) } } bb1: { - StorageDead(_3); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:33: +1:34 - _1 = std::mem::drop::<String>(move _2) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:5: +1:35 + StorageDead(_3); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:33: +1:34 + _1 = std::mem::drop::<String>(move _2) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:5: +1:35 // mir::Constant - // + span: $DIR/no-spurious-drop-after-call.rs:9:5: 9:19 + // + span: $DIR/no_spurious_drop_after_call.rs:9:5: 9:19 // + literal: Const { ty: fn(String) {std::mem::drop::<String>}, val: Value(<ZST>) } } bb2: { - StorageDead(_2); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:34: +1:35 - StorageDead(_4); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:35: +1:36 - StorageDead(_1); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:35: +1:36 - _0 = const (); // scope 0 at $DIR/no-spurious-drop-after-call.rs:+0:11: +2:2 - return; // scope 0 at $DIR/no-spurious-drop-after-call.rs:+2:2: +2:2 + StorageDead(_2); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:34: +1:35 + StorageDead(_4); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:35: +1:36 + StorageDead(_1); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:35: +1:36 + _0 = const (); // scope 0 at $DIR/no_spurious_drop_after_call.rs:+0:11: +2:2 + return; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+2:2: +2:2 } bb3 (cleanup): { - drop(_2) -> bb4; // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:34: +1:35 + drop(_2) -> bb4; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:34: +1:35 } bb4 (cleanup): { - resume; // scope 0 at $DIR/no-spurious-drop-after-call.rs:+0:1: +2:2 + resume; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+0:1: +2:2 } } diff --git a/src/test/mir-opt/no-spurious-drop-after-call.rs b/src/test/mir-opt/no_spurious_drop_after_call.rs index bb5bb9aa4e5..bb5bb9aa4e5 100644 --- a/src/test/mir-opt/no-spurious-drop-after-call.rs +++ b/src/test/mir-opt/no_spurious_drop_after_call.rs diff --git a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff index ce35f920bf6..61a16065bfb 100644 --- a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff +++ b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff @@ -2,42 +2,42 @@ + // MIR for `nrvo` after RenameReturnPlace fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] { - debug init => _1; // in scope 0 at $DIR/nrvo-simple.rs:+0:9: +0:13 -- let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/nrvo-simple.rs:+0:39: +0:49 -+ let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/nrvo-simple.rs:+1:9: +1:16 - let mut _2: [u8; 1024]; // in scope 0 at $DIR/nrvo-simple.rs:+1:9: +1:16 - let _3: (); // in scope 0 at $DIR/nrvo-simple.rs:+2:5: +2:19 - let mut _4: for<'a> fn(&'a mut [u8; 1024]); // in scope 0 at $DIR/nrvo-simple.rs:+2:5: +2:9 - let mut _5: &mut [u8; 1024]; // in scope 0 at $DIR/nrvo-simple.rs:+2:10: +2:18 - let mut _6: &mut [u8; 1024]; // in scope 0 at $DIR/nrvo-simple.rs:+2:10: +2:18 + debug init => _1; // in scope 0 at $DIR/nrvo_simple.rs:+0:9: +0:13 +- let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/nrvo_simple.rs:+0:39: +0:49 ++ let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/nrvo_simple.rs:+1:9: +1:16 + let mut _2: [u8; 1024]; // in scope 0 at $DIR/nrvo_simple.rs:+1:9: +1:16 + let _3: (); // in scope 0 at $DIR/nrvo_simple.rs:+2:5: +2:19 + let mut _4: for<'a> fn(&'a mut [u8; 1024]); // in scope 0 at $DIR/nrvo_simple.rs:+2:5: +2:9 + let mut _5: &mut [u8; 1024]; // in scope 0 at $DIR/nrvo_simple.rs:+2:10: +2:18 + let mut _6: &mut [u8; 1024]; // in scope 0 at $DIR/nrvo_simple.rs:+2:10: +2:18 scope 1 { -- debug buf => _2; // in scope 1 at $DIR/nrvo-simple.rs:+1:9: +1:16 -+ debug buf => _0; // in scope 1 at $DIR/nrvo-simple.rs:+1:9: +1:16 +- debug buf => _2; // in scope 1 at $DIR/nrvo_simple.rs:+1:9: +1:16 ++ debug buf => _0; // in scope 1 at $DIR/nrvo_simple.rs:+1:9: +1:16 } bb0: { -- StorageLive(_2); // scope 0 at $DIR/nrvo-simple.rs:+1:9: +1:16 -- _2 = [const 0_u8; 1024]; // scope 0 at $DIR/nrvo-simple.rs:+1:19: +1:28 -+ _0 = [const 0_u8; 1024]; // scope 0 at $DIR/nrvo-simple.rs:+1:19: +1:28 - StorageLive(_3); // scope 1 at $DIR/nrvo-simple.rs:+2:5: +2:19 - StorageLive(_4); // scope 1 at $DIR/nrvo-simple.rs:+2:5: +2:9 - _4 = _1; // scope 1 at $DIR/nrvo-simple.rs:+2:5: +2:9 - StorageLive(_5); // scope 1 at $DIR/nrvo-simple.rs:+2:10: +2:18 - StorageLive(_6); // scope 1 at $DIR/nrvo-simple.rs:+2:10: +2:18 -- _6 = &mut _2; // scope 1 at $DIR/nrvo-simple.rs:+2:10: +2:18 -+ _6 = &mut _0; // scope 1 at $DIR/nrvo-simple.rs:+2:10: +2:18 - _5 = &mut (*_6); // scope 1 at $DIR/nrvo-simple.rs:+2:10: +2:18 - _3 = move _4(move _5) -> bb1; // scope 1 at $DIR/nrvo-simple.rs:+2:5: +2:19 +- StorageLive(_2); // scope 0 at $DIR/nrvo_simple.rs:+1:9: +1:16 +- _2 = [const 0_u8; 1024]; // scope 0 at $DIR/nrvo_simple.rs:+1:19: +1:28 ++ _0 = [const 0_u8; 1024]; // scope 0 at $DIR/nrvo_simple.rs:+1:19: +1:28 + StorageLive(_3); // scope 1 at $DIR/nrvo_simple.rs:+2:5: +2:19 + StorageLive(_4); // scope 1 at $DIR/nrvo_simple.rs:+2:5: +2:9 + _4 = _1; // scope 1 at $DIR/nrvo_simple.rs:+2:5: +2:9 + StorageLive(_5); // scope 1 at $DIR/nrvo_simple.rs:+2:10: +2:18 + StorageLive(_6); // scope 1 at $DIR/nrvo_simple.rs:+2:10: +2:18 +- _6 = &mut _2; // scope 1 at $DIR/nrvo_simple.rs:+2:10: +2:18 ++ _6 = &mut _0; // scope 1 at $DIR/nrvo_simple.rs:+2:10: +2:18 + _5 = &mut (*_6); // scope 1 at $DIR/nrvo_simple.rs:+2:10: +2:18 + _3 = move _4(move _5) -> bb1; // scope 1 at $DIR/nrvo_simple.rs:+2:5: +2:19 } bb1: { - StorageDead(_5); // scope 1 at $DIR/nrvo-simple.rs:+2:18: +2:19 - StorageDead(_4); // scope 1 at $DIR/nrvo-simple.rs:+2:18: +2:19 - StorageDead(_6); // scope 1 at $DIR/nrvo-simple.rs:+2:19: +2:20 - StorageDead(_3); // scope 1 at $DIR/nrvo-simple.rs:+2:19: +2:20 -- _0 = _2; // scope 1 at $DIR/nrvo-simple.rs:+3:5: +3:8 -- StorageDead(_2); // scope 0 at $DIR/nrvo-simple.rs:+4:1: +4:2 - return; // scope 0 at $DIR/nrvo-simple.rs:+4:2: +4:2 + StorageDead(_5); // scope 1 at $DIR/nrvo_simple.rs:+2:18: +2:19 + StorageDead(_4); // scope 1 at $DIR/nrvo_simple.rs:+2:18: +2:19 + StorageDead(_6); // scope 1 at $DIR/nrvo_simple.rs:+2:19: +2:20 + StorageDead(_3); // scope 1 at $DIR/nrvo_simple.rs:+2:19: +2:20 +- _0 = _2; // scope 1 at $DIR/nrvo_simple.rs:+3:5: +3:8 +- StorageDead(_2); // scope 0 at $DIR/nrvo_simple.rs:+4:1: +4:2 + return; // scope 0 at $DIR/nrvo_simple.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/nrvo-simple.rs b/src/test/mir-opt/nrvo_simple.rs index 5786ae62127..5786ae62127 100644 --- a/src/test/mir-opt/nrvo-simple.rs +++ b/src/test/mir-opt/nrvo_simple.rs diff --git a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir index f9ed1036f00..e522534867d 100644 --- a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir @@ -1,60 +1,60 @@ // MIR for `main` after SimplifyCfg-elaborate-drops fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/packed-struct-drop-aligned.rs:+0:11: +0:11 - let mut _1: Packed; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:9: +1:14 - let mut _2: Aligned; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:24: +1:42 - let mut _3: Droppy; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:32: +1:41 - let mut _4: Aligned; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+2:11: +2:29 - let mut _5: Droppy; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+2:19: +2:28 - let mut _6: Aligned; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 + let mut _0: (); // return place in scope 0 at $DIR/packed_struct_drop_aligned.rs:+0:11: +0:11 + let mut _1: Packed; // in scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:9: +1:14 + let mut _2: Aligned; // in scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42 + let mut _3: Droppy; // in scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41 + let mut _4: Aligned; // in scope 0 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29 + let mut _5: Droppy; // in scope 0 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28 + let mut _6: Aligned; // in scope 0 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 scope 1 { - debug x => _1; // in scope 1 at $DIR/packed-struct-drop-aligned.rs:+1:9: +1:14 + debug x => _1; // in scope 1 at $DIR/packed_struct_drop_aligned.rs:+1:9: +1:14 } bb0: { - StorageLive(_1); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:9: +1:14 - StorageLive(_2); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:24: +1:42 - StorageLive(_3); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:32: +1:41 - Deinit(_3); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:32: +1:41 - (_3.0: usize) = const 0_usize; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:32: +1:41 - Deinit(_2); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:24: +1:42 - (_2.0: Droppy) = move _3; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:24: +1:42 - StorageDead(_3); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:41: +1:42 - Deinit(_1); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:17: +1:43 - (_1.0: Aligned) = move _2; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:17: +1:43 - StorageDead(_2); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:42: +1:43 - StorageLive(_4); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:11: +2:29 - StorageLive(_5); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:19: +2:28 - Deinit(_5); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:19: +2:28 - (_5.0: usize) = const 0_usize; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:19: +2:28 - Deinit(_4); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:11: +2:29 - (_4.0: Droppy) = move _5; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:11: +2:29 - StorageDead(_5); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:28: +2:29 - StorageLive(_6); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - _6 = move (_1.0: Aligned); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - drop(_6) -> [return: bb4, unwind: bb3]; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 + StorageLive(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:9: +1:14 + StorageLive(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42 + StorageLive(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41 + Deinit(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41 + (_3.0: usize) = const 0_usize; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41 + Deinit(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42 + (_2.0: Droppy) = move _3; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42 + StorageDead(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:41: +1:42 + Deinit(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43 + (_1.0: Aligned) = move _2; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43 + StorageDead(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:42: +1:43 + StorageLive(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29 + StorageLive(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28 + Deinit(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28 + (_5.0: usize) = const 0_usize; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28 + Deinit(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29 + (_4.0: Droppy) = move _5; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29 + StorageDead(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:28: +2:29 + StorageLive(_6); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 + _6 = move (_1.0: Aligned); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 + drop(_6) -> [return: bb4, unwind: bb3]; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 } bb1: { - StorageDead(_1); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+3:1: +3:2 - return; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+3:2: +3:2 + StorageDead(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2 + return; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:2: +3:2 } bb2 (cleanup): { - resume; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+0:1: +3:2 + resume; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+0:1: +3:2 } bb3 (cleanup): { - (_1.0: Aligned) = move _4; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - drop(_1) -> bb2; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+3:1: +3:2 + (_1.0: Aligned) = move _4; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 + drop(_1) -> bb2; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2 } bb4: { - StorageDead(_6); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - (_1.0: Aligned) = move _4; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - StorageDead(_4); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:28: +2:29 - _0 = const (); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+0:11: +3:2 - drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+3:1: +3:2 + StorageDead(_6); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 + (_1.0: Aligned) = move _4; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 + StorageDead(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:28: +2:29 + _0 = const (); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+0:11: +3:2 + drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2 } } diff --git a/src/test/mir-opt/packed-struct-drop-aligned.rs b/src/test/mir-opt/packed_struct_drop_aligned.rs index cb652426090..cb652426090 100644 --- a/src/test/mir-opt/packed-struct-drop-aligned.rs +++ b/src/test/mir-opt/packed_struct_drop_aligned.rs diff --git a/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir b/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir index 76bdd23be16..8eb0e9c8f48 100644 --- a/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir +++ b/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir @@ -1,11 +1,11 @@ // MIR for `no_codegen` after PreCodegen fn no_codegen() -> () { - let mut _0: (); // return place in scope 0 at $DIR/remove-never-const.rs:+0:20: +0:20 + let mut _0: (); // return place in scope 0 at $DIR/remove_never_const.rs:+0:20: +0:20 scope 1 { } bb0: { - unreachable; // scope 0 at $DIR/remove-never-const.rs:+1:13: +1:33 + unreachable; // scope 0 at $DIR/remove_never_const.rs:+1:13: +1:33 } } diff --git a/src/test/mir-opt/remove-never-const.rs b/src/test/mir-opt/remove_never_const.rs index 16095cfdd7d..16095cfdd7d 100644 --- a/src/test/mir-opt/remove-never-const.rs +++ b/src/test/mir-opt/remove_never_const.rs diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify_arm.rs index c247872e2af..c247872e2af 100644 --- a/src/test/mir-opt/simplify-arm.rs +++ b/src/test/mir-opt/simplify_arm.rs diff --git a/src/test/mir-opt/simplify-arm-identity.rs b/src/test/mir-opt/simplify_arm_identity.rs index cf6ff57aa96..cf6ff57aa96 100644 --- a/src/test/mir-opt/simplify-arm-identity.rs +++ b/src/test/mir-opt/simplify_arm_identity.rs diff --git a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff index 5d7517e4eb4..1a5143aa0fa 100644 --- a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff @@ -2,32 +2,32 @@ + // MIR for `c` after SimplifyLocals fn c() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:+0:8: +0:8 - let _1: [u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:+1:9: +1:14 -- let mut _2: &[u8]; // in scope 0 at $DIR/simplify-locals.rs:+3:20: +3:26 -- let mut _3: &[u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:+3:20: +3:26 -- let _4: &[u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:+3:20: +3:26 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:8: +0:8 + let _1: [u8; 10]; // in scope 0 at $DIR/simplify_locals.rs:+1:9: +1:14 +- let mut _2: &[u8]; // in scope 0 at $DIR/simplify_locals.rs:+3:20: +3:26 +- let mut _3: &[u8; 10]; // in scope 0 at $DIR/simplify_locals.rs:+3:20: +3:26 +- let _4: &[u8; 10]; // in scope 0 at $DIR/simplify_locals.rs:+3:20: +3:26 scope 1 { - debug bytes => _1; // in scope 1 at $DIR/simplify-locals.rs:+1:9: +1:14 + debug bytes => _1; // in scope 1 at $DIR/simplify_locals.rs:+1:9: +1:14 scope 2 { } } bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:+1:9: +1:14 - _1 = [const 0_u8; 10]; // scope 0 at $DIR/simplify-locals.rs:+1:17: +1:26 -- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:+3:20: +3:26 -- StorageLive(_3); // scope 1 at $DIR/simplify-locals.rs:+3:20: +3:26 -- StorageLive(_4); // scope 1 at $DIR/simplify-locals.rs:+3:20: +3:26 -- _4 = &_1; // scope 1 at $DIR/simplify-locals.rs:+3:20: +3:26 -- _3 = &(*_4); // scope 1 at $DIR/simplify-locals.rs:+3:20: +3:26 -- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 1 at $DIR/simplify-locals.rs:+3:20: +3:26 -- StorageDead(_3); // scope 1 at $DIR/simplify-locals.rs:+3:25: +3:26 -- StorageDead(_4); // scope 1 at $DIR/simplify-locals.rs:+3:26: +3:27 -- StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:+3:26: +3:27 - _0 = const (); // scope 0 at $DIR/simplify-locals.rs:+0:8: +4:2 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:+4:1: +4:2 - return; // scope 0 at $DIR/simplify-locals.rs:+4:2: +4:2 + StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+1:9: +1:14 + _1 = [const 0_u8; 10]; // scope 0 at $DIR/simplify_locals.rs:+1:17: +1:26 +- StorageLive(_2); // scope 1 at $DIR/simplify_locals.rs:+3:20: +3:26 +- StorageLive(_3); // scope 1 at $DIR/simplify_locals.rs:+3:20: +3:26 +- StorageLive(_4); // scope 1 at $DIR/simplify_locals.rs:+3:20: +3:26 +- _4 = &_1; // scope 1 at $DIR/simplify_locals.rs:+3:20: +3:26 +- _3 = &(*_4); // scope 1 at $DIR/simplify_locals.rs:+3:20: +3:26 +- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 1 at $DIR/simplify_locals.rs:+3:20: +3:26 +- StorageDead(_3); // scope 1 at $DIR/simplify_locals.rs:+3:25: +3:26 +- StorageDead(_4); // scope 1 at $DIR/simplify_locals.rs:+3:26: +3:27 +- StorageDead(_2); // scope 1 at $DIR/simplify_locals.rs:+3:26: +3:27 + _0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:8: +4:2 + StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+4:1: +4:2 + return; // scope 0 at $DIR/simplify_locals.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff index a9ea8869a96..6426bf926a4 100644 --- a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff @@ -2,18 +2,18 @@ + // MIR for `d1` after SimplifyLocals fn d1() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:+0:9: +0:9 -- let mut _1: E; // in scope 0 at $DIR/simplify-locals.rs:+2:13: +2:17 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 +- let mut _1: E; // in scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17 scope 1 { } bb0: { -- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:+2:13: +2:17 -- Deinit(_1); // scope 0 at $DIR/simplify-locals.rs:+2:13: +2:17 -- discriminant(_1) = 0; // scope 0 at $DIR/simplify-locals.rs:+2:13: +2:17 -- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:+2:17: +2:18 - _0 = const (); // scope 0 at $DIR/simplify-locals.rs:+0:9: +3:2 - return; // scope 0 at $DIR/simplify-locals.rs:+3:2: +3:2 +- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17 +- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17 +- discriminant(_1) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17 +- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:17: +2:18 + _0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:9: +3:2 + return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff index 6a89e45843b..db5ab182d6f 100644 --- a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff @@ -2,28 +2,28 @@ + // MIR for `d2` after SimplifyLocals fn d2() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:+0:9: +0:9 -- let mut _1: E; // in scope 0 at $DIR/simplify-locals.rs:+2:22: +2:26 -- let mut _2: (i32, E); // in scope 0 at $DIR/simplify-locals.rs:+2:5: +2:17 -- let mut _3: E; // in scope 0 at $DIR/simplify-locals.rs:+2:11: +2:15 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 +- let mut _1: E; // in scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26 +- let mut _2: (i32, E); // in scope 0 at $DIR/simplify_locals.rs:+2:5: +2:17 +- let mut _3: E; // in scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 bb0: { -- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:+2:22: +2:26 -- Deinit(_1); // scope 0 at $DIR/simplify-locals.rs:+2:22: +2:26 -- discriminant(_1) = 1; // scope 0 at $DIR/simplify-locals.rs:+2:22: +2:26 -- StorageLive(_2); // scope 0 at $DIR/simplify-locals.rs:+2:5: +2:17 -- StorageLive(_3); // scope 0 at $DIR/simplify-locals.rs:+2:11: +2:15 -- Deinit(_3); // scope 0 at $DIR/simplify-locals.rs:+2:11: +2:15 -- discriminant(_3) = 0; // scope 0 at $DIR/simplify-locals.rs:+2:11: +2:15 -- Deinit(_2); // scope 0 at $DIR/simplify-locals.rs:+2:6: +2:16 -- (_2.0: i32) = const 10_i32; // scope 0 at $DIR/simplify-locals.rs:+2:6: +2:16 -- (_2.1: E) = move _3; // scope 0 at $DIR/simplify-locals.rs:+2:6: +2:16 -- StorageDead(_3); // scope 0 at $DIR/simplify-locals.rs:+2:15: +2:16 -- (_2.1: E) = move _1; // scope 0 at $DIR/simplify-locals.rs:+2:5: +2:26 -- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:+2:25: +2:26 -- StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:+2:26: +2:27 - _0 = const (); // scope 0 at $DIR/simplify-locals.rs:+0:9: +3:2 - return; // scope 0 at $DIR/simplify-locals.rs:+3:2: +3:2 +- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26 +- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26 +- discriminant(_1) = 1; // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26 +- StorageLive(_2); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:17 +- StorageLive(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 +- Deinit(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 +- discriminant(_3) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 +- Deinit(_2); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 +- (_2.0: i32) = const 10_i32; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 +- (_2.1: E) = move _3; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 +- StorageDead(_3); // scope 0 at $DIR/simplify_locals.rs:+2:15: +2:16 +- (_2.1: E) = move _1; // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:26 +- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:25: +2:26 +- StorageDead(_2); // scope 0 at $DIR/simplify_locals.rs:+2:26: +2:27 + _0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:9: +3:2 + return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff index 204a1bffc81..c707b0da07e 100644 --- a/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff @@ -2,20 +2,20 @@ + // MIR for `expose_addr` after SimplifyLocals fn expose_addr(_1: *const usize) -> () { - debug p => _1; // in scope 0 at $DIR/simplify-locals.rs:+0:16: +0:17 - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:+0:33: +0:33 - let _2: usize; // in scope 0 at $DIR/simplify-locals.rs:+2:5: +2:15 - let mut _3: *const usize; // in scope 0 at $DIR/simplify-locals.rs:+2:5: +2:6 + debug p => _1; // in scope 0 at $DIR/simplify_locals.rs:+0:16: +0:17 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:33: +0:33 + let _2: usize; // in scope 0 at $DIR/simplify_locals.rs:+2:5: +2:15 + let mut _3: *const usize; // in scope 0 at $DIR/simplify_locals.rs:+2:5: +2:6 bb0: { - StorageLive(_2); // scope 0 at $DIR/simplify-locals.rs:+2:5: +2:15 - StorageLive(_3); // scope 0 at $DIR/simplify-locals.rs:+2:5: +2:6 - _3 = _1; // scope 0 at $DIR/simplify-locals.rs:+2:5: +2:6 - _2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/simplify-locals.rs:+2:5: +2:15 - StorageDead(_3); // scope 0 at $DIR/simplify-locals.rs:+2:14: +2:15 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:+2:15: +2:16 - _0 = const (); // scope 0 at $DIR/simplify-locals.rs:+0:33: +3:2 - return; // scope 0 at $DIR/simplify-locals.rs:+3:2: +3:2 + StorageLive(_2); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:15 + StorageLive(_3); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:6 + _3 = _1; // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:6 + _2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:15 + StorageDead(_3); // scope 0 at $DIR/simplify_locals.rs:+2:14: +2:15 + StorageDead(_2); // scope 0 at $DIR/simplify_locals.rs:+2:15: +2:16 + _0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:33: +3:2 + return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff index 329e2a65a0d..ff6eb2cff5e 100644 --- a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff @@ -2,12 +2,12 @@ + // MIR for `r` after SimplifyLocals fn r() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:+0:8: +0:8 - let mut _1: i32; // in scope 0 at $DIR/simplify-locals.rs:+1:9: +1:14 -- let mut _2: &i32; // in scope 0 at $DIR/simplify-locals.rs:+3:13: +3:15 -- let mut _3: &mut i32; // in scope 0 at $DIR/simplify-locals.rs:+4:13: +4:19 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:8: +0:8 + let mut _1: i32; // in scope 0 at $DIR/simplify_locals.rs:+1:9: +1:14 +- let mut _2: &i32; // in scope 0 at $DIR/simplify_locals.rs:+3:13: +3:15 +- let mut _3: &mut i32; // in scope 0 at $DIR/simplify_locals.rs:+4:13: +4:19 scope 1 { - debug a => _1; // in scope 1 at $DIR/simplify-locals.rs:+1:9: +1:14 + debug a => _1; // in scope 1 at $DIR/simplify_locals.rs:+1:9: +1:14 scope 2 { scope 3 { } @@ -15,17 +15,17 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:+1:9: +1:14 - _1 = const 1_i32; // scope 0 at $DIR/simplify-locals.rs:+1:17: +1:18 -- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:+3:13: +3:15 -- _2 = &_1; // scope 1 at $DIR/simplify-locals.rs:+3:13: +3:15 -- StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:+3:15: +3:16 -- StorageLive(_3); // scope 2 at $DIR/simplify-locals.rs:+4:13: +4:19 -- _3 = &mut _1; // scope 2 at $DIR/simplify-locals.rs:+4:13: +4:19 -- StorageDead(_3); // scope 2 at $DIR/simplify-locals.rs:+4:19: +4:20 - _0 = const (); // scope 0 at $DIR/simplify-locals.rs:+0:8: +5:2 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:+5:1: +5:2 - return; // scope 0 at $DIR/simplify-locals.rs:+5:2: +5:2 + StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+1:9: +1:14 + _1 = const 1_i32; // scope 0 at $DIR/simplify_locals.rs:+1:17: +1:18 +- StorageLive(_2); // scope 1 at $DIR/simplify_locals.rs:+3:13: +3:15 +- _2 = &_1; // scope 1 at $DIR/simplify_locals.rs:+3:13: +3:15 +- StorageDead(_2); // scope 1 at $DIR/simplify_locals.rs:+3:15: +3:16 +- StorageLive(_3); // scope 2 at $DIR/simplify_locals.rs:+4:13: +4:19 +- _3 = &mut _1; // scope 2 at $DIR/simplify_locals.rs:+4:13: +4:19 +- StorageDead(_3); // scope 2 at $DIR/simplify_locals.rs:+4:19: +4:20 + _0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:8: +5:2 + StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+5:1: +5:2 + return; // scope 0 at $DIR/simplify_locals.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/simplify-locals.rs b/src/test/mir-opt/simplify_locals.rs index 89d9391f832..89d9391f832 100644 --- a/src/test/mir-opt/simplify-locals.rs +++ b/src/test/mir-opt/simplify_locals.rs diff --git a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff index b31156ad697..49db7747963 100644 --- a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff @@ -2,21 +2,21 @@ + // MIR for `t1` after SimplifyLocals fn t1() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:+0:9: +0:9 -- let _1: u32; // in scope 0 at $DIR/simplify-locals.rs:+2:14: +2:15 -- let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:+2:14: +2:15 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 +- let _1: u32; // in scope 0 at $DIR/simplify_locals.rs:+2:14: +2:15 +- let mut _2: *mut u32; // in scope 0 at $DIR/simplify_locals.rs:+2:14: +2:15 scope 1 { } bb0: { -- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:+2:5: +2:17 -- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:15 -- _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:15 -- _1 = (*_2); // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:15 -- StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:+2:17: +2:18 -- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:+2:17: +2:18 - _0 = const (); // scope 0 at $DIR/simplify-locals.rs:+0:9: +3:2 - return; // scope 0 at $DIR/simplify-locals.rs:+3:2: +3:2 +- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:17 +- StorageLive(_2); // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:15 +- _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:15 +- _1 = (*_2); // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:15 +- StorageDead(_2); // scope 0 at $DIR/simplify_locals.rs:+2:17: +2:18 +- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:17: +2:18 + _0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:9: +3:2 + return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff index 66b6d8d6486..e3f4ae3701b 100644 --- a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff @@ -2,21 +2,21 @@ + // MIR for `t2` after SimplifyLocals fn t2() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:+0:9: +0:9 -- let _1: &mut u32; // in scope 0 at $DIR/simplify-locals.rs:+2:14: +2:20 -- let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:+2:19: +2:20 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 +- let _1: &mut u32; // in scope 0 at $DIR/simplify_locals.rs:+2:14: +2:20 +- let mut _2: *mut u32; // in scope 0 at $DIR/simplify_locals.rs:+2:19: +2:20 scope 1 { } bb0: { -- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:+2:5: +2:22 -- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:+2:19: +2:20 -- _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:+2:19: +2:20 -- _1 = &mut (*_2); // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:20 -- StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:+2:22: +2:23 -- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:+2:22: +2:23 - _0 = const (); // scope 0 at $DIR/simplify-locals.rs:+0:9: +3:2 - return; // scope 0 at $DIR/simplify-locals.rs:+3:2: +3:2 +- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:22 +- StorageLive(_2); // scope 1 at $DIR/simplify_locals.rs:+2:19: +2:20 +- _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify_locals.rs:+2:19: +2:20 +- _1 = &mut (*_2); // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:20 +- StorageDead(_2); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:23 +- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:23 + _0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:9: +3:2 + return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff index f6b6b78cdfb..f1ce7778e19 100644 --- a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff @@ -2,25 +2,25 @@ + // MIR for `t3` after SimplifyLocals fn t3() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:+0:9: +0:9 -- let _1: u32; // in scope 0 at $DIR/simplify-locals.rs:+2:14: +2:21 -- let mut _2: &mut u32; // in scope 0 at $DIR/simplify-locals.rs:+2:15: +2:21 -- let mut _3: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:+2:20: +2:21 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 +- let _1: u32; // in scope 0 at $DIR/simplify_locals.rs:+2:14: +2:21 +- let mut _2: &mut u32; // in scope 0 at $DIR/simplify_locals.rs:+2:15: +2:21 +- let mut _3: *mut u32; // in scope 0 at $DIR/simplify_locals.rs:+2:20: +2:21 scope 1 { } bb0: { -- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:+2:5: +2:23 -- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:+2:15: +2:21 -- StorageLive(_3); // scope 1 at $DIR/simplify-locals.rs:+2:20: +2:21 -- _3 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:+2:20: +2:21 -- _2 = &mut (*_3); // scope 1 at $DIR/simplify-locals.rs:+2:15: +2:21 -- _1 = (*_2); // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:21 -- StorageDead(_3); // scope 0 at $DIR/simplify-locals.rs:+2:23: +2:24 -- StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:+2:23: +2:24 -- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:+2:23: +2:24 - _0 = const (); // scope 0 at $DIR/simplify-locals.rs:+0:9: +3:2 - return; // scope 0 at $DIR/simplify-locals.rs:+3:2: +3:2 +- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:23 +- StorageLive(_2); // scope 1 at $DIR/simplify_locals.rs:+2:15: +2:21 +- StorageLive(_3); // scope 1 at $DIR/simplify_locals.rs:+2:20: +2:21 +- _3 = &/*tls*/ mut X; // scope 1 at $DIR/simplify_locals.rs:+2:20: +2:21 +- _2 = &mut (*_3); // scope 1 at $DIR/simplify_locals.rs:+2:15: +2:21 +- _1 = (*_2); // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:21 +- StorageDead(_3); // scope 0 at $DIR/simplify_locals.rs:+2:23: +2:24 +- StorageDead(_2); // scope 0 at $DIR/simplify_locals.rs:+2:23: +2:24 +- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:23: +2:24 + _0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:9: +3:2 + return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff index 1c1da29aa67..71cf9594b9e 100644 --- a/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff @@ -2,21 +2,21 @@ + // MIR for `t4` after SimplifyLocals fn t4() -> u32 { - let mut _0: u32; // return place in scope 0 at $DIR/simplify-locals.rs:+0:12: +0:15 - let mut _1: u32; // in scope 0 at $DIR/simplify-locals.rs:+2:14: +2:15 - let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:+2:14: +2:15 + let mut _0: u32; // return place in scope 0 at $DIR/simplify_locals.rs:+0:12: +0:15 + let mut _1: u32; // in scope 0 at $DIR/simplify_locals.rs:+2:14: +2:15 + let mut _2: *mut u32; // in scope 0 at $DIR/simplify_locals.rs:+2:14: +2:15 scope 1 { } bb0: { - StorageLive(_1); // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:15 - StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:15 - _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:15 - _1 = (*_2); // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:15 - _0 = Add(move _1, const 1_u32); // scope 1 at $DIR/simplify-locals.rs:+2:14: +2:19 - StorageDead(_1); // scope 1 at $DIR/simplify-locals.rs:+2:18: +2:19 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:+3:1: +3:2 - return; // scope 0 at $DIR/simplify-locals.rs:+3:2: +3:2 + StorageLive(_1); // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:15 + StorageLive(_2); // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:15 + _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:15 + _1 = (*_2); // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:15 + _0 = Add(move _1, const 1_u32); // scope 1 at $DIR/simplify_locals.rs:+2:14: +2:19 + StorageDead(_1); // scope 1 at $DIR/simplify_locals.rs:+2:18: +2:19 + StorageDead(_2); // scope 0 at $DIR/simplify_locals.rs:+3:1: +3:2 + return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2 } } diff --git a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff index ac7a47ba58f..8feddcef2ce 100644 --- a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff @@ -2,61 +2,61 @@ + // MIR for `foo` after SimplifyLocals fn foo() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals-fixedpoint.rs:+0:13: +0:13 - let mut _1: (std::option::Option<u8>, std::option::Option<T>); // in scope 0 at $DIR/simplify-locals-fixedpoint.rs:+1:30: +1:69 - let mut _2: std::option::Option<u8>; // in scope 0 at $DIR/simplify-locals-fixedpoint.rs:+1:31: +1:49 - let mut _3: std::option::Option<T>; // in scope 0 at $DIR/simplify-locals-fixedpoint.rs:+1:51: +1:68 - let mut _4: isize; // in scope 0 at $DIR/simplify-locals-fixedpoint.rs:+1:22: +1:26 - let mut _5: isize; // in scope 0 at $DIR/simplify-locals-fixedpoint.rs:+1:13: +1:20 -- let mut _7: bool; // in scope 0 at $DIR/simplify-locals-fixedpoint.rs:+2:12: +2:20 -- let mut _8: u8; // in scope 0 at $DIR/simplify-locals-fixedpoint.rs:+2:12: +2:13 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+0:13: +0:13 + let mut _1: (std::option::Option<u8>, std::option::Option<T>); // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 + let mut _2: std::option::Option<u8>; // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49 + let mut _3: std::option::Option<T>; // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 + let mut _4: isize; // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:22: +1:26 + let mut _5: isize; // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:13: +1:20 +- let mut _7: bool; // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:20 +- let mut _8: u8; // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:13 scope 1 { - debug a => _6; // in scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:18: +1:19 - let _6: u8; // in scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:18: +1:19 + debug a => _6; // in scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19 + let _6: u8; // in scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19 } bb0: { - StorageLive(_1); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:30: +1:69 - StorageLive(_2); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:31: +1:49 - Deinit(_2); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:31: +1:49 - discriminant(_2) = 0; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:31: +1:49 - StorageLive(_3); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:51: +1:68 - Deinit(_3); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:51: +1:68 - discriminant(_3) = 0; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:51: +1:68 - Deinit(_1); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:30: +1:69 - (_1.0: std::option::Option<u8>) = move _2; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:30: +1:69 - (_1.1: std::option::Option<T>) = move _3; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:30: +1:69 - StorageDead(_3); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:68: +1:69 - StorageDead(_2); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:68: +1:69 - _5 = discriminant((_1.0: std::option::Option<u8>)); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:12: +1:27 - switchInt(move _5) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:12: +1:27 + StorageLive(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 + StorageLive(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49 + Deinit(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49 + discriminant(_2) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49 + StorageLive(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 + Deinit(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 + discriminant(_3) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 + Deinit(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 + (_1.0: std::option::Option<u8>) = move _2; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 + (_1.1: std::option::Option<T>) = move _3; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 + StorageDead(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69 + StorageDead(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69 + _5 = discriminant((_1.0: std::option::Option<u8>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27 + switchInt(move _5) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27 } bb1: { - _4 = discriminant((_1.1: std::option::Option<T>)); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:12: +1:27 - switchInt(move _4) -> [0_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:12: +1:27 + _4 = discriminant((_1.1: std::option::Option<T>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27 + switchInt(move _4) -> [0_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27 } bb2: { - StorageLive(_6); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:18: +1:19 - _6 = (((_1.0: std::option::Option<u8>) as Some).0: u8); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+1:18: +1:19 -- StorageLive(_7); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+2:12: +2:20 -- StorageLive(_8); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+2:12: +2:13 -- _8 = _6; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+2:12: +2:13 -- _7 = Gt(move _8, const 42_u8); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+2:12: +2:20 -- StorageDead(_8); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+2:19: +2:20 -- StorageDead(_7); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:+4:9: +4:10 - StorageDead(_6); // scope 0 at $DIR/simplify-locals-fixedpoint.rs:+5:5: +5:6 - goto -> bb3; // scope 0 at $DIR/simplify-locals-fixedpoint.rs:+1:5: +5:6 + StorageLive(_6); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19 + _6 = (((_1.0: std::option::Option<u8>) as Some).0: u8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19 +- StorageLive(_7); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:20 +- StorageLive(_8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:13 +- _8 = _6; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:13 +- _7 = Gt(move _8, const 42_u8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:20 +- StorageDead(_8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:19: +2:20 +- StorageDead(_7); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+4:9: +4:10 + StorageDead(_6); // scope 0 at $DIR/simplify_locals_fixedpoint.rs:+5:5: +5:6 + goto -> bb3; // scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:5: +5:6 } bb3: { - drop(_1) -> bb4; // scope 0 at $DIR/simplify-locals-fixedpoint.rs:+6:1: +6:2 + drop(_1) -> bb4; // scope 0 at $DIR/simplify_locals_fixedpoint.rs:+6:1: +6:2 } bb4: { - StorageDead(_1); // scope 0 at $DIR/simplify-locals-fixedpoint.rs:+6:1: +6:2 - return; // scope 0 at $DIR/simplify-locals-fixedpoint.rs:+6:2: +6:2 + StorageDead(_1); // scope 0 at $DIR/simplify_locals_fixedpoint.rs:+6:1: +6:2 + return; // scope 0 at $DIR/simplify_locals_fixedpoint.rs:+6:2: +6:2 } } diff --git a/src/test/mir-opt/simplify-locals-fixedpoint.rs b/src/test/mir-opt/simplify_locals_fixedpoint.rs index 78b1f9f55e5..78b1f9f55e5 100644 --- a/src/test/mir-opt/simplify-locals-fixedpoint.rs +++ b/src/test/mir-opt/simplify_locals_fixedpoint.rs diff --git a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff index b41527ba02d..78272272b07 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff @@ -2,108 +2,108 @@ + // MIR for `main` after SimplifyLocals fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+0:11: +0:11 -- let mut _1: ((), ()); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:20: +1:28 -- let mut _2: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:21: +1:23 -- let mut _3: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:25: +1:27 -- let _4: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+2:5: +2:22 -- let mut _5: ((), ()); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -- let mut _6: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+2:14: +2:16 -- let mut _7: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+2:18: +2:20 -- let _8: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+4:5: +4:35 -- let mut _9: u8; // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:34 -- let mut _10: u8; // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:30 -- let mut _11: Temp; // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:28 -+ let _1: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+2:5: +2:22 -+ let mut _2: ((), ()); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -+ let mut _3: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+2:14: +2:16 -+ let mut _4: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+2:18: +2:20 -+ let _5: (); // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+4:5: +4:35 -+ let mut _6: u8; // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:34 -+ let mut _7: u8; // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:30 -+ let mut _8: Temp; // in scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:28 + let mut _0: (); // return place in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+0:11: +0:11 +- let mut _1: ((), ()); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 +- let mut _2: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23 +- let mut _3: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27 +- let _4: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 +- let mut _5: ((), ()); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 +- let mut _6: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 +- let mut _7: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 +- let _8: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+4:5: +4:35 +- let mut _9: u8; // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 +- let mut _10: u8; // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 +- let mut _11: Temp; // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 ++ let _1: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 ++ let mut _2: ((), ()); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 ++ let mut _3: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 ++ let mut _4: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 ++ let _5: (); // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+4:5: +4:35 ++ let mut _6: u8; // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 ++ let mut _7: u8; // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 ++ let mut _8: Temp; // in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 scope 1 { } bb0: { -- StorageLive(_1); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:20: +1:28 -- StorageLive(_2); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:21: +1:23 -- Deinit(_2); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:21: +1:23 -- StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:25: +1:27 -- Deinit(_3); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:25: +1:27 -- Deinit(_1); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:20: +1:28 -- (_1.0: ()) = move _2; // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:20: +1:28 -- (_1.1: ()) = move _3; // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:20: +1:28 -- StorageDead(_3); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:27: +1:28 -- StorageDead(_2); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:27: +1:28 -- StorageDead(_1); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+1:28: +1:29 -- StorageLive(_4); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:5: +2:22 -- StorageLive(_5); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -- StorageLive(_6); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:14: +2:16 -- Deinit(_6); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:14: +2:16 -- StorageLive(_7); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:18: +2:20 -- Deinit(_7); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:18: +2:20 -- Deinit(_5); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -- (_5.0: ()) = move _6; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -- (_5.1: ()) = move _7; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -- StorageDead(_7); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:20: +2:21 -- StorageDead(_6); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:20: +2:21 -- _4 = use_zst(move _5) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:5: +2:22 -+ StorageLive(_1); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:5: +2:22 -+ StorageLive(_2); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -+ StorageLive(_3); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:14: +2:16 -+ Deinit(_3); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:14: +2:16 -+ StorageLive(_4); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:18: +2:20 -+ Deinit(_4); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:18: +2:20 -+ Deinit(_2); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -+ (_2.0: ()) = move _3; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -+ (_2.1: ()) = move _4; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:13: +2:21 -+ StorageDead(_4); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:20: +2:21 -+ StorageDead(_3); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:20: +2:21 -+ _1 = use_zst(move _2) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:5: +2:22 +- StorageLive(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 +- StorageLive(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23 +- Deinit(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23 +- StorageLive(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27 +- Deinit(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27 +- Deinit(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 +- (_1.0: ()) = move _2; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 +- (_1.1: ()) = move _3; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 +- StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28 +- StorageDead(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28 +- StorageDead(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:28: +1:29 +- StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 +- StorageLive(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 +- StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 +- Deinit(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 +- StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 +- Deinit(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 +- Deinit(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 +- (_5.0: ()) = move _6; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 +- (_5.1: ()) = move _7; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 +- StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21 +- StorageDead(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21 +- _4 = use_zst(move _5) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 ++ StorageLive(_1); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 ++ StorageLive(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 ++ StorageLive(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 ++ Deinit(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 ++ StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 ++ Deinit(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 ++ Deinit(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 ++ (_2.0: ()) = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 ++ (_2.1: ()) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 ++ StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21 ++ StorageDead(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21 ++ _1 = use_zst(move _2) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:15:5: 15:12 + // + span: $DIR/simplify_locals_removes_unused_consts.rs:15:5: 15:12 // + literal: Const { ty: fn(((), ())) {use_zst}, val: Value(<ZST>) } } bb1: { -- StorageDead(_5); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:21: +2:22 -- StorageDead(_4); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:22: +2:23 -- StorageLive(_8); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:5: +4:35 -- StorageLive(_9); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:34 -- StorageLive(_10); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:30 -- StorageLive(_11); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:28 -- Deinit(_11); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:28 -- (_11.0: u8) = const 40_u8; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:28 -- _10 = (_11.0: u8); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:30 -- _9 = Add(move _10, const 2_u8); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:34 -- StorageDead(_10); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:33: +4:34 -- _8 = use_u8(move _9) -> bb2; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:5: +4:35 -+ StorageDead(_2); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:21: +2:22 -+ StorageDead(_1); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+2:22: +2:23 -+ StorageLive(_5); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:5: +4:35 -+ StorageLive(_6); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:34 -+ StorageLive(_7); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:30 -+ StorageLive(_8); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:28 -+ Deinit(_8); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:28 -+ (_8.0: u8) = const 40_u8; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:28 -+ _7 = (_8.0: u8); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:30 -+ _6 = Add(move _7, const 2_u8); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:12: +4:34 -+ StorageDead(_7); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:33: +4:34 -+ _5 = use_u8(move _6) -> bb2; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:5: +4:35 +- StorageDead(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:21: +2:22 +- StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:22: +2:23 +- StorageLive(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:5: +4:35 +- StorageLive(_9); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 +- StorageLive(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 +- StorageLive(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 +- Deinit(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 +- (_11.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 +- _10 = (_11.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 +- _9 = Add(move _10, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 +- StorageDead(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34 +- _8 = use_u8(move _9) -> bb2; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:5: +4:35 ++ StorageDead(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:21: +2:22 ++ StorageDead(_1); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:22: +2:23 ++ StorageLive(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:5: +4:35 ++ StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 ++ StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 ++ StorageLive(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 ++ Deinit(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 ++ (_8.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 ++ _7 = (_8.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 ++ _6 = Add(move _7, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 ++ StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34 ++ _5 = use_u8(move _6) -> bb2; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:5: +4:35 // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:17:5: 17:11 + // + span: $DIR/simplify_locals_removes_unused_consts.rs:17:5: 17:11 // + literal: Const { ty: fn(u8) {use_u8}, val: Value(<ZST>) } } bb2: { -- StorageDead(_9); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:34: +4:35 -- StorageDead(_11); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:35: +4:36 -+ StorageDead(_6); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:34: +4:35 - StorageDead(_8); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:35: +4:36 -+ StorageDead(_5); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:+4:35: +4:36 - _0 = const (); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+0:11: +5:2 - return; // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:+5:2: +5:2 +- StorageDead(_9); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:34: +4:35 +- StorageDead(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:35: +4:36 ++ StorageDead(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:34: +4:35 + StorageDead(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:35: +4:36 ++ StorageDead(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:35: +4:36 + _0 = const (); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+0:11: +5:2 + return; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs b/src/test/mir-opt/simplify_locals_removes_unused_consts.rs index 39b7911d4ae..39b7911d4ae 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs +++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.rs diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff index 51d26b08b2a..6e7294003af 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff @@ -2,51 +2,51 @@ + // MIR for `map` after SimplifyLocals fn map(_1: Option<Box<()>>) -> Option<Box<()>> { - debug x => _1; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:8: +0:9 - let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:31: +0:46 - let mut _2: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:9: +2:13 - let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 - let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 -- let mut _5: bool; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 -- let mut _6: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 -- let mut _7: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 + debug x => _1; // in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+0:8: +0:9 + let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+0:31: +0:46 + let mut _2: isize; // in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:9: +2:13 + let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:14: +3:15 + let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26 +- let mut _5: bool; // in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+5:1: +5:2 +- let mut _6: isize; // in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+5:1: +5:2 +- let mut _7: isize; // in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+5:1: +5:2 scope 1 { - debug x => _3; // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + debug x => _3; // in scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:14: +3:15 } bb0: { -- _5 = const false; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 -- _5 = const true; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 - _2 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 - switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12 +- _5 = const false; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12 +- _5 = const true; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12 + _2 = discriminant(_1); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12 + switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:5: +1:12 } bb1: { - StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 - _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 - StorageLive(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 - _4 = move _3; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 - Deinit(_0); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 - ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 - discriminant(_0) = 1; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 - StorageDead(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 - StorageDead(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 - goto -> bb4; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 + StorageLive(_3); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:14: +3:15 + _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:14: +3:15 + StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26 + _4 = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26 + Deinit(_0); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27 + ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27 + discriminant(_0) = 1; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27 + StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27 + StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27 + goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27 } bb2: { - unreachable; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 + unreachable; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12 } bb3: { - Deinit(_0); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21 - discriminant(_0) = 0; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21 - goto -> bb4; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21 + Deinit(_0); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21 + discriminant(_0) = 0; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21 + goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21 } bb4: { -- _6 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 - return; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2 +- _6 = discriminant(_1); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+5:1: +5:2 + return; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs index d09bd92c4e8..d09bd92c4e8 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice_drop_shim.rs index 344c1af2c91..344c1af2c91 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice_drop_shim.rs diff --git a/src/test/mir-opt/spanview_block.main.built.after.html b/src/test/mir-opt/spanview_block.main.built.after.html index fbf751d6d30..b962d80c59e 100644 --- a/src/test/mir-opt/spanview_block.main.built.after.html +++ b/src/test/mir-opt/spanview_block.main.built.after.html @@ -59,7 +59,7 @@ </style> </head> <body> -<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() </span><span><span class="code even" style="--layer: 1" title="0: $DIR/spanview-block.rs:5:11: 5:13: +<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() </span><span><span class="code even" style="--layer: 1" title="0: $DIR/spanview_block.rs:5:11: 5:13: 5:11-5:13: Assign: _0 = const () 5:13-5:13: Return: return"><span class="annotation">0⦊</span>{}<span class="annotation">⦉0</span></span></span></span></div> </body> diff --git a/src/test/mir-opt/spanview-block.rs b/src/test/mir-opt/spanview_block.rs index 0ecf35ad6a2..0ecf35ad6a2 100644 --- a/src/test/mir-opt/spanview-block.rs +++ b/src/test/mir-opt/spanview_block.rs diff --git a/src/test/mir-opt/spanview_statement.main.built.after.html b/src/test/mir-opt/spanview_statement.main.built.after.html index 02b2720feef..43bff7d096e 100644 --- a/src/test/mir-opt/spanview_statement.main.built.after.html +++ b/src/test/mir-opt/spanview_statement.main.built.after.html @@ -59,8 +59,8 @@ </style> </head> <body> -<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() </span><span><span class="code even" style="--layer: 1" title="0[0]: $DIR/spanview-statement.rs:5:11: 5:13: - 5:11-5:13: Assign: _0 = const ()"><span class="annotation">0[0]⦊</span>{}<span class="annotation">⦉0[0]</span></span></span><span><span class="code odd" style="--layer: 1" title="0:Return: $DIR/spanview-statement.rs:5:13: 5:13: +<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() </span><span><span class="code even" style="--layer: 1" title="0[0]: $DIR/spanview_statement.rs:5:11: 5:13: + 5:11-5:13: Assign: _0 = const ()"><span class="annotation">0[0]⦊</span>{}<span class="annotation">⦉0[0]</span></span></span><span><span class="code odd" style="--layer: 1" title="0:Return: $DIR/spanview_statement.rs:5:13: 5:13: 5:13-5:13: Return: return"><span class="annotation">0:Return⦊</span>‸<span class="annotation">⦉0:Return</span></span></span></span></div> </body> </html> diff --git a/src/test/mir-opt/spanview-statement.rs b/src/test/mir-opt/spanview_statement.rs index 457052617b7..457052617b7 100644 --- a/src/test/mir-opt/spanview-statement.rs +++ b/src/test/mir-opt/spanview_statement.rs diff --git a/src/test/mir-opt/spanview_terminator.main.built.after.html b/src/test/mir-opt/spanview_terminator.main.built.after.html index a4cda7dd67e..aa7e44c1571 100644 --- a/src/test/mir-opt/spanview_terminator.main.built.after.html +++ b/src/test/mir-opt/spanview_terminator.main.built.after.html @@ -59,7 +59,7 @@ </style> </head> <body> -<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() {}</span><span><span class="code even" style="--layer: 1" title="0:Return: $DIR/spanview-terminator.rs:5:13: 5:13: +<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() {}</span><span><span class="code even" style="--layer: 1" title="0:Return: $DIR/spanview_terminator.rs:5:13: 5:13: 5:13-5:13: Return: return"><span class="annotation">0:Return⦊</span>‸<span class="annotation">⦉0:Return</span></span></span></span></div> </body> </html> diff --git a/src/test/mir-opt/spanview-terminator.rs b/src/test/mir-opt/spanview_terminator.rs index 76fced188f1..76fced188f1 100644 --- a/src/test/mir-opt/spanview-terminator.rs +++ b/src/test/mir-opt/spanview_terminator.rs diff --git a/src/test/mir-opt/tls_access.main.PreCodegen.after.mir b/src/test/mir-opt/tls_access.main.PreCodegen.after.mir index b6c36be2bbe..09453b8ba9c 100644 --- a/src/test/mir-opt/tls_access.main.PreCodegen.after.mir +++ b/src/test/mir-opt/tls_access.main.PreCodegen.after.mir @@ -1,28 +1,28 @@ // MIR for `main` after PreCodegen fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/tls-access.rs:+0:11: +0:11 - let _2: *mut u8; // in scope 0 at $DIR/tls-access.rs:+2:18: +2:21 - let mut _3: *mut u8; // in scope 0 at $DIR/tls-access.rs:+3:9: +3:12 + let mut _0: (); // return place in scope 0 at $DIR/tls_access.rs:+0:11: +0:11 + let _2: *mut u8; // in scope 0 at $DIR/tls_access.rs:+2:18: +2:21 + let mut _3: *mut u8; // in scope 0 at $DIR/tls_access.rs:+3:9: +3:12 scope 1 { - let _1: &u8; // in scope 1 at $DIR/tls-access.rs:+2:13: +2:14 + let _1: &u8; // in scope 1 at $DIR/tls_access.rs:+2:13: +2:14 scope 2 { - debug a => _1; // in scope 2 at $DIR/tls-access.rs:+2:13: +2:14 + debug a => _1; // in scope 2 at $DIR/tls_access.rs:+2:13: +2:14 } } bb0: { - StorageLive(_1); // scope 1 at $DIR/tls-access.rs:+2:13: +2:14 - StorageLive(_2); // scope 1 at $DIR/tls-access.rs:+2:18: +2:21 - _2 = &/*tls*/ mut FOO; // scope 1 at $DIR/tls-access.rs:+2:18: +2:21 - _1 = &(*_2); // scope 1 at $DIR/tls-access.rs:+2:17: +2:21 - StorageLive(_3); // scope 2 at $DIR/tls-access.rs:+3:9: +3:12 - _3 = &/*tls*/ mut FOO; // scope 2 at $DIR/tls-access.rs:+3:9: +3:12 - (*_3) = const 42_u8; // scope 2 at $DIR/tls-access.rs:+3:9: +3:17 - StorageDead(_3); // scope 2 at $DIR/tls-access.rs:+3:17: +3:18 - _0 = const (); // scope 1 at $DIR/tls-access.rs:+1:5: +4:6 - StorageDead(_2); // scope 1 at $DIR/tls-access.rs:+4:5: +4:6 - StorageDead(_1); // scope 1 at $DIR/tls-access.rs:+4:5: +4:6 - return; // scope 0 at $DIR/tls-access.rs:+5:2: +5:2 + StorageLive(_1); // scope 1 at $DIR/tls_access.rs:+2:13: +2:14 + StorageLive(_2); // scope 1 at $DIR/tls_access.rs:+2:18: +2:21 + _2 = &/*tls*/ mut FOO; // scope 1 at $DIR/tls_access.rs:+2:18: +2:21 + _1 = &(*_2); // scope 1 at $DIR/tls_access.rs:+2:17: +2:21 + StorageLive(_3); // scope 2 at $DIR/tls_access.rs:+3:9: +3:12 + _3 = &/*tls*/ mut FOO; // scope 2 at $DIR/tls_access.rs:+3:9: +3:12 + (*_3) = const 42_u8; // scope 2 at $DIR/tls_access.rs:+3:9: +3:17 + StorageDead(_3); // scope 2 at $DIR/tls_access.rs:+3:17: +3:18 + _0 = const (); // scope 1 at $DIR/tls_access.rs:+1:5: +4:6 + StorageDead(_2); // scope 1 at $DIR/tls_access.rs:+4:5: +4:6 + StorageDead(_1); // scope 1 at $DIR/tls_access.rs:+4:5: +4:6 + return; // scope 0 at $DIR/tls_access.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/tls-access.rs b/src/test/mir-opt/tls_access.rs index 19344c86862..19344c86862 100644 --- a/src/test/mir-opt/tls-access.rs +++ b/src/test/mir-opt/tls_access.rs diff --git a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir index 6ed53643f4b..2c0fcc6621a 100644 --- a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir +++ b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir @@ -1,16 +1,16 @@ // MIR for `process_never` after SimplifyLocals fn process_never(_1: *const !) -> () { - debug input => _1; // in scope 0 at $DIR/uninhabited-enum.rs:+0:22: +0:27 - let mut _0: (); // return place in scope 0 at $DIR/uninhabited-enum.rs:+0:39: +0:39 - let _2: &!; // in scope 0 at $DIR/uninhabited-enum.rs:+1:8: +1:14 + debug input => _1; // in scope 0 at $DIR/uninhabited_enum.rs:+0:22: +0:27 + let mut _0: (); // return place in scope 0 at $DIR/uninhabited_enum.rs:+0:39: +0:39 + let _2: &!; // in scope 0 at $DIR/uninhabited_enum.rs:+1:8: +1:14 scope 1 { - debug _input => _2; // in scope 1 at $DIR/uninhabited-enum.rs:+1:8: +1:14 + debug _input => _2; // in scope 1 at $DIR/uninhabited_enum.rs:+1:8: +1:14 } scope 2 { } bb0: { - unreachable; // scope 0 at $DIR/uninhabited-enum.rs:+0:39: +2:2 + unreachable; // scope 0 at $DIR/uninhabited_enum.rs:+0:39: +2:2 } } diff --git a/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir index bbb81724ccf..ae341a7b97b 100644 --- a/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir +++ b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir @@ -1,18 +1,18 @@ // MIR for `process_void` after SimplifyLocals fn process_void(_1: *const Void) -> () { - debug input => _1; // in scope 0 at $DIR/uninhabited-enum.rs:+0:21: +0:26 - let mut _0: (); // return place in scope 0 at $DIR/uninhabited-enum.rs:+0:41: +0:41 - let _2: &Void; // in scope 0 at $DIR/uninhabited-enum.rs:+1:8: +1:14 + debug input => _1; // in scope 0 at $DIR/uninhabited_enum.rs:+0:21: +0:26 + let mut _0: (); // return place in scope 0 at $DIR/uninhabited_enum.rs:+0:41: +0:41 + let _2: &Void; // in scope 0 at $DIR/uninhabited_enum.rs:+1:8: +1:14 scope 1 { - debug _input => _2; // in scope 1 at $DIR/uninhabited-enum.rs:+1:8: +1:14 + debug _input => _2; // in scope 1 at $DIR/uninhabited_enum.rs:+1:8: +1:14 } scope 2 { } bb0: { - StorageLive(_2); // scope 0 at $DIR/uninhabited-enum.rs:+1:8: +1:14 - StorageDead(_2); // scope 0 at $DIR/uninhabited-enum.rs:+4:1: +4:2 - return; // scope 0 at $DIR/uninhabited-enum.rs:+4:2: +4:2 + StorageLive(_2); // scope 0 at $DIR/uninhabited_enum.rs:+1:8: +1:14 + StorageDead(_2); // scope 0 at $DIR/uninhabited_enum.rs:+4:1: +4:2 + return; // scope 0 at $DIR/uninhabited_enum.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/uninhabited-enum.rs b/src/test/mir-opt/uninhabited_enum.rs index 97c6e8cd531..97c6e8cd531 100644 --- a/src/test/mir-opt/uninhabited-enum.rs +++ b/src/test/mir-opt/uninhabited_enum.rs diff --git a/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.built.after.mir b/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.built.after.mir index c8b0f8e41b7..5257491f0d4 100644 --- a/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.built.after.mir +++ b/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.built.after.mir @@ -1,10 +1,10 @@ // MIR for `E::V::{constant#0}` after built E::V::{constant#0}: isize = { - let mut _0: isize; // return place in scope 0 at $DIR/unusual-item-types.rs:+0:9: +0:10 + let mut _0: isize; // return place in scope 0 at $DIR/unusual_item_types.rs:+0:9: +0:10 bb0: { - _0 = const 5_isize; // scope 0 at $DIR/unusual-item-types.rs:+0:9: +0:10 - return; // scope 0 at $DIR/unusual-item-types.rs:+0:9: +0:10 + _0 = const 5_isize; // scope 0 at $DIR/unusual_item_types.rs:+0:9: +0:10 + return; // scope 0 at $DIR/unusual_item_types.rs:+0:9: +0:10 } } diff --git a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir b/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir index a46e6017377..ee029676311 100644 --- a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir +++ b/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir @@ -1,12 +1,12 @@ // MIR for `Test::X` after built fn Test::X(_1: usize) -> Test { - let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 + let mut _0: Test; // return place in scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 bb0: { - Deinit(_0); // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 - ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 - discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 - return; // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 + Deinit(_0); // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 + ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 + discriminant(_0) = 0; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 + return; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 } } diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual_item_types.rs index 6dad636416f..6dad636416f 100644 --- a/src/test/mir-opt/unusual-item-types.rs +++ b/src/test/mir-opt/unusual_item_types.rs diff --git a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir index 7cb9050bc4b..90444b48122 100644 --- a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir +++ b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir @@ -1,10 +1,10 @@ -// MIR for `<impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT` after built +// MIR for `<impl at $DIR/unusual_item_types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT` after built -const <impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT: i32 = { - let mut _0: i32; // return place in scope 0 at $DIR/unusual-item-types.rs:+0:32: +0:35 +const <impl at $DIR/unusual_item_types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT: i32 = { + let mut _0: i32; // return place in scope 0 at $DIR/unusual_item_types.rs:+0:32: +0:35 bb0: { - _0 = const 2_i32; // scope 0 at $DIR/unusual-item-types.rs:+0:38: +0:39 - return; // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:40 + _0 = const 2_i32; // scope 0 at $DIR/unusual_item_types.rs:+0:38: +0:39 + return; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:40 } } diff --git a/src/test/mir-opt/while-storage.rs b/src/test/mir-opt/while_storage.rs index afd083acb34..afd083acb34 100644 --- a/src/test/mir-opt/while-storage.rs +++ b/src/test/mir-opt/while_storage.rs diff --git a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir index a5e7d6afdf3..68aa3e5db32 100644 --- a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir +++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir @@ -1,56 +1,56 @@ // MIR for `while_loop` after PreCodegen fn while_loop(_1: bool) -> () { - debug c => _1; // in scope 0 at $DIR/while-storage.rs:+0:15: +0:16 - let mut _0: (); // return place in scope 0 at $DIR/while-storage.rs:+0:24: +0:24 - let mut _2: bool; // in scope 0 at $DIR/while-storage.rs:+1:11: +1:22 - let mut _3: bool; // in scope 0 at $DIR/while-storage.rs:+1:20: +1:21 - let mut _4: bool; // in scope 0 at $DIR/while-storage.rs:+2:12: +2:23 - let mut _5: bool; // in scope 0 at $DIR/while-storage.rs:+2:21: +2:22 + debug c => _1; // in scope 0 at $DIR/while_storage.rs:+0:15: +0:16 + let mut _0: (); // return place in scope 0 at $DIR/while_storage.rs:+0:24: +0:24 + let mut _2: bool; // in scope 0 at $DIR/while_storage.rs:+1:11: +1:22 + let mut _3: bool; // in scope 0 at $DIR/while_storage.rs:+1:20: +1:21 + let mut _4: bool; // in scope 0 at $DIR/while_storage.rs:+2:12: +2:23 + let mut _5: bool; // in scope 0 at $DIR/while_storage.rs:+2:21: +2:22 bb0: { - goto -> bb1; // scope 0 at $DIR/while-storage.rs:+1:5: +5:6 + goto -> bb1; // scope 0 at $DIR/while_storage.rs:+1:5: +5:6 } bb1: { - StorageLive(_2); // scope 0 at $DIR/while-storage.rs:+1:11: +1:22 - StorageLive(_3); // scope 0 at $DIR/while-storage.rs:+1:20: +1:21 - _3 = _1; // scope 0 at $DIR/while-storage.rs:+1:20: +1:21 - _2 = get_bool(move _3) -> bb2; // scope 0 at $DIR/while-storage.rs:+1:11: +1:22 + StorageLive(_2); // scope 0 at $DIR/while_storage.rs:+1:11: +1:22 + StorageLive(_3); // scope 0 at $DIR/while_storage.rs:+1:20: +1:21 + _3 = _1; // scope 0 at $DIR/while_storage.rs:+1:20: +1:21 + _2 = get_bool(move _3) -> bb2; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22 // mir::Constant - // + span: $DIR/while-storage.rs:10:11: 10:19 + // + span: $DIR/while_storage.rs:10:11: 10:19 // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(<ZST>) } } bb2: { - StorageDead(_3); // scope 0 at $DIR/while-storage.rs:+1:21: +1:22 - switchInt(move _2) -> [false: bb7, otherwise: bb3]; // scope 0 at $DIR/while-storage.rs:+1:11: +1:22 + StorageDead(_3); // scope 0 at $DIR/while_storage.rs:+1:21: +1:22 + switchInt(move _2) -> [false: bb7, otherwise: bb3]; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22 } bb3: { - StorageLive(_4); // scope 0 at $DIR/while-storage.rs:+2:12: +2:23 - StorageLive(_5); // scope 0 at $DIR/while-storage.rs:+2:21: +2:22 - _5 = _1; // scope 0 at $DIR/while-storage.rs:+2:21: +2:22 - _4 = get_bool(move _5) -> bb4; // scope 0 at $DIR/while-storage.rs:+2:12: +2:23 + StorageLive(_4); // scope 0 at $DIR/while_storage.rs:+2:12: +2:23 + StorageLive(_5); // scope 0 at $DIR/while_storage.rs:+2:21: +2:22 + _5 = _1; // scope 0 at $DIR/while_storage.rs:+2:21: +2:22 + _4 = get_bool(move _5) -> bb4; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23 // mir::Constant - // + span: $DIR/while-storage.rs:11:12: 11:20 + // + span: $DIR/while_storage.rs:11:12: 11:20 // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(<ZST>) } } bb4: { - StorageDead(_5); // scope 0 at $DIR/while-storage.rs:+2:22: +2:23 - switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while-storage.rs:+2:12: +2:23 + StorageDead(_5); // scope 0 at $DIR/while_storage.rs:+2:22: +2:23 + switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23 } bb5: { - StorageDead(_4); // scope 0 at $DIR/while-storage.rs:+4:9: +4:10 + StorageDead(_4); // scope 0 at $DIR/while_storage.rs:+4:9: +4:10 goto -> bb8; // scope 0 at no-location } bb6: { - StorageDead(_4); // scope 0 at $DIR/while-storage.rs:+4:9: +4:10 - StorageDead(_2); // scope 0 at $DIR/while-storage.rs:+5:5: +5:6 - goto -> bb1; // scope 0 at $DIR/while-storage.rs:+1:5: +5:6 + StorageDead(_4); // scope 0 at $DIR/while_storage.rs:+4:9: +4:10 + StorageDead(_2); // scope 0 at $DIR/while_storage.rs:+5:5: +5:6 + goto -> bb1; // scope 0 at $DIR/while_storage.rs:+1:5: +5:6 } bb7: { @@ -58,7 +58,7 @@ fn while_loop(_1: bool) -> () { } bb8: { - StorageDead(_2); // scope 0 at $DIR/while-storage.rs:+5:5: +5:6 - return; // scope 0 at $DIR/while-storage.rs:+6:2: +6:2 + StorageDead(_2); // scope 0 at $DIR/while_storage.rs:+5:5: +5:6 + return; // scope 0 at $DIR/while_storage.rs:+6:2: +6:2 } } diff --git a/src/test/run-make-fulldeps/libtest-json/output-default.json b/src/test/run-make-fulldeps/libtest-json/output-default.json index 63342abc6ef..ad22b66eda6 100644 --- a/src/test/run-make-fulldeps/libtest-json/output-default.json +++ b/src/test/run-make-fulldeps/libtest-json/output-default.json @@ -2,7 +2,7 @@ { "type": "test", "event": "started", "name": "a" } { "type": "test", "name": "a", "event": "ok" } { "type": "test", "event": "started", "name": "b" } -{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'b' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n" } { "type": "test", "event": "started", "name": "c" } { "type": "test", "name": "c", "event": "ok" } { "type": "test", "event": "started", "name": "d" } diff --git a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json index 8f19114460e..ec98172eb1c 100644 --- a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json +++ b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json @@ -2,9 +2,9 @@ { "type": "test", "event": "started", "name": "a" } { "type": "test", "name": "a", "event": "ok", "stdout": "print from successful test\n" } { "type": "test", "event": "started", "name": "b" } -{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'b' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n" } { "type": "test", "event": "started", "name": "c" } -{ "type": "test", "name": "c", "event": "ok", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:15:5\n" } +{ "type": "test", "name": "c", "event": "ok", "stdout": "thread 'c' panicked at 'assertion failed: false', f.rs:15:5\n" } { "type": "test", "event": "started", "name": "d" } { "type": "test", "name": "d", "event": "ignored", "message": "msg" } { "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME } diff --git a/src/test/run-make/emit-shared-files/Makefile b/src/test/run-make/emit-shared-files/Makefile index 09b4c29c1dd..cad0c9e5b81 100644 --- a/src/test/run-make/emit-shared-files/Makefile +++ b/src/test/run-make/emit-shared-files/Makefile @@ -23,24 +23,24 @@ invocation-only: toolchain-only: $(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources --output $(TOOLCHAIN_ONLY) --resource-suffix=-xxx --extend-css z.css x.rs - [ -e $(TOOLCHAIN_ONLY)/storage-xxx.js ] - ! [ -e $(TOOLCHAIN_ONLY)/SourceSerif4-It.ttf.woff2 ] + [ -e $(TOOLCHAIN_ONLY)/static.files/storage-*.js ] + [ -e $(TOOLCHAIN_ONLY)/static.files/SourceSerif4-It-*.ttf.woff2 ] ! [ -e $(TOOLCHAIN_ONLY)/search-index-xxx.js ] ! [ -e $(TOOLCHAIN_ONLY)/x/index.html ] ! [ -e $(TOOLCHAIN_ONLY)/theme.css ] - [ -e $(TOOLCHAIN_ONLY)/main-xxx.js ] + [ -e $(TOOLCHAIN_ONLY)/static.files/main-*.js ] ! [ -e $(TOOLCHAIN_ONLY)/y-xxx.css ] all-shared: $(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources,unversioned-shared-resources --output $(ALL_SHARED) --resource-suffix=-xxx --extend-css z.css x.rs - [ -e $(ALL_SHARED)/storage-xxx.js ] - [ -e $(ALL_SHARED)/SourceSerif4-It.ttf.woff2 ] + [ -e $(ALL_SHARED)/static.files/storage-*.js ] + [ -e $(ALL_SHARED)/static.files/SourceSerif4-It-*.ttf.woff2 ] ! [ -e $(ALL_SHARED)/search-index-xxx.js ] ! [ -e $(ALL_SHARED)/settings.html ] ! [ -e $(ALL_SHARED)/x ] ! [ -e $(ALL_SHARED)/src ] ! [ -e $(ALL_SHARED)/theme.css ] - [ -e $(ALL_SHARED)/main-xxx.js ] + [ -e $(ALL_SHARED)/static.files/main-*.js ] ! [ -e $(ALL_SHARED)/y-xxx.css ] diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout index 80cd08ee167..b280698230d 100644 --- a/src/test/run-make/issue-88756-default-output/output-default.stdout +++ b/src/test/run-make/issue-88756-default-output/output-default.stdout @@ -115,8 +115,6 @@ Options: Provide width of the output for truncated error messages --json CONFIG Configure the structure of JSON diagnostics - --disable-minification - Disable minification applied on JS files -A, --allow LINT Set lint allowed -W, --warn LINT Set lint warnings --force-warn LINT @@ -173,6 +171,8 @@ Options: --scrape-tests Include test code when scraping examples --with-examples path to function call information (for displaying examples in the documentation) + --disable-minification + removed --plugin-path DIR removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for diff --git a/src/test/run-make/valid-print-requests/valid-print-requests.stderr b/src/test/run-make/valid-print-requests/valid-print-requests.stderr index 85782866d12..5191e467648 100644 --- a/src/test/run-make/valid-print-requests/valid-print-requests.stderr +++ b/src/test/run-make/valid-print-requests/valid-print-requests.stderr @@ -1,2 +1,2 @@ -error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `link-args` +error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `link-args`, `split-debuginfo` diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs index 7f365ce2bba..ece4dea9aaf 100644 --- a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs @@ -1,7 +1,8 @@ #![feature(unsized_locals)] #![feature(unboxed_closures)] +#![feature(tuple_trait)] -pub trait FnOnce<Args> { +pub trait FnOnce<Args: std::marker::Tuple> { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs index a78b897d194..94df2b0b83f 100644 --- a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs @@ -1,7 +1,8 @@ #![feature(unsized_locals)] #![feature(unboxed_closures)] +#![feature(tuple_trait)] -pub trait FnOnce<Args> { +pub trait FnOnce<Args: std::marker::Tuple> { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } diff --git a/src/test/rustdoc-gui/code-tags.goml b/src/test/rustdoc-gui/code-tags.goml index 837a2c1d57f..94c1a6525aa 100644 --- a/src/test/rustdoc-gui/code-tags.goml +++ b/src/test/rustdoc-gui/code-tags.goml @@ -1,4 +1,8 @@ // This test ensures that items and documentation code blocks are wrapped in <pre><code> + +// We need to disable this check because `implementors/test_docs/trait.AnotherOne.js` +// doesn't exist. +fail-on-request-error: false goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html" size: (1080, 600) // There should be four doc codeblocks. diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml index 911ee34be94..fec21ad35c3 100644 --- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml +++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml @@ -30,10 +30,10 @@ wait-for: "#settings" assert-css: ("#settings", {"display": "block"}) // Then, click the toggle button. -click: "input#line-numbers + .slider" +click: "input#line-numbers" wait-for: 100 // wait-for-false does not exist assert-false: "pre.example-line-numbers" // Finally, turn it on again. -click: "input#line-numbers + .slider" +click: "input#line-numbers" wait-for: "pre.example-line-numbers" diff --git a/src/test/rustdoc-gui/huge-logo.goml b/src/test/rustdoc-gui/huge-logo.goml new file mode 100644 index 00000000000..01f06771c15 --- /dev/null +++ b/src/test/rustdoc-gui/huge-logo.goml @@ -0,0 +1,21 @@ +// huge_logo crate has a custom 712x860 logo +// test to ensure the maximum size in the layout works correctly +goto: "file://" + |DOC_PATH| + "/huge_logo/index.html" + +size: (1280, 1024) +// offsetWidth = width of sidebar +assert-property: (".sidebar .logo-container", {"offsetWidth": "200", "offsetHeight": 100}) +assert-property: (".sidebar .logo-container img", {"offsetWidth": "100", "offsetHeight": 100}) + +size: (400, 600) +// offset = size + margin +assert-property: (".mobile-topbar .logo-container", {"offsetWidth": "55", "offsetHeight": 45}) +assert-property: (".mobile-topbar .logo-container img", {"offsetWidth": "35", "offsetHeight": 35}) + +goto: "file://" + |DOC_PATH| + "/src/huge_logo/lib.rs.html" + +size: (1280, 1024) +assert-property: (".sub-logo-container", {"offsetWidth": "60", "offsetHeight": 60}) + +size: (400, 600) +assert-property: (".sub-logo-container", {"offsetWidth": "35", "offsetHeight": 35}) diff --git a/src/test/rustdoc-gui/item-decl-colors.goml b/src/test/rustdoc-gui/item-decl-colors.goml index ce688287a74..9a46f256056 100644 --- a/src/test/rustdoc-gui/item-decl-colors.goml +++ b/src/test/rustdoc-gui/item-decl-colors.goml @@ -1,4 +1,9 @@ // This test ensures that the color of the items in the type decl are working as expected. + +// We need to disable this check because `implementors/test_docs/trait.TraitWithoutGenerics.js` +// doesn't exist. +fail-on-request-error: false + define-function: ( "check-colors", ( diff --git a/src/test/rustdoc-gui/no-docblock.goml b/src/test/rustdoc-gui/no-docblock.goml index 2366a60f5c6..17a955064d7 100644 --- a/src/test/rustdoc-gui/no-docblock.goml +++ b/src/test/rustdoc-gui/no-docblock.goml @@ -1,4 +1,9 @@ // This test checks that there are margins applied to methods with no docblocks. + +// We need to disable this check because `implementors/test_docs/trait.TraitWithNoDocblock.js` +// doesn't exist. +fail-on-request-error: false + goto: "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithNoDocblocks.html" // Check that the two methods are more than 24px apart. compare-elements-position-near-false: ("//*[@id='tymethod.first_fn']", "//*[@id='tymethod.second_fn']", {"y": 24}) diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml index efe0cb15f08..d8261d8dc90 100644 --- a/src/test/rustdoc-gui/notable-trait.goml +++ b/src/test/rustdoc-gui/notable-trait.goml @@ -25,22 +25,28 @@ assert-position: ( {"x": 951}, ) // The tooltip should be beside the `i` +// Also, clicking the tooltip should bring its text into the DOM +assert-count: ("//*[@class='notable-traits-tooltiptext']", 0) click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']" +assert-count: ("//*[@class='notable-traits-tooltiptext']", 1) compare-elements-position-near: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", - "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", + "//*[@class='notable-traits-tooltiptext']", {"y": 2} ) compare-elements-position-false: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", - "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", + "//*[@class='notable-traits-tooltiptext']", ("x") ) // The docblock should be flush with the border. assert-css: ( - "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']/*[@class='docblock']", + "//*[@class='notable-traits-tooltiptext']/*[@class='docblock']", {"margin-left": "0px"} ) +click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']" +move-cursor-to: "//h1" +assert-count: ("//*[@class='notable-traits-tooltiptext']", 0) // Now only the `i` should be on the next line. size: (1055, 600) @@ -98,26 +104,31 @@ assert-position: ( {"x": 289}, ) // The tooltip should be below `i` +click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']" +assert-count: ("//*[@class='notable-traits-tooltiptext']", 1) compare-elements-position-near-false: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", - "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", + "//*[@class='notable-traits-tooltiptext']", {"y": 2} ) compare-elements-position-false: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", - "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", + "//*[@class='notable-traits-tooltiptext']", ("x") ) compare-elements-position-near: ( - "//*[@id='method.create_an_iterator_from_read']/parent::*", - "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']", - {"x": 5} + "//*[@id='method.create_an_iterator_from_read']", + "//*[@class='notable-traits-tooltiptext']", + {"x": 10} ) // The docblock should be flush with the border. assert-css: ( - "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']/*[@class='docblock']", + "//*[@class='notable-traits-tooltiptext']/*[@class='docblock']", {"margin-left": "0px"} ) +click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']" +move-cursor-to: "//h1" +assert-count: ("//*[@class='notable-traits-tooltiptext']", 0) // Checking on very small mobile. The `i` should be on its own line. size: (365, 600) @@ -126,3 +137,76 @@ compare-elements-position-false: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", ("y", "x"), ) + +// Now check the colors. +define-function: ( + "check-colors", + (theme, header_color, content_color, type_color, trait_color), + [ + ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"), + // This is needed to ensure that the text color is computed. + ("show-text", true), + + // Setting the theme. + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + // We reload the page so the local storage settings are being used. + ("reload"), + + ("move-cursor-to", "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"), + ("assert-count", (".notable-traits-tooltiptext", 1)), + + ("assert-css", ( + ".notable-traits-tooltiptext h3.notable", + {"color": |header_color|}, + ALL, + )), + ("assert-css", ( + ".notable-traits-tooltiptext pre.content", + {"color": |content_color|}, + ALL, + )), + ("assert-css", ( + ".notable-traits-tooltiptext pre.content a.struct", + {"color": |type_color|}, + ALL, + )), + ("assert-css", ( + ".notable-traits-tooltiptext pre.content a.trait", + {"color": |trait_color|}, + ALL, + )), + ] +) + +call-function: ( + "check-colors", + { + "theme": "ayu", + "content_color": "rgb(230, 225, 207)", + "header_color": "rgb(255, 255, 255)", + "type_color": "rgb(255, 160, 165)", + "trait_color": "rgb(57, 175, 215)", + }, +) + +call-function: ( + "check-colors", + { + "theme": "dark", + "content_color": "rgb(221, 221, 221)", + "header_color": "rgb(221, 221, 221)", + "type_color": "rgb(45, 191, 184)", + "trait_color": "rgb(183, 140, 242)", + }, +) + +call-function: ( + "check-colors", + { + "theme": "light", + "content_color": "rgb(0, 0, 0)", + "header_color": "rgb(0, 0, 0)", + "type_color": "rgb(173, 55, 138)", + "trait_color": "rgb(110, 79, 201)", + }, +) diff --git a/src/test/rustdoc-gui/run-on-hover.goml b/src/test/rustdoc-gui/run-on-hover.goml index 6c785e1c4bb..57d63049f28 100644 --- a/src/test/rustdoc-gui/run-on-hover.goml +++ b/src/test/rustdoc-gui/run-on-hover.goml @@ -1,7 +1,54 @@ // Example code blocks sometimes have a "Run" button to run them on the // Playground. That button is hidden until the user hovers over the code block. -// This test checks that it is hidden, and that it shows on hover. +// This test checks that it is hidden, and that it shows on hover. It also +// checks for its color. goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html" -assert-css: (".test-arrow", {"visibility": "hidden"}) -move-cursor-to: ".example-wrap" -assert-css: (".test-arrow", {"visibility": "visible"}) +show-text: true + +define-function: ( + "check-run-button", + (theme, color, background, hover_color, hover_background), + [ + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + ("assert-css", (".test-arrow", {"visibility": "hidden"})), + ("move-cursor-to", ".example-wrap"), + ("assert-css", (".test-arrow", { + "visibility": "visible", + "color": |color|, + "background-color": |background|, + "font-size": "22px", + "border-radius": "5px", + })), + ("move-cursor-to", ".test-arrow"), + ("assert-css", (".test-arrow:hover", { + "visibility": "visible", + "color": |hover_color|, + "background-color": |hover_background|, + "font-size": "22px", + "border-radius": "5px", + })), + ], +) + +call-function: ("check-run-button", { + "theme": "ayu", + "color": "rgb(120, 135, 151)", + "background": "rgba(57, 175, 215, 0.09)", + "hover_color": "rgb(197, 197, 197)", + "hover_background": "rgba(57, 175, 215, 0.37)", +}) +call-function: ("check-run-button", { + "theme": "dark", + "color": "rgb(222, 222, 222)", + "background": "rgba(78, 139, 202, 0.2)", + "hover_color": "rgb(222, 222, 222)", + "hover_background": "rgb(78, 139, 202)", +}) +call-function: ("check-run-button", { + "theme": "light", + "color": "rgb(245, 245, 245)", + "background": "rgba(78, 139, 202, 0.2)", + "hover_color": "rgb(245, 245, 245)", + "hover_background": "rgb(78, 139, 202)", +}) diff --git a/src/test/rustdoc-gui/rust-logo.goml b/src/test/rustdoc-gui/rust-logo.goml index 6c8dc859419..816cc9abd69 100644 --- a/src/test/rustdoc-gui/rust-logo.goml +++ b/src/test/rustdoc-gui/rust-logo.goml @@ -17,6 +17,15 @@ define-function: ( ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), ("reload"), ("assert-css", (".rust-logo", {"filter": |filter|})), + // Now we check that the non-rust logos don't have a CSS filter set. + ("goto", "file://" + |DOC_PATH| + "/huge_logo/index.html"), + // Changing theme on the new page (again...). + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + // Check there is no rust logo + ("assert-false", ".rust-logo"), + // Check there is no filter. + ("assert-css", (".sidebar .logo-container img", {"filter": "none"})), ], ) diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml index 27db816e685..e0228694eec 100644 --- a/src/test/rustdoc-gui/search-filter.goml +++ b/src/test/rustdoc-gui/search-filter.goml @@ -14,6 +14,7 @@ click: "#crate-search" // We select "lib2" option then press enter to change the filter. press-key: "ArrowDown" press-key: "ArrowDown" +press-key: "ArrowDown" press-key: "Enter" // Waiting for the search results to appear... wait-for: "#titles" @@ -37,6 +38,7 @@ assert-property: ("#crate-search", {"value": "lib2"}) click: "#crate-search" press-key: "ArrowUp" press-key: "ArrowUp" +press-key: "ArrowUp" press-key: "Enter" // Waiting for the search results to appear... wait-for: "#titles" diff --git a/src/test/rustdoc-gui/search-no-result.goml b/src/test/rustdoc-gui/search-no-result.goml new file mode 100644 index 00000000000..b88be32c94a --- /dev/null +++ b/src/test/rustdoc-gui/search-no-result.goml @@ -0,0 +1,36 @@ +// The goal of this test is to check the color of the "no result" links. +goto: "file://" + |DOC_PATH| + "/lib2/index.html?search=sdkfskjfsdks" +show-text: true + +define-function: ( + "check-no-result", + (theme, link, link_hover), + [ + // Changing theme. + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + ("wait-for", "#results"), + ("assert", ".search-failed.active"), + ("assert-css", ("#results a", {"color": |link|}, ALL)), + ("move-cursor-to", "#results a"), + ("assert-css", ("#results a:hover", {"color": |link_hover|})), + // Moving the cursor to some other place to not create issues with next function run. + ("move-cursor-to", ".search-input"), + ] +) + +call-function: ("check-no-result", { + "theme": "ayu", + "link": "rgb(57, 175, 215)", + "link_hover": "rgb(57, 175, 215)", +}) +call-function: ("check-no-result", { + "theme": "dark", + "link": "rgb(210, 153, 29)", + "link_hover": "rgb(210, 153, 29)", +}) +call-function: ("check-no-result", { + "theme": "light", + "link": "rgb(56, 115, 173)", + "link_hover": "rgb(56, 115, 173)", +}) diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml index 69bb30df954..d437ad75970 100644 --- a/src/test/rustdoc-gui/search-result-color.goml +++ b/src/test/rustdoc-gui/search-result-color.goml @@ -67,7 +67,7 @@ reload: // Waiting for the search results to appear... wait-for: "#titles" assert-css: ( - "//*[@class='desc']//*[text()='Just a normal struct.']", + "//*[@class='desc'][text()='Just a normal struct.']", {"color": "rgb(197, 197, 197)"}, ) assert-css: ( @@ -75,6 +75,12 @@ assert-css: ( {"color": "rgb(0, 150, 207)"}, ) +// Checking the color of the bottom border. +assert-css: ( + ".search-results > a", + {"border-bottom-color": "rgba(170, 170, 170, 0.2)"} +) + // Checking the color of "keyword" text. assert-css: ( "//*[@class='result-name']//*[text()='(keyword)']", @@ -153,7 +159,7 @@ assert-css: ( ) // Checking color and background on hover. -move-cursor-to: "//*[@class='desc']//*[text()='Just a normal struct.']" +move-cursor-to: "//*[@class='desc'][text()='Just a normal struct.']" assert-css: ( "//*[@class='result-name']/*[text()='test_docs::']", {"color": "rgb(255, 255, 255)"}, @@ -173,7 +179,7 @@ reload: // Waiting for the search results to appear... wait-for: "#titles" assert-css: ( - "//*[@class='desc']//*[text()='Just a normal struct.']", + "//*[@class='desc'][text()='Just a normal struct.']", {"color": "rgb(221, 221, 221)"}, ) assert-css: ( @@ -181,6 +187,12 @@ assert-css: ( {"color": "rgb(221, 221, 221)"}, ) +// Checking the color of the bottom border. +assert-css: ( + ".search-results > a", + {"border-bottom-color": "rgba(170, 170, 170, 0.2)"} +) + // Checking the color for "keyword" text. assert-css: ( "//*[@class='result-name']//*[text()='(keyword)']", @@ -264,7 +276,7 @@ reload: // Waiting for the search results to appear... wait-for: "#titles" assert-css: ( - "//*[@class='desc']//*[text()='Just a normal struct.']", + "//*[@class='desc'][text()='Just a normal struct.']", {"color": "rgb(0, 0, 0)"}, ) assert-css: ( @@ -272,6 +284,12 @@ assert-css: ( {"color": "rgb(0, 0, 0)"}, ) +// Checking the color of the bottom border. +assert-css: ( + ".search-results > a", + {"border-bottom-color": "rgba(170, 170, 170, 0.2)"} +) + // Checking the color for "keyword" text. assert-css: ( "//*[@class='result-name']//*[text()='(keyword)']", diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml index 053bfd8c905..fa349c872ae 100644 --- a/src/test/rustdoc-gui/search-result-display.goml +++ b/src/test/rustdoc-gui/search-result-display.goml @@ -7,7 +7,7 @@ press-key: 'Enter' wait-for: "#crate-search" // The width is returned by "getComputedStyle" which returns the exact number instead of the // CSS rule which is "50%"... -assert-css: (".search-results div.desc", {"width": "318px"}) +assert-css: (".search-results div.desc", {"width": "310px"}) size: (600, 100) // As counter-intuitive as it may seem, in this width, the width is "100%", which is why // when computed it's larger. @@ -35,3 +35,43 @@ assert-css: ("#crate-search", {"width": "527px"}) assert-css: (".search-results-title", {"height": "44px", "width": "640px"}) // And we check that the `<select>` isn't bigger than its container (".search-results-title"). assert-css: ("#search", {"width": "640px"}) + +// Now checking that the crate filter is working as expected too. +show-text: true +define-function: ( + "check-filter", + (theme, border, filter, hover_border, hover_filter), + [ + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + ("wait-for", "#crate-search"), + ("assert-css", ("#crate-search", {"border": "1px solid " + |border|})), + ("assert-css", ("#crate-search-div::after", {"filter": |filter|})), + ("move-cursor-to", "#crate-search"), + ("assert-css", ("#crate-search", {"border": "1px solid " + |hover_border|})), + ("assert-css", ("#crate-search-div::after", {"filter": |hover_filter|})), + ("move-cursor-to", ".search-input"), + ], +) + +call-function: ("check-filter", { + "theme": "ayu", + "border": "rgb(92, 103, 115)", + "filter": "invert(0.41) sepia(0.12) saturate(4.87) hue-rotate(171deg) brightness(0.94) contrast(0.94)", + "hover_border": "rgb(224, 224, 224)", + "hover_filter": "invert(0.98) sepia(0.12) saturate(0.81) hue-rotate(343deg) brightness(1.13) contrast(0.76)", +}) +call-function: ("check-filter", { + "theme": "dark", + "border": "rgb(224, 224, 224)", + "filter": "invert(0.94) sepia(0) saturate(7.21) hue-rotate(255deg) brightness(0.9) contrast(0.9)", + "hover_border": "rgb(33, 150, 243)", + "hover_filter": "invert(0.69) sepia(0.6) saturate(66.13) hue-rotate(184deg) brightness(1) contrast(0.91)", +}) +call-function: ("check-filter", { + "theme": "light", + "border": "rgb(224, 224, 224)", + "filter": "invert(1) sepia(0) saturate(42.23) hue-rotate(289deg) brightness(1.14) contrast(0.76)", + "hover_border": "rgb(113, 113, 113)", + "hover_filter": "invert(0.44) sepia(0.18) saturate(0.23) hue-rotate(317deg) brightness(0.96) contrast(0.93)", +}) diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml index f258f4d2a83..7e7971d47fb 100644 --- a/src/test/rustdoc-gui/settings.goml +++ b/src/test/rustdoc-gui/settings.goml @@ -48,7 +48,8 @@ assert: ".setting-line.hidden #preferred-light-theme" assert-property: ("#theme .choices #theme-dark", {"checked": "true"}) // Some style checks... -// First we check the "default" display. +move-cursor-to: "#settings-menu > a" +// First we check the "default" display for radio buttons. assert-css: ( "#theme-dark", { @@ -57,7 +58,7 @@ assert-css: ( }, ) assert-css: ("#theme-light", {"border-color": "rgb(221, 221, 221)", "box-shadow": "none"}) -// Let's start with the hover. +// Let's start with the hover for radio buttons. move-cursor-to: "#theme-dark" assert-css: ( "#theme-dark", @@ -69,7 +70,7 @@ assert-css: ( move-cursor-to: "#theme-light" assert-css: ("#theme-light", {"border-color": "rgb(33, 150, 243)", "box-shadow": "none"}) move-cursor-to: "#theme-ayu" -// Let's now check with the focus. +// Let's now check with the focus for radio buttons. focus: "#theme-dark" assert-css: ( "#theme-dark", @@ -86,7 +87,7 @@ assert-css: ( "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", }, ) -// Now we check we both focus and hover. +// Now we check we both focus and hover for radio buttons. move-cursor-to: "#theme-dark" focus: "#theme-dark" assert-css: ( @@ -106,6 +107,80 @@ assert-css: ( }, ) +// First we check the "default" display for toggles. +assert-css: ( + "#auto-hide-large-items", + { + "background-color": "rgb(33, 150, 243)", + "border-color": "rgb(221, 221, 221)", + }, +) +assert-css: ( + "#use-system-theme", + { + "background-color": "rgba(0, 0, 0, 0)", + "border-color": "rgb(221, 221, 221)", + } +) +// Let's start with the hover for toggles. +move-cursor-to: "#auto-hide-large-items" +assert-css: ( + "#auto-hide-large-items", + { + "background-color": "rgb(33, 150, 243)", + "border-color": "rgb(33, 150, 243)", + }, +) +move-cursor-to: "#use-system-theme" +assert-css: ( + "#use-system-theme", + { + "background-color": "rgba(0, 0, 0, 0)", + "border-color": "rgb(33, 150, 243)", + } +) +move-cursor-to: "#settings-menu > a" +// Let's now check with the focus for toggles. +focus: "#auto-hide-large-items" +assert-css: ( + "#auto-hide-large-items", + { + "background-color": "rgb(33, 150, 243)", + "border-color": "rgb(221, 221, 221)", + "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + }, +) +focus: "#use-system-theme" +assert-css: ( + "#use-system-theme", + { + "background-color": "rgba(0, 0, 0, 0)", + "border-color": "rgb(221, 221, 221)", + "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + }, +) +// Now we check we both focus and hover for toggles. +move-cursor-to: "#auto-hide-large-items" +focus: "#auto-hide-large-items" +assert-css: ( + "#auto-hide-large-items", + { + "background-color": "rgb(33, 150, 243)", + "border-color": "rgb(33, 150, 243)", + "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + }, +) +move-cursor-to: "#use-system-theme" +focus: "#use-system-theme" +assert-css: ( + "#use-system-theme", + { + "background-color": "rgba(0, 0, 0, 0)", + "border-color": "rgb(33, 150, 243)", + "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + }, +) + // We now switch the display. click: "#use-system-theme" // Wait for the hidden element to show up. @@ -118,7 +193,7 @@ assert: ".setting-line.hidden #theme" assert-text: ("#preferred-dark-theme .setting-name", "Preferred dark theme") assert-text: ("#preferred-light-theme .setting-name", "Preferred light theme") -// We now check that clicking on the "sliders"' text is like clicking on the slider. +// We now check that clicking on the toggles' text is like clicking on the checkbox. // To test it, we use the "Disable keyboard shortcuts". local-storage: {"rustdoc-disable-shortcuts": "false"} click: ".setting-line:last-child .toggle .label" @@ -141,10 +216,7 @@ assert-css: ("#settings-menu .popover", {"display": "none"}) // Now we go to the settings page to check that the CSS is loaded as expected. goto: "file://" + |DOC_PATH| + "/settings.html" wait-for: "#settings" -assert-css: ( - ".setting-line .toggle .slider", - {"width": "45px", "margin-right": "20px", "border": "0px none rgb(0, 0, 0)"}, -) +assert-css: (".setting-line", {"position": "relative"}) assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS) compare-elements-position: (".sub form", "#settings", ("x")) @@ -162,4 +234,4 @@ reload: size: (300, 1000) click: "#settings-menu" wait-for: "#settings" -assert-css: ("#settings .slider", {"width": "45px"}, ALL) +assert-css: (".setting-line", {"position": "relative"}) diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 9ba66368772..e9a987d52bb 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -28,7 +28,7 @@ assert: "//*[@class='dir-entry' and @open]/*[text()='sub_mod']" // Only "another_folder" should be "open" in "lib2". assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']" // All other trees should be collapsed. -assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 5) +assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 6) // We now switch to mobile mode. size: (600, 600) diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index a2dac2aa681..3c4db978d5f 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -78,7 +78,7 @@ assert: ".source-sidebar-expanded" // We check that the first entry of the sidebar is collapsed assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) -assert-text: ("#source-sidebar details:first-of-type > summary", "implementors") +assert-text: ("#source-sidebar details:first-of-type > summary", "huge_logo") // We now click on it. click: "#source-sidebar details:first-of-type > summary" assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) diff --git a/src/test/rustdoc-gui/src-font-size.goml b/src/test/rustdoc-gui/src-font-size.goml index b17dfd94cf0..9233f37444b 100644 --- a/src/test/rustdoc-gui/src-font-size.goml +++ b/src/test/rustdoc-gui/src-font-size.goml @@ -9,3 +9,8 @@ assert-css: (".impl.has-srclink .code-header", {"font-size": "18px", "font-weigh // Check the impl items. assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px", "font-weight": 400}, ALL) assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px", "font-weight": 600}, ALL) + +// Check that we can click on source link +store-document-property: (url, "URL") +click: ".impl-items .has-srclink .srclink" +assert-document-property-false: {"URL": |url|} diff --git a/src/test/rustdoc-gui/src/huge_logo/Cargo.lock b/src/test/rustdoc-gui/src/huge_logo/Cargo.lock new file mode 100644 index 00000000000..14280575064 --- /dev/null +++ b/src/test/rustdoc-gui/src/huge_logo/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "huge_logo" +version = "0.1.0" diff --git a/src/test/rustdoc-gui/src/huge_logo/Cargo.toml b/src/test/rustdoc-gui/src/huge_logo/Cargo.toml new file mode 100644 index 00000000000..3f10d09c80a --- /dev/null +++ b/src/test/rustdoc-gui/src/huge_logo/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "huge_logo" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/test/rustdoc-gui/src/huge_logo/src/lib.rs b/src/test/rustdoc-gui/src/huge_logo/src/lib.rs new file mode 100644 index 00000000000..ec137fb9a88 --- /dev/null +++ b/src/test/rustdoc-gui/src/huge_logo/src/lib.rs @@ -0,0 +1,17 @@ +// ignore-tidy-linelength +#![doc(html_logo_url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsgAAANcCAQAAADoIpEcAAAAAmJLR0QA/4ePzL8AAHSISURBVHja7Z15vFbT/sefzNflXtzr+qHOXvs5p051KtVJIg1IhqRoQlHKVKbKUBkaRQiRpEhKkqIQkURyJJUkQxNKs4bTPJ7h8/uj5Ax772fvZ6+999r7+bzXP14vPXufs9b3+znr+a7v+n5jMUIIIYQQ95zxTz1Tr6e10Dpp3bX+4nkxRrwnZonvxW/iN/Gb2CpyRa7YIyAgIHaLXJErcsVqsUxfoM0QU7Sx+ouij9ZFuyZ+oZ6ZeTLnkxBCbJJ1XLy8uEx01p4Wb4vZYrnYfVhqZY1csVC8qz+j3y0u1zXONyGEFCPt1PiF4nZtqJgpVol8yQJsObRdYp4YrT+gXZTxL64DISRlySirXSsGielirZ8SbDoKxBJtrH63qB47imtDCEkJxAnaRdrD4j2xXgkZNg5qvCe6UpgJIdHlmLRs0UObIfYpK8QlwxmbxUT9pvi/uXSEkMig6frdYnp4hLjE2C+m67ee/R+uIyEkzBwVv1AMEj+FVIiLj4PiI/0mHvwRQkJIWpboK36LhBQXHfvExHijWBmuLyEkFIiK+sAISnHR8YvolnYqV5oQojAZx+uttBmiMNJi/Hf+8ghRkWtOCFFyXyyeF7mpIMXFMpenaBdw7QkhChG/UEz0936dSkPPEQ1pA4SQwMk+Vr9RfJ+qUlxkTIufS2sghAQpxjdpKyjGh0ehmKjptApCiP8cpbcSyynDJcYB8Tzv9RFCfEW7Riyj/JqM9XprWgghxB8xriG+oOwmGJ/HK9BSCCGeIv5PvCYKKLg2xh6tO2vFEUK8oox+k9hCqXUwvk7PoNkQQqSjZ4ovKbGOxw5xM22HECKTo7WHQls6M/gxPuskmhAhRM7eWOPe2OVYGq9KOyKEuEa0Fzsoqa7Hbq0tbYkQ4oKsk8QEiqm08QSzLgghSRKvoP1IGZU6PmK/EUJIEmgtxE5KqPSxqNxZtC1CiBPK6I+lRpH5AMbv8fI0MEKITTKO18dROD0cW0QdWhkhxAYV/qvnUDS9vi6i16OlEUISIARLavrTj4+STAixJF5BrKZY+lZ86CJaHCHETI6rig0USj93ydr5tDpCiAFaTVZy833kpleh5RFCSqBnio0UyADGOnbhI4QUD1aUZ7AisLE843RaICHkMELwKC/IoedkHE8rJITEYrGyp4mlFMWAx4RYGVoiISlPxvGsdaxExsXDtEVCUp0y2liKoRKjUDSnORKS0oi+lEJ1UuCYb0FICqM3FQUUQpVKc551Iq2SkJQkXkFspwgqNkbQLglJQbJOYjcQJVPgWtM2CUm96PEYip+akeR4Gq2TkNSS4zaUPmXHTLZCJSSFyCgrtlL4FA5b3EUbJSRVOErMpugpXpaTCXCEpEi4ohslT/nxOa9SE5ICpMXFbgpeCHbJnWirhESdMuJTil0oxtYK/6W5EhJp9FsodaHZI79CeyUkyuGKU8UmCl1oRgE77hES5f3xMMpcqPbI85mRTEhESa+i5VHkQpaRfCPtlpBIwkL0IRyry/6DlktI5IhfRXljJxFCiAocLX6iuIVybE87leZLSKTQOlLaQjv60H4JiRBZx4k/KGyhHdvi/6YNExIZ9Fspa6EevWnDhEQnfrycohbuOLI4hWZMSCQQ7Slpoc9HfoR2TEgUKCN+oaCFv9RQxr9oyoSEHq0J5SwS+cgP0ZYJCX/AYibFLBJjffaxtGZCQk28qiikmEVktKE9ExLu/fFrFLLIBC2+oj0TEub98b/FHgpZdEZaNm2akNCi300RYw8RQogSaD9SxCI19p79H1o1IeGU4wsoYZHbI99HuyYklIiXKWCRG7+xqRMhISTrOLGFAhbB0ZC2TUj4AhYtKF482COEqBGwmELximZ1ZHECrZuQUJF5sthH8Ypo5beWtG9CwhWwuIHCFdkxhfZNSKjQ36FwRXYcYDYyISHirBPFbgpXhMfttHFCwrM/vpqiFekxmzZOSHgEeRhFK9KjsOzZtHJCQoL4laLFoAUhRAE0nYIV+dS3D2nnhIRjf9yZghX5sT/rJFo6IWEQZN7RS4XRjJZOiPocI7ZTrlIgaPEqTZ0Q5dHrUaxSYvzJQpyEKI82gGKVIuM8WjshqkeQZ1OqUiRo8RitnRClyT6WfaZTZsylvROidsCiJoUqZUrV52X8ixZPiMoBC+Ygp5IkN6HFE6KyIL9OmUqhKPJgWjwhKgvyUspUCo3vaPGEqCvHp4gCylQKjYK0U2n1hKgqyJdRpHiBmhCihiD3pkSl2BhCqydEVUGeTIlKsbGIVk+IqoK8jBKValHkzJNp94QoSMbxWh4lKuVGA1o+IQqin0N5SsFc5Ado+YQoiHYD5SkFx0RaPiEq7pAfozyl4FhFyydEQdi6KUWDFmfQ9glRT5CZY5GagtyUtk+IanJ8gsinOKVkzbf+tH5CFCMti9KUouNjWj8hiqFdSWlK0bGW1k+IaiELlqZP2XH2f2j/hKglyIMoTCl7rFef9k+IWoL8FoUpZY/1utD+CVFLkOdQmFJ2vET7J0QtQV5HYUrZHfJXtH9CFCLrODZvSuGxPVaGPkCIMpRLpyyl8sgoSx8gRJ2ARQOKUkoHLa6gDxCiDHprilJKj3voA4Qog3YnRSlhti7qoAXaojO6oAs6oA0aoEJUfrvn6QOEqBOy6EvBNRuX4FG8g+U4ACPWYjoGowXSw/3H5kP6ACHqCPJLFF4jKR6O32GPXLyD66CH9XddSh8gRJ2QxSTKb/HwRGfMRSGcshL9UCmMv/GB2NH0AkJU2SHPogj/PW7FL0ieLXgcmeH7rQW9gBBVBPlnyvCh0RBfwj3r0T1kv3e8Eb2AEFVCFpspxQIZeAEHIYvPUDtMv/0d9AJC1OAotm8SaIBFkEsu7grP1ZCn6QaEKEHmyZTjztgNLxgXllzlifQDQtQIWJwpOR6JZngaH2MZcgEAediM7zEJPXCBmvFTDE0io8Iui1AnDII8h35AiBLEK8hz7Dp4ERtNxakQC/GAYjkIFTAN3rIBjdUPWayhHxCixg65phynzsYY5NkQqM3ojQxFhKgyvoL37EAb1SU5P3YMPYEQBZBT663L4QCFPVbheiXkeAH8Ya/ykswSnISosUNu4l7YPnAsUQUYHnAFiPKYBf/Yi9ZqBy3OpycQosIO+Tp3rlwXS5IUqfmoFeBR3nT4y3ZcovJ18Vb0BEIUQL/FjSNfjPWuDryuDEiAhsF/ViNb3R1yd3oCISrskLsm78aNsMX1gVfzAOTnLg8T3ayYq26hzmfpCYSoIMg9k3Xi+tggQaR2oYXP4lPfo2sgdnheVUEeT08gRIWQxaPJuXAVLJckUrtwha81KxYhOAqUyC8xiCF/Rk8gRAG0/sk4cDpmS7084d99tucRLGtRWUVJXkxPIESFkMUTyTjwc5Jl6nufqj5cZNKMyU9GqyjIG+kJhKgQsnjGuftea+tOnjPG+NIL5BsET0EgB5kJ7+odRV8gJPiQxQvOr1Ss8ESobvZcdu6BGixUsP9exun0BUKCD1kMd+q6T3kkUxtxjsd381ZBFdSrlZxWmb5ASPCCPMppESHvksbe8FRy+kAdVqO8apLckL5ASPAhi7HOHHeMp9HVZp4JTkVshkr0VC3xrTV9gZDgBfkNJ257vsS+c0bM8UxwekMt/lDt1l5n+gIhIdshj/RcqLypipaOP6Aa96lVzeIh+gIhwceQxzi5nbfLc5n62qPqFerxi1o75CfpC4QEL8iv23faHr4IlRd75HlQEaXK1o+gLxASvCCPtu+0/lyryJEuNo2hJh+rJMhv0xcICV6QX7N/oFfgk1A1kSw2YxQV5LwAS/SXGp/SFwgJXpBt5yE/6ZtQyb1GneGo35+/DFBHkOfRFwgJHP1Vuy671DeZ2olKEqXmZkk50ovxKcbhNXyKn6WVKFLoYG85fYGQwNFesdusyU+6SpSaKa5/msXojprFnlkV3ZAj5TdtpIogb6IvEBJ8yOIlFS9WzJGYgbzD1U+yCreYlgJqj19d/6ZPqSLIB+gLhAQvyEPsOezHvgpyIRpIEprWrn6Oj1AtQcGiSa4rQasStMg+lt5ASNAhi6fs7TO3+Xzc1T/w/tIF6G3zsLPQ1Z8eVXpRx/9NbyAkYPTH7DhrU9/zD76UJDOLk3x/PrrZfsdjrn7TOxUR5HJn0RsICTpk0duOsw5Kaoe5DhuSzkfYLyXTolKSvU0KHR4ruqnxMU6VHXJ5egMhQQtyTzvOOs2hFH+Ctsg65OZogTFJyXJHCSLTJkmRHOG4OdQXSQvyClWiyNXpDYQEHUPubsdZlzsQmDW4ttTn6ybRpVrG9ZBBSUlkThKlMc9LOspecPhPV+A9Q+rSGwgJOoZ8l527bva/+P9o0ogpjucdCtWvEkTmvSQEcg8uSOpdXZPeI7dSo0R9Y3oDIUEL8i2JXbWRAxGtafGcAQ53jpVdi8wvScjjoKTftihJQe6rRkXka+kNhAQdsmib2FU72xSWfWic4EnPOBKqa1xfCtnvWBx/ddHt7qYkBfkNNXbI7egNhAQtyNckdtXBNoWlt43Dr88cCNVDLiXmwiTEsZurN85XpOBoUjvkjvQGQoIOWTSWVb5yma2jsHOwybedYyvH0rgeGa7eeG9SgryaXfUIIbFYLBa/MLGrfmBLVm636fjdbQvVApcSc7djaezj8o2Z2J7UJRQlGp52pTcQEnTIokZiV51lqwiPbjtnd4FNodruUmKc3qDbKyEBLbli+EoUqu9BbyAk6JBFZmJX/cGGpAz25PDL3W29oQ5l8T0JstYiKUG+XAVB7k1vICRgMsomdtWVNiSlricVJuq5kpjXHcpiBynlPpPpT9JWhSyLgfQGQgKm7GmJXTXXxoGeN4df17qSmMmORDFXUiT3/SQE+Q4VBPkZegMhAZN1XGJXTXwp+BXHh187fBAqZxU4PpQkbN2TEORuKgjyi/QGQgJH7E3kqps9KAQ03pZQPepKYj51JIoPSxK2ZJpdPaRCDHkEfYGQ4AX5z0SuusGDLIEbbAnV864k5jNHonixrDKW2O1YkJ9Q4WLIK/QFQoIX5OWJXHVtAjnZkIT7Z2CnB2Uwi4+ZjiLI8qTtW8eCPESFHfIo+gIhgaPNd5tlMcuzCO/rvgnyfInSNs6xIA9WQZBH0xcICX6HPDORq65IICdvJiUAfWwI1Zu+HepNkChtzzgW5CdVEOQx9AVCghfkyW4vhjyblABcY0Oo3nElMU46Qj8mUdoedCzIA1WIIb9BXyAkeEEe7fZwrGeSdR8Sl73/wLdrzDJbjbZ3LMi9VNghv0lfICR4QX7ebYpaslm0vycUqimuJGZYQHflWoaz8/Rb9AVCAkfrn8hVhySQk7uSlIDEjUHddWTu70ASm0iUtmscC3I7FQT5bfoCIYGj35/IVR/y6D5d4pDCSFcSc6cDSbxQorRd5ViQr1Lhpt479AVCghfkWxO56i0J5KRrkhLwlMf5uU5CBzUkStsVjgW5pgo75Mn0BUKCjyG3SeSqTRLIySNJSkDfhEL1uCuJqeOgXLxMSbzeoRzvs11L2tPxHn2BkOAF+XK3+RDJ9mnuYVksfjruQzXX15ivwkB8buMy83kSpa2zQ0H+XY0WTh/QFwgJHO38xM66zFJQXk5SAu4xfFoB5uA+VJYqNulog5H4zacY8kMOBfkzNbpOf0hfICRw0rISO+sUS0GZmqQE3FrqSZsxxGGpe2ejAQbgGxQY/A4NJb7lKYeCPEyNHfI0+gIhgWOnZ8hAS0FZlKQEdCz2lCW4HxV8kZ46GIifSvwOzSU+f7RDQb5XDUGeTl8gJHCyTkrsrO08qZTW7cgTfrFZUbkyLsdt6I9hGIXx+BAfYSrGYwyGYwA6o6mjo7lGGIp1nlzN+NKhIF+qhCBrM+gLhCiAOJjIWasbfs3/mzouLm6sxF2IW/67LNyAwfgMf9oQtz2Yj9HohkYJnvnXoV8n5EjI5yg+1jmS4+22flIfxkx6AiEqCPKmxO66yFJUbkuyK/R+DLEMU9RHf8yxUfPCiF2Yjl64wMbP0RSTMUqasFVGoaOfc6YacgzxKT2BEBUEeVlid7W+Pv1iklkWDUz/X1U8ip8hg2UYYSNCnClN2FqFsfQmBMTH9ARCVBDkb93WZ1gkVRqaYjz2QC6/YQjq+yJsQxz+ZE0UEWSmvRGihiB/YieTN9dCVAqS6KpnlnmxGF5RgDno7nkmxzxHP9OfatzS48UQQpQR5LfsOOz7lsLygJSylXPhPVswRGrlipIR5IOOfpq3VZFjiCn0BEJUEOThdhz2dkth+dp1mOIr+MdevCH1Ksjfo6vDn+RmZQSZ1d4IUUOQH7d3/XiThbAUuojQVsaryIffFGAaGkmXtVmOfoZcZKizQ2Y9ZEKUEOQH7bnsCEtxGZqkEHTAGgRFAT6yyPRwPrIdpui9oY4cs2MIIWqQuCLyoXGRZYbtTlR1LAJVE1TJ8IMDGI1sSaL2tMN3t1BIkPVx9ARCVBDkVnaddr6lvDzhUAKuxh9Qgz0YgooS9sfbHL11iUr7Y4gx9ARCFCDeyHn1CeOIqJPshV4O8xG85g+b9TTMr2F/6vCNj6olyK/REwhRQZBr2XXajATx3rdsH+NNh4p86qIu8gjHV7urKCXI+qv0BEIUoFy6fbd9JMEh2Q22yl/+mECs8vEtnsGduBpN0RYP4ytH9SE2YCg6oiWuwo3ojSmOAgn7MCSpa9R9HIv/y2rtjyFG0BMIUYCM0+27bQVsSHDtIlHlt5bYYvmElRhgcMh2m+0Ax7RSd/HScRM+TVCvrnhLpfaOe4QUOpTjA1KbRkkZL9ETCFEAcYLzopnmLLbshHcPDlh8diPuNy1G+blNqatjWv/YSY7wdNSzPSO9HcsxME41OYY2lJ5AiBqSfNDJHvn3BGLzo+nhXh/Lfeosi6hqA+yQUD3tQQcXUPbheVuJfN0c7L3/Yr+tsqA+j+fpB4SoIci5ybdeMuJXXGLwuUGWn1mDSoZvq4J2eMtR9bd5eND03uBQR8K5G8NxToLZaIxhjq+2DFdPjiGepR8QooYgr3bmvJ8lEJwfSrUqjWNcgs+MNris3RPfJn2pej1exfkG8umUnRhm8JzStThGY7PtC9NVFRRk7Wn6ASFqCPLPzpy3PvZZCM6oUhUa0jExoUx9WeIz9fC96zS2Xehe6nAwuSvWOeiC9IRJgR0xBXsTPu0RFffHEIPoB4SoIchznbrvw6Z33u4yEKoPbZairFHk8G8b5PD2kUPGOLpaVnVOfHVkiI3KF1XQC79YPOU7VXrolRyP0w8IUQJthnMHnmIYO25scAg4w7bk5WE+JuA1yUXqczERYzANWyU8qxAL8IiNG4lNMd5wr3zAgwpzkkIWA+gHhKixQ57s3IGzsLKE2ExB5VL/qhJmI3rkIwfdkZWwV/cA/FrikwMVlWMB0Zd+QIgaO+SxybhwY2wvUvK9h2G5nfmILnsxFbcmaAml4zq8fyT3eqY6DZtKj970A0KUQB+WnBM3w24AwApcZvi1fT2iz3ZMwA0J4sLZGIJcrPOwdZSEkMXD9ANC1AhZDEq+D94eTDbMIH4E+5E6bMCLuMhypiqqeBmk6OhJPyBEjZDFw8k78nmGheenIhVZjH5K74ItgysP0A8IUWOH3FWma7fEOqQuezEJzUIoyNp99ANC1Igh3yXLreMY7LCvXFT3yj0Mck6UHl3pB4SosUO+XY5Tn4scanGRS9evK5t1bBCyuJt+QIgaMeSOMlz6BvxJFS7FfHRSOdnt75BFF/oBIWqELG50687peDGJMpSpwlJ0Vl+U76AfEKJGyOI6d858fqQvgMjhe1yntiDfTj8gRI0dcms3rtzJVcmeVOIjg+ZU3CETQorHkNsm68bl8WoSDYxSl224V1VB7kw/IESNkEWH5Jy4Lr6jxjpmsklvlIAP9e6kHxCixg65UzIufCd2Ul2TzFKuxbQ3QojJDvkOp+6bidHUVResRkNenSaEGAryPc6c9xIspaa6LkekWLGhvvQDQtQIWfR34rr3O+oBTcxYoVQhIjY5JUSVHfJwu25bGZOppNL4XKHrIvow+gEhauyQJ9lz2jr4mSoqlcfU2SG/QT8gRI0d8pd2XLYpNlJBJbMX56siydPoB4SoIcg/J3bYy7CD+ukB76siyPPoB4SoIcibEgcr1lM7bVKId9ERbfEoltj41wVooIYg/0Y/IEQFjhL5iWq5/UidtUk+7izS3soOr6ohyDvoCIQogHZmImcdTJ21zePFuk3bYaMiuRaZJ9MXCAmctGxrR62HA9RZm8wsJq6P2fzU1WrkWVSiLxASOHpTa0d9jTpr+/Zd0aseNbDF5uf6qJGJ3Ji+QEjgWHfUq4JdVFpb5KFNUXnDdNuffFuNHXIn+gIhwQtyX+uabqWZjevwNDZTg4tlSxSvdPyCg89+qYYgD6AvEBI42kgrNx1rkNZV+/BX8kXU4cMcRPdis9bDUdn+xWrkWUygLxASfAz5Qys3LZ1L+8eR/1eTfaYBALkl+uV1d9jwVRFB/p6+QEjwO+Qfrdy0dL+8VUX+bxeqMeajTrEZexD5jp+ghCDvjpWhNxAStCDvMnfSuIG4HEBmkX+R2v2mC/EaMorNWN8kegx+qMj16fRy9AZCAiXjdOvOIEYU/YLeIoXleDPalbjROCqp57ysSsW3JvQHQoKNINe2dlKjYvQfFfsXH6SoHOfg3GLzUA2zknzS3aoI8kP0B0KCFeTW1k662rBeQ+Mi/6IWNqRgxYpnEC82Txfh16SfpkwJzrfpD4QEiuhh7aQ5hhLyCyoU+TdXGBz9RftGXusSs9QO25N+2q/qNHJaRn8gJFhBftnaSc0uOEwqtkNslEK75M9L9cLrizwXzxuqjiAXVvgvPYKQIAX5c2snvdFUSD4oll9QF7+nxPXo50qEKrLwvstnNlap93QzegQhQQry+kRtTc17TM8olgBXK/Id91aheYnZuRIrXT7zG5XkGPpgegQhgZHxr8ROOslCTuaiSrE8gyhnJb+LrBIz0w17XT/1VqUEWXxLnyAkuP3xeYmdtE2Ca79FI6qV8EVEL0ffXqoK3lQJz12sSHH6I4lveVkn0SsICUqQ29v4GotllqKyotjV4QzLHXU4mXW4nNLf42rXoYpD3KTW/hgCaZfQKwgJSpAft+OktyWQlTVoWEzAh0ZIjPegd4ldbHkMdZVV8TcfKyfHAqIvvYKQoAR5iq2jHixMeIn4ymKf6CVJsoLm01KXNprY6iVth90lihIpMj6nVxASlCCvtOemrRKWzNmDDtKuSqjBRnQr1X17EA5Ke/4DKsoxxD5GkQkJRo5PEYV2HfV1Gzm6PYt9ogFWhFaMCzC+VE5FYyyW+IZpasoxBLRr6RmEBIB2kX03rWTj4kchBpcot/NlSA/xLi+Vjf2SxL0x8CuqKivIYgw9g5AgBLm7E0e9xlZceEqxyyLpeN5h94ygWYy2pX7z27FO6ju2FzsEVW5sjR1D3yDEf0Ee68xVH7IlNwtLJIm1w5aQiPFq3FsqL7iJSXml5DmA60u8o4ZqktyQvkGI/4L8o1NXtVeAfQOaFvvUefg2BBXcHkb5Er/tBXhH+v4+H11KSf7nqgnyc/QNQnzmrBO1PMdNfjDTluzsR98SraD64oCyYrwVg1CxxG9aE8OxX/qb8nFfifdUx2ocRGW1BPl3egchPiMaJuOslfGNTfGZXEJm5GYpyGILnkClEr9jNl7BPk9qxd1Tqmfhl0re2NOr0T8I8VeQeyXnrJXwtU0B+g2XlcrjVWmfvBZ9S4lxdTyHXZ68bZ9BIaGRh//fSNUEeSD9gxB/I8hTk3XXivjKpgjtxSMljskuSbrznFyWoVuJftECVTHEIzEGctGy1DwOOPJ/f1Itirw2djQ9hBD/KCM2Je+wmfjYthTloG6JT3fCqkDFeC5uKZVNURlPY5uH8t+g1Bz2LpbBna2aJF9GFyHEN/RMl19qMSjhdeq/2IWeJQSwAgZhRyClgsYZdOiohIHY6uFb3zc4tOteIn/jbtUEeQJ9hBD/Isjt3TvtPQ7yEL4stUesisG+Nkf9FX2KldP/6zbh057mSe/DowYzdz/yS/y7CcrVtCh7Gr2EEL8EebQMt22O9Q4uRAwvVR+iMh7HZs+leBcm4QaDUvDnYrhnMeND/IhLDWbN6LvFWvVqWnShlxDilyCvluO25zjqnPEnupcSxop40LPWTwcwHV2KXeb+a9THOA/yjItyEC+UumoikIG3Tf79RaoJ8nx6CSGhiCAXH10cxYMX4gaDZ1yCEVL3yvvxFXrgHMPod1tMLxUykM18w27SWZht+on+yu2RmY1MiC9od8p13foO97gLSlRP/mv32BETXMvyb3gNHUrlF/8liL19KAq6weB7wKGrMVbNsGarV2ZoBD2FED8CFpNlO28cPR2mjS3GbYayFcfVeAJfYKdDGVyF9/EQLjT9CRtjDHb7kMcxxOQidPcEt/8OqHaBGmK/fgZ9hRCvOVrkupXfqobx5NEOi/EsxwDUNE2sa4A7MRRTsdgkKW0/1uAbjEM/tEN1i5/2fDyOX3xJqhtdqh3qXzNjJ2/7VvX2yH3oLIR4vT8+z62j1sB6g7rBAgItsdTx4dfH6Ij0hGWNzkVjNEULtMU1aIoGtopWVkcvfOtLReYdGG56ueNmrLX1jPHqCfKf4gT6CyGeog9066gXAyjEeMMv2enohz1JxF1fRgvEJUa1e2OW1C4fVnWUB6Gayc9RG5MdzIGu3sHeLfQXQjzFeR3kkqPFYQn5A60N/39D2wWIStZem4SurroxZ6MLxuJXny6bHMRHuMn0z0gcvRzmOV+u3h55aawMPYYQ7wIWwr2bdixS4XeU4T5Zx2Mu9qcrMQWP4TrbvTRq4wYMxAf43fZ1brcUYgH6msa/BQRuSKLc6FMqtnS6nD5DiHeCfI97J72vmIxsxB2G/+oqG41RE7EdP+ADvIbB6IEuuANt0RZt0Rld0BPPYAym4UcfcieKsxQDcYHl/DSzWci/JPNUFOSZ9BlCvBPkme6ddEApKZmKcw3zfj9DlMjFaFyVYG4a49Ok9+l5ltki7LFHSNTk+BRx0L2LjjDcy/Y0OJTSMSQiYrwW/Uyum/w9rsMnLnM6uqooyLPpN4R4I8gdZLjo+6YXhhsZBjgOhFyMV6F7qXL2okRB0e5Scp2nqSjIiDei5xDihSBPl+Ggcy1qSDxmsE++1oeabl6xDYNQwXI2GmCotHrKewxLIQU+5jHXghDppP/Peadpo2Hd8SPHIJ58oWUdB1XJwwjDO4l/X5DphfmSMzs6KrlH1q6k9xAiGf1uOe6ZqCfzRjQzKAU/L2RyPNewYtuhUQUPIMeTmnFvKSnI+gLukQmRHbD4WoZzVrfVKeMug+aoM0Ijxptxr+nv3wbvYq+Hb44rKcmiOf2HEJn7Y00UynDNpjavTgwvFU1Ox1uhkOOPTK6k6OiERZ6/vYWaQYsVWcfRhwiRhvawHNe807a0vF/qiEr9NLg/0M7k974dy335CV5Wc4cM0ZU+RIgsymgr5Djm0w7EZaFBDbQ+nvfrSP4Q72VUNLl7518E/DdVBTm3wn/pRoTICVhcKssx33ZYl6J+qSd0SqIenPcsRhOTgkXv+FYj4xCNFJVkbSj9iBApiImy3PJbh/KyCVeWesbl2KCUGO9EP8OazHE8iu2+/zRPqbpHzk+vQk8ixDUV/iv2y3JL51K6y6CxaR38rIwcz8T5hr/pFT4c4Rnxo6qCDP0z+hIh7gMW98tyyaykvr4fxN2lnlTVogezf/xu0vukIob4VODeiAbKSjKviBDiPmDxiyyHbJ6kxBRggEF3kSG+NFgyv+g9xOSqcjv8EeifiSfUFeQVbOtEiLv98aXyHLKHC5mZYFCi52bkBiJ5hfjQ4LjxUEvS8T4f4pXmB2UFWUDrT48ixM3+eJo8d3zFldDMQpVST6yFT30XvO/Q0uTqx4MB/YEo+efiQnUl+UBaZfoUIcnujzNFgTx3/NKl1CxDXcN99w4fxbiDye92OeYrc9A4UOE9spjNyhaEJLs/HiHTGde7lpo/cbVhhYzRPlwYmY9OpuWCRiFPoUS8hSoLMrSO9CtCkqDsaWK3PEesLiW6uh8PmXTh+9yz6O0BTME1pr/XPdio2DWVQpNUPEXG1vT/0bcIcYysChaHRltpgjPFsFu1QBNMk5558QcGWXSIvgQ5Sl7k7q/2HnksfYsQh2QcL9bLdMPHpWYAX2vyljoYhJVS3rEeo9HSoIfJX+NcjFMqUFE8vCLUluQr6F+EOIsfd5brhB9IlZx8jDBtWaSjBV7E4iR3y3uRg2fQ3EKKBbIwRMmaGn9nbtdRW5LXpZ1KDyPENtnHipVynfB3D2qb3Wz5xhrojKGYgTW2rmgvwiQ8jpYon+D3qIrBSqS3hTjTAgLidfoYIbbRb5HrgFU8ulc3C5fYurTdCNejKwZiOIZjOEZjPMbjZTyBHrgdrW0fgtXAkAAKBiXDYtUFGdq19DJC7HG0WC7X/dp4Jj15mIiLfRCQJngb+xEeGqouyRvO/g8djRA78eP2st1vkMcx0w9NKhLLKYrUXaFrH3YZrPweWbxJTyPEzv54qWzn86NJ6XLLFLVkRjraYrLSx3fm/Kq+IEO7hs5GSKL48Y3yXW+zTzJ0ANPwAM5z/fNegJ6Y5uOlbC+4TH1B3qydSX8jxIKs48Rvsh2vnu931X7By7jVcZmdDFyFXngLKxAFhoVgjyw+ZW0LQizQust3u3sDE6Ud+AavYwDuRWtcXOqGXzXUwqXogIcwDO/hBxxAlPjDMpdamdGNPkeICfF/iy3yne51hWRqP7YjF9tDlTGRLM3DIMj7RXX6HSHG8eOBXjjdUpAgGBUGQYb45awT6XmElA5XnCmzvttfo2bgXTRSlT8N+2ErOF6i7xFSCrn1j/8ad1IZA6NdOAS5UL+a3kdIMdKytDwv3G0cdTEw3g2HIEPkajo9kJCi++MvvHG236mLgbHHpHa0gmNe1nH0QUL+kuM23jjaeVTFQLk3LIIMMYReSEgsFovFyv5DrPLGzbpREwPli/AIMvSW9ERCYrGY1t8rJ5tITQyUPJwbGkHWdomK9EWS8sTTxB6vnGwNNTFg+oVojywWl/0H/ZGkevx4ilcOVp96GDg/hEmQoY2kP5LUDldc6Z179aAeKkDjUEmyfhN9kqQsmSeL1d451xSqoQIMDZUgi91plemXJFX3x0M93OvgT6qhAqxBPFySvDTzZHomSUH02iLfO8dqSi1UhLbhEmSIt+ibJPU4RnzvpVsNoRIqwpSwCTL0W+meJNXCFQ9761SLqYSKsA/VwibJ+7Sa9FCSQsQriH1eulRtlt1UiIdDt0fWVohT6KUkVThKzPbWoXpSBRViUegEWUBMjx1NRyUpgejptTvNoAoqxeVhlOS+9FSSCtHjSt6GKwQqYg81UClGhlGQC7Vr6a0k6hwj5nntSh2pgIqxBRlhlOSdWiU6LIl2uKKv9470BhVQOW4LoyBDLMn4F32WRDdcUUMc9N6N1lL/lGNGOAUZYnKsDP2WRHN3fIL4yXsXupLqpyB5qB1SSda603NJNAV5lB8ONJjqpySPh3WPnK83pu+SyKE/4I8DLaL2KcmKsAoyxBYh6L8kWnLc2MtSQn+PC3hHT1muCa8kL2Q3ERIlOc4U2/xxncepe8oyPryCDDGGXkwiQsa/xM9+Oc4P1D1l2YVKIZZk1oAj0eBoMc0vp7mQAQul6RbmPfJ+cR6dmYQ/XDHYP6dhwEJt5oRZkCE2pJejP5Nwy/GNfroMAxZqU4gG4ZbkhWf8kz5NQktattjrn7swYKE+z4dbkKG/w5t7JKRoZ4q1fjrLE9Q75dmA9JBLsuhNzyYhRJwg5vrrKgxYhIEbwy7IhaINvZuET5BH+eso9RiwCAUfh12QIfbGz6V/k3DJ8YN+uwkDFuEgD3XCL8nryp5NHyfhkePL/LkozT7TYeTZ8AsytPm8TE1Cgn8Xpf8eDRiw4MGev5I8lp5OQkDWSf5dlP57DKHOhYhbIyDIAuJBejtRnTLapACyQ7GKKhciZkVDkAv0q+nwhId5pUZLalyoCP2NvSNtUNOy6PNEWbSLtbwgHONNalzIGB4NQYZYLk6h3xMlSS8nNgXhFOWRS4ULGbmoEBVJ/iB2FH2fKEfG8WJeMC7RmfoWQu6JiiBDf5TeT9QLV4wMyiFmUN1CyLeREWRRoF1J/ydK4W+ZzaKjBg5S3UJJ4+hIcm65dGoAUWd3XFPsC8oZelPZQsro6AgyxPdnnUgdIEqQebJYGpwrLKKyhZSdqBwlSX6TSkBUoIz+TnBu0JBXpkNMjygJMvS7KQYkcES3IJ1gKFUtxPwQKUEWB/X61AMS7GFebXEgOBeIYy1VLdQ0jZYkb2RZThIgaaeKlUE6wM1UtJAzIVqCDPFN1nHUBRJQ9Fi8F6z5f0xFCzl7cU7EJFkbSmEgwUSPewZr+rWQR0ULPX2itkeGfiO1gfgfPa4fTCGhv8fjVLMIsDxygix2a5WoD8RXMk4X64I2/BVUs0hwQ/QkeTEbPBF/o8fvB230ralkEWFG9AQZ4mWKBPEN7b7gTf5dKllEKMBFEZRkrS11gvhCWnaQuceHRlXspZJFhteiKMi74hWoFcRzsk4Sy4I390epYhFiN6pGUJL1BRnHUy+I19kV41Qw9h+pYpGiXxTjyBDPUS+It3J8iwqGfjkVLGKsRnoUBblQNKdmEM+IV9B2qWDoY6lgkeOWaO6Rc4WgbhBPECeIRSoYeWXson5Fjq+jKcgQc7OPpXYQL8IVw9QwcR7oRZMroirJT1A7iPz98eWiUA0DX0rtiiTuK79dgv5orWATVL0x9YNIJeN0sUEN825F5Yoo+1DDlWWciwMADuJO9ST5z3JnUUOIPMqID1Qx7g+oXJFlsCvLqH34Kfl4WD1JnhU7mjJCJKHdqYph18QB6lZk2Yjyrqxj4ZEnDVdPkntRR4gcOa4k9qhi1oOpWpHmXlfW0anIk15W7Sp1nl6bWkJck32smKeKUaezh17EWezSQiYXedYrqu2Rl5x1IvWEuN0fP6WOSd9KxYo817osOrWqyLNGqFbd4kXqCXGFXk/kq2PQs6lXkWeqSxtpgFx1d8mFWhNqCkmatFPFanXMuSEKqVeRJw91XNrJ9cUOfhU73ttQ4b/UFZIk4k2VjPkVqlVK8JJrS7mlWPvbQWpJ8nvUFZJc9LiFSoZcGdupVSnBNmS5tpbORSS5EL3UyrfoRG0hjsk4XWxUyYwfolKlDI9JsJe7ikhyPu5SSZJ36Br1hTg9zntHqfNpLKdOpQwbXF4QKS3JB9FeJUmeGStDhSFOosft1UoYupEqlVI8IMVqigYu9qK5SmGLLtQYYpuyZ4tctQR5JjUqpfgNcemSvAl11bHo3ekZ1BlijzJimhyzq415uF/CcxqggBqVYtwuSfruLZIsuQzV1AnC5bDcELEXrugsy+g+hNvqBIfGaOpTyrFImvQ9UeSpc1FBnV1yV2oNSZzspoudcgyuHQDgMtfPqcKWTSnJddKkb0yRp74LXRVB3pdWmXpDrDlKzJZjbuXxG4BVEp7Uj9qUknwhTfri+KTIc59UZ4/8dewoSg6xClfcK8vYngEAPC8h4e13alOK0kSa9FXEd0eeWoCO6kSS76bmEFN0Tdslx9DqYx8A4FLXT+pIXUpZ3pMofdnYcOS5O3GxMtkWaXHqDjHbH0+Xm6b2rYQn5VCXUpZ8NJAofs2KFB36XZ18i4+pO8T4OK+jLCO77bDZd3b9pMas8JbSjJEqfr2KPPlzSZnOEsIW7ag9pPTu+P9kXQapjHUAgHVId/2st6lJKc0+ZEsVv6L29IIqe+Qt6f+j/pCSgvyuLAMbftjgn3D9pFrYT01KcYZKFb9M/FDkcE+Z+hbjqT+k+HFea1nGdTEOAgD2orrrZw2lHqU82yUU4yw66hbpKJLruhi+tNGMGkSOcPZ/5JXa/PKwsb8mIfSxjXpEMFCy+HUsci6xABlqCPLqrJOoQ+Sv47w3ZB/nHZSw9+hNLSKQVYyz6Bhb5OmqdN3TB1OHyCE5vkJehG71YTOf4PpZ6cX6B5NU5iHJ4lcJK448uxC3qVGQM09UpxaR2Bn/FH/IMqpnj+SPNpRQOJEQHM7Xkb1HbnL4pAMAduACXqQmyhznDZZlUOdjz2ETf1/C076jDpEj9JAuf8VrwKmRk8xueylPvKo4KMucph35Eui+BkFLahApwlrpe+Q4vvbw4DDJsTXjdGpSKnOUmCPLmNoeMe7pEp72CTWIeLxHPh87jjz9AK5UQ5Jfoyil8nFeF1mGlI6lR/bHV0goTZRPBSIe75EFehZ5/gpUUkGQC0VD6lKqyvGZYpssQ+p/xLA/kpyWRMghHvSgl/ncIs8fo0Yc+cfYMdSmlERMkFfacOdhoy5AY9dPq4G9VB9SilUSaqOUvle6v0gC3A1qhC3uoTalohxfJs+E3jxi1DIq2D5L7SE+xZEFBhd5/hrJ17STHLk82ks5yv5D/CrLgBodabWej0tcP60CNlF5iCEbUFG6/KXjZ+XCFuJlKlSq7Y8fl2c+s46Y8zuSD1oIKU5/D+SvWZEj5AK0UUGQC+K1qFEpRFplcUCW8dxwxJjzcZGEY5blVB1iSq4nQYWiXalXo7IKkvwlVSqV9sfT5X3hW3rElCdIeB476BFrBnsgf1WKhcleVaPYUGvqVIqgt/KiKc5+nC/hed9QcYglOyXU2S49ehR5QwGaq5D+tuaMf1KrUuM4b6Uso6mMP4+Y8UgJz2tKvSEJGeaB/MWxuMgbFnuQYJfE6Eu1SgG0/vJM5u+OHrul9D57n2pDErLPkz4f1xV7x6MqCPKesmdTryJOPE3skWUwdYpc4HhGyvPyqDbEBt4kp00v8oZdqK2CJI+iYkX9OO89eeYy+Yj5bpFy9v0KlYbY4iDqeyB/DYvUSAamKJH+ptWgZkV5f9xIZonvgiPG21fC887BbioNsclkTwSw+JZAiYvU06hakSX7WLFEnqn8XU12LSpIeN7TVBliGxk1U0qPakU6UgMrlGiAql9K5Ypqutv98sykbRHDvV9KN77NVBnigE89kb8+xd7RV4U98iI2doqmHJ8htsszk4VHjPY3KSlCj1BhiEOu9UD+KmBDkTdsRw0V9sjtqF5RPM57XZ6J3FLEaO+Qct+PHaaJU+Z4In+9i71DiVt7q8QJ1K+oZR/XFAXykuiXHDHYH6FLeOKdVBeSBG093yMflNA/XcIe+X4qWNQCFp/JM497ixjszVKeuJjaQpJgvg975Okq7JG3ZPyLGhalcEUzmfVjfztirD9I2R+3pbKQJLnB8z2yN/twx3vkR6li0eEY8bM3ZVjkmOpX1BWSJPN82CMvlrLtcDm2lz2NQhaV+PGdMncP644Y6lxJF0wIUXuPfIcCe2RtAJUsEmSeLDbKM4t+0l1hKjWFKB5HXoZ48IK8K/1/VLMoxI8HyTOKykWubyyU8sT6RdrnEKLKHjmzSGFZAOiqwh75KapZ6MkoK6+6W/HrzZ2kPPEN6glRco88uNg7VqlQIXkvy3GGf3/8pjyDqIrtRwx0iZSDjmzso54QJffINYoUlwWAHiqkvz1PRQs18VqiUJ45PFPEPO+WXOCeENX2yGOLvWOdlBJaLse+jLJUtTDvj2fJM4asIpWwVkr5AlcZ26glRAqtPamPXFDsHY+osEceQlULb7rbFTJN4YkiptlLyhP7U0eIJD73RP5mFnvHHyrEkfdknE5lCydlxLfyDKESthwxzG2oJOGJGUUymglxy5UeyF/HEu+4V4Vci/6UtnDuj1vINIMBRcxyqJQn3kcNIRLxoodIHKuLvWOJEnf24v+muoWPo8QP3txcypPS81fHMmoIkUge6nogf4NKvKWjCnHkHpS30KHfKNMEeknfiXSkghDJvOZJ8tuBYu+Yp4Igbyz7DypcqMg+Vvwq84vbyiIm2VTKM7+lfhDJ7PWkv8dHJd7SUoU48p3UuHClu90uc/nvKGKOcgoKXU31IB7wrAfi16HEOz5TYY+8Ous4qlx45PgEbY3M5f+uiDl29mTXQYgMclFZuvill6j8VqhEDxHRnjoXHkHuJnPp2xQxxs1SGqPXQx61g3hCbw/E7+US7xipQtDix1gZKl0oOOOfMsttFk+OHy7lia9TN4hHrPbg8kajEu/YhooqSPJF1Lpw5B8/LHPZL0VhkS9rDSQ8sTr2UDeIZ9zjgfj9XOIdD6oQtHifWhcCMv4lcmUu+1tFzPArD8oaEiKX7z0QvydLvONnFQS5ID2Deqd+/LinzEU/p9huVsaBXgVsomYQT2kmXfzqFfmeeIhrWYyT2MmvEOu9uqck50CvJ/WCeMy7HojfDyXeMUUFQd7JS9SqC3JXuQk/Rcv/vCzlwvQK6gXxmAPIli5+A0u94xwVDva6U/MUJus48YfM5e5SzAQvk/DEW6gWxAcGS5e++qXe8bAKe+RVsWOoe8qi3yZ3uecXMb8lUp44j1pBfGCjlPBa8bG8xDu+U0GQoV1L3VOVo7UVMpf6ymLmN0jCE5tRKYhPdJEufcNLveMiBQRZ/4zCp2r8uL3cpR5XxPQKcaGEJ06jThCf+Fa69LUs9Y6hKuyRC+PlqX0qcpT4SeZCV8YuyeZdH/nUCeIbl0uvabG1xBvWIa6CJA+i+KkYP24td5mLp6fJ6KE3hhpBfOQt6dL3fql3XK9CFHlzxvHUP9UoI77zLu/yIKrzwjQJGXslWG3x8WCpd0xS4mBPb0UBVIz4VXKXuEkxs5NRAZYXponfDJQsfHVLvWG7B9kcSeyRZ1ABVTvQm+XdgZ6MUirleWGa+M5q6THelaXe0U6Jgz1WtVAKrYbcBa5U7ECvALUkXzEhxB86SJa+N0q94Q0lghbicaqgSoI8Vu7ydi1mcgskPDGH2kACYJpk4bu71Bs2qZFpsTH7WOqgKnJ8pjggd3m/KmZyT0qolVVAbSABkIdzPY4iK1L3Ddo1VEJVEt4Gyl3a80rkC1/q+okvUhlIQDwuWfg2lHrDCDWCFu9SCZXgrBPFFrlLO6iYua2SkFC/kbpAAuJ36FK9Y5rB0aESgnzg7P9QDVXIr7hD9tIuK2Zuo1w/7zaqAgmQVp6W4QSAxmpkI99GNVThQsgvcpe1aQljc38X6XNqAgkQueXqWxq8ob8ae+TZlMPgD/SayF7WUcVMbY/rxPcLWMGCBMpeZEn0jyqlmjkBM9UQ5EJNpyIGfaD3meSvPVhfzNS+dP3EIVQEEjAPSPWR1aWev1uJ+3oC2sNUxEBJryIK5S5pixKm9pTL58WLNYEiJAjmSPWR6QZvaKnGHnkJNTHYgMVIbwMW7nMsO1INSOAUop5EHzH6zjdEDUGGqE5VDIzMk8VO2QGLdZIjyJ9SDYgCyOyxd4fB8+crIsjaAOpicAlvnWUv5zUlzGy2y+fVQB61gCjASonZyI0Nnp+HKmpI8jLqYnCC/J3s5RxZwsyedvm8h6gERBGukVh6q9Dg+R0U2SOnZVEZg8mvqC1/MVdLPqqYSx0gijDW0+vTCkWRe1Mbg9kfj5K9lCW/iu1FeZc1MVhSiKhCLtKlecq3Bs//QhVB/oHaGADxf4vdspfyiRIm5rax6QCqAFGIG6V5ytuGgq8rIsl6JvXR/4S3LvIXsmSA4XWJXfkICZq3pXnKM4bPb6DKHrkX9dH/gMVC2ctYtVRGhLv7TQ0Mjz4ICYodqOBJR/a/uFcVQZ5DffRbjuvIX8a7ShnYVR7sIggJjk6SfKWT4dNHqSLIBen/o0b6K8ivyV/Gd0qYV57L/cQy+j9RjCkeVUQ8xAJVBBlaW2qkvwd6e6QfBGBLCfNa6up5l9H7iXLsRkUp3lLHJCSiiiCLN6mSfmYg3yp/CUvfPprs6nnD6P1EQTpL8ZYMk/OR81QR5K2xo6mT/gUsZslfwj6ljOsxV/vt1fR9EuGgxV7Dp9+gTtDiAuqkT6SXEwXyF7B0p7C2Lp7WnJ5PlGSHy8tOf43Nhk/vrY4gs8iQb/vjBz1IJcfWUsaVzS7TJILcJMVjVhk+e4w6UeSFVEq/BHmxHxHkXcywIJFknBSPWWL47K/VEeTCCv+lVvpAWmUvlq93KdP6ycXT6tLribL8ibgEj5lv8myhTtCiBdXSj/3xIC8W76NSpvWRVHknRB1aSPCYHJNnV1RHkIdSLb2njFjpxeKVLic4zMXTvqTPE4UZKcFjvjZ5dgN19sg/US69z0Cu78XS1TIwrIeTflplHKDPE4VZ6eEOuY1CUWT9DCqm1wGLEV4snVEj0uRv/d9OjyeK09CzHfK9CkWR9dZUTE/JOk5s8WLhjLroNpVaK5YQlejnmSA/rpAgi+HUTG8DFld7s3AzDQwr2UugcWyivxPFme3aZ+aYPPk1lQR5CTXTU7Sx3ixc6VtH+Um3u2lGbyfKsx+VXfrMQpMnT1NJkJmL7ClHexOwuMDArHKTftoL9HYSAtxWRl5u8tz5KgkytCspm97tjy/2ZtE6ST2H/om+TkLAGy69Zr3Jc5cqJciiL3XTuwyL571ZtMcNzGpR0nVi2baJhIG1Lr1mp8lz16glyB9TN70T5N+9WbQJEg89utPTSUi41FUxrnyTp+aqJchbY2WonN7IcXWvFm2egVl9mOSz3qWfk5DgJvWtiulTD6glyIiXp3Z6I8h9vFqyrQZmNUnaFWxC1ORTFz7TyOK55dU61mN3PY8EeaE3C3aOoVGNl26mhKjFzqRTOwXaWjy3ulqC/AK10wPiaaLQmwW7xtCokiu0zSpvJEw0T9prulk89UKlBFnPoXp6sT++x6sFMz6GeyWpZ02nj5MQ8VTSXvOkxVMbqBVF3s5jPS8EeaZXC/a0oVENT+rS9Db6OAkROUl7zZjQ7JAF0stRPyWTdZI44NVyGZvWCCltoAhRmf3ITNJrPrd46vmKCbLWhAoq+47eFd4t18eGRvVqEk96hB5OQsZ1SXrNGotnnqeYIIseVFDJ6IO9W64F0g713qN/k5DxfFI+UwkFFs88V7Ud8htUUNkR5O+9Wy7jv/XJ3PRfT/8mKRFFbmr5zJqq7ZAXUUGlcvZ/RIF3y7XP0KjedvycC+ndJHTsSSoXuavlM2uoJsj7Y8dQRWUGLFp6t1jVTIxqmmQjJURNrkrCa4ZZPjFLNUGGnkkVlRmwGO7dUjWQ9lVuDH2bhJA+EhucAkAedOUEWbuCKipTkJd7t1SXmZjVYsdPWkzfJiHkgyTy7XdZPG+zcnIsoN1JFZVGejkvl6qZiVk5LVCfiYP0bRJCNjj2mcstn7dcQUHWB1NH5e2PO3i5VG1MzGqbw+dcS88mIcXpRY6elk+br6Agi8nUUXmXQt7wcqnamxpWRUfPGUC/JiHlLoc+M9HyaZ+qKMhMfJO4Q17t5VLdbmpYzkqkfEC/JiFllEOfWWn5tEkqCvJO6qis/fGZ3i6VebKas0ulq+jXJKTMc2Tp9RI8baSKgoyM06mlcvbHzbxdqAdNDaurg6dkWV4lJURldiMuseb3ACUFWa9NLZVzKWSgtwtl3pT0aQdPaUWvJiHmEge2PjPBs25RUpBFM2qpnJDFDG8X6i5Tw5rs4Cl96dMkxNxr29IrYE+CZ12q5g75NmqpDMqIbd4u1K2mhrVY2rkzIWpjvz/OjQmeVJB0hWWPBflRiqmMCHJFrxeqvalp7XFwBfQX+jQJMd/YtvTxCZ60Xs2ABfQXqaYyIsg3er1Q11kYl92E+Qze0iOhZqfNzUcGcqVJu8+C/A7VVEYE+QWvF8rqht3NNp9xKT2ahJyGtiy9Y8LnTFBUkLWvqKYyQhZzvV6oJhbG9ZzNZ3ShP5OQswQ5yEEOZmEyRuIxdEUrg7rGiXviPKGoIIvlVFPXZB0n9nm9UFZl5T+3+Yzn6M8kkmzBHLyB+3ExBAQqJ8ywANqqKsg7qKeuScv2fqEqoNDUuLbafMaH9FwScXLxGaYk/FeFqKaqIBfGjqaiug1YdPBjqayOKerZesJy+ishAH5VVY4hkHkyFdXtkd7TfizUEgsD68YcC0JsM0VhQdbOpKK63SF/7MdCfWFhYO/a+PzF9ENCACTXDsqvES9PRXUryKv9WKgJFga20UZ+Zkf6ISEAgGtU3iHXoKK6IuNfotCPhXrB0sQS38zvRz8kBECew6YOPu+QL6SmurulV9ufhephaWT92G2aEFvkYwquUneHzM7TLo/0bvBnoZpZGllOws/PoicScoT56IJ0FS9Pt6SmutshP+rPQlVEvuVf/Wz2CiHEEavQD5VVE+R21FR3R3pj/Fqq3yyNq4flZ9ORR/8jpBTbMBTVVRLkG6mp7gT5a7+W6iNLw/rS8rMX0PMIMWEPhuMcCnJEBHmjX0s1OMHZsdXf+Zb0OhKZPe0vWIzF+B45WIQ1NipX2GEnhihxoVq/iZrqRo5P8CfpTUCgUwKT6p1U12pCwrCH/QrPoTOuMhTNCqiDVngIo5GDDS7esgPPoQoFOczEy/u3VOcnMKefLT77FH2ahJJ9mIyOjhou1UJnvIbFlofg5mxFX5SnIIc26e1iPxdrbQJjamr6yXH0bBI6tmKQizBCFm7C61iTxHv/wD0OGqNJHu2pqm6S3m7yc7HeTWBIb5p+8nN6NwkVBzBUUkraZXgaC1Hg8P0/oh0FOYQ75If8XKwHExjRLlMT/pkeTkLET7hEsu/UwUDLiolGfI6LKMgh2yEP83Ox6iY0of4mn9xEHyehYQIqeORBl2OEo2O/g3gZWf7GkFtRVd3skCf5+/dzWQIDWocMo4IlSR5wEOI/g70u34P2+MyBR2xENx8jyqxl4S7tbZa/gvxSQvPpavCpbHo5CQnP+ORJF+IlbLX9U823UU9R0g65HlXVjSD/5K8gJ77gscTgr/nl9HMSCsb56k0V0BU/2D5kfNaXdDitJlXVjSD/6XO1VGxMaDodS32qHT2dhID5hgE3r8f1+NLmz7cMzb338ApU1eQpo+X5bT6jE5rNL4jznh4JHbttNuv1YjTBB7aiyvl41dElFeej3FmU1aTJ+Jf/ptPChtmUjCP3obcT5ekd8KXl+phgqybiMjT2cof8b+pq0pQ9O4CrlTYqG68pkTb0LL2dKM4yJcrF17MlyvvR27O8i9jR1NXks5AzgzCap22Yd/GWTqPo70RxOilTkdieKM9EDS/evoOq6qa0UK0gDOY8G+aSW8xc3qG/E8X3x7oygiwg0BDTUJjgZ16LK+W/eSlV1U2ORcNgzOVTGyb+dpF/P4MeT5Smh4Ld7a7BvAQ/9R50kf3WWVRVN/f0mgRjKtfbMPFCtDzy7+fR44nC7FGus91f4xb8nsDLhpbKaXI13qaquhHka4IylJ9sfQ38K6vzF/o8UZh3FJXjQ5dHnkrQk+QDmdnTz1FV3RzqtQrKTLrZMvRBh//1Svo8UZhbFRbkQx0ppyU44Kso6109qapuYsjXB2UiGbYKb+8/nDG5kT5PlGUfKikuyAICHSyrxM2V1fqJxTdd7ZDbBWcgPWwZ+y+oAIEd9HqiLF+HQI4FBKpigkXmxfdy4uCXUVXd7JDbB2ceGVhty9xHQuAgvZ4oy5CQCLKAQHuLffKXEmLJ+jlUVTeC3CFI47jflrkX4Eb6PFGYm0IkyAI1MMv0N5nsNpu6MOskqmpIQxYCcZuNmbbQ54nC1A6VIAvoeMr0atZL7p69jprqbofcJljTuIHeTEJObsjk+NC4DtsMf5tCd1fAeS3EZR7ytUEbxmf0aBJq5oVSkAUuNinylYs6yRenf4Wa6i5k0TT4Qih76dMkxLwdUkEWqInvDH+jucnXrXuQmuouZHFZ8GYxiD5NQsyToRVkgUr4xvB3Srays3YNNdUV8QuDN4p0m0d7hKhI5xALskBlfGvwO21PsjRnWhY11V3IopoKRtHUVp8DQtRjAxqEWpAFqhrWlRmdzLMKyv6DmuouZCHUMIpn6NkkZOThU3RUokuI+0oXWw1+u/rOAxYrqKguKXuaGiaRju/p4SQ07MfrLnIRVEyCK/0ddaTz50ygorrlGFVMogF20s9JCNiH13BehMT40Bhc6vfc5rwCHHMsJAQtdqhiEp0TtpwhJGimoW7kxFhAoDyWlfpdH3B687YR9dS9IC9XxyjYypSozO+4IZJifGi0QEGJ33emwzoWZU+jnrq/q/eVOiaRgfn0eqIkhRgTiqrHMjtd7nZW/e13qqkMQZ6k1t2h1fR9ohxbcWPExfjQHrkkrZzkWEyimsoQ5KFqGUVj7KL/E6X4AeengBwLCCwo8ZsPdvLpXlRTGVdDHlGv1QyviRB1mIIKKSLHAn1L/O6O6nSwV4gUQb5RPbPoWup4gZBgGI14ysixQN0Sv7395lRaXsa/qKYRqWZRegygEhAFeCKFxPjQ+LXY77/a/ifnUkulUO4sNQ1jKNWABMyglJNjgY+LzYCD4vtPUEvlUEbsUdM0hlERSIA8Y8NGr8W0iAnySyWySxhB9v9qyM/OlqwCzsOlaIm2uA5N0RCZnhnHi1QFEhDjE1rneZiMQhRK6NSs0nik2Cxsth1BzjyZSion7a2G2GZv0uujL97BUoMciE1YgHF4CI3d9qwtNV6gMpAA+DJBFTcdfbDn8L+tHSlB7llsHjbY/dwcKqkcOa4ptti5rjEIi20Z8mZMwa1S98z9mHFBfGYVqibYG+cU+ddXRkqQexSbiUU2P6UPpJbKyLCoJbYmmuo6eM1x17tdeAOXSzORe3GQGkF8Yx+usLTH1thU7N/fHClB7l3sd3vfriBfSjWVkfCWoNJbJp7HgaQNew7aSjKSm3h7j/hGT0tbfKBUyK5vpAR5ZLHfbai9T+0960TqqVs5rpoodnwdfndt3N+hpaQL1axxQfzgM0s7fMqgROyYSAnytGK/W3d7n3qfeuqSjLLaGsvKpnhOUuy2ENOkVAKoyUpwxHO2WR7RPWf4mVmREuTiVZHttXHSOlFRXVH2NLHEaoJrYJZUM9+NvhJ6j1XABCoG8RSrHeETJp9ZEyE5rlnsG8A6e58qEP9HTXWTd3yCnmN9n/1XD0x9oZTuvN2OJBsRIpv5Fmmbd5r2sylEjcgI8p3FfrN3mfLmiyCPsprey7HRI3Pfgc4STOZyrKRyEA/IQ2NTq2uG/RafbBsZQW6NQUVGM3bS80GOu1lNblPs8NDkC/GChKsjVTCF6kGkY344VznB8XbqlSAqlvKWSVVNmrRLtDzzqb0CuZ6b/UxUkdIQdRsVhEhkD2qZWtukBJ+dlsJyrK2gqiZ/L0+3upfX2Ac5BoCfcYEEQzgfc6giRBrPW/zxT0RuStVMLjGGU1eTJPtY8Y2VwG3wzfg3J7gLZfOrEnphN5WESGA3qplek95u4/NXpHLIIkdvFTuG+uo8evy8VVz2F18dYIfdA4OEFbdmUE2Ia0aZWtg7tj4/IKWjyAJilX4bRdnZzbyrRKHZdGYUK5biDztxjSRjuM/WHoYQM/JQz8S2rrJ5PerzVBdkCIhleqtYGSqtvd2xELnmU/l2IG6wE9dKMoVamExVIUkz1dSy7G5UDkg5qo7AEd9X8QpUWzvR4znmk/hogJG7FtJMoSPWUVlIUjQ3sanbHTzjbsrxobFP9IgdTc213h8/a9WEJsjilttwiTRTqIThyKe6EIfMMz00Xu7gKR9Siv8e38TTqLrmyW5NzKPH55Wo7eo/q3GuRFNoUaI4CiGJuNfElto7esoeVKYQ/z22xBtReQ3RNfMi9PEADvNK86NUU87AIBc1nEmqYS6ksx0+6YFQS2gGzkEd1EcTND0yLkZ9nJtkjrWWJ7pSfR1Gj4co4hRfSKgFV3Q04KURYpPJptekCh0+aX4ohfhVbE1QLiEff+JnTMcL6IwGzkofvMxocsno8ZPm03W9QhHX8ZLNLI6H2WWE2OAmEwtKptRro9DJ8VDHv+NWTEYXZNndJ0/KOJ4q/LccXy4KzCufblTKMXpKN7a6+IZ6QyzZYvLd7BzL6m5mjA6ZHD+W9LztxVsWtfGKjfd4YeQw5c4Sm8yvHX+mmGscwNXyL3WiH+PJxIJRtnov249HVw+RHA90HJQpTiG+sld49HVeF4nFYrGj9M/MJ+lJBZ1jnSeFvi/z+VI4CRNmF/iTPYMYHBo5HiRpBmfiwsRv6005jol+wqLcdp6S7pEj+XDvr/PjIcxPJobx0LhJMmiy/SS3oGIYygGV6C3tjr0YjPLWbywUzVNdjhuIfLPpqY61yrrIUI9M8Fqsov6QEkw2/TKfPE8qL8cVPGjwsBh1rd+6XYhUvgpyplhv/tdR5fpoBbjKIzPMwngqEClGVxNbWezimTsV77BXA996Mpe5aGf95tkpmwKXfayY7cXJqj9846Ex3ootVCFy5I9/tkllcG8OClUYl3r4TTEfj1u/vVuqhitGmE/K1YFWrrBHBw8NMluJu4lEBRZLzbD4m4PK5iPf5XnP9tFW9/r2pGTYQtxuviDVsDoEjrLCk6O9v0Y6hiR9ZEOihNl5xTTXT16oYEundAz3ZVbHWl4TSb3o8cXigHn0+JOQuMqDHhtnB5+6BxKVaW0iXDL6rj+imBzXxXzf5vUxi58jrW5qyXENsdN8MvqHxlU2el45q46PBkpUJA+VTOoFymCXnexc30Y37PR1ZptbHe2lDhlltTXhjh7/zWAfvsIxdJHK/GBiFy9Ie34FJcS4qgdJbolYZ3FjMWX2yOkZYrlVssuaULnLLtT0wVg7YhuVKUUxqzsh75vTGAXk+LaAKtZMsaptkRJHeXW0zVa7wa9D5zBjfIqtfU9tSknuMbSH8kkVFTKjW6BiXFvC8WSyFJr3yyzUKkVfjtuLfVZLMyaUMb6GPt1bmkh1SkGMb5Y1l/qOg4kuS3g24nhIyuFk8nxvWjlZGxlpMT77P9ok68W5L6QuM8038+2laG0P4hV/mlhCP8nv2Y2mAchxa/yowBx3NW2DWva06O6Nm5lfkj40rgttAcpCiT2pEyfC7aRKpRCfmNjBVOlv2oIrfRXjC/GRInP8m3k29h3RTHKrKT5PtDyNsT3EbrPQWcMYV6MhfqVOpQzPmljBOg/etROtfLLhbLwqNQbullvMbkTkRG9nXFEba94N5O9s23Uhd5w7fNxbnMNr1SnD7SZlN71hH271oWjQS55fjHbKt6YHe+XSI3X9QxtrXlyzqMAsC73j/I6MCF4vJUHT0CQN0rvw2zAPCwLUxouKdpC8Otol68v+Q79JfG3368tPkXCd3j4fiPTkAV/k2Wsijt720ZmHOh7Y6xV4R+ErX6bNi5eEP0hRXTwvcu0u0wX4LSLOs8V2h1tZoy12U7MijVmdtykev3cn+kncJ2fiLuXvF+xAplliXvnQSnG5s8S94jsnS3Ul1kfIfYb6njZ0NbZStSLMRJN196P74lJcL8FCm2JMSI7ru0SpOrI4Rb9Jm6rlOVus+7EvYl8w6/guyQ3Y8inCDDDpvehXguh36Jxkgc44mmEYlodormea/S4zwyXFJ+hNxUTzUpoqlRLxngkBJNefh6VUrohyk0k3DT9ZhSG4wpE93onx+DN0c52Hqsa/0UFxSkgaMOlNxZtidzIicn2kQhV/k4/LApDkah51HyNB08Ckn4b//IHR6I7LTXKJ4qiLtuiNyaFoLGHGPWbZyC2VF+O0ymKQ2JhsHuLYCJeT/Dyg/rwfUb0iR56J/D0b4M90AEvxNT7BRIzCOEzBdORgmVKXPJLnA7OaFkMVluIz/inucHZwVzz61SvyPTDaBtT4ZgIVLGKsMlnrdzk1nrAT5Y1nfLGqFz3OFH3FluTrOt0RmRQ3KxYH1KdMD2WtPGLOl55XQia2NlOFFf6rnhhXEm85zaIoujPuHqoTV3d0DaiUISU5Wpi14dzMqfGIF818q7lSYqxrYkTyYlwNfbE2pZZ1TWBNcXSMpVdFBuMmnJVRyKnxiO/MPOs5ZcS4wn/Fy+Jg8mnh45UrJOIHAwPrvkBJjg7GNcgu58R4Rp7ZbduFquyNW4lNyXZLHpjC+bHbLZonei/J4+lZkeByw/W9nRPjIe2NvSpfgVzktLiYnlz32PuRk/J9kkcG2KOMu+RocI7h6g7kxHjIy2apb02CvoF3s9jrVAgqohMmYy9XFcBBk6R+vyT5HS5ByNlrsravcWo8ZJGZID8VoBhnHK+NdHoxoRMms/ZYMd4LtJNvOj7lEoSa301WdhqnxkPyUc143r8NTI7Ty4m5Thz/RrzDPm8GFAbSNvLvUQnfcRFCzNcm67qQU+MpHY13yHlZJwUTqjhP22zX5S/BEKzhCpoyN1BBFqiREhdxosq7Jqu6gVPjKWanP2mXBHH94yKx096+uBP7uiX919a/UR+buAghZZiJ57FPjLf8YOZNfXyX43gjsc9OB7xnQ1hcLxiWedifzG4m+B4uQyjpbZJOSrwlD5WMgxYz/M45rif2JHLvLAzCDq6ZA3oELMgCN3FPFUqM+00348R4ThtjQd4VO8bP2HHFRH3wMvCEoh1jVWYjKgcuyX25DCHkWsO1vI0T4zlPmZVHq+XnBelfrZ26JZZxpZLimcAFWWASlyF0GOexP8yJ8ZzPAu+ud5T4xMqdy+N1FjRJmt2oFbggZ2IxFyJkGFdVeI4T4zm50I2vW73jV7iil3VVCuazumOsAnvkupFvDBAt9pmsIy/F+8HFxrO/KVbGj1S3mlalNdvQkV2TZ7bAvo62yOdShIa1vKcXIA+YlSTI9F6Pj7FqyNSaSVNS+EQBQRZ4igsRGsyyYdnO1g/eMvOhzt6HK3pSjv2gpQKCrONzLkRIMGuWy7uXfrDMzIfe9bpuxf/EDjP3vQb7uDLS+M7koMDfUZsBqJAwyWQFt3FqfKDArJ75ttjR3saPXzGvg8AqFXLprETYguXNw8EIk7sAzHbyh9uCyEXWKol8sw7Rs7kmkvnDrMm4z+N9LkUIeMrkGw7xh1FmdZEf9lKQ3zBz2he4Ih7QRwlBrob1XArlechw7RpzYnziFzP/meuZHJdLN9sfN8QBrogH5KKqEpLcjl98ledOw5VrxYnxiULUMPaeAvF/Xu2PnzZz2FlcD494UQlBFnibS6E47QzXrRMnxjfMzny0Tp7IcdZx4k/jF3bmWnjGPlyghCBns2af4lxluG73c2J8Y6KZ97zvTf5xM7Oabsyu8JJJiuyRH+NSKE09rlrAbEHc2Hf2p53qhSCPMXbUrlwJTylAEyUEOZ3V+5TG+LRhKCfGR5qbXbC6xYsL01uMX7aI6+AxsxTZI3fgUihLvsk1IpYW8pMXzHxnlvxmTbWMX9WCq+ADbRWR5JlcCkXZzhxyBVhi5jkF8TTZAYtuxq8axVXwgV/MolM+j0tQwMVQErNab6xF4i+Xm/nO47JT3iYZv4hxRX/opsgemcUcw7U3m8+p8ZURZp6z9awT5e6Qlxu95lxeGPCJDSadbf0eV3MplGS+yXot4dT4ykbzrvEyC3GedaIoMHrJPVwB33hCkT1yDpdCQcyKb67l1PiM6XnPMok9qPVzWMEiaHaYXc30/Ro1UY8PWHxTET409x15e2S9qfErPuD8+8goRfbIbH+qHuNN1iqPU+Mz+SbdvwXEpvi/ZUWQ7zB+xY+cfx85gDpKCPJ9XArlGGm4UpU5MQEwxtRztKdkCXIP4xewm4S/vKGEIFfGbi6FYjzLasjKsBc1zQQ5T68nJ+mtP78QqUCeScUC1n5LdfobrtPFnJhAeM7cdzZIKcapP2P08EzOvO9MVEKQb+RCKIZxG/pmnJhA2I1sc++ZLqHLnnjZ6NE1OfO+U4CmCghyBk/vFcO4Fm9bTkxAjLbyn5c9at10Iec9AOYosUeewoVQihvZoFYp8nCZlf/c43aH/KbRY+tw3gPhVgUEmYXP1aI5V0kxFpnf2YMoEM3dxZBfNXpsLc56IKxD5cAF+QIug1I0MlylvpyYAHnMyoP2ivPcCPKLRg+tzjkPiFcV2CNv4DIohHGG+jOcmAA5YN1aYoOuSW5vyrTzoMhX4GiPtZFVIstwjUZwYgLld1Sz8qGfxSnJCvIAw8YkzEMOjCXICFiQ2RxIHQpM+oW8yakJmK+sIskQX2Qdl5wg32f8wC2c8cAYGLAgP8glUAb2C1GX0dZ+9FJyMeR2xo9bwfkOjL2oH6ggM8dVHZabrNEsTo0C9LH2pJuTEeRLjR82j7MdIME2P72MC6AMOWDxL5UDSpaJqvvSsp0LcjXjh33M2Q6UhwIU5PqcfmV4l5kwin+bbWblS6sq/NepIJ9h/KhXONcBL/TFgQkyK4mpw8swPnQ/wKlRhI3WpXM/dVrf4iixz+hBvTnTAfMjygckyPU4+crQG7y4pTrLUNXKn/o6vTy9xOgxHTnPgTM0IEFuzKlXBuM+bs05MUoxy/IytXals8S3qUaPacRZDpwCXMfeeimO8dfhuzgxivG6lUdtLXeWkx3yEOOKyIWc5cBZj3MCEOQenHhF2GVyLWQQp0Y5ulpHksvYP9a72/ghGznHCjAlAEF+ndOuCN+brNBkTo1y7LOub3GH/ZDFlcaPWMA5VoL7fRfkhZx0RZhkskI/c2oUZKXV4d7ueHm7O+RMFipXmf24wlc5roaDnHRFML4Jls6kN0WZYRJiEhAQc2wmwGUdJ/KNHvAC51cRfkcVHwW5GydcGa4xXKFLOTHK8riVb/W0e6y3ko6pNu/5KMg5nG5FyENF5liEbs3amPvWfr2avaDFZ+xrqzoP+ZaDzOwaVfjZZI1e5NQozAarzKhvYkfZ2SEPN/pwFbqmQhzAVb4I8iecamUYb7JGn3FqlGaShX/pt9gR5G4sYKI+q6wvaEoZ13GaFaKnySqt4dQozi3mPrbFRrmh+FWMJoaB6VZnuBJGZazkJCvEJaxjEVK2Itt8j/xiYkGuYPzRMZxZxRjsoRzrmMoJVsqpjf/83sGpCcXmyczPtDytUiJFPkYcZMW3MFCAjp4J8jBOr1J8YrJOIzk1oeAuc1+bnDiKvJStfMLBbjTyRI5ZHUE1+pus1PecmlCw2eL2QLxWUhXf6nBWFeRX6ddEMjGR06ocTQ3XqiLvUYaGYeY+916iTOTBxh/cxVlVMj4l83DvEvZnU5BdJhV2W3FqQsNBNDTzusIE3fbE7cYfXMxZVZKnJIlxJQxhXQQlmWGyYk9yakK1dTI9Qh9nHbK4yPhjH3JOlaQAN0tIcuuHTZxKReltsmozOTWh4iYz/zsg/s8qZKHx5D1cbEcDF2LcFOOxm5OoMBeZ1HnbzqkJFYvNvbCPZeKblsfeEeFiRRKHew3QA5N5A1N51pqs39WcmtDR1swb/7Csa2Fc8a0N51NhPrE83KuMy9EMbXELumMIJmMBtnLKQsJbJmv6FKcmdOSY+2gDK0H+wugjdTmfSvOEhSBn4VdOUEjpzNKoEaKp2Z29kVaC/LrRR8qz4pvSFKCDhSRfhj2cohCSj+omOcj7OTkh5EMzD91oEbQQjxt/KJfzqTTbLA/37uEEhRCz1qa8ORtO8kxLDVnc2BP3Gn9kCedTcZagMjtIR4qhJmv5EqcmpJi1l9AfNU98a238kVmcTeV530KQMzCPExQyWoPXtKLFHDP//NhckOsbf2QyZzMEDLSQ5HOxkRMUInYjw3AdqyOfkxNS8nGusXdujZUxEeS0LGN3HsfZDMWCWx3utWBBmhAxg+cBEaSHWaaFbhZDFqy+GmasD/cGcIJCg9ml6SmcmhAzziyK3NhEkDNON/7AC5zLkGB9uMfQU1gw/sMaxxZOTYhZZLZD7mIiyGX/wcLlYedji5t7lbGMExQCfjVZv2s5NaFmv8nJgP6YeeJbodEH+nMuQ8TjFnvkhtjJCVKekSarN5RTE8lvPvow87563CGHnny0s5DkW3jvUnnMStGwiUDYucZZXWRxgrEhDOFMhoptqGchycM5QUqzG+UN1602/5SGntbOBDnzZGMXfpkzGTJ+RkVTQU7HfE6Qwph1mmYZ3PDTwnhtXzcR5PT/GZvCaM5k6HjLYo9ch9VJFMYsW/UTTk3oqW28ti+ZNXGqYWwK7EccRh60kOSO/PqrKIWoA+Oai+zuEnb2mGRAaQ+bCHL8KmP3/YZzGUL2m9ZgFRAYxQlSkp9Z5S2ymLZyutlsh9zF+APrOJehZB1qWBQcWsgJUpAXTdbrVU5N6HnOrADnuWZZFs8Zuy4LmoSVHKSbSnJ95iQrSEuT1fqNUxN6LjUOWOSV/YfZDnm+cVNMEr2/ygICnTk9irHd5A8ofTD8/GLmh/NM5DjrJOOu0x05lyEmH9dZSPIbnCClMKtq3ZdTE3o6mXlhP7OAxeW8sBlFNpvVYYVABfzECVKGj3COyTp9yckJOfNNfVCvbRawGMkut9HkC4uCQxezCaoSbMGtFkWh2Ng03Bw0z3haZlKePvtYbbNxl9u9nM/QY1Vw6BFOjwJ/Mmtb1h8h4aav+eo+6DBg0YGzGQHyzC5tQkDH55ygANmO+yzEWEDgTU5SqLEoibsj7VQzQX6Nxz5RZg2qmTp8NgufB8ZMk5t5vAcQFRZYNY143CzD4jix1bgQDV01KkyzcPnbOD0BsAXdE4qxwJWcqBCzEFnma7u17Glm/aabGn+kHWc0QvSwcPt3OT0+M8XiHmXR8TSnKrTMR1Wrtb3DtFOIPs74IxM4pxFij0UT1KrYwAnyjVW4yZYYCwh8x+kKKVMtiuAK6Dmxo80L0+8wvjTNMo1R+4udblEBjvjBPgxBBdtyXJ2FC0JJIYZYJJsKaLvKpZvvj682/tDNnNfIMdDCSKZyejxnpmU3l9KjK6cshGxBxwTrqt0QM0e8xLhiqnAAl5kaSU1+I/KU3xK6aenxAactdHxlmVUuIKANjVkhfjO+VstqYFHkJ5OebQICt/NOmEfswACTJvBWI51/IkPGHvS2DFUICIgpsWMs5DhenjHF1OIFC2NpwHYE0inAZGQ7FmMBgeacvFDxBS5MuKbajIzjLffH+l3GHxzL+Y0oebjawmDi6MP6FhKZgcZJibGAwLOcvtCwDb3srOmcrJNi1mhTjT+6inMcWZYk+Pp8IWZzkiSwEG2SFmMBwf7godnijEZ1Oyv6dfzfCeQ46zhtl9FH63GWI82AhMZzH29puvyj19GVGAtUQR6nMQTk2P0O9K5pb5Ai++OLjT/8KOc50uy1Ee2qhlGUhKRYhrsRdynHAndwIkOw0u3trufzsaNiidEHGn/8U851xPnElhldhC84VQ5dtLvF9RsnYzwnU2nWoZfNldbyROeYPcRM43QbprxFn1ts79RWc7Jshik6S9gZ/zU46+qSi0H271v+kVbXphzHyohtRo9oxRlPAdZaFQYsNjIxAFs5YZbMRcfEGagOxsWcUkXZhIG2PUdATDat6WY/B3kwZz0lGOFAICpjEHZwygwowExcK1GKD43enFgF2YC+liWDSoy9FhXdDI/02ho/6BPOfEqQh4sciUQNjMQ+TlsR9mCsRQ09N2MaJ1cx1qGfEzGG9pWoGHOGeM74USzFmCpMcywUdTCKF0cAAL+jL6p4IsYCOpMOlWIt+iHTyQpuF/fayqoosUP+yuhhtTj/KUSLpDJk++HPlA5S5KCT1IhxydGYhqkMq9HLaR2SyeXOiiXB0WI3q1ikOvOSlIwK6J6Stzk3YDjqeyjFjCCrxDJ0dZrE+LPeOJYc5dKNHzmE65BSJH+jLAN34hsUpsg87cd7aCsxrY0RZLX5xXlGea7okXVcLFn0xrwUQoClLi8yNMLrEc9bL8Bc9LLo280IctSY7zwkdVB7wUGCm2EE+U7jRy/leqQY97uWkMroie8jOTeL8Rjq+CbFjCCrIMZtna5YoZiYnhFziz7Y+PG8pZdqrLMoWu9kXITnIxNXLsQPeNphWiAjyGFf85lo5ny9PtVqxmQg3jQuKUNSjwckft1ugbGh7nRxELPxiO+74qLjPRqk7+RjSjKVq79OuyQmC/G50Suu4NqkIL9JPqxKRxu8Errd8jpMQBdUDVCKWYs8CArwES5xvk7f6E1jMhE/Gb3mFq5PSnK7R9HQp7BQ+Vb2e/AF+qFR4EJ8aFRPmbwVVcIUTZyv0hxxWUw2Yq3Rq3pyjVKSeR5KTGW0xXAsVk5odiEHg9BSUgRd1uhAY/SNHFwV/M74iCBvN3pdH65SitLEc6nJxt14HQsD7m19AD/gDTyIRp7etUt+sJOeX2J8tTpiHIvFYlqe0SsHcqVSlDd9k5wMNMUjmIRfcMC33y4X8/AmeuEqp9dgfR8zaYo+iHES2RTfaFfEvEQUGr32Sa5WirIHWb6LTzoa4jY8hSlYLD0zYx+WYybG4BFcj2zFRbjo2ExT9JSv0dJ57lCOhzvjI4Kcz4vTpCj3BSxFlXApOuAhDMUEfIr5WIEttg4EC7Adq7EQn+FtvIj+uAvNUStEEly84zfxjhXooqYYx2KxmDhg9PpnuGop/EVORYk6B9VRHw3QFFejLdqiLZoeHpehPqo7K4uo/OhMM/SIDXjAcXKnNkM7P+YXYqvRj9CLK5eyFAR6HYKD31C9C8cNcVRcXkAUalP12jE/0VYwD5kUpzclMeDxIY1Q+jZjAmo6W4UCbWpadsxvxLdGP0wzrmAK8wUlMeCxjEYolcVO+x0WiLe0SrEgEJONW/SQ1GU/KlEUAxzpPiYCRp9c9HMWNS7Upmo1YkGhPWX8Y23iSqYwHSiLAY6GNEBJ5GOUw6ok2owAwhTFym/exm4FpCRDKYsBjltpgFJY4vTix8fxc2NBo9c2/uH6cz1TmBzKYoCD17JkhN2GOKpOoueIhjEVyDpO7Ge/AlKc3T51jeMwGu/SAF0yz1khTZn1jCUc631j/GMu5LqmMMxFDm7Mo/m5YA96OikYtciDEpouBbmv8Y96H9c2hbmewsjS9CFkERraP8Bbo98WOzqmGuI84x+3IgucpDAPURgDG3tofkmRh+H2q/jlih5l/xFTkqPESuMfuivXOGUZTGEMaFSh8SXFGtv127Q87YWyp8XURetv9qN/xXVOUV6mNAY0LqbxJcEkVLY7w1/Eq8bUJi1uXIRToB62cq1TkjcpjQGN62h8DjmAfnZnd6XWIhYGxESzX6EpI1oUZA4fxz00PkesR3N7M7tP9FE1alx6j5xt3DlEQKATDnLVU45XKI0BjcdofA6YY7cPzCw9MxYmxNvmv0wrBi5SjhcojQGNoTQ+mxRgiL0LTNvEvbGjYuFCCLHP/Feqh6Vc/5SiH6UxoDGKxmczcny3vRmdmP6/WBgRPa1+rQwMCrhxO/GT2ymNAY3xND4bbEMrO7O50adOeB7lI89OlJCTQ0tIEZpRGgMaU2h8CVmJBnbmcpp2ZizM6JrYlOiXbImZKKRFRJ7alMaAxgc0vgQstHOQt1O/LRZ+tIu1vMQm0wQTsIt2EWHyWO0tsPEezc+SaXY6jM/W9Fg00NuJAjtmUxFdMRt5tI9IsoLCyJCFkkxFeqIZLBTPZx8biw6is3lOcslRGZ0wHhtpJxHjAwojqyEryOTEcpwb5mM8813yQScmFMeV6IOp2ECLiQhPUxgDG2/Q/Ex4L7EcL0yLx6KI3lhsTcaY6qIzhmIm1tN6Qk1HCmNg4yWanyETEp9rvJxxfCyqpMXF927MqjraoCdGYiZWMtIcOtgvJLjxFM3PgPGJuoDk63fFok32saKvWRU4p+McNEUXDMJ4zMRi7KZ9Kc1KymKAoycNsBQfJtod745g5Nikm8h3XhjduWiGzhiAUfgIC7Cee2ilYKW3IEd7GmAJvk2U6LZOqxlLGY4Wd2hrvDbCOGqjGW5DHwzHFMzFakp0gNwZLgnbJ9aJJdp8bYaYoo8TI8QoMVFMFBPFFG2GvkAs0dZYVWlRb7Dfe3GW4xzrGfshvVwstcg4XtwhVvlrlumoizbojucwCd9QoH2kADXVlKrdYomYLd7WXtAf0TrqTeMXpmWVO8tehdvMk+MV0uqK5vpd2tPibTFXbFBXkLN4E7YIG3GB5WxpX2X8K5aKZB+rdRK/BGemhwT6PgzFh/gZe2mpHn5BVESa9oif9Q/1F/X79ZbxWhX+KzkYd4KeqV+q36IN0MaKOYlLBvg51tIID7MbV1rP1RdZJ8VSGe18baTYEbzJ6rgA7dAb47CAl7gl80hgq6rt0uZrY0VPvbVe2++SifF/x2uJ6/RHxBgxR9scrHXPoBECAPLQ1tpeZpx1YoycdaJ+o/hI7FVnR1EPt2AwPsJq2rAEJ/A5YLFVz9FGat3FZboWK6PMYfYp8VriOu1h8Zr4Uqy1f3OVJerlUYjuCWq5haYhk0+yfLU2UqxTK/5WEx0xBF8gl/acJLP8WKeD4gcxRuuedol+RihyjU5Iy9Kbiq7aUDFNLPP+iLADzRDAM9a746kRvgTigjLxqloX8aZYrdrRSAM8iMm8zO2YW71bk23iCzFE3KzVyDou5Ifcp+vVtCb6baKvGCU+Fj+JXLkzVZldLDHBOmSZw91xohhcmnaD9rQ2Q2xRTZh7YArLH9lkpfyym6vF+6KfaC5ExL8vZooG2jVaJ/0BMUgbKSZqM8RsfYFYJlaKXJErcrVdRbJFcrU14jfxg77A7BvmvJT/nlaqakXRGpRLyp5GxbVNern4VaKXNlabL3aqlN05CPNRQM314UBPyxM/izf1B+KNzv4P/cEyGNLeeAYfT2krXIQso6KaBw7/1/po/3H3WpwbiTvEk2KiNl+FvXMtPIiPsYfKa8hWVHIzuyv1D8Ugra2ozuieXcqdZXxgeB7yU9YKl6K6WZ3j3aJQ7NRq0G5kxd7+pZ8jmotu2gvaVPGT2B2ULGeiEz5inK4UvZ3O5AbxjXhLPK7fop2foun57hNJfzSe229SNmh2rnVOzqW0Gc9IOzVeNX6V6Cwe18aKL8XvR76U+DKqoTtmpvBOpCS/I8Nsrv4Qv+oL9AXaDDFBH6b117poV6ZV5rGKlKBFP+M5vzMlbXAd6lr3AulAi/E1Z0M7U5yntdDu04ZqU8VPYo/3snw+BjMXAwBwm9kcLVYnPziCm5Iss5upq1LOAjegvrW39qG9BB2D/p9eW28tHhTDxcdiiVcZoOm4HTkpXkHgC/MUo1a0wyCCFg+nmAWuQQNrP32NGwPldtC6pl+qddFeEJ+I3+01Y3WSIDc8ZS+U7DAvSf9T7CganqdBi3uMZ748/kghC1yNetb++UmkGpdGkbNOjNfSOopntRlio7yU/IHYlIKCfK/5nDSnpXksyKeYhea6pYz9/ZqoR833mSfTUkIV2tCuEL21qTLKKlZE3xSLKr9nPhszaVs+BC1GmlUJ/zEl7O/nRPVTlon/o5WEVZrLaddoT4tvtTw3olwe3VPmUOUn8+zjfP0cWpT3lEs3a5XWPgXs7xtUs/bGVSlXgD6KZJ0kLtMH6jnJp9JloEcK1I/70+LLov4i7cgf9HFma/BlxO1vKipY++H69AzaR4Q445/61eLlZIsfRV2Ud6GZxc27FC/+7SPx8uKg8SrUjfS90tEJaqdom9OyaB3R3INUEz3E7GS6aGegO1ZG0h32oI1FEj7vRPlqny+arcSgiIpxIZ5I5Hvb07JpGdE+PjlT3Cu+cV5wPAP3Y1nEHGI3WloVOBxGa/H17ON/ZqW40vFTBOV4t/lFpCPXpOO1aBepYfzlxL16jvO2UTdHqMLAJqtgBcQPvBjt+x75UbPVaBq5uiu/45JE/vYnD5RTbbdcU3vFtMBRoblzfBiB+hdLrHv57oiXp334f9oh1putyMBIyfGsRHkVEOu0SrSIVDxM+bd+t0Ev7ULroMb5GIrNIXaI6Ub1ZouWAm9Gywhkj3yj+bezzyMTOX4xcROEP5hZkdKIhuL9ohJsJ4e5PLqEsv7FPvSDbn2y3Z0WEZglfmLeLTIKl5VycXPi4OBSXaMlcHdyjph4uDpGvv0qGZdjdKjqX/yAixP9Ti/RFgIUZGFeJfxa7Au5HM/BeYl9ag67zJDDpFXWxmp5TmvKpaNtKMrd70C/0p3KSu6OJ8WOph0EKsndzFenc4hbkOVjSELrExDvnXUibYAUjSqX115J5tp1TfTDd8qGMAowHjUS/xZTYsfQAgLmaDHXfIWeDG1WRQs7eUzDuB0gBpRLF6OTq4VRB/2Ua6VagI8SJxlBQExhLzwVSM8Q281XaVzoxLgAr6BiYusrFD259sQqmjci2QJFddAHX2K/Ekd4ExKV/f5rjOHuWJnzjJZW2fBjQyXHf1jdBv07VLZLu4brThLulPVXxf7ky3i2xWisDcwVfsMgO2GKQ+MJdmNQSpJftJLkN0MixgcxzFYfc21FWmWuObH3BfJ/oq/Y6qaU5yV4CO/jTx8dYT1es7wWXWLsZ+tI1cg4Xl9gJcljQiDHOfYCZRCfpJ3KFScOyDxZu09b47bw/UXoibex1MN7fgX4CS+jeYI845J3osR5XGElQ2aWzRZ6IU9hMf4T3e1ZYaH2FA/ySBJkH6u3szr/dtImqiX6YzIWY68k88/DTxiHLvYDFH/vtT7MOJ1rqyZp2douq7Vrj11KivEeDEcVe/a3RW/KdSaunES8JvbK6uCnox46YCDGYCaWYIcjs9+PFZiJ19ADV6F8cu/fp9/NyLHKaE2sj5WvwK/KRY3HINum/WlfsRMIkUDZ0/T7xa9yO14fGlVwCVqiE+7HY3gRwzEa4zEeUzEe4/E6huMF9ENXtEdTnOcsLGE0vtQzuZbKBy5uT/Rt6y1lxDgPU+xm9EAU6I8xq4fI4yjtIjHG/Jqr4iNXv41745BIcq9Eq9lZgcv7BzDevhhDrI434soS+Xvlf+ittBnOy90HOg6KEen/49qFKHBxX6I1rY7xAV5G2oNRFn0ZDcbEsqdxVYlnlEvXHhaLQiHGBdqkeAWuWOh2yfck/qN/NX4IQIx/RR9UdWKBa7UruZ7EB+IVFJflAjEhvQrXKaSS3DlxBUIdt/nY7OkgpqGt05OM18UpXEviqyyLB8WsZK9cezZ2iOe5Mw65JDezToL7S5RvwULPS8zPx8Oo7tQGf9Eu5iqSYJznFNFGjBGbVBBjbb7WJfNkrkn40c8Rf9hb8yswFjs9KaG5AE/iQudWuFv0zDqOK0iC5ai0bO0+bapV7S5Px0rxBGsEREqSzxBz7F8/uhtTpV0dycVUdE3i4pGAgJgcT+PaEXU4Oi1bu0+8J9b5dnQ3X3+UPXujSMbx4jknWT0V0B6v4vukr1n/gcnohUuTz3r/VruIq0YUpezZopn+mJgutniU0LZIe0G7hklFEQ+IXWbendq88mBrDMCbmJOwyNU+/IYcjMFDaOksf6L0WKa3ZLY7CcdO53TRUNyhvaDNEH+4OwLUNou54mX9tngtlpdPIet5L3mLqYjz0RQdcC96HRl3oRPa4vJkgxJGJavuyD6WK0XCyDHxtPiFWlvRSzyvvSE+Et+IZWKLwZn6XpErVovvxMfaG+I50VNvpdWM/5vTl6L75OvEWkUTLH8Tt3NzQKLpdieknZp2atqp/OpHSpJ5sva0OKiYGP+kt2ONCkJISpJWWXysiBQXiul609hRXBNCSCp/i6qjTQ24nsp2MSItiytBCCGxWEzUER8FIsoFYpbW8awTuQKEEFKE9AwxyNfboT+LvmlxzjshhBjvlE/QbxSzRL7Hu+JvRe94Vc42IYQk3iv/T79NfOJBBkaumCjas5o2IYQ4JO1UvaX2gliUuHBnwrFKe0PckV6FORSEEOIujHFK/Cr9UTFBLBYHHIjwHm2+eE27T29c7izOISGEyOYYPVNcpt+kPyCe1ceJ97UZ2gztK32BmKvNEJPFeDFCPKHfpV+t1dTP4GQRQghJYf4fTci7RwYvH54AAAAASUVORK5CYII=")] + +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/src/test/rustdoc-gui/target.goml b/src/test/rustdoc-gui/target.goml new file mode 100644 index 00000000000..3e5c30dc7ea --- /dev/null +++ b/src/test/rustdoc-gui/target.goml @@ -0,0 +1,35 @@ +// Check that the targetted element has the expected styles. +goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html#method.a_method" +show-text: true + +// Confirming that the method is the target. +assert: "#method\.a_method:target" + +define-function: ( + "check-style", + (theme, background, border), + [ + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + ("assert-css", ("#method\.a_method:target", { + "background-color": |background|, + "border-right": "3px solid " + |border|, + })), + ], +) + +call-function: ("check-style", { + "theme": "ayu", + "background": "rgba(255, 236, 164, 0.06)", + "border": "rgba(255, 180, 76, 0.85)", +}) +call-function: ("check-style", { + "theme": "dark", + "background": "rgb(73, 74, 61)", + "border": "rgb(187, 116, 16)", +}) +call-function: ("check-style", { + "theme": "light", + "background": "rgb(253, 255, 211)", + "border": "rgb(173, 124, 55)", +}) diff --git a/src/test/rustdoc-gui/trait-sidebar-item-order.goml b/src/test/rustdoc-gui/trait-sidebar-item-order.goml index a799444a108..e5d023544d6 100644 --- a/src/test/rustdoc-gui/trait-sidebar-item-order.goml +++ b/src/test/rustdoc-gui/trait-sidebar-item-order.goml @@ -1,4 +1,9 @@ // Checks that the elements in the sidebar are alphabetically sorted. + +// We need to disable this check because `implementors/test_docs/trait.AnotherOne.js` +// doesn't exist. +fail-on-request-error: false + goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html" assert-text: (".sidebar-elems section .block li:nth-of-type(1) > a", "another") assert-text: (".sidebar-elems section .block li:nth-of-type(2) > a", "func1") diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml index fce3002e750..dcffe956c21 100644 --- a/src/test/rustdoc-gui/type-declation-overflow.goml +++ b/src/test/rustdoc-gui/type-declation-overflow.goml @@ -1,4 +1,10 @@ // This test ensures that the items declaration content overflow is handled inside the <pre> directly. + +// We need to disable this check because +// `implementors/test_docs/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.js` +// doesn't exist. +fail-on-request-error: false + goto: "file://" + |DOC_PATH| + "/lib2/long_trait/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.html" // We set a fixed size so there is no chance of "random" resize. size: (1100, 800) diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs index e58bba64058..94ea0e93bf6 100644 --- a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs +++ b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs @@ -1,3 +1,4 @@ +// check-pass // This test ensures that rustdoc does not panic on inherented associated types // that are referred to without fully-qualified syntax. @@ -9,8 +10,4 @@ pub struct Struct; impl Struct { pub type AssocTy = usize; pub const AssocConst: Self::AssocTy = 42; - //~^ ERROR ambiguous associated type - //~| HELP use fully-qualified syntax - //~| ERROR ambiguous associated type - //~| HELP use fully-qualified syntax } diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr deleted file mode 100644 index b963b722f66..00000000000 --- a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0223]: ambiguous associated type - --> $DIR/ambiguous-inherent-assoc-ty.rs:11:27 - | -LL | pub const AssocConst: Self::AssocTy = 42; - | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Struct as Trait>::AssocTy` - -error[E0223]: ambiguous associated type - --> $DIR/ambiguous-inherent-assoc-ty.rs:11:27 - | -LL | pub const AssocConst: Self::AssocTy = 42; - | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Struct as Trait>::AssocTy` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0223`. diff --git a/src/test/rustdoc-ui/issue-103997.rs b/src/test/rustdoc-ui/issue-103997.rs new file mode 100644 index 00000000000..36f42fb15f7 --- /dev/null +++ b/src/test/rustdoc-ui/issue-103997.rs @@ -0,0 +1,6 @@ +// check-pass + +pub fn foo() {} + +/// [`foo`](Self::foo) //~ WARNING unresolved link to `Self::foo` +pub use foo as bar; diff --git a/src/test/rustdoc-ui/issue-103997.stderr b/src/test/rustdoc-ui/issue-103997.stderr new file mode 100644 index 00000000000..c06db91496f --- /dev/null +++ b/src/test/rustdoc-ui/issue-103997.stderr @@ -0,0 +1,10 @@ +warning: unresolved link to `Self::foo` + --> $DIR/issue-103997.rs:5:13 + | +LL | /// [`foo`](Self::foo) + | ^^^^^^^^^ no item named `Self` in scope + | + = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index a3e10ee5555..3da19a13e53 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -46,6 +46,7 @@ pub fn f(_: &(ToString + 'static)) {} impl Bar { // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.F"]' \ // "const F: fn(_: &(dyn ToString + 'static))" + // FIXME(fmease): Hide default lifetime, render "const F: fn(_: &dyn ToString)" pub const F: fn(_: &(ToString + 'static)) = f; } diff --git a/src/test/rustdoc/async-trait-sig.rs b/src/test/rustdoc/async-trait-sig.rs new file mode 100644 index 00000000000..2578bc8f7a1 --- /dev/null +++ b/src/test/rustdoc/async-trait-sig.rs @@ -0,0 +1,14 @@ +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +pub trait Foo { + // @has async_trait_sig/trait.Foo.html '//h4[@class="code-header"]' "async fn bar() -> i32" + async fn bar() -> i32; + + // @has async_trait_sig/trait.Foo.html '//h4[@class="code-header"]' "async fn baz() -> i32" + async fn baz() -> i32 { + 1 + } +} diff --git a/src/test/rustdoc/doc-notable_trait-slice.bare_fn_matches.html b/src/test/rustdoc/doc-notable_trait-slice.bare_fn_matches.html new file mode 100644 index 00000000000..6b58be7e685 --- /dev/null +++ b/src/test/rustdoc/doc-notable_trait-slice.bare_fn_matches.html @@ -0,0 +1 @@ +<script type="text/json" id="notable-traits-data">{"&'static [SomeStruct]":"<h3 class=\"notable\">Notable traits for <code>&amp;[<a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait_slice::SomeStruct\">SomeStruct</a>]</code></h3><pre class=\"content\"><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait_slice::SomeTrait\">SomeTrait</a> for &amp;[<a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait_slice::SomeStruct\">SomeStruct</a>]</span>"}</script> \ No newline at end of file diff --git a/src/test/rustdoc/doc-notable_trait-slice.rs b/src/test/rustdoc/doc-notable_trait-slice.rs index b0d41402721..2411da8cd45 100644 --- a/src/test/rustdoc/doc-notable_trait-slice.rs +++ b/src/test/rustdoc/doc-notable_trait-slice.rs @@ -8,13 +8,13 @@ pub struct OtherStruct; impl SomeTrait for &[SomeStruct] {} // @has doc_notable_trait_slice/fn.bare_fn_matches.html -// @has - '//code[@class="content"]' 'impl SomeTrait for &[SomeStruct]' +// @snapshot bare_fn_matches - '//script[@id="notable-traits-data"]' pub fn bare_fn_matches() -> &'static [SomeStruct] { &[] } // @has doc_notable_trait_slice/fn.bare_fn_no_matches.html -// @!has - '//code[@class="content"]' 'impl SomeTrait for &[SomeStruct]' +// @count - '//script[@id="notable-traits-data"]' 0 pub fn bare_fn_no_matches() -> &'static [OtherStruct] { &[] } diff --git a/src/test/rustdoc/doc-notable_trait.bare-fn.html b/src/test/rustdoc/doc-notable_trait.bare-fn.html new file mode 100644 index 00000000000..4e4a3f18f24 --- /dev/null +++ b/src/test/rustdoc/doc-notable_trait.bare-fn.html @@ -0,0 +1 @@ +<script type="text/json" id="notable-traits-data">{"SomeStruct":"<h3 class=\"notable\">Notable traits for <code><a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></code></h3><pre class=\"content\"><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></span>"}</script> \ No newline at end of file diff --git a/src/test/rustdoc/doc-notable_trait.rs b/src/test/rustdoc/doc-notable_trait.rs index 58a24b855d6..1f2cd7181c3 100644 --- a/src/test/rustdoc/doc-notable_trait.rs +++ b/src/test/rustdoc/doc-notable_trait.rs @@ -9,7 +9,8 @@ impl<T: SomeTrait> SomeTrait for Wrapper<T> {} #[doc(notable_trait)] pub trait SomeTrait { // @has doc_notable_trait/trait.SomeTrait.html - // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>' + // @has - '//span[@class="notable-traits"]/@data-ty' 'Wrapper<Self>' + // @snapshot wrap-me - '//script[@id="notable-traits-data"]' fn wrap_me(self) -> Wrapper<Self> where Self: Sized { Wrapper { inner: self, @@ -22,15 +23,16 @@ impl SomeTrait for SomeStruct {} impl SomeStruct { // @has doc_notable_trait/struct.SomeStruct.html - // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct' - // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>' + // @has - '//span[@class="notable-traits"]/@data-ty' 'SomeStruct' + // @snapshot some-struct-new - '//script[@id="notable-traits-data"]' pub fn new() -> SomeStruct { SomeStruct } } // @has doc_notable_trait/fn.bare_fn.html -// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct' +// @has - '//span[@class="notable-traits"]/@data-ty' 'SomeStruct' +// @snapshot bare-fn - '//script[@id="notable-traits-data"]' pub fn bare_fn() -> SomeStruct { SomeStruct } diff --git a/src/test/rustdoc/doc-notable_trait.some-struct-new.html b/src/test/rustdoc/doc-notable_trait.some-struct-new.html new file mode 100644 index 00000000000..c0fd9748fd3 --- /dev/null +++ b/src/test/rustdoc/doc-notable_trait.some-struct-new.html @@ -0,0 +1 @@ +<script type="text/json" id="notable-traits-data">{"SomeStruct":"<h3 class=\"notable\">Notable traits for <code><a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></code></h3><pre class=\"content\"><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></span>","Wrapper<Self>":"<h3 class=\"notable\">Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre class=\"content\"><code><span class=\"where fmt-newline\">impl&lt;T:&nbsp;<a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script> \ No newline at end of file diff --git a/src/test/rustdoc/doc-notable_trait.wrap-me.html b/src/test/rustdoc/doc-notable_trait.wrap-me.html new file mode 100644 index 00000000000..9a59d5edd12 --- /dev/null +++ b/src/test/rustdoc/doc-notable_trait.wrap-me.html @@ -0,0 +1 @@ +<script type="text/json" id="notable-traits-data">{"Wrapper<Self>":"<h3 class=\"notable\">Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre class=\"content\"><code><span class=\"where fmt-newline\">impl&lt;T:&nbsp;<a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script> \ No newline at end of file diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs index 5f4712aab5b..db2491b87b4 100644 --- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs +++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs @@ -33,8 +33,12 @@ extern crate assoc_item_trait_bounds as aux; // @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]' // // @has - '//*[@id="tymethod.make"]' \ -// "fn make<F>(F, impl FnMut(&str) -> bool)\ +// "fn make<F>(_: F, _: impl FnMut(&str) -> bool)\ // where \ // F: FnOnce(u32) -> String, \ // Self::Out2<()>: Protocol<u8, Q0 = Self::Item, Q1 = ()>" pub use aux::Main; + +// @has main/trait.Aid.html +// @has - '//*[@id="associatedtype.Result"]' "type Result<'inter: 'src>" +pub use aux::Aid; diff --git a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs index d326e61daea..6644c8e4147 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs @@ -42,5 +42,5 @@ pub trait Helper { } pub trait Aid<'src> { - type Result<'inter>; + type Result<'inter: 'src>; } diff --git a/src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs b/src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs new file mode 100644 index 00000000000..9ac2e3d96de --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs @@ -0,0 +1,17 @@ +pub type Ty0 = dyn for<'any> FnOnce(&'any str) -> bool; + +pub type Ty1<'obj> = dyn std::fmt::Display + 'obj; + +pub type Ty2 = dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>; + +pub type Ty3<'s> = &'s dyn ToString; + +pub fn func0(_: &(dyn Fn() + '_)) {} + +pub fn func1<'func>(_: &(dyn Fn() + 'func)) {} + +pub trait Container<'r> { + type Item<'a, 'ctx>; +} + +pub trait Shape<'a> {} diff --git a/src/test/rustdoc/inline_cross/dyn_trait.rs b/src/test/rustdoc/inline_cross/dyn_trait.rs new file mode 100644 index 00000000000..fa760540e43 --- /dev/null +++ b/src/test/rustdoc/inline_cross/dyn_trait.rs @@ -0,0 +1,31 @@ +#![crate_name = "user"] + +// aux-crate:dyn_trait=dyn_trait.rs +// edition:2021 + +// @has user/type.Ty0.html +// @has - '//*[@class="item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static" +// FIXME(fmease): Hide default lifetime bound `'static` +pub use dyn_trait::Ty0; + +// @has user/type.Ty1.html +// @has - '//*[@class="item-decl"]//code' "dyn Display + 'obj" +pub use dyn_trait::Ty1; + +// @has user/type.Ty2.html +// @has - '//*[@class="item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>" +pub use dyn_trait::Ty2; + +// @has user/type.Ty3.html +// @has - '//*[@class="item-decl"]//code' "&'s (dyn ToString + 's)" +// FIXME(fmease): Hide default lifetime bound, render "&'s dyn ToString" +pub use dyn_trait::Ty3; + +// @has user/fn.func0.html +// @has - '//pre[@class="rust fn"]' "func0(_: &dyn Fn())" +// FIXME(fmease): Show placeholder-lifetime bound, render "func0(_: &(dyn Fn() + '_))" +pub use dyn_trait::func0; + +// @has user/fn.func1.html +// @has - '//pre[@class="rust fn"]' "func1<'func>(_: &(dyn Fn() + 'func))" +pub use dyn_trait::func1; diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index 6c1cf8252a9..9c4f6465920 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -29,7 +29,7 @@ pub use impl_trait_aux::func4; // @has impl_trait/fn.func5.html // @has - '//pre[@class="rust fn"]' "func5(" // @has - '//pre[@class="rust fn"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>," -// @has - '//pre[@class="rust fn"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>" +// @has - '//pre[@class="rust fn"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>" // @!has - '//pre[@class="rust fn"]' 'where' pub use impl_trait_aux::func5; diff --git a/src/test/rustdoc/issue-20727.rs b/src/test/rustdoc/issue-20727.rs index f7acffcb4e5..c1a98cd57da 100644 --- a/src/test/rustdoc/issue-20727.rs +++ b/src/test/rustdoc/issue-20727.rs @@ -19,6 +19,6 @@ pub mod reexport { // @has - '//*[@class="rust trait"]' 'trait Deref {' // @has - '//*[@class="rust trait"]' 'type Target: ?Sized;' // @has - '//*[@class="rust trait"]' \ - // "fn deref(&'a self) -> &'a Self::Target;" + // "fn deref<'a>(&'a self) -> &'a Self::Target;" pub use issue_20727::Deref; } diff --git a/src/test/rustdoc/spotlight-from-dependency.odd.html b/src/test/rustdoc/spotlight-from-dependency.odd.html new file mode 100644 index 00000000000..987a949af44 --- /dev/null +++ b/src/test/rustdoc/spotlight-from-dependency.odd.html @@ -0,0 +1 @@ +<script type="text/json" id="notable-traits-data">{"Odd":"<h3 class=\"notable\">Notable traits for <code><a class=\"struct\" href=\"struct.Odd.html\" title=\"struct foo::Odd\">Odd</a></code></h3><pre class=\"content\"><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"{{channel}}/core/iter/traits/iterator/trait.Iterator.html\" title=\"trait core::iter::traits::iterator::Iterator\">Iterator</a> for <a class=\"struct\" href=\"struct.Odd.html\" title=\"struct foo::Odd\">Odd</a></span><span class=\"where fmt-newline\"> type <a href=\"{{channel}}/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item\" class=\"associatedtype\">Item</a> = <a class=\"primitive\" href=\"{{channel}}/std/primitive.usize.html\">usize</a>;</span>"}</script> \ No newline at end of file diff --git a/src/test/rustdoc/spotlight-from-dependency.rs b/src/test/rustdoc/spotlight-from-dependency.rs index 5245789212d..156aedca62b 100644 --- a/src/test/rustdoc/spotlight-from-dependency.rs +++ b/src/test/rustdoc/spotlight-from-dependency.rs @@ -3,7 +3,8 @@ use std::iter::Iterator; // @has foo/struct.Odd.html -// @has - '//*[@id="method.new"]//span[@class="notable-traits"]//code/span' 'impl Iterator for Odd' +// @has - '//*[@id="method.new"]//span[@class="notable-traits"]/@data-ty' 'Odd' +// @snapshot odd - '//script[@id="notable-traits-data"]' pub struct Odd { current: usize, } diff --git a/src/test/rustdoc/static-root-path.rs b/src/test/rustdoc/static-root-path.rs index 08c055c5b8d..86928b0fb0a 100644 --- a/src/test/rustdoc/static-root-path.rs +++ b/src/test/rustdoc/static-root-path.rs @@ -1,18 +1,18 @@ // compile-flags:-Z unstable-options --static-root-path /cache/ // @has static_root_path/struct.SomeStruct.html -// @matchesraw - '"/cache/main\.js"' -// @!matchesraw - '"\.\./main\.js"' +// @matchesraw - '"/cache/main-' +// @!matchesraw - '"\.\./main' // @matchesraw - 'data-root-path="\.\./"' // @!matchesraw - '"/cache/search-index\.js"' pub struct SomeStruct; // @has src/static_root_path/static-root-path.rs.html -// @matchesraw - '"/cache/source-script\.js"' -// @!matchesraw - '"\.\./\.\./source-script\.js"' +// @matchesraw - '"/cache/source-script-' +// @!matchesraw - '"\.\./\.\./source-script' // @matchesraw - '"\.\./\.\./source-files.js"' // @!matchesraw - '"/cache/source-files\.js"' // @has settings.html -// @matchesraw - '/cache/settings\.js' -// @!matchesraw - '\./settings\.js' +// @matchesraw - '/cache/settings-' +// @!matchesraw - '\../settings' diff --git a/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs b/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs new file mode 100644 index 00000000000..d7f5e19219e --- /dev/null +++ b/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs @@ -0,0 +1,192 @@ +// This test check that even if we mixup target feature of function with homogenous floats, +// the abi is sound and still produce the right answer. +// +// This is basically the same test as src/test/ui/simd/target-feature-mixup.rs but for floats and +// without #[repr(simd)] + +// run-pass +// ignore-emscripten +// ignore-sgx no processes + +#![feature(avx512_target_feature)] + +#![allow(overflowing_literals)] +#![allow(unused_variables)] + +use std::process::{Command, ExitStatus}; +use std::env; + +fn main() { + if let Some(level) = env::args().nth(1) { + return test::main(&level) + } + + match std::env::var("TARGET") { + Ok(s) => { + // Skip this tests on i586-unknown-linux-gnu where sse2 is disabled + if s.contains("i586") { + return + } + } + Err(_) => return, + } + + let me = env::current_exe().unwrap(); + for level in ["sse", "avx", "avx512"].iter() { + let status = Command::new(&me).arg(level).status().unwrap(); + if status.success() { + println!("success with {}", level); + continue + } + + // We don't actually know if our computer has the requisite target features + // for the test below. Testing for that will get added to libstd later so + // for now just assume sigill means this is a machine that can't run this test. + if is_sigill(status) { + println!("sigill with {}, assuming spurious", level); + continue + } + panic!("invalid status at {}: {}", level, status); + } +} + +#[cfg(unix)] +fn is_sigill(status: ExitStatus) -> bool { + use std::os::unix::prelude::*; + status.signal() == Some(4) +} + +#[cfg(windows)] +fn is_sigill(status: ExitStatus) -> bool { + status.code() == Some(0xc000001d) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[allow(nonstandard_style)] +mod test { + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x2(f32, f32); + + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x4(f32, f32, f32, f32); + + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); + + pub fn main(level: &str) { + unsafe { + main_normal(level); + main_sse(level); + if level == "sse" { + return + } + main_avx(level); + if level == "avx" { + return + } + main_avx512(level); + } + } + + macro_rules! mains { + ($( + $(#[$attr:meta])* + unsafe fn $main:ident(level: &str) { + ... + } + )*) => ($( + $(#[$attr])* + unsafe fn $main(level: &str) { + let m128 = f32x2(1., 2.); + let m256 = f32x4(3., 4., 5., 6.); + let m512 = f32x8(7., 8., 9., 10., 11., 12., 13., 14.); + assert_eq!(id_sse_128(m128), m128); + assert_eq!(id_sse_256(m256), m256); + assert_eq!(id_sse_512(m512), m512); + + if level == "sse" { + return + } + assert_eq!(id_avx_128(m128), m128); + assert_eq!(id_avx_256(m256), m256); + assert_eq!(id_avx_512(m512), m512); + + if level == "avx" { + return + } + assert_eq!(id_avx512_128(m128), m128); + assert_eq!(id_avx512_256(m256), m256); + assert_eq!(id_avx512_512(m512), m512); + } + )*) + } + + mains! { + unsafe fn main_normal(level: &str) { ... } + #[target_feature(enable = "sse2")] + unsafe fn main_sse(level: &str) { ... } + #[target_feature(enable = "avx")] + unsafe fn main_avx(level: &str) { ... } + #[target_feature(enable = "avx512bw")] + unsafe fn main_avx512(level: &str) { ... } + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } +} + +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +mod test { + pub fn main(level: &str) {} +} diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.rs b/src/test/ui/abi/issues/issue-22565-rust-call.rs index a08e0bfb5e5..a572666c888 100644 --- a/src/test/ui/abi/issues/issue-22565-rust-call.rs +++ b/src/test/ui/abi/issues/issue-22565-rust-call.rs @@ -1,32 +1,31 @@ #![feature(unboxed_closures)] extern "rust-call" fn b(_i: i32) {} -//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument that is a tuple +//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument trait Tr { extern "rust-call" fn a(); + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument extern "rust-call" fn b() {} - //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument } struct Foo; impl Foo { extern "rust-call" fn bar() {} - //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument } impl Tr for Foo { extern "rust-call" fn a() {} - //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument } -fn main () { +fn main() { b(10); - Foo::bar(); - <Foo as Tr>::a(); <Foo as Tr>::b(); } diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.stderr b/src/test/ui/abi/issues/issue-22565-rust-call.stderr index 3eee10bc5e9..9d205b444fa 100644 --- a/src/test/ui/abi/issues/issue-22565-rust-call.stderr +++ b/src/test/ui/abi/issues/issue-22565-rust-call.stderr @@ -1,26 +1,33 @@ -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument --> $DIR/issue-22565-rust-call.rs:3:1 | LL | extern "rust-call" fn b(_i: i32) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `i32` -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/issue-22565-rust-call.rs:9:5 - | -LL | extern "rust-call" fn b() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/issue-22565-rust-call.rs:16:5 +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:17:5 | LL | extern "rust-call" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/issue-22565-rust-call.rs:21:5 +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:22:5 | LL | extern "rust-call" fn a() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:7:5 + | +LL | extern "rust-call" fn a(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:10:5 + | +LL | extern "rust-call" fn b() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/abi/rustcall-generic.rs b/src/test/ui/abi/rustcall-generic.rs index 411c98e1031..6eaccc436b6 100644 --- a/src/test/ui/abi/rustcall-generic.rs +++ b/src/test/ui/abi/rustcall-generic.rs @@ -2,9 +2,9 @@ // check-pass //[opt] compile-flags: -Zmir-opt-level=3 -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -extern "rust-call" fn foo<T>(_: T) {} +extern "rust-call" fn foo<T: std::marker::Tuple>(_: T) {} fn main() { foo(()); diff --git a/src/test/ui/argument-suggestions/formal-and-expected-differ.rs b/src/test/ui/argument-suggestions/formal-and-expected-differ.rs new file mode 100644 index 00000000000..5e3b55ca525 --- /dev/null +++ b/src/test/ui/argument-suggestions/formal-and-expected-differ.rs @@ -0,0 +1,25 @@ +pub trait Foo { + type T; +} + +impl Foo for i32 { + type T = f32; +} + +pub struct U<T1, T2>(T1, S<T2>) +where + T1: Foo<T = T2>; + +pub struct S<T>(T); + +fn main() { + // The error message here isn't great -- it has to do with the fact that the + // `expected_inputs_for_expected_output` deduced inputs differs from the inputs + // that we infer from the constraints of the signature. + // + // I am not really sure what the best way of presenting this error message is, + // since right now it just suggests changing `3u32` <=> `3f32` back and forth. + let _: U<_, u32> = U(1, S(3u32)); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/src/test/ui/argument-suggestions/formal-and-expected-differ.stderr b/src/test/ui/argument-suggestions/formal-and-expected-differ.stderr new file mode 100644 index 00000000000..905875b5277 --- /dev/null +++ b/src/test/ui/argument-suggestions/formal-and-expected-differ.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/formal-and-expected-differ.rs:22:29 + | +LL | let _: U<_, u32> = U(1, S(3u32)); + | - ^^^^^^^ expected `f32`, found `u32` + | | + | arguments to this struct are incorrect + | + = note: expected struct `S<f32>` + found struct `S<u32>` +note: tuple struct defined here + --> $DIR/formal-and-expected-differ.rs:9:12 + | +LL | pub struct U<T1, T2>(T1, S<T2>) + | ^ + +error[E0308]: mismatched types + --> $DIR/formal-and-expected-differ.rs:22:24 + | +LL | let _: U<_, u32> = U(1, S(3u32)); + | --------- ^^^^^^^^^^^^^ expected `u32`, found `f32` + | | + | expected due to this + | + = note: expected struct `U<_, u32>` + found struct `U<i32, f32>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/array-slice-vec/array-break-length.stderr b/src/test/ui/array-slice-vec/array-break-length.stderr index 93f1c238bcc..2df7b6d7f63 100644 --- a/src/test/ui/array-slice-vec/array-break-length.stderr +++ b/src/test/ui/array-slice-vec/array-break-length.stderr @@ -1,8 +1,8 @@ -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/array-break-length.rs:3:17 | LL | |_: [_; break]| {} - | ^^^^^ cannot `break` outside of a loop + | ^^^^^ cannot `break` outside of a loop or labeled block error[E0268]: `continue` outside of a loop --> $DIR/array-break-length.rs:7:17 diff --git a/src/test/ui/asm/aarch64/llvm-58384.rs b/src/test/ui/asm/aarch64/llvm-58384.rs new file mode 100644 index 00000000000..308f7890829 --- /dev/null +++ b/src/test/ui/asm/aarch64/llvm-58384.rs @@ -0,0 +1,16 @@ +// only-aarch64 +// run-pass +// needs-asm-support + +// Test that we properly work around this LLVM issue: +// https://github.com/llvm/llvm-project/issues/58384 + +use std::arch::asm; + +fn main() { + let a: i32; + unsafe { + asm!("", inout("x0") 435 => a); + } + assert_eq!(a, 435); +} diff --git a/src/test/ui/asm/issue-92378.rs b/src/test/ui/asm/issue-92378.rs index 6e3c26e98c3..809b0d1555a 100644 --- a/src/test/ui/asm/issue-92378.rs +++ b/src/test/ui/asm/issue-92378.rs @@ -3,7 +3,7 @@ // needs-asm-support // build-pass -#![feature(no_core, lang_items, rustc_attrs, isa_attribute)] +#![feature(no_core, lang_items, rustc_attrs)] #![no_core] #![crate_type = "rlib"] diff --git a/src/test/ui/asm/naked-invalid-attr.stderr b/src/test/ui/asm/naked-invalid-attr.stderr index 58344be9334..e8ddccc854a 100644 --- a/src/test/ui/asm/naked-invalid-attr.stderr +++ b/src/test/ui/asm/naked-invalid-attr.stderr @@ -36,7 +36,7 @@ error: attribute should be applied to a function definition --> $DIR/naked-invalid-attr.rs:5:1 | LL | #![naked] - | ^^^^^^^^^ + | ^^^^^^^^^ cannot be applied to crates error: aborting due to 5 previous errors diff --git a/src/test/ui/assoc-inherent.rs b/src/test/ui/assoc-inherent.rs deleted file mode 100644 index c579c962ffc..00000000000 --- a/src/test/ui/assoc-inherent.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Test that inherent associated types work with -// inherent_associated_types feature gate. - -#![feature(inherent_associated_types)] -#![allow(incomplete_features)] - -struct Foo; - -impl Foo { - type Bar = isize; -} - -impl Foo { - type Baz; //~ ERROR associated type in `impl` without body -} - -fn main() { - let x : Foo::Bar; //~ERROR ambiguous associated type - x = 0isize; -} diff --git a/src/test/ui/assoc-inherent.stderr b/src/test/ui/assoc-inherent.stderr deleted file mode 100644 index b703453fa03..00000000000 --- a/src/test/ui/assoc-inherent.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: associated type in `impl` without body - --> $DIR/assoc-inherent.rs:14:5 - | -LL | type Baz; - | ^^^^^^^^- - | | - | help: provide a definition for the type: `= <type>;` - -error[E0223]: ambiguous associated type - --> $DIR/assoc-inherent.rs:18:13 - | -LL | let x : Foo::Bar; - | ^^^^^^^^ help: use fully-qualified syntax: `<Foo as Trait>::Bar` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0223`. diff --git a/src/test/ui/associated-inherent-types/assoc-inherent-no-body.rs b/src/test/ui/associated-inherent-types/assoc-inherent-no-body.rs new file mode 100644 index 00000000000..71f65b92eae --- /dev/null +++ b/src/test/ui/associated-inherent-types/assoc-inherent-no-body.rs @@ -0,0 +1,10 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + type Baz; //~ ERROR associated type in `impl` without body +} + +fn main() {} diff --git a/src/test/ui/associated-inherent-types/assoc-inherent-no-body.stderr b/src/test/ui/associated-inherent-types/assoc-inherent-no-body.stderr new file mode 100644 index 00000000000..387a5658da3 --- /dev/null +++ b/src/test/ui/associated-inherent-types/assoc-inherent-no-body.stderr @@ -0,0 +1,10 @@ +error: associated type in `impl` without body + --> $DIR/assoc-inherent-no-body.rs:7:5 + | +LL | type Baz; + | ^^^^^^^^- + | | + | help: provide a definition for the type: `= <type>;` + +error: aborting due to previous error + diff --git a/src/test/ui/associated-inherent-types/assoc-inherent-use.rs b/src/test/ui/associated-inherent-types/assoc-inherent-use.rs new file mode 100644 index 00000000000..7ae425e2aaa --- /dev/null +++ b/src/test/ui/associated-inherent-types/assoc-inherent-use.rs @@ -0,0 +1,14 @@ +// check-pass +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + type Bar = isize; +} + +fn main() { + let x: Foo::Bar; + x = 0isize; +} diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs index 6e464f69510..f67410986e5 100644 --- a/src/test/ui/associated-type-bounds/duplicate.rs +++ b/src/test/ui/associated-type-bounds/duplicate.rs @@ -132,12 +132,15 @@ where } fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] iter::empty() } fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] iter::empty() } fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] iter::empty() } fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr index e4f4836f71a..c3061327f56 100644 --- a/src/test/ui/associated-type-bounds/duplicate.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.stderr @@ -191,7 +191,31 @@ LL | T: Iterator<Item: 'static, Item: 'static>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:143:40 + --> $DIR/duplicate.rs:134:42 + | +LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:138:42 + | +LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:142:45 + | +LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:146:40 | LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} | ---------- ^^^^^^^^^^ re-bound here @@ -199,7 +223,7 @@ LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:145:40 + --> $DIR/duplicate.rs:148:40 | LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {} | ---------- ^^^^^^^^^^ re-bound here @@ -207,7 +231,7 @@ LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:147:43 + --> $DIR/duplicate.rs:150:43 | LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -215,7 +239,7 @@ LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:150:35 + --> $DIR/duplicate.rs:153:35 | LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -223,7 +247,7 @@ LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:152:35 + --> $DIR/duplicate.rs:155:35 | LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -231,7 +255,7 @@ LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:154:38 + --> $DIR/duplicate.rs:157:38 | LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -239,7 +263,7 @@ LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:158:29 + --> $DIR/duplicate.rs:161:29 | LL | T: Iterator<Item: Copy, Item: Send>, | ---------- ^^^^^^^^^^ re-bound here @@ -247,7 +271,7 @@ LL | T: Iterator<Item: Copy, Item: Send>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:163:29 + --> $DIR/duplicate.rs:166:29 | LL | T: Iterator<Item: Copy, Item: Copy>, | ---------- ^^^^^^^^^^ re-bound here @@ -255,7 +279,7 @@ LL | T: Iterator<Item: Copy, Item: Copy>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:168:32 + --> $DIR/duplicate.rs:171:32 | LL | T: Iterator<Item: 'static, Item: 'static>, | ------------- ^^^^^^^^^^^^^ re-bound here @@ -263,7 +287,7 @@ LL | T: Iterator<Item: 'static, Item: 'static>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:172:36 + --> $DIR/duplicate.rs:175:36 | LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -271,7 +295,7 @@ LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:174:36 + --> $DIR/duplicate.rs:177:36 | LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -279,7 +303,7 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:176:39 + --> $DIR/duplicate.rs:179:39 | LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -287,7 +311,7 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:178:40 + --> $DIR/duplicate.rs:181:40 | LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -295,7 +319,7 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:180:40 + --> $DIR/duplicate.rs:183:40 | LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; | ---------- ^^^^^^^^^^ re-bound here @@ -303,7 +327,7 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:182:43 + --> $DIR/duplicate.rs:185:43 | LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -311,7 +335,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:185:36 + --> $DIR/duplicate.rs:188:36 | LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} | ---------- ^^^^^^^^^^ re-bound here @@ -319,7 +343,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:187:36 + --> $DIR/duplicate.rs:190:36 | LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {} | ---------- ^^^^^^^^^^ re-bound here @@ -327,7 +351,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:189:39 + --> $DIR/duplicate.rs:192:39 | LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -335,7 +359,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:191:34 + --> $DIR/duplicate.rs:194:34 | LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -343,7 +367,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:193:34 + --> $DIR/duplicate.rs:196:34 | LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -351,7 +375,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:195:37 + --> $DIR/duplicate.rs:198:37 | LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -359,7 +383,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:199:29 + --> $DIR/duplicate.rs:202:29 | LL | T: Iterator<Item: Copy, Item: Send>, | ---------- ^^^^^^^^^^ re-bound here @@ -367,7 +391,7 @@ LL | T: Iterator<Item: Copy, Item: Send>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:205:29 + --> $DIR/duplicate.rs:208:29 | LL | T: Iterator<Item: Copy, Item: Copy>, | ---------- ^^^^^^^^^^ re-bound here @@ -375,7 +399,7 @@ LL | T: Iterator<Item: Copy, Item: Copy>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:211:32 + --> $DIR/duplicate.rs:214:32 | LL | T: Iterator<Item: 'static, Item: 'static>, | ------------- ^^^^^^^^^^^^^ re-bound here @@ -383,7 +407,7 @@ LL | T: Iterator<Item: 'static, Item: 'static>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:217:32 + --> $DIR/duplicate.rs:220:32 | LL | Self: Iterator<Item: Copy, Item: Send>, | ---------- ^^^^^^^^^^ re-bound here @@ -391,7 +415,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:217:32 + --> $DIR/duplicate.rs:220:32 | LL | Self: Iterator<Item: Copy, Item: Send>, | ---------- ^^^^^^^^^^ re-bound here @@ -399,7 +423,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:224:32 + --> $DIR/duplicate.rs:227:32 | LL | Self: Iterator<Item: Copy, Item: Copy>, | ---------- ^^^^^^^^^^ re-bound here @@ -407,7 +431,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:224:32 + --> $DIR/duplicate.rs:227:32 | LL | Self: Iterator<Item: Copy, Item: Copy>, | ---------- ^^^^^^^^^^ re-bound here @@ -415,7 +439,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:231:35 + --> $DIR/duplicate.rs:234:35 | LL | Self: Iterator<Item: 'static, Item: 'static>, | ------------- ^^^^^^^^^^^^^ re-bound here @@ -423,7 +447,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:231:35 + --> $DIR/duplicate.rs:234:35 | LL | Self: Iterator<Item: 'static, Item: 'static>, | ------------- ^^^^^^^^^^^^^ re-bound here @@ -431,7 +455,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:249:40 + --> $DIR/duplicate.rs:252:40 | LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -439,7 +463,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:251:44 + --> $DIR/duplicate.rs:254:44 | LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; | ---------- ^^^^^^^^^^ re-bound here @@ -447,7 +471,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:253:43 + --> $DIR/duplicate.rs:256:43 | LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -455,7 +479,7 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:237:34 + --> $DIR/duplicate.rs:240:34 | LL | type A: Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -463,7 +487,7 @@ LL | type A: Iterator<Item: Copy, Item: Send>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:241:34 + --> $DIR/duplicate.rs:244:34 | LL | type A: Iterator<Item: Copy, Item: Copy>; | ---------- ^^^^^^^^^^ re-bound here @@ -471,13 +495,13 @@ LL | type A: Iterator<Item: Copy, Item: Copy>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:245:37 + --> $DIR/duplicate.rs:248:37 | LL | type A: Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here | | | `Item` bound here first -error: aborting due to 60 previous errors +error: aborting due to 63 previous errors For more information about this error, try `rustc --explain E0719`. diff --git a/src/test/ui/async-await/issues/issue-65159.rs b/src/test/ui/async-await/issues/issue-65159.rs index 1dbf5db6c32..df2ca025705 100644 --- a/src/test/ui/async-await/issues/issue-65159.rs +++ b/src/test/ui/async-await/issues/issue-65159.rs @@ -6,7 +6,6 @@ async fn copy() -> Result<()> //~^ ERROR this enum takes 2 generic arguments { Ok(()) - //~^ ERROR type annotations needed } fn main() { } diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr index 9918f569cbc..45f5ec40cd7 100644 --- a/src/test/ui/async-await/issues/issue-65159.stderr +++ b/src/test/ui/async-await/issues/issue-65159.stderr @@ -16,18 +16,6 @@ help: add missing generic argument LL | async fn copy() -> Result<(), E> | +++ -error[E0282]: type annotations needed - --> $DIR/issue-65159.rs:8:5 - | -LL | Ok(()) - | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` - | -help: consider specifying the generic arguments - | -LL | Ok::<(), E>(()) - | +++++++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0107, E0282. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/attributes/key-value-non-ascii.rs b/src/test/ui/attributes/key-value-non-ascii.rs index 12942eabdf7..e14e2fc05ad 100644 --- a/src/test/ui/attributes/key-value-non-ascii.rs +++ b/src/test/ui/attributes/key-value-non-ascii.rs @@ -1,4 +1,4 @@ #![feature(rustc_attrs)] -#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte constant +#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte string literal fn main() {} diff --git a/src/test/ui/attributes/key-value-non-ascii.stderr b/src/test/ui/attributes/key-value-non-ascii.stderr index 422107867f7..23d482de6a8 100644 --- a/src/test/ui/attributes/key-value-non-ascii.stderr +++ b/src/test/ui/attributes/key-value-non-ascii.stderr @@ -1,8 +1,8 @@ -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/key-value-non-ascii.rs:3:19 | LL | #[rustc_dummy = b"ffi.rs"] - | ^ byte constant must be ASCII + | ^ must be ASCII | help: if you meant to use the UTF-8 encoding of 'ffi', use \xHH escapes | diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs index e2f016614bf..a3350024e75 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs @@ -1,4 +1,4 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] // Tests that we can't assign to or mutably borrow upvars from `Fn` // closures (issue #17780) @@ -7,10 +7,10 @@ fn set(x: &mut usize) { *x = 5; } -fn to_fn<A, F: Fn<A>>(f: F) -> F { +fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F { f } -fn to_fn_mut<A, F: FnMut<A>>(f: F) -> F { +fn to_fn_mut<A: std::marker::Tuple, F: FnMut<A>>(f: F) -> F { f } diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr index 093589ed092..a0eaf1f163b 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr @@ -1,8 +1,8 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:21:27 | -LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _f = to_fn(|| x = 42); | ----- -- ^^^^^^ cannot assign @@ -13,8 +13,8 @@ LL | let _f = to_fn(|| x = 42); error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:24:31 | -LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _g = to_fn(|| set(&mut y)); | ----- -- ^^^^^^ cannot borrow as mutable @@ -25,8 +25,8 @@ LL | let _g = to_fn(|| set(&mut y)); error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:29:22 | -LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | to_fn(|| z = 42); | ----- -- ^^^^^^ cannot assign @@ -37,8 +37,8 @@ LL | to_fn(|| z = 42); error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:36:32 | -LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _f = to_fn(move || x = 42); | ----- ------- ^^^^^^ cannot assign @@ -49,8 +49,8 @@ LL | let _f = to_fn(move || x = 42); error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:39:36 | -LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _g = to_fn(move || set(&mut y)); | ----- ------- ^^^^^^ cannot borrow as mutable @@ -61,8 +61,8 @@ LL | let _g = to_fn(move || set(&mut y)); error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:44:27 | -LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | to_fn(move || z = 42); | ----- ------- ^^^^^^ cannot assign diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr index a6af129bf39..4eeec09b910 100644 --- a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr +++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x = defer(&vec!["Goodbye", "world!"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | x.x[0]; | ------ borrow later used here | diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr index dea8ac90bec..c62d5f903c8 100644 --- a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr +++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | buggy_map.insert(42, &*Box::new(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | buggy_map.insert(43, &*tmp); | --------------------------- borrow later used here diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.rs b/src/test/ui/borrowck/borrowck-move-by-capture.rs index f26edef17f3..6f0eb1870f3 100644 --- a/src/test/ui/borrowck/borrowck-move-by-capture.rs +++ b/src/test/ui/borrowck/borrowck-move-by-capture.rs @@ -1,7 +1,7 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f } -fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f } +fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f } +fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f } pub fn main() { let bar: Box<_> = Box::new(3); diff --git a/src/test/ui/borrowck/issue-11493.stderr b/src/test/ui/borrowck/issue-11493.stderr index a5d1f2816f1..2720b09b0fc 100644 --- a/src/test/ui/borrowck/issue-11493.stderr +++ b/src/test/ui/borrowck/issue-11493.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let y = x.as_ref().unwrap_or(&id(5)); | ^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | let _ = &y; | -- borrow later used here | diff --git a/src/test/ui/borrowck/issue-17545.stderr b/src/test/ui/borrowck/issue-17545.stderr index 79a1e09bd7c..3ae7e64d202 100644 --- a/src/test/ui/borrowck/issue-17545.stderr +++ b/src/test/ui/borrowck/issue-17545.stderr @@ -5,7 +5,7 @@ LL | pub fn foo<'a, F: Fn(&'a ())>(bar: F) { | -- lifetime `'a` defined here LL | / bar.call(( LL | | &id(()), - | | ^^^^^^ creates a temporary which is freed while still in use + | | ^^^^^^ creates a temporary value which is freed while still in use LL | | )); | | -- temporary value is freed at the end of this statement | |______| diff --git a/src/test/ui/borrowck/issue-36082.fixed b/src/test/ui/borrowck/issue-36082.fixed index 8640ca7a509..8fc963a8566 100644 --- a/src/test/ui/borrowck/issue-36082.fixed +++ b/src/test/ui/borrowck/issue-36082.fixed @@ -10,7 +10,7 @@ fn main() { let val: &_ = binding.0; //~^ ERROR temporary value dropped while borrowed [E0716] //~| NOTE temporary value is freed at the end of this statement - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| HELP consider using a `let` binding to create a longer lived value println!("{}", val); //~^ borrow later used here diff --git a/src/test/ui/borrowck/issue-36082.rs b/src/test/ui/borrowck/issue-36082.rs index 877d372fb84..20f66b4d45d 100644 --- a/src/test/ui/borrowck/issue-36082.rs +++ b/src/test/ui/borrowck/issue-36082.rs @@ -9,7 +9,7 @@ fn main() { let val: &_ = x.borrow().0; //~^ ERROR temporary value dropped while borrowed [E0716] //~| NOTE temporary value is freed at the end of this statement - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| HELP consider using a `let` binding to create a longer lived value println!("{}", val); //~^ borrow later used here diff --git a/src/test/ui/borrowck/issue-36082.stderr b/src/test/ui/borrowck/issue-36082.stderr index 4bd586db1cd..a6357f8182f 100644 --- a/src/test/ui/borrowck/issue-36082.stderr +++ b/src/test/ui/borrowck/issue-36082.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let val: &_ = x.borrow().0; | ^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | println!("{}", val); | --- borrow later used here diff --git a/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs b/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs index 2c8a700bc2e..dd0320bc53b 100644 --- a/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs +++ b/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs @@ -17,7 +17,6 @@ async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> { //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied //~^^ ERROR this struct takes 1 generic argument but 0 generic arguments were supplied LockedMarket(generator.lock().unwrap().buy()) - //~^ ERROR cannot return value referencing temporary } struct LockedMarket<T>(T); diff --git a/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr b/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr index 4bd06673043..d2b927fb664 100644 --- a/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr +++ b/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr @@ -7,7 +7,7 @@ LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> | expected 0 lifetime arguments | note: struct defined here, with 0 lifetime parameters - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 | LL | struct LockedMarket<T>(T); | ^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> | ^^^^^^^^^^^^ expected 1 generic argument | note: struct defined here, with 1 generic parameter: `T` - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 | LL | struct LockedMarket<T>(T); | ^^^^^^^^^^^^ - @@ -28,16 +28,6 @@ help: add missing generic argument LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> { | +++ -error[E0515]: cannot return value referencing temporary value - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5 - | -LL | LockedMarket(generator.lock().unwrap().buy()) - | ^^^^^^^^^^^^^-------------------------^^^^^^^ - | | | - | | temporary value created here - | returns a value referencing data owned by the current function - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0107, E0515. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/c-variadic/issue-86053-1.stderr b/src/test/ui/c-variadic/issue-86053-1.stderr index 60b379faf4e..075bd1fc488 100644 --- a/src/test/ui/c-variadic/issue-86053-1.stderr +++ b/src/test/ui/c-variadic/issue-86053-1.stderr @@ -66,8 +66,8 @@ LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn<Args>: FnMut<Args> { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | -------------------------------------- similarly named trait `Fn` defined here | help: a trait with a similar name exists | diff --git a/src/test/ui/cannot-mutate-captured-non-mut-var.rs b/src/test/ui/cannot-mutate-captured-non-mut-var.rs index a83884acb1d..952dab25bf9 100644 --- a/src/test/ui/cannot-mutate-captured-non-mut-var.rs +++ b/src/test/ui/cannot-mutate-captured-non-mut-var.rs @@ -1,8 +1,8 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] use std::io::Read; -fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f } +fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f } fn main() { let x = 1; diff --git a/src/test/ui/chalkify/closure.rs b/src/test/ui/chalkify/closure.rs index 81114d491d7..408e8802d86 100644 --- a/src/test/ui/chalkify/closure.rs +++ b/src/test/ui/chalkify/closure.rs @@ -1,4 +1,5 @@ -// check-fail +// known-bug: unknown +// FIXME(chalk): Chalk needs support for the Tuple trait // compile-flags: -Z chalk fn main() -> () { @@ -25,7 +26,7 @@ fn main() -> () { let mut c = b; c(); - b(); //~ ERROR + b(); // FIXME: reenable when this is fixed ~ ERROR // FIXME(chalk): this doesn't quite work /* diff --git a/src/test/ui/chalkify/closure.stderr b/src/test/ui/chalkify/closure.stderr index 515e0cf0142..bcee0cab96a 100644 --- a/src/test/ui/chalkify/closure.stderr +++ b/src/test/ui/chalkify/closure.stderr @@ -1,22 +1,80 @@ -error[E0382]: borrow of moved value: `b` - --> $DIR/closure.rs:28:5 +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:7:5 + | +LL | t(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:13:5 + | +LL | b(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:17:5 + | +LL | c(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:18:5 | -LL | let mut c = b; - | - value moved here -... LL | b(); - | ^ value borrowed here after move + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:24:5 + | +LL | b(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:28:5 + | +LL | c(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:29:5 | -note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `a` out of its environment - --> $DIR/closure.rs:21:9 +LL | b(); // FIXME: reenable when this is fixed ~ ERROR + | ^^^ the trait `Tuple` is not implemented for `()` | -LL | a = 1; - | ^ -help: consider mutably borrowing `b` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | -LL | let mut c = &mut b; - | ++++ +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ -error: aborting due to previous error +error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0382`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/chalkify/trait-objects.rs b/src/test/ui/chalkify/trait-objects.rs index d56abc42bf5..30929e943bd 100644 --- a/src/test/ui/chalkify/trait-objects.rs +++ b/src/test/ui/chalkify/trait-objects.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: unknown +// FIXME(chalk): Chalk needs support for the Tuple trait // compile-flags: -Z chalk use std::fmt::Display; diff --git a/src/test/ui/chalkify/trait-objects.stderr b/src/test/ui/chalkify/trait-objects.stderr new file mode 100644 index 00000000000..422d39742eb --- /dev/null +++ b/src/test/ui/chalkify/trait-objects.stderr @@ -0,0 +1,32 @@ +error: the type `&dyn Fn(i32) -> _` is not well-formed (chalk) + --> $DIR/trait-objects.rs:11:12 + | +LL | let f: &dyn Fn(i32) -> _ = &|x| x + x; + | ^^^^^^^^^^^^^^^^^ + +error[E0277]: `(i32,)` is not a tuple + --> $DIR/trait-objects.rs:12:5 + | +LL | f(2); + | ^^^^ the trait `Tuple` is not implemented for `(i32,)` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() where (i32,): Tuple { + | +++++++++++++++++++ + +error[E0277]: expected a `Fn<(i32,)>` closure, found `dyn Fn(i32) -> i32` + --> $DIR/trait-objects.rs:12:5 + | +LL | f(2); + | ^^^^ expected an `Fn<(i32,)>` closure, found `dyn Fn(i32) -> i32` + | + = help: the trait `Fn<(i32,)>` is not implemented for `dyn Fn(i32) -> i32` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() where dyn Fn(i32) -> i32: Fn<(i32,)> { + | ++++++++++++++++++++++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr index 4ec74494fe0..6c0dc05ba23 100644 --- a/src/test/ui/check-cfg/well-known-values.stderr +++ b/src/test/ui/check-cfg/well-known-values.stderr @@ -6,7 +6,7 @@ LL | #[cfg(target_os = "linuz")] | | | help: did you mean: `"linux"` | - = note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous + = note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value diff --git a/src/test/ui/cleanup-rvalue-scopes-cf.stderr b/src/test/ui/cleanup-rvalue-scopes-cf.stderr index 40f14c38984..425cd75141c 100644 --- a/src/test/ui/cleanup-rvalue-scopes-cf.stderr +++ b/src/test/ui/cleanup-rvalue-scopes-cf.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x1 = arg(&AddFlags(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -21,7 +21,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x2 = AddFlags(1).get(); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -38,7 +38,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x3 = &*arg(&AddFlags(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -55,7 +55,7 @@ error[E0716]: temporary value dropped while borrowed LL | let ref x4 = *arg(&AddFlags(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -72,7 +72,7 @@ error[E0716]: temporary value dropped while borrowed LL | let &ref x5 = arg(&AddFlags(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -89,7 +89,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x6 = AddFlags(1).get(); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -106,7 +106,7 @@ error[E0716]: temporary value dropped while borrowed LL | let StackBox { f: x7 } = StackBox { f: AddFlags(1).get() }; | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr index 38401085971..39ec71ba22a 100644 --- a/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr @@ -16,7 +16,7 @@ LL | / || match out_ref { LL | | Variant::A => (), LL | | Variant::B => (), LL | | }; - | |______^ + | |_____^ | = note: closures are lazy and do nothing unless called = note: `#[warn(unused_must_use)]` on by default @@ -28,7 +28,7 @@ LL | / || match here.field { LL | | Variant::A => (), LL | | Variant::B => (), LL | | }; - | |______^ + | |_____^ | = note: closures are lazy and do nothing unless called diff --git a/src/test/ui/closures/binder/late-bound-in-body.rs b/src/test/ui/closures/binder/late-bound-in-body.rs new file mode 100644 index 00000000000..bb5c7552fda --- /dev/null +++ b/src/test/ui/closures/binder/late-bound-in-body.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(closure_lifetime_binder)] + +fn main() { + let _ = for<'a> || -> () { + let _: &'a bool = &true; + }; +} diff --git a/src/test/ui/closures/binder/nested-closures-regions.rs b/src/test/ui/closures/binder/nested-closures-regions.rs new file mode 100644 index 00000000000..6bfc6c80b78 --- /dev/null +++ b/src/test/ui/closures/binder/nested-closures-regions.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(closure_lifetime_binder)] +#![feature(rustc_attrs)] + +#[rustc_regions] +fn main() { + for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; +} diff --git a/src/test/ui/closures/binder/nested-closures-regions.stderr b/src/test/ui/closures/binder/nested-closures-regions.stderr new file mode 100644 index 00000000000..b385e0ed6e0 --- /dev/null +++ b/src/test/ui/closures/binder/nested-closures-regions.stderr @@ -0,0 +1,38 @@ +note: external requirements + --> $DIR/nested-closures-regions.rs:8:24 + | +LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: main::{closure#0}::{closure#0} with closure substs [ + i8, + extern "rust-call" fn((&(),)), + (), + ] + = note: late-bound region is '_#4r + = note: late-bound region is '_#2r + = note: number of external vids: 3 + = note: where '_#1r: '_#2r + = note: where '_#2r: '_#1r + +note: no external requirements + --> $DIR/nested-closures-regions.rs:8:5 + | +LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; + | ^^^^^^^^^^^^^^^^ + | + = note: defining type: main::{closure#0} with closure substs [ + i8, + extern "rust-call" fn(()), + (), + ] + = note: late-bound region is '_#2r + +note: no external requirements + --> $DIR/nested-closures-regions.rs:7:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = note: defining type: main + diff --git a/src/test/ui/closures/binder/nested-closures.rs b/src/test/ui/closures/binder/nested-closures.rs new file mode 100644 index 00000000000..b3c36e7eebb --- /dev/null +++ b/src/test/ui/closures/binder/nested-closures.rs @@ -0,0 +1,7 @@ +// check-pass + +#![feature(closure_lifetime_binder)] + +fn main() { + for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; +} diff --git a/src/test/ui/closures/closure-array-break-length.stderr b/src/test/ui/closures/closure-array-break-length.stderr index 2b8ab9bfc44..7e0b0027a6f 100644 --- a/src/test/ui/closures/closure-array-break-length.stderr +++ b/src/test/ui/closures/closure-array-break-length.stderr @@ -10,11 +10,11 @@ error[E0268]: `continue` outside of a loop LL | while |_: [_; continue]| {} {} | ^^^^^^^^ cannot `continue` outside of a loop -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/closure-array-break-length.rs:6:19 | LL | while |_: [_; break]| {} {} - | ^^^^^ cannot `break` outside of a loop + | ^^^^^ cannot `break` outside of a loop or labeled block error: aborting due to 3 previous errors diff --git a/src/test/ui/closures/issue-23012-supertrait-signature-inference.rs b/src/test/ui/closures/issue-23012-supertrait-signature-inference.rs new file mode 100644 index 00000000000..5899b703e7c --- /dev/null +++ b/src/test/ui/closures/issue-23012-supertrait-signature-inference.rs @@ -0,0 +1,29 @@ +// check-pass +// Checks that we can infer a closure signature even if the `FnOnce` bound is +// a supertrait of the obligations we have currently registered for the Ty var. + +pub trait Receive<T, E>: FnOnce(Result<T, E>) { + fn receive(self, res: Result<T, E>); +} + +impl<T, E, F: FnOnce(Result<T, E>)> Receive<T, E> for F { + fn receive(self, res: Result<T, E>) { + self(res) + } +} + +pub trait Async<T, E> { + fn receive<F: Receive<T, E>>(self, f: F); +} + +impl<T, E> Async<T, E> for Result<T, E> { + fn receive<F: Receive<T, E>>(self, f: F) { + f(self) + } +} + +pub fn main() { + Ok::<u32, ()>(123).receive(|res| { + res.unwrap(); + }); +} diff --git a/src/test/ui/closures/issue-78720.stderr b/src/test/ui/closures/issue-78720.stderr index 3dd13877298..da3f539a007 100644 --- a/src/test/ui/closures/issue-78720.stderr +++ b/src/test/ui/closures/issue-78720.stderr @@ -12,8 +12,8 @@ LL | _func: F, | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn<Args>: FnMut<Args> { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | -------------------------------------- similarly named trait `Fn` defined here | help: a trait with a similar name exists | diff --git a/src/test/ui/closures/supertrait-hint-references-assoc-ty.rs b/src/test/ui/closures/supertrait-hint-references-assoc-ty.rs new file mode 100644 index 00000000000..270bf14c35e --- /dev/null +++ b/src/test/ui/closures/supertrait-hint-references-assoc-ty.rs @@ -0,0 +1,17 @@ +// check-pass + +pub trait Fn0: Fn(i32) -> Self::Out { + type Out; +} + +impl<F: Fn(i32) -> ()> Fn0 for F { + type Out = (); +} + +pub fn closure_typer(_: impl Fn0) {} + +fn main() { + closure_typer(move |x| { + let _: i64 = x.into(); + }); +} diff --git a/src/test/ui/codegen/issue-99551.rs b/src/test/ui/codegen/issue-99551.rs index f24874c992e..b223aff4e94 100644 --- a/src/test/ui/codegen/issue-99551.rs +++ b/src/test/ui/codegen/issue-99551.rs @@ -1,6 +1,5 @@ // build-pass #![feature(trait_upcasting)] -#![allow(incomplete_features)] pub trait A {} pub trait B {} diff --git a/src/test/ui/compiletest-self-test/compile-flags-last.rs b/src/test/ui/compiletest-self-test/compile-flags-last.rs new file mode 100644 index 00000000000..232df10f1a8 --- /dev/null +++ b/src/test/ui/compiletest-self-test/compile-flags-last.rs @@ -0,0 +1,7 @@ +// Check that the arguments provided through `// compile-flags` are added last to the command line +// in UI tests. To ensure that we invoke rustc with a flag that expects an argument withut actually +// providing it. If the compile-flags are not last, the test will fail as rustc will interpret the +// next flag as the argument of this flag. +// +// compile-flags: --cap-lints +// error-pattern: Argument to option 'cap-lints' missing diff --git a/src/test/ui/compiletest-self-test/compile-flags-last.stderr b/src/test/ui/compiletest-self-test/compile-flags-last.stderr new file mode 100644 index 00000000000..d8d40a7d9f1 --- /dev/null +++ b/src/test/ui/compiletest-self-test/compile-flags-last.stderr @@ -0,0 +1,2 @@ +error: Argument to option 'cap-lints' missing + diff --git a/src/test/ui/ui-testing-optout.rs b/src/test/ui/compiletest-self-test/ui-testing-optout.rs index 88e81158316..88e81158316 100644 --- a/src/test/ui/ui-testing-optout.rs +++ b/src/test/ui/compiletest-self-test/ui-testing-optout.rs diff --git a/src/test/ui/ui-testing-optout.stderr b/src/test/ui/compiletest-self-test/ui-testing-optout.stderr index 652c472c0bc..652c472c0bc 100644 --- a/src/test/ui/ui-testing-optout.stderr +++ b/src/test/ui/compiletest-self-test/ui-testing-optout.stderr diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr index 5f278f94b93..fbfcd45652f 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr @@ -28,7 +28,7 @@ warning: unused `MustUseDeprecated` that must be used --> $DIR/cfg-attr-multi-true.rs:19:5 | LL | MustUseDeprecated::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/cfg-attr-multi-true.rs:7:9 diff --git a/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs b/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs index d68acd2451f..99a7949db17 100644 --- a/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs +++ b/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs @@ -46,7 +46,7 @@ const C: bool = true; trait Trait {} impl dyn Trait { fn existing() {} } -// FIXME: Should be a error for edition > 2015 +// FIXME: Should be an error for edition > 2015 #[cfg_accessible(Trait::existing)] //~ ERROR not sure const A: bool = true; #[cfg_accessible(Trait::unresolved)] //~ ERROR not sure diff --git a/src/test/ui/const-generics/min_const_generics/macro-fail.rs b/src/test/ui/const-generics/min_const_generics/macro-fail.rs index f83518fc9d4..7fb69032e6f 100644 --- a/src/test/ui/const-generics/min_const_generics/macro-fail.rs +++ b/src/test/ui/const-generics/min_const_generics/macro-fail.rs @@ -14,7 +14,6 @@ impl<const N: usize> Marker<N> for Example<N> {} fn make_marker() -> impl Marker<gimme_a_const!(marker)> { //~^ ERROR: type provided when a constant was expected Example::<gimme_a_const!(marker)> - //~^ ERROR: type provided when a constant was expected } fn from_marker(_: impl Marker<{ @@ -34,9 +33,7 @@ fn main() { }>; let _fail = Example::<external_macro!()>; - //~^ ERROR: type provided when a constant was expected let _fail = Example::<gimme_a_const!()>; - //~^ ERROR: type provided when a constant was expected - //~| ERROR unexpected end of macro invocation + //~^ ERROR unexpected end of macro invocation } diff --git a/src/test/ui/const-generics/min_const_generics/macro-fail.stderr b/src/test/ui/const-generics/min_const_generics/macro-fail.stderr index d5dd70d9b48..2b75c197748 100644 --- a/src/test/ui/const-generics/min_const_generics/macro-fail.stderr +++ b/src/test/ui/const-generics/min_const_generics/macro-fail.stderr @@ -1,5 +1,5 @@ error: expected type, found `{` - --> $DIR/macro-fail.rs:29:27 + --> $DIR/macro-fail.rs:28:27 | LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> { | ---------------------- @@ -13,7 +13,7 @@ LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected type, found `{` - --> $DIR/macro-fail.rs:29:27 + --> $DIR/macro-fail.rs:28:27 | LL | Example::<gimme_a_const!(marker)> | ---------------------- @@ -46,7 +46,7 @@ LL | let _fail = Example::<external_macro!()>; = note: this error originates in the macro `external_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: unexpected end of macro invocation - --> $DIR/macro-fail.rs:39:25 + --> $DIR/macro-fail.rs:37:25 | LL | macro_rules! gimme_a_const { | -------------------------- when calling this macro @@ -60,24 +60,6 @@ error[E0747]: type provided when a constant was expected LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> { | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0747]: type provided when a constant was expected - --> $DIR/macro-fail.rs:16:13 - | -LL | Example::<gimme_a_const!(marker)> - | ^^^^^^^^^^^^^^^^^^^^^^ - -error[E0747]: type provided when a constant was expected - --> $DIR/macro-fail.rs:36:25 - | -LL | let _fail = Example::<external_macro!()>; - | ^^^^^^^^^^^^^^^^^ - -error[E0747]: type provided when a constant was expected - --> $DIR/macro-fail.rs:39:25 - | -LL | let _fail = Example::<gimme_a_const!()>; - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 8 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr index 78143042ece..ed6a6ee6e0f 100644 --- a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr +++ b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x: &'static usize = | -------------- type annotation requires that borrow lasts for `'static` LL | &std::intrinsics::size_of::<i32>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr index 69e3ca716a9..2e697b219c5 100644 --- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr +++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr @@ -10,7 +10,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn.rs:17:28 | LL | let _: &'static u32 = &foo(); - | ------------ ^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } @@ -20,7 +20,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn.rs:21:28 | LL | let _: &'static u32 = &meh(); - | ------------ ^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -31,7 +31,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn.rs:22:26 | LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis(); - | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr index 129f0615107..aa742d784e0 100644 --- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr +++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:8:28 | LL | let _: &'static u32 = &foo(); - | ------------ ^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let _x: &'static u32 = &foo(); @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:9:29 | LL | let _x: &'static u32 = &foo(); - | ------------ ^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr index 596fa090d97..2d4e7c83d3e 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_fn_fail.rs:17:27 | LL | let x: &'static u8 = &(bar() + 1); - | ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr index 63dc43a41a8..9ebae3a18a3 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_fn_fail_deny_const_err.rs:18:27 | LL | let x: &'static u8 = &(bar() + 1); - | ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr index 8ac60da3863..01fcf2ec213 100644 --- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_raw_ptr_ops.rs:2:29 | LL | let x: &'static bool = &(42 as *const i32 == 43 as *const i32); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_raw_ptr_ops.rs:4:30 | LL | let y: &'static usize = &(&1 as *const i32 as usize + 1); - | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_raw_ptr_ops.rs:6:28 | LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) }); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_raw_ptr_ops.rs:8:29 | LL | let a: &'static bool = &(main as fn() == main as fn()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-eval/transmute-const-promotion.stderr b/src/test/ui/consts/const-eval/transmute-const-promotion.stderr index 15b9b56ea66..434a957f648 100644 --- a/src/test/ui/consts/const-eval/transmute-const-promotion.stderr +++ b/src/test/ui/consts/const-eval/transmute-const-promotion.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/transmute-const-promotion.rs:4:37 | LL | let x: &'static u32 = unsafe { &mem::transmute(3.0f32) }; - | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-eval/union_promotion.stderr b/src/test/ui/consts/const-eval/union_promotion.stderr index 70808c520d3..42f17de2003 100644 --- a/src/test/ui/consts/const-eval/union_promotion.stderr +++ b/src/test/ui/consts/const-eval/union_promotion.stderr @@ -7,7 +7,7 @@ LL | let x: &'static bool = &unsafe { | | type annotation requires that borrow lasts for `'static` LL | | Foo { a: &1 }.b == Foo { a: &2 }.b LL | | }; - | |_____^ creates a temporary which is freed while still in use + | |_____^ creates a temporary value which is freed while still in use LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/consts/const-int-conversion.stderr b/src/test/ui/consts/const-int-conversion.stderr index 61162a79226..5dd757e3f5e 100644 --- a/src/test/ui/consts/const-int-conversion.stderr +++ b/src/test/ui/consts/const-int-conversion.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:2:28 | LL | let x: &'static i32 = &(5_i32.reverse_bits()); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:4:28 | LL | let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78])); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:6:28 | LL | let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78])); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:8:28 | LL | let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]))); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:10:29 | LL | let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -57,7 +57,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:12:29 | LL | let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -68,7 +68,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:14:29 | LL | let d: &'static [u8] = &(i32::MIN.to_be().to_ne_bytes()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-int-overflowing.stderr b/src/test/ui/consts/const-int-overflowing.stderr index 56c7f7f092d..7d3689e6ec7 100644 --- a/src/test/ui/consts/const-int-overflowing.stderr +++ b/src/test/ui/consts/const-int-overflowing.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-overflowing.rs:2:36 | LL | let x: &'static (i32, bool) = &(5_i32.overflowing_add(3)); - | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-overflowing.rs:4:36 | LL | let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3)); - | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-overflowing.rs:6:36 | LL | let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); - | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-int-rotate.stderr b/src/test/ui/consts/const-int-rotate.stderr index ed265804bbc..039da1c31c5 100644 --- a/src/test/ui/consts/const-int-rotate.stderr +++ b/src/test/ui/consts/const-int-rotate.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-rotate.rs:2:28 | LL | let x: &'static i32 = &(5_i32.rotate_left(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-rotate.rs:4:28 | LL | let y: &'static i32 = &(5_i32.rotate_right(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-int-sign.stderr b/src/test/ui/consts/const-int-sign.stderr index 5f8fd414180..fc23d9d2b29 100644 --- a/src/test/ui/consts/const-int-sign.stderr +++ b/src/test/ui/consts/const-int-sign.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-sign.rs:2:29 | LL | let x: &'static bool = &(5_i32.is_negative()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-sign.rs:4:29 | LL | let y: &'static bool = &(5_i32.is_positive()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-int-wrapping.stderr b/src/test/ui/consts/const-int-wrapping.stderr index 5174b72659c..1342fadc405 100644 --- a/src/test/ui/consts/const-int-wrapping.stderr +++ b/src/test/ui/consts/const-int-wrapping.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:2:28 | LL | let x: &'static i32 = &(5_i32.wrapping_add(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:4:28 | LL | let y: &'static i32 = &(5_i32.wrapping_sub(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:6:28 | LL | let z: &'static i32 = &(5_i32.wrapping_mul(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:8:28 | LL | let a: &'static i32 = &(5_i32.wrapping_shl(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:10:28 | LL | let b: &'static i32 = &(5_i32.wrapping_shr(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr index 3a9ce79f10e..78c58b5ab09 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -11,7 +11,7 @@ LL | const B3: Option<&mut i32> = Some(&mut 42); | ----------^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -21,7 +21,7 @@ LL | const B4: Option<&mut i32> = helper(&mut 42); | ------------^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -31,7 +31,7 @@ LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -41,7 +41,7 @@ LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -51,7 +51,7 @@ LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a static requires that borrow lasts for `'static` error: aborting due to 6 previous errors diff --git a/src/test/ui/consts/const-ptr-nonnull.stderr b/src/test/ui/consts/const-ptr-nonnull.stderr index 26946fb9902..dbcb0c86052 100644 --- a/src/test/ui/consts/const-ptr-nonnull.stderr +++ b/src/test/ui/consts/const-ptr-nonnull.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-ptr-nonnull.rs:4:37 | LL | let x: &'static NonNull<u32> = &(NonNull::dangling()); - | --------------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | --------------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-ptr-nonnull.rs:9:37 | LL | let x: &'static NonNull<u32> = &(non_null.cast()); - | --------------------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | --------------------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-ptr-unique.stderr b/src/test/ui/consts/const-ptr-unique.stderr index 3644cf4cec7..83448c3e8d8 100644 --- a/src/test/ui/consts/const-ptr-unique.stderr +++ b/src/test/ui/consts/const-ptr-unique.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-ptr-unique.rs:8:33 | LL | let x: &'static *mut u32 = &(unique.as_ptr()); - | ----------------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ----------------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/control-flow/interior-mutability.stderr b/src/test/ui/consts/control-flow/interior-mutability.stderr index 4f9c7d34c35..db2ffb91b98 100644 --- a/src/test/ui/consts/control-flow/interior-mutability.stderr +++ b/src/test/ui/consts/control-flow/interior-mutability.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/interior-mutability.rs:40:26 | LL | let x: &'static _ = &X; - | ---------- ^ creates a temporary which is freed while still in use + | ---------- ^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/interior-mutability.rs:41:26 | LL | let y: &'static _ = &Y; - | ---------- ^ creates a temporary which is freed while still in use + | ---------- ^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let z: &'static _ = &Z; @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/interior-mutability.rs:42:26 | LL | let z: &'static _ = &Z; - | ---------- ^ creates a temporary which is freed while still in use + | ---------- ^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/consts/fn_trait_refs.rs b/src/test/ui/consts/fn_trait_refs.rs new file mode 100644 index 00000000000..b507492970a --- /dev/null +++ b/src/test/ui/consts/fn_trait_refs.rs @@ -0,0 +1,77 @@ +// check-pass + +#![feature(const_fn_trait_ref_impls)] +#![feature(fn_traits)] +#![feature(unboxed_closures)] +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] +#![feature(const_cmp)] +#![feature(const_refs_to_cell)] + +use std::marker::Destruct; + +const fn tester_fn<T>(f: T) -> T::Output +where + T: ~const Fn<()> + ~const Destruct, +{ + f() +} + +const fn tester_fn_mut<T>(mut f: T) -> T::Output +where + T: ~const FnMut<()> + ~const Destruct, +{ + f() +} + +const fn tester_fn_once<T>(f: T) -> T::Output +where + T: ~const FnOnce<()>, +{ + f() +} + +const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output) +where + T: ~const Fn<()> + ~const Destruct, +{ + ( + // impl<A: Tuple, F: ~const Fn + ?Sized> const Fn<A> for &F + tester_fn(&f), + // impl<A: Tuple, F: ~const Fn + ?Sized> const FnMut<A> for &F + tester_fn_mut(&f), + // impl<A: Tuple, F: ~const Fn + ?Sized> const FnOnce<A> for &F + tester_fn_once(&f), + ) +} + +const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output) +where + T: ~const FnMut<()> + ~const Destruct, +{ + ( + // impl<A: Tuple, F: ~const FnMut + ?Sized> const FnMut<A> for &mut F + tester_fn_mut(&mut f), + // impl<A: Tuple, F: ~const FnMut + ?Sized> const FnOnce<A> for &mut F + tester_fn_once(&mut f), + ) +} +const fn test(i: i32) -> i32 { + i + 1 +} + +fn main() { + const fn one() -> i32 { + 1 + }; + const fn two() -> i32 { + 2 + }; + const _: () = { + let test_one = test_fn(one); + assert!(test_one == (1, 1, 1)); + + let test_two = test_fn_mut(two); + assert!(test_two == (2, 2)); + }; +} diff --git a/src/test/ui/consts/invalid-const-in-body.rs b/src/test/ui/consts/invalid-const-in-body.rs new file mode 100644 index 00000000000..f0fa3bb7bd1 --- /dev/null +++ b/src/test/ui/consts/invalid-const-in-body.rs @@ -0,0 +1,6 @@ +fn f() -> impl Sized { + 2.0E + //~^ ERROR expected at least one digit in exponent +} + +fn main() {} diff --git a/src/test/ui/consts/invalid-const-in-body.stderr b/src/test/ui/consts/invalid-const-in-body.stderr new file mode 100644 index 00000000000..3be65835946 --- /dev/null +++ b/src/test/ui/consts/invalid-const-in-body.stderr @@ -0,0 +1,8 @@ +error: expected at least one digit in exponent + --> $DIR/invalid-const-in-body.rs:2:5 + | +LL | 2.0E + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/issue-102117.rs b/src/test/ui/consts/issue-102117.rs index b77342c4135..3ed90aed235 100644 --- a/src/test/ui/consts/issue-102117.rs +++ b/src/test/ui/consts/issue-102117.rs @@ -14,11 +14,11 @@ pub struct VTable { impl VTable { pub fn new<T>() -> &'static Self { const { - //~^ ERROR the parameter type `T` may not live long enough - //~| ERROR the parameter type `T` may not live long enough &VTable { layout: Layout::new::<T>(), type_id: TypeId::of::<T>(), + //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough drop_in_place: unsafe { transmute::<unsafe fn(*mut T), unsafe fn(*mut ())>(drop_in_place::<T>) }, diff --git a/src/test/ui/consts/issue-102117.stderr b/src/test/ui/consts/issue-102117.stderr index eb4b329bd81..f42bcf90fb7 100644 --- a/src/test/ui/consts/issue-102117.stderr +++ b/src/test/ui/consts/issue-102117.stderr @@ -1,14 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/issue-102117.rs:16:9 + --> $DIR/issue-102117.rs:19:26 | -LL | / const { -LL | | -LL | | -LL | | &VTable { -... | -LL | | } -LL | | } - | |_________^ ...so that the type `T` will meet its required lifetime bounds +LL | type_id: TypeId::of::<T>(), + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -16,16 +10,10 @@ LL | pub fn new<T: 'static>() -> &'static Self { | +++++++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/issue-102117.rs:16:9 + --> $DIR/issue-102117.rs:19:26 | -LL | / const { -LL | | -LL | | -LL | | &VTable { -... | -LL | | } -LL | | } - | |_________^ ...so that the type `T` will meet its required lifetime bounds +LL | type_id: TypeId::of::<T>(), + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/consts/issue-104155.rs b/src/test/ui/consts/issue-104155.rs new file mode 100644 index 00000000000..1cc8f81b0d2 --- /dev/null +++ b/src/test/ui/consts/issue-104155.rs @@ -0,0 +1,5 @@ +// check-pass +const _: () = core::mem::forget(Box::<u32>::default); +const _: () = core::mem::forget(|| Box::<u32>::default()); + +fn main() {} diff --git a/src/test/ui/consts/issue-54224.stderr b/src/test/ui/consts/issue-54224.stderr index 8dcb4daca3b..55fe55759df 100644 --- a/src/test/ui/consts/issue-54224.stderr +++ b/src/test/ui/consts/issue-54224.stderr @@ -5,7 +5,7 @@ LL | const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]); | ------^^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -15,7 +15,7 @@ LL | pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]); | ---------------^^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/consts/issue-54954.rs index d4e1df22770..d4e1df22770 100644 --- a/src/test/ui/issues/issue-54954.rs +++ b/src/test/ui/consts/issue-54954.rs diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/consts/issue-54954.stderr index 668985c2b59..668985c2b59 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/consts/issue-54954.stderr diff --git a/src/test/ui/consts/min_const_fn/promotion.stderr b/src/test/ui/consts/min_const_fn/promotion.stderr index 550423c2d93..0b8dc0ce0e9 100644 --- a/src/test/ui/consts/min_const_fn/promotion.stderr +++ b/src/test/ui/consts/min_const_fn/promotion.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:11:27 | LL | let x: &'static () = &foo1(); - | ----------- ^^^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:12:28 | LL | let y: &'static i32 = &foo2(42); - | ------------ ^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:13:28 | LL | let z: &'static i32 = &foo3(); - | ------------ ^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:14:34 | LL | let a: &'static Cell<i32> = &foo4(); - | ------------------ ^^^^^^ creates a temporary which is freed while still in use + | ------------------ ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:15:42 | LL | let a: &'static Option<Cell<i32>> = &foo5(); - | -------------------------- ^^^^^^ creates a temporary which is freed while still in use + | -------------------------- ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let a: &'static Option<Cell<i32>> = &foo6(); @@ -57,7 +57,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:16:42 | LL | let a: &'static Option<Cell<i32>> = &foo6(); - | -------------------------- ^^^^^^ creates a temporary which is freed while still in use + | -------------------------- ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/consts/promote-not.stderr b/src/test/ui/consts/promote-not.stderr index 0d0b0f9c689..b93358e8dcc 100644 --- a/src/test/ui/consts/promote-not.stderr +++ b/src/test/ui/consts/promote-not.stderr @@ -5,14 +5,14 @@ LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); | ----------^^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:11:18 | LL | let x = &mut [1,2,3]; - | ^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^ creates a temporary value which is freed while still in use LL | x | - using this value as a static requires that borrow lasts for `'static` LL | }; @@ -22,7 +22,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:20:32 | LL | let _x: &'static () = &foo(); - | ----------- ^^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } @@ -32,7 +32,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:28:29 | LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } @@ -42,7 +42,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:33:29 | LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | }; @@ -52,7 +52,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:39:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).1; - | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | }; @@ -62,7 +62,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:46:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).0; - | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -73,7 +73,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:47:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).1; - | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -84,7 +84,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:50:29 | LL | let _val: &'static _ = &(1/0); - | ---------- ^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -95,7 +95,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:51:29 | LL | let _val: &'static _ = &(1/(1-1)); - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -106,7 +106,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:52:29 | LL | let _val: &'static _ = &(1%0); - | ---------- ^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -117,7 +117,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:53:29 | LL | let _val: &'static _ = &(1%(1-1)); - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -128,7 +128,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:54:29 | LL | let _val: &'static _ = &([1,2,3][4]+1); - | ---------- ^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -139,7 +139,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:57:29 | LL | let _val: &'static _ = &TEST_DROP; - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -150,7 +150,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:59:29 | LL | let _val: &'static _ = &&TEST_DROP; - | ---------- ^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -161,7 +161,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:59:30 | LL | let _val: &'static _ = &&TEST_DROP; - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -172,7 +172,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:62:29 | LL | let _val: &'static _ = &(&TEST_DROP,); - | ---------- ^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -183,7 +183,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:62:31 | LL | let _val: &'static _ = &(&TEST_DROP,); - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -194,7 +194,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:65:29 | LL | let _val: &'static _ = &[&TEST_DROP; 1]; - | ---------- ^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -207,7 +207,7 @@ error[E0716]: temporary value dropped while borrowed LL | let _val: &'static _ = &[&TEST_DROP; 1]; | ---------- ^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error: aborting due to 20 previous errors diff --git a/src/test/ui/consts/promote_const_let.stderr b/src/test/ui/consts/promote_const_let.stderr index c47d297c904..975a235a649 100644 --- a/src/test/ui/consts/promote_const_let.stderr +++ b/src/test/ui/consts/promote_const_let.stderr @@ -19,7 +19,7 @@ LL | let x: &'static u32 = &{ LL | | let y = 42; LL | | y LL | | }; - | |_____^ creates a temporary which is freed while still in use + | |_____^ creates a temporary value which is freed while still in use LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/consts/promoted-const-drop.stderr b/src/test/ui/consts/promoted-const-drop.stderr index 184ba0ea3b3..4802834173f 100644 --- a/src/test/ui/consts/promoted-const-drop.stderr +++ b/src/test/ui/consts/promoted-const-drop.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted-const-drop.rs:13:26 | LL | let _: &'static A = &A(); - | ---------- ^^^ creates a temporary which is freed while still in use + | ---------- ^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let _: &'static [A] = &[C]; @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted-const-drop.rs:14:28 | LL | let _: &'static [A] = &[C]; - | ------------ ^^^ creates a temporary which is freed while still in use + | ------------ ^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/consts/qualif-union.stderr b/src/test/ui/consts/qualif-union.stderr index 8ec68ada048..d847cf88f50 100644 --- a/src/test/ui/consts/qualif-union.stderr +++ b/src/test/ui/consts/qualif-union.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:28:26 | LL | let _: &'static _ = &C1; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:29:26 | LL | let _: &'static _ = &C2; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:30:26 | LL | let _: &'static _ = &C3; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:31:26 | LL | let _: &'static _ = &C4; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let _: &'static _ = &C5; @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:32:26 | LL | let _: &'static _ = &C5; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.rs index 15d06817577..6ab1fb7b039 100644 --- a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.rs +++ b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.rs @@ -3,7 +3,7 @@ #[derive(Debug)] pub struct Whatever { pub field0: (), - field1: (), //~ ERROR fields `field1`, `field2`, `field3` and `field4` are never read + field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read field2: (), field3: (), field4: (), diff --git a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr index 512b870fa4b..7f4f78cebc9 100644 --- a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr +++ b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr @@ -1,4 +1,4 @@ -error: fields `field1`, `field2`, `field3` and `field4` are never read +error: fields `field1`, `field2`, `field3`, and `field4` are never read --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5 | LL | pub struct Whatever { diff --git a/src/test/ui/did_you_mean/issue-103909.rs b/src/test/ui/did_you_mean/issue-103909.rs new file mode 100644 index 00000000000..20b67cd102d --- /dev/null +++ b/src/test/ui/did_you_mean/issue-103909.rs @@ -0,0 +1,9 @@ +#![allow(unused_variables)] +use std::fs::File; + +fn main() { + if Err(err) = File::open("hello.txt") { + //~^ ERROR: cannot find value `err` in this scope + //~| ERROR: mismatched types + } +} diff --git a/src/test/ui/did_you_mean/issue-103909.stderr b/src/test/ui/did_you_mean/issue-103909.stderr new file mode 100644 index 00000000000..8641017470b --- /dev/null +++ b/src/test/ui/did_you_mean/issue-103909.stderr @@ -0,0 +1,26 @@ +error[E0425]: cannot find value `err` in this scope + --> $DIR/issue-103909.rs:5:12 + | +LL | if Err(err) = File::open("hello.txt") { + | ^^^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | if let Err(err) = File::open("hello.txt") { + | +++ + +error[E0308]: mismatched types + --> $DIR/issue-103909.rs:5:8 + | +LL | if Err(err) = File::open("hello.txt") { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Err(err) = File::open("hello.txt") { + | +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-54943-1.rs b/src/test/ui/dropck/issue-54943-1.rs index ec682d96081..ec682d96081 100644 --- a/src/test/ui/issues/issue-54943-1.rs +++ b/src/test/ui/dropck/issue-54943-1.rs diff --git a/src/test/ui/issues/issue-54943-2.rs b/src/test/ui/dropck/issue-54943-2.rs index d400ae58db4..d400ae58db4 100644 --- a/src/test/ui/issues/issue-54943-2.rs +++ b/src/test/ui/dropck/issue-54943-2.rs diff --git a/src/test/ui/enum-discriminant/get_discr.rs b/src/test/ui/enum-discriminant/get_discr.rs new file mode 100644 index 00000000000..71eea4e0f78 --- /dev/null +++ b/src/test/ui/enum-discriminant/get_discr.rs @@ -0,0 +1,114 @@ +// run-pass + +// Now that there are several variations on the code generated in +// `codegen_get_discr`, let's make sure the various cases yield the correct +// result. + +// To get the discriminant of an E<X1> value, there are no shortcuts - we must +// do the full algorithm. +#[repr(u8)] +pub enum X1 { + _1 = 1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, + _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, + _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, + _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, + _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, + _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112, + _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128, + _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144, + _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160, + _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, _174, _175, _176, + _177, _178, _179, _180, _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, _191, _192, + _193, _194, _195, _196, _197, _198, _199, _200, _201, _202, _203, _204, _205, _206, _207, _208, + _209, _210, _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, _221, _222, _223, _224, + _225, _226, _227, _228, _229, _230, _231, _232, _233, _234, _235, _236, _237, _238, _239, _240, + _241, _242, _243, _244, _245, _246, _247, _248, _249, _250, _251, _252, _253, _254, +} + +#[repr(i8)] +pub enum X2 { + _1 = -1, _2 = 0, _3 = 1, +} + +#[repr(i8)] +pub enum X3 { + _1 = -128, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, + _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, + _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, + _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, + _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, + _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112, + _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128, + _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144, + _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160, + _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, _174, _175, _176, + _177, _178, _179, _180, _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, _191, _192, + _193, _194, _195, _196, _197, _198, _199, _200, _201, _202, _203, _204, _205, _206, _207, _208, + _209, _210, _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, _221, _222, _223, _224, + _225, _226, _227, _228, _229, _230, _231, _232, _233, _234, _235, _236, _237, _238, _239, _240, + _241, _242, _243, _244, _245, _246, _247, _248, _249, _250, _251, _252, _253, _254, +} + +#[repr(i8)] +pub enum X4 { + _1 = -126, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, + _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, + _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, + _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, + _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, + _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112, + _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128, + _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144, + _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160, + _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, _174, _175, _176, + _177, _178, _179, _180, _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, _191, _192, + _193, _194, _195, _196, _197, _198, _199, _200, _201, _202, _203, _204, _205, _206, _207, _208, + _209, _210, _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, _221, _222, _223, _224, + _225, _226, _227, _228, _229, _230, _231, _232, _233, _234, _235, _236, _237, _238, _239, _240, + _241, _242, _243, _244, _245, _246, _247, _248, _249, _250, _251, _252, _253, _254, +} + +pub enum E<X> { + A(X), + B, + C, +} + +pub fn match_e<X>(e: E<X>) -> u8 { + use E::*; + match e { + A(_) => 0, + B => 1, + C => 2, + } +} + +fn main() { + assert_eq!(match_e(E::A(X1::_1)), 0); + assert_eq!(match_e(E::A(X1::_2)), 0); + assert_eq!(match_e(E::A(X1::_254)), 0); + assert_eq!(match_e(E::<X1>::B), 1); + assert_eq!(match_e(E::<X1>::C), 2); + assert_eq!(match_e(E::A(X2::_1)), 0); + assert_eq!(match_e(E::A(X2::_2)), 0); + assert_eq!(match_e(E::A(X2::_3)), 0); + assert_eq!(match_e(E::<X2>::B), 1); + assert_eq!(match_e(E::<X2>::C), 2); + assert_eq!(match_e(E::A(X3::_1)), 0); + assert_eq!(match_e(E::A(X3::_2)), 0); + assert_eq!(match_e(E::A(X3::_254)), 0); + assert_eq!(match_e(E::<X3>::B), 1); + assert_eq!(match_e(E::<X3>::C), 2); + assert_eq!(match_e(E::A(X4::_1)), 0); + assert_eq!(match_e(E::A(X4::_2)), 0); + assert_eq!(match_e(E::A(X4::_254)), 0); + assert_eq!(match_e(E::<X4>::B), 1); + assert_eq!(match_e(E::<X4>::C), 2); + assert_eq!(match_e(E::A(false)), 0); + assert_eq!(match_e(E::A(true)), 0); + assert_eq!(match_e(E::<bool>::B), 1); + assert_eq!(match_e(E::<bool>::C), 2); +} diff --git a/src/test/ui/error-codes/E0059.stderr b/src/test/ui/error-codes/E0059.stderr index a1b8aeaedbb..f331d014226 100644 --- a/src/test/ui/error-codes/E0059.stderr +++ b/src/test/ui/error-codes/E0059.stderr @@ -1,8 +1,14 @@ -error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit - --> $DIR/E0059.rs:3:41 +error[E0059]: type parameter to bare `Fn` trait must be a tuple + --> $DIR/E0059.rs:3:11 | LL | fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) } - | ^^^^ + | ^^^^^^^ the trait `Tuple` is not implemented for `i32` + | +note: required by a bound in `Fn` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | ^^^^^ required by this bound in `Fn` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0268.stderr b/src/test/ui/error-codes/E0268.stderr index c926f9e4874..6422e8a9490 100644 --- a/src/test/ui/error-codes/E0268.stderr +++ b/src/test/ui/error-codes/E0268.stderr @@ -1,8 +1,8 @@ -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/E0268.rs:2:5 | LL | break; - | ^^^^^ cannot `break` outside of a loop + | ^^^^^ cannot `break` outside of a loop or labeled block error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0282.rs b/src/test/ui/error-codes/E0282.rs index 9bd16abb7bb..f1f93b3aed6 100644 --- a/src/test/ui/error-codes/E0282.rs +++ b/src/test/ui/error-codes/E0282.rs @@ -1,3 +1,4 @@ fn main() { - let x = "hello".chars().rev().collect(); //~ ERROR E0282 + let x = "hello".chars().rev().collect(); + //~^ ERROR E0282 } diff --git a/src/test/ui/error-codes/E0401.rs b/src/test/ui/error-codes/E0401.rs index c30e5f47188..8f8d6b87ef2 100644 --- a/src/test/ui/error-codes/E0401.rs +++ b/src/test/ui/error-codes/E0401.rs @@ -8,7 +8,9 @@ fn foo<T>(x: T) { W: Fn()> (y: T) { //~ ERROR E0401 } - bfnr(x); //~ ERROR type annotations needed + bfnr(x); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr index b0e2ef5b6f7..9687eca61fa 100644 --- a/src/test/ui/error-codes/E0401.stderr +++ b/src/test/ui/error-codes/E0401.stderr @@ -21,7 +21,7 @@ LL | (y: T) { | ^ use of generic parameter from outer function error[E0401]: can't use generic parameters from outer function - --> $DIR/E0401.rs:22:25 + --> $DIR/E0401.rs:24:25 | LL | impl<T> Iterator for A<T> { | ---- `Self` type implicitly declared here, by this `impl` @@ -43,7 +43,28 @@ help: consider specifying the generic arguments LL | bfnr::<U, V, W>(x); | +++++++++++ -error: aborting due to 4 previous errors +error[E0283]: type annotations needed + --> $DIR/E0401.rs:11:5 + | +LL | bfnr(x); + | ^^^^ cannot infer type of the type parameter `W` declared on the function `bfnr` + | + = note: multiple `impl`s satisfying `_: Fn<()>` found in the following crates: `alloc`, `core`: + - impl<A, F> Fn<A> for &F + where A: Tuple, F: Fn<A>, F: ?Sized; + - impl<Args, F, A> Fn<Args> for Box<F, A> + where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized; +note: required by a bound in `bfnr` + --> $DIR/E0401.rs:4:30 + | +LL | fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) { + | ^^^^ required by this bound in `bfnr` +help: consider specifying the type arguments in the function call + | +LL | bfnr::<U, V, W>(x); + | +++++++++++ + +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0282, E0401. +Some errors have detailed explanations: E0282, E0283, E0401. For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/error-codes/E0767.rs b/src/test/ui/error-codes/E0767.rs index 6c6cb746e6c..14215d36a38 100644 --- a/src/test/ui/error-codes/E0767.rs +++ b/src/test/ui/error-codes/E0767.rs @@ -1,6 +1,7 @@ -fn main () { +fn main() { 'a: loop { || { + //~^ ERROR mismatched types loop { break 'a; } //~ ERROR E0767 } } diff --git a/src/test/ui/error-codes/E0767.stderr b/src/test/ui/error-codes/E0767.stderr index 2429823306b..ee85247301c 100644 --- a/src/test/ui/error-codes/E0767.stderr +++ b/src/test/ui/error-codes/E0767.stderr @@ -1,14 +1,27 @@ error[E0767]: use of unreachable label `'a` - --> $DIR/E0767.rs:4:26 + --> $DIR/E0767.rs:5:26 | LL | 'a: loop { | -- unreachable label defined here -LL | || { +... LL | loop { break 'a; } | ^^ unreachable label `'a` | = note: labels are unreachable through functions, closures, async blocks and modules -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/E0767.rs:3:9 + | +LL | / || { +LL | | +LL | | loop { break 'a; } +LL | | } + | |_________^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/E0767.rs:3:9: 3:11]` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0767`. +Some errors have detailed explanations: E0308, E0767. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/error-codes/E0778.rs b/src/test/ui/error-codes/E0778.rs index 60e5c2598f1..74653886d41 100644 --- a/src/test/ui/error-codes/E0778.rs +++ b/src/test/ui/error-codes/E0778.rs @@ -1,8 +1,4 @@ -#![feature(isa_attribute)] - #[instruction_set()] //~ ERROR -fn no_isa_defined() { -} +fn no_isa_defined() {} -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0778.stderr b/src/test/ui/error-codes/E0778.stderr index 6ecae792423..42647e5c6a1 100644 --- a/src/test/ui/error-codes/E0778.stderr +++ b/src/test/ui/error-codes/E0778.stderr @@ -1,5 +1,5 @@ error[E0778]: `#[instruction_set]` requires an argument - --> $DIR/E0778.rs:3:1 + --> $DIR/E0778.rs:1:1 | LL | #[instruction_set()] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/error-codes/E0779.rs b/src/test/ui/error-codes/E0779.rs index 1b4dbce2036..c32dae12c9c 100644 --- a/src/test/ui/error-codes/E0779.rs +++ b/src/test/ui/error-codes/E0779.rs @@ -1,6 +1,2 @@ -#![feature(isa_attribute)] - #[instruction_set(arm::magic)] //~ ERROR -fn main() { - -} +fn main() {} diff --git a/src/test/ui/error-codes/E0779.stderr b/src/test/ui/error-codes/E0779.stderr index da787260d4f..7c6a119a096 100644 --- a/src/test/ui/error-codes/E0779.stderr +++ b/src/test/ui/error-codes/E0779.stderr @@ -1,5 +1,5 @@ error[E0779]: invalid instruction set specified - --> $DIR/E0779.rs:3:1 + --> $DIR/E0779.rs:1:1 | LL | #[instruction_set(arm::magic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-abi-efiapi.rs b/src/test/ui/feature-gates/feature-gate-abi-efiapi.rs new file mode 100644 index 00000000000..0c0d736acd0 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi-efiapi.rs @@ -0,0 +1,33 @@ +// needs-llvm-components: x86 +// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +// Functions +extern "efiapi" fn f1() {} //~ ERROR efiapi ABI is experimental + +// Methods in trait defintion +trait Tr { + extern "efiapi" fn f2(); //~ ERROR efiapi ABI is experimental + extern "efiapi" fn f3() {} //~ ERROR efiapi ABI is experimental +} + +struct S; + +// Methods in trait impl +impl Tr for S { + extern "efiapi" fn f2() {} //~ ERROR efiapi ABI is experimental +} + +// Methods in inherent impl +impl S { + extern "efiapi" fn f4() {} //~ ERROR efiapi ABI is experimental +} + +// Function pointer types +type A = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental + +// Foreign modules +extern "efiapi" {} //~ ERROR efiapi ABI is experimental diff --git a/src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr b/src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr new file mode 100644 index 00000000000..5b01dcc6d85 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr @@ -0,0 +1,66 @@ +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:9:8 + | +LL | extern "efiapi" fn f1() {} + | ^^^^^^^^ + | + = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:13:12 + | +LL | extern "efiapi" fn f2(); + | ^^^^^^^^ + | + = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:14:12 + | +LL | extern "efiapi" fn f3() {} + | ^^^^^^^^ + | + = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:21:12 + | +LL | extern "efiapi" fn f2() {} + | ^^^^^^^^ + | + = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:26:12 + | +LL | extern "efiapi" fn f4() {} + | ^^^^^^^^ + | + = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:30:17 + | +LL | type A = extern "efiapi" fn(); + | ^^^^^^^^ + | + = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:33:8 + | +LL | extern "efiapi" {} + | ^^^^^^^^ + | + = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs index 855263595d0..712655f9775 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.rs +++ b/src/test/ui/feature-gates/feature-gate-abi.rs @@ -1,6 +1,5 @@ // gate-test-intrinsics // gate-test-platform_intrinsics -// gate-test-abi_efiapi // compile-flags: --crate-type=rlib #![feature(no_core, lang_items)] @@ -9,13 +8,15 @@ #[lang="sized"] trait Sized { } +#[lang="tuple_trait"] +trait Tuple { } + // Functions extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change -extern "efiapi" fn f10() {} //~ ERROR efiapi ABI is experimental and subject to change // Methods in trait definition trait Tr { @@ -24,10 +25,8 @@ trait Tr { extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change - extern "efiapi" fn m10(); //~ ERROR efiapi ABI is experimental and subject to change extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change - extern "efiapi" fn dm10() {} //~ ERROR efiapi ABI is experimental and subject to change } struct S; @@ -39,7 +38,6 @@ impl Tr for S { extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change - extern "efiapi" fn m10() {} //~ ERROR efiapi ABI is experimental and subject to change } // Methods in inherent impl @@ -49,17 +47,14 @@ impl S { extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change - extern "efiapi" fn im10() {} //~ ERROR efiapi ABI is experimental and subject to change } // Function pointer types type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change -type A10 = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental and subject to change // Foreign modules extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental extern "rust-call" {} //~ ERROR rust-call ABI is subject to change -extern "efiapi" {} //~ ERROR efiapi ABI is experimental and subject to change diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr index bcca39c8fb8..e9791b9513f 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi.stderr @@ -1,5 +1,5 @@ error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:13:8 + --> $DIR/feature-gate-abi.rs:15:8 | LL | extern "rust-intrinsic" fn f1() {} | ^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" fn f1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:15:8 + --> $DIR/feature-gate-abi.rs:17:8 | LL | extern "platform-intrinsic" fn f2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | extern "platform-intrinsic" fn f2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:17:8 + --> $DIR/feature-gate-abi.rs:19:8 | LL | extern "rust-call" fn f4(_: ()) {} | ^^^^^^^^^^^ @@ -24,17 +24,8 @@ LL | extern "rust-call" fn f4(_: ()) {} = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:18:8 - | -LL | extern "efiapi" fn f10() {} - | ^^^^^^^^ - | - = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:22:12 + --> $DIR/feature-gate-abi.rs:23:12 | LL | extern "rust-intrinsic" fn m1(); | ^^^^^^^^^^^^^^^^ @@ -42,7 +33,7 @@ LL | extern "rust-intrinsic" fn m1(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:24:12 + --> $DIR/feature-gate-abi.rs:25:12 | LL | extern "platform-intrinsic" fn m2(); | ^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +42,7 @@ LL | extern "platform-intrinsic" fn m2(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:26:12 + --> $DIR/feature-gate-abi.rs:27:12 | LL | extern "rust-call" fn m4(_: ()); | ^^^^^^^^^^^ @@ -59,15 +50,6 @@ LL | extern "rust-call" fn m4(_: ()); = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:27:12 - | -LL | extern "efiapi" fn m10(); - | ^^^^^^^^ - | - = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: rust-call ABI is subject to change --> $DIR/feature-gate-abi.rs:29:12 | @@ -77,17 +59,8 @@ LL | extern "rust-call" fn dm4(_: ()) {} = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:30:12 - | -LL | extern "efiapi" fn dm10() {} - | ^^^^^^^^ - | - = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:37:12 + --> $DIR/feature-gate-abi.rs:36:12 | LL | extern "rust-intrinsic" fn m1() {} | ^^^^^^^^^^^^^^^^ @@ -95,7 +68,7 @@ LL | extern "rust-intrinsic" fn m1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:39:12 + --> $DIR/feature-gate-abi.rs:38:12 | LL | extern "platform-intrinsic" fn m2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +77,7 @@ LL | extern "platform-intrinsic" fn m2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:41:12 + --> $DIR/feature-gate-abi.rs:40:12 | LL | extern "rust-call" fn m4(_: ()) {} | ^^^^^^^^^^^ @@ -112,17 +85,8 @@ LL | extern "rust-call" fn m4(_: ()) {} = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:42:12 - | -LL | extern "efiapi" fn m10() {} - | ^^^^^^^^ - | - = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:47:12 + --> $DIR/feature-gate-abi.rs:45:12 | LL | extern "rust-intrinsic" fn im1() {} | ^^^^^^^^^^^^^^^^ @@ -130,7 +94,7 @@ LL | extern "rust-intrinsic" fn im1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:49:12 + --> $DIR/feature-gate-abi.rs:47:12 | LL | extern "platform-intrinsic" fn im2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -139,7 +103,7 @@ LL | extern "platform-intrinsic" fn im2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:51:12 + --> $DIR/feature-gate-abi.rs:49:12 | LL | extern "rust-call" fn im4(_: ()) {} | ^^^^^^^^^^^ @@ -147,17 +111,8 @@ LL | extern "rust-call" fn im4(_: ()) {} = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:52:12 - | -LL | extern "efiapi" fn im10() {} - | ^^^^^^^^ - | - = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:56:18 + --> $DIR/feature-gate-abi.rs:53:18 | LL | type A1 = extern "rust-intrinsic" fn(); | ^^^^^^^^^^^^^^^^ @@ -165,7 +120,7 @@ LL | type A1 = extern "rust-intrinsic" fn(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:57:18 + --> $DIR/feature-gate-abi.rs:54:18 | LL | type A2 = extern "platform-intrinsic" fn(); | ^^^^^^^^^^^^^^^^^^^^ @@ -174,7 +129,7 @@ LL | type A2 = extern "platform-intrinsic" fn(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:58:18 + --> $DIR/feature-gate-abi.rs:55:18 | LL | type A4 = extern "rust-call" fn(_: ()); | ^^^^^^^^^^^ @@ -182,17 +137,8 @@ LL | type A4 = extern "rust-call" fn(_: ()); = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:59:19 - | -LL | type A10 = extern "efiapi" fn(); - | ^^^^^^^^ - | - = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:62:8 + --> $DIR/feature-gate-abi.rs:58:8 | LL | extern "rust-intrinsic" {} | ^^^^^^^^^^^^^^^^ @@ -200,7 +146,7 @@ LL | extern "rust-intrinsic" {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:63:8 + --> $DIR/feature-gate-abi.rs:59:8 | LL | extern "platform-intrinsic" {} | ^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +155,7 @@ LL | extern "platform-intrinsic" {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:64:8 + --> $DIR/feature-gate-abi.rs:60:8 | LL | extern "rust-call" {} | ^^^^^^^^^^^ @@ -217,63 +163,54 @@ LL | extern "rust-call" {} = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:65:8 - | -LL | extern "efiapi" {} - | ^^^^^^^^ - | - = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:22:32 + --> $DIR/feature-gate-abi.rs:23:32 | LL | extern "rust-intrinsic" fn m1(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:24:36 + --> $DIR/feature-gate-abi.rs:25:36 | LL | extern "platform-intrinsic" fn m2(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:13:33 + --> $DIR/feature-gate-abi.rs:15:33 | LL | extern "rust-intrinsic" fn f1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:15:37 + --> $DIR/feature-gate-abi.rs:17:37 | LL | extern "platform-intrinsic" fn f2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:37:37 + --> $DIR/feature-gate-abi.rs:36:37 | LL | extern "rust-intrinsic" fn m1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:39:41 + --> $DIR/feature-gate-abi.rs:38:41 | LL | extern "platform-intrinsic" fn m2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:47:38 + --> $DIR/feature-gate-abi.rs:45:38 | LL | extern "rust-intrinsic" fn im1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:49:42 + --> $DIR/feature-gate-abi.rs:47:42 | LL | extern "platform-intrinsic" fn im2() {} | ^^ -error: aborting due to 34 previous errors +error: aborting due to 27 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-custom_mir.rs b/src/test/ui/feature-gates/feature-gate-custom_mir.rs new file mode 100644 index 00000000000..0126dde2f7d --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-custom_mir.rs @@ -0,0 +1,12 @@ +#![feature(core_intrinsics)] + +extern crate core; + +#[custom_mir(dialect = "built")] //~ ERROR the `#[custom_mir]` attribute is just used for the Rust test suite +pub fn foo(_x: i32) -> i32 { + 0 +} + +fn main() { + assert_eq!(2, foo(2)); +} diff --git a/src/test/ui/feature-gates/feature-gate-custom_mir.stderr b/src/test/ui/feature-gates/feature-gate-custom_mir.stderr new file mode 100644 index 00000000000..3c149d30d82 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-custom_mir.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[custom_mir]` attribute is just used for the Rust test suite + --> $DIR/feature-gate-custom_mir.rs:5:1 + | +LL | #[custom_mir(dialect = "built")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(custom_mir)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-isa_attribute.rs b/src/test/ui/feature-gates/feature-gate-isa_attribute.rs deleted file mode 100644 index cb02a0955e9..00000000000 --- a/src/test/ui/feature-gates/feature-gate-isa_attribute.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[instruction_set] -//~^ ERROR the `#[instruction_set]` attribute is an experimental feature [E0658] -//~| ERROR malformed `instruction_set` attribute input -//~| ERROR must specify an instruction set [E0778] -fn main() { -} diff --git a/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr b/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr deleted file mode 100644 index 2a95a80ca61..00000000000 --- a/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: malformed `instruction_set` attribute input - --> $DIR/feature-gate-isa_attribute.rs:1:1 - | -LL | #[instruction_set] - | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` - -error[E0658]: the `#[instruction_set]` attribute is an experimental feature - --> $DIR/feature-gate-isa_attribute.rs:1:1 - | -LL | #[instruction_set] - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #74727 <https://github.com/rust-lang/rust/issues/74727> for more information - = help: add `#![feature(isa_attribute)]` to the crate attributes to enable - -error[E0778]: must specify an instruction set - --> $DIR/feature-gate-isa_attribute.rs:1:1 - | -LL | #[instruction_set] - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0658, E0778. -For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 5a645cf4ef9..78767040421 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -110,19 +110,19 @@ error: attribute should be applied to an `extern crate` item --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1 | LL | #![no_link] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ not an `extern crate` item error: attribute should be applied to a free function, impl method or static --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:27:1 | LL | #![export_name = "2200"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:29:1 | LL | #![inline] - | ^^^^^^^^^^ + | ^^^^^^^^^^ not a function or closure error: `macro_export` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 8db12e55d25..1fa315f3d21 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -1,6 +1,6 @@ //~ NOTE not a function //~| NOTE not a foreign function or static -//~| NOTE not a function or static +//~| NOTE cannot be applied to crates //~| NOTE not an `extern` block // This test enumerates as many compiler-builtin ungated attributes as // possible (that is, all the mutually compatible ones), and checks diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 310d1f720eb..30039267979 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -403,7 +403,7 @@ warning: attribute should be applied to a function definition --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 | LL | #![cold] - | ^^^^^^^^ + | ^^^^^^^^ cannot be applied to crates | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -411,7 +411,7 @@ warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 | LL | #![link()] - | ^^^^^^^^^^ + | ^^^^^^^^^^ not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -419,7 +419,7 @@ warning: attribute should be applied to a foreign function or static --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 | LL | #![link_name = "1900"] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -427,7 +427,7 @@ warning: attribute should be applied to a function or static --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 | LL | #![link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/fmt/unicode-escape-spans.rs b/src/test/ui/fmt/unicode-escape-spans.rs new file mode 100644 index 00000000000..753d91ce58e --- /dev/null +++ b/src/test/ui/fmt/unicode-escape-spans.rs @@ -0,0 +1,19 @@ +fn main() { + // 1 byte in UTF-8 + format!("\u{000041}{a}"); //~ ERROR cannot find value + format!("\u{0041}{a}"); //~ ERROR cannot find value + format!("\u{41}{a}"); //~ ERROR cannot find value + format!("\u{0}{a}"); //~ ERROR cannot find value + + // 2 bytes + format!("\u{0df}{a}"); //~ ERROR cannot find value + format!("\u{df}{a}"); //~ ERROR cannot find value + + // 3 bytes + format!("\u{00211d}{a}"); //~ ERROR cannot find value + format!("\u{211d}{a}"); //~ ERROR cannot find value + + // 4 bytes + format!("\u{1f4a3}{a}"); //~ ERROR cannot find value + format!("\u{10ffff}{a}"); //~ ERROR cannot find value +} diff --git a/src/test/ui/fmt/unicode-escape-spans.stderr b/src/test/ui/fmt/unicode-escape-spans.stderr new file mode 100644 index 00000000000..1d8473f01b8 --- /dev/null +++ b/src/test/ui/fmt/unicode-escape-spans.stderr @@ -0,0 +1,63 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:3:25 + | +LL | format!("\u{000041}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:4:23 + | +LL | format!("\u{0041}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:5:21 + | +LL | format!("\u{41}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:6:20 + | +LL | format!("\u{0}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:9:22 + | +LL | format!("\u{0df}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:10:21 + | +LL | format!("\u{df}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:13:25 + | +LL | format!("\u{00211d}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:14:23 + | +LL | format!("\u{211d}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:17:24 + | +LL | format!("\u{1f4a3}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:18:25 + | +LL | format!("\u{10ffff}{a}"); + | ^ not found in this scope + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/for-loop-while/break-outside-loop.stderr b/src/test/ui/for-loop-while/break-outside-loop.stderr index 287bf9af62e..9092f34df35 100644 --- a/src/test/ui/for-loop-while/break-outside-loop.stderr +++ b/src/test/ui/for-loop-while/break-outside-loop.stderr @@ -9,11 +9,11 @@ LL | break 'lab; | = note: labels are unreachable through functions, closures, async blocks and modules -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/break-outside-loop.rs:10:15 | LL | let pth = break; - | ^^^^^ cannot `break` outside of a loop + | ^^^^^ cannot `break` outside of a loop or labeled block error[E0268]: `continue` outside of a loop --> $DIR/break-outside-loop.rs:11:17 @@ -38,11 +38,11 @@ LL | if cond() { break } LL | if cond() { continue } | ^^^^^^^^ cannot `continue` inside of a closure -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/break-outside-loop.rs:24:25 | LL | let unconstrained = break; - | ^^^^^ cannot `break` outside of a loop + | ^^^^^ cannot `break` outside of a loop or labeled block error[E0267]: `break` inside of a closure --> $DIR/break-outside-loop.rs:30:13 diff --git a/src/test/ui/function-pointer/unsized-ret.rs b/src/test/ui/function-pointer/unsized-ret.rs index 60af5769d6d..79009c5cb6c 100644 --- a/src/test/ui/function-pointer/unsized-ret.rs +++ b/src/test/ui/function-pointer/unsized-ret.rs @@ -1,7 +1,8 @@ #![feature(fn_traits)] #![feature(unboxed_closures)] +#![feature(tuple_trait)] -fn foo<F: Fn<T>, T>(f: Option<F>, t: T) { +fn foo<F: Fn<T>, T:std::marker::Tuple>(f: Option<F>, t: T) { let y = (f.unwrap()).call(t); } diff --git a/src/test/ui/function-pointer/unsized-ret.stderr b/src/test/ui/function-pointer/unsized-ret.stderr index bec3e2aa3fe..40bf7a3898a 100644 --- a/src/test/ui/function-pointer/unsized-ret.stderr +++ b/src/test/ui/function-pointer/unsized-ret.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/unsized-ret.rs:9:27 + --> $DIR/unsized-ret.rs:10:27 | LL | foo::<fn() -> str, _>(None, ()); | --------------------- ^^^^ doesn't have a size known at compile-time @@ -9,13 +9,13 @@ LL | foo::<fn() -> str, _>(None, ()); = help: within `fn() -> str`, the trait `Sized` is not implemented for `str` = note: required because it appears within the type `fn() -> str` note: required by a bound in `foo` - --> $DIR/unsized-ret.rs:4:11 + --> $DIR/unsized-ret.rs:5:11 | -LL | fn foo<F: Fn<T>, T>(f: Option<F>, t: T) { +LL | fn foo<F: Fn<T>, T:std::marker::Tuple>(f: Option<F>, t: T) { | ^^^^^ required by this bound in `foo` error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time - --> $DIR/unsized-ret.rs:12:66 + --> $DIR/unsized-ret.rs:13:66 | LL | foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),)); | ------------------------------------------------------------ ^^^^ doesn't have a size known at compile-time @@ -25,9 +25,9 @@ LL | foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&() = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)` = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)` note: required by a bound in `foo` - --> $DIR/unsized-ret.rs:4:11 + --> $DIR/unsized-ret.rs:5:11 | -LL | fn foo<F: Fn<T>, T>(f: Option<F>, t: T) { +LL | fn foo<F: Fn<T>, T:std::marker::Tuple>(f: Option<F>, t: T) { | ^^^^^ required by this bound in `foo` error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 23324af6171..0b1f34aeb96 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | assert_foo(a); | - borrow later used here @@ -17,7 +17,7 @@ error[E0716]: temporary value dropped while borrowed LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | assert_foo(a); | - borrow later used here diff --git a/src/test/ui/generator/issue-52398.stderr b/src/test/ui/generator/issue-52398.stderr index 30a6732f759..539343275df 100644 --- a/src/test/ui/generator/issue-52398.stderr +++ b/src/test/ui/generator/issue-52398.stderr @@ -4,7 +4,7 @@ warning: unused generator that must be used LL | / move || { LL | | A.test(yield); LL | | }; - | |______^ + | |_____^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default @@ -16,7 +16,7 @@ LL | / static move || { LL | | yield *y.borrow(); LL | | return "Done"; LL | | }; - | |______^ + | |_____^ | = note: generators are lazy and do nothing unless resumed diff --git a/src/test/ui/generator/issue-57084.stderr b/src/test/ui/generator/issue-57084.stderr index 29aca94408a..8f1fc5e8031 100644 --- a/src/test/ui/generator/issue-57084.stderr +++ b/src/test/ui/generator/issue-57084.stderr @@ -7,7 +7,7 @@ LL | | loop { LL | | yield LL | | } LL | | }; - | |______^ + | |_____^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/generator/match-bindings.stderr b/src/test/ui/generator/match-bindings.stderr index b911b666190..3dd2d595445 100644 --- a/src/test/ui/generator/match-bindings.stderr +++ b/src/test/ui/generator/match-bindings.stderr @@ -8,7 +8,7 @@ LL | | match Enum::A(String::new()) { ... | LL | | } LL | | }; - | |______^ + | |_____^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/generator/reborrow-mut-upvar.stderr b/src/test/ui/generator/reborrow-mut-upvar.stderr index e83dbf833bf..2e1fec35eaf 100644 --- a/src/test/ui/generator/reborrow-mut-upvar.stderr +++ b/src/test/ui/generator/reborrow-mut-upvar.stderr @@ -8,7 +8,7 @@ LL | | yield; ... | LL | | *bar = 2; LL | | }; - | |______^ + | |_____^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/generator/too-live-local-in-immovable-gen.stderr b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr index 5cb43067fee..e262f213f63 100644 --- a/src/test/ui/generator/too-live-local-in-immovable-gen.stderr +++ b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr @@ -8,7 +8,7 @@ LL | | // and it should also find out that `a` is not live. ... | LL | | let _ = &a; LL | | }; - | |__________^ + | |_________^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/generator/yield-in-args-rev.stderr b/src/test/ui/generator/yield-in-args-rev.stderr index c9e1ab722d4..a87248f6621 100644 --- a/src/test/ui/generator/yield-in-args-rev.stderr +++ b/src/test/ui/generator/yield-in-args-rev.stderr @@ -5,7 +5,7 @@ LL | / || { LL | | let b = true; LL | | foo(yield, &b); LL | | }; - | |______^ + | |_____^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/generator/yield-in-box.stderr b/src/test/ui/generator/yield-in-box.stderr index 8587e1dc663..9d03ee00800 100644 --- a/src/test/ui/generator/yield-in-box.stderr +++ b/src/test/ui/generator/yield-in-box.stderr @@ -8,7 +8,7 @@ LL | | let _t = box (&x, yield 0, &y); ... | LL | | } LL | | }; - | |______^ + | |_____^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/generator/yield-in-initializer.stderr b/src/test/ui/generator/yield-in-initializer.stderr index 07de24662cf..ed14a2e3273 100644 --- a/src/test/ui/generator/yield-in-initializer.stderr +++ b/src/test/ui/generator/yield-in-initializer.stderr @@ -8,7 +8,7 @@ LL | | // See https://github.com/rust-lang/rust/issues/52792 ... | LL | | } LL | | }; - | |______^ + | |_____^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/generator/yield-subtype.stderr b/src/test/ui/generator/yield-subtype.stderr index fe10477bf73..97862e91cd4 100644 --- a/src/test/ui/generator/yield-subtype.stderr +++ b/src/test/ui/generator/yield-subtype.stderr @@ -5,7 +5,7 @@ LL | / || { LL | | yield a; LL | | yield b; LL | | }; - | |______^ + | |_____^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr index 414999881d4..1c9abc4e837 100644 --- a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr +++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/hrtb-implied-1.rs:31:22 | LL | let slice = &mut (); - | ^^ creates a temporary which is freed while still in use + | ^^ creates a temporary value which is freed while still in use ... LL | print_items::<WindowsMut<'_>>(windows); | -------------------------------------- argument requires that borrow lasts for `'static` diff --git a/src/test/ui/generic-associated-types/bugs/issue-100013.rs b/src/test/ui/generic-associated-types/bugs/issue-100013.rs new file mode 100644 index 00000000000..fc4e47a3ba1 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-100013.rs @@ -0,0 +1,39 @@ +// check-fail +// known-bug +// edition: 2021 + +// We really should accept this, but we need implied bounds between the regions +// in a generator interior. + +pub trait FutureIterator { + type Future<'s, 'cx>: Send + where + 's: 'cx; +} + +fn call<I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + //~^ lifetime bound not satisfied + let x = None::<I::Future<'_, '_>>; // a type referencing GAT + async {}.await; // a yield point + } +} + +fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + //~^ lifetime bound not satisfied + let x = None::<I::Future<'a, 'b>>; // a type referencing GAT + //~^ lifetime may not live long enough + async {}.await; // a yield point + } +} + +fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + //~^ lifetime bound not satisfied + let x = None::<I::Future<'a, 'b>>; // a type referencing GAT + async {}.await; // a yield point + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-100013.stderr b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr new file mode 100644 index 00000000000..72ae288dcab --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr @@ -0,0 +1,82 @@ +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:15:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | +LL | | let x = None::<I::Future<'_, '_>>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:17:38 + | +LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:17:34 + | +LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:23:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | +LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT +LL | | +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:22:14 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:22:10 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + +error: lifetime may not live long enough + --> $DIR/issue-100013.rs:25:17 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT + | ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:32:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | +LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:31:18 + | +LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:31:10 + | +LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.rs b/src/test/ui/generic-associated-types/bugs/issue-80626.rs index f6aa6b36e13..d6e18010f3b 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.rs @@ -1,7 +1,4 @@ -// check-fail -// known-bug: #80626 - -// This should pass, but it requires `Sized` to be coinductive. +// check-pass trait Allocator { type Allocated<T>; @@ -9,7 +6,7 @@ trait Allocator { enum LinkedList<A: Allocator> { Head, - Next(A::Allocated<Self>) + Next(A::Allocated<Self>), } fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr deleted file mode 100644 index 9a0f332ed47..00000000000 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0275]: overflow evaluating the requirement `LinkedList<A>: Sized` - --> $DIR/issue-80626.rs:12:10 - | -LL | Next(A::Allocated<Self>) - | ^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `Allocator::Allocated` - --> $DIR/issue-80626.rs:7:20 - | -LL | type Allocated<T>; - | ^ required by this bound in `Allocator::Allocated` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/issue-87750.rs b/src/test/ui/generic-associated-types/issue-87750.rs index 0a11a0f3ae0..b35657989ef 100644 --- a/src/test/ui/generic-associated-types/issue-87750.rs +++ b/src/test/ui/generic-associated-types/issue-87750.rs @@ -1,3 +1,5 @@ +// check-pass + trait PointerFamily { type Pointer<T>; } @@ -10,11 +12,13 @@ impl PointerFamily for RcFamily { } #[allow(dead_code)] -enum Node<T, P: PointerFamily> where P::Pointer<Node<T, P>>: Sized { +enum Node<T, P: PointerFamily> +where + P::Pointer<Node<T, P>>: Sized, +{ Cons(P::Pointer<Node<T, P>>), } fn main() { let _list: <RcFamily as PointerFamily>::Pointer<Node<i32, RcFamily>>; - //~^ ERROR overflow evaluating the requirement `Node<i32, RcFamily>: Sized` } diff --git a/src/test/ui/generic-associated-types/issue-87750.stderr b/src/test/ui/generic-associated-types/issue-87750.stderr deleted file mode 100644 index b358ca273ca..00000000000 --- a/src/test/ui/generic-associated-types/issue-87750.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0275]: overflow evaluating the requirement `Node<i32, RcFamily>: Sized` - --> $DIR/issue-87750.rs:18:16 - | -LL | let _list: <RcFamily as PointerFamily>::Pointer<Node<i32, RcFamily>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs index 5fc6071c939..e321da53d56 100644 --- a/src/test/ui/generic-associated-types/issue-91139.rs +++ b/src/test/ui/generic-associated-types/issue-91139.rs @@ -21,6 +21,7 @@ fn foo<T>() { //~| ERROR `T` does not live long enough //~| ERROR `T` does not live long enough //~| ERROR `T` may not live long enough + //~| ERROR `T` may not live long enough // // FIXME: This error is bogus, but it arises because we try to validate // that `<() as Foo<T>>::Type<'a>` is valid, which requires proving diff --git a/src/test/ui/generic-associated-types/issue-91139.stderr b/src/test/ui/generic-associated-types/issue-91139.stderr index 8bbe98fa1e5..5485570cecd 100644 --- a/src/test/ui/generic-associated-types/issue-91139.stderr +++ b/src/test/ui/generic-associated-types/issue-91139.stderr @@ -22,6 +22,17 @@ error: `T` does not live long enough LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-91139.rs:14:58 + | +LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn foo<T: 'static>() { + | +++++++++ + error: `T` does not live long enough --> $DIR/issue-91139.rs:14:58 | @@ -57,6 +68,6 @@ error: `T` does not live long enough LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); | ^^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs index 58d57df63c1..ecf6f69c9fa 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -21,6 +21,7 @@ impl<T> Foo for Number<T> { // ``` // which it is :) type Item = [T] where [T]: Sized; + //~^ ERROR overflow evaluating the requirement `<Number<T> as Foo>::Item == _` } struct OnlySized<T> where T: Sized { f: T } @@ -40,7 +41,6 @@ impl<T> Bar for T where T: Foo { // can use the bound on `Foo::Item` for this, but that requires // `wf(<T as Foo>::Item)`, which is an invalid cycle. type Assoc = OnlySized<<T as Foo>::Item>; - //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized` } fn foo<T: Print>() { diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr index 27c1a82994a..aae9a56bb61 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -1,14 +1,8 @@ -error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized` - --> $DIR/projection-bound-cycle-generic.rs:42:18 +error[E0275]: overflow evaluating the requirement `<Number<T> as Foo>::Item == _` + --> $DIR/projection-bound-cycle-generic.rs:23:5 | -LL | type Assoc = OnlySized<<T as Foo>::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `OnlySized` - --> $DIR/projection-bound-cycle-generic.rs:26:18 - | -LL | struct OnlySized<T> where T: Sized { f: T } - | ^ required by this bound in `OnlySized` +LL | type Item = [T] where [T]: Sized; + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.rs b/src/test/ui/generic-associated-types/projection-bound-cycle.rs index 4cad1f61319..b51ae7ef201 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.rs @@ -24,6 +24,7 @@ impl Foo for Number { // ``` // which it is :) type Item = str where str: Sized; + //~^ ERROR overflow evaluating the requirement `<Number as Foo>::Item == _` } struct OnlySized<T> where T: Sized { f: T } @@ -43,7 +44,6 @@ impl<T> Bar for T where T: Foo { // can use the bound on `Foo::Item` for this, but that requires // `wf(<T as Foo>::Item)`, which is an invalid cycle. type Assoc = OnlySized<<T as Foo>::Item>; - //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized` } fn foo<T: Print>() { diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr index a46518c80da..b1b8afeecd0 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr @@ -1,14 +1,8 @@ -error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized` - --> $DIR/projection-bound-cycle.rs:45:18 +error[E0275]: overflow evaluating the requirement `<Number as Foo>::Item == _` + --> $DIR/projection-bound-cycle.rs:26:5 | -LL | type Assoc = OnlySized<<T as Foo>::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `OnlySized` - --> $DIR/projection-bound-cycle.rs:29:18 - | -LL | struct OnlySized<T> where T: Sized { f: T } - | ^ required by this bound in `OnlySized` +LL | type Item = str where str: Sized; + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/cross-return-site-inference.rs b/src/test/ui/impl-trait/cross-return-site-inference.rs index d881af9ed8f..00aed2ad95a 100644 --- a/src/test/ui/impl-trait/cross-return-site-inference.rs +++ b/src/test/ui/impl-trait/cross-return-site-inference.rs @@ -30,16 +30,19 @@ fn baa(b: bool) -> impl std::fmt::Debug { fn muh() -> Result<(), impl std::fmt::Debug> { Err("whoops")?; - Ok(()) //~ ERROR type annotations needed + Ok(()) + //~^ ERROR type annotations needed } fn muh2() -> Result<(), impl std::fmt::Debug> { - return Err(From::from("foo")); //~ ERROR type annotations needed + return Err(From::from("foo")); + //~^ ERROR type annotations needed Ok(()) } fn muh3() -> Result<(), impl std::fmt::Debug> { - Err(From::from("foo")) //~ ERROR type annotations needed + Err(From::from("foo")) + //~^ ERROR type annotations needed } fn main() {} diff --git a/src/test/ui/impl-trait/cross-return-site-inference.stderr b/src/test/ui/impl-trait/cross-return-site-inference.stderr index 1ff777e6503..766614e9e50 100644 --- a/src/test/ui/impl-trait/cross-return-site-inference.stderr +++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr @@ -10,7 +10,7 @@ LL | Ok::<(), E>(()) | +++++++++ error[E0282]: type annotations needed - --> $DIR/cross-return-site-inference.rs:37:12 + --> $DIR/cross-return-site-inference.rs:38:12 | LL | return Err(From::from("foo")); | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` @@ -21,7 +21,7 @@ LL | return Err::<(), E>(From::from("foo")); | +++++++++ error[E0282]: type annotations needed - --> $DIR/cross-return-site-inference.rs:42:5 + --> $DIR/cross-return-site-inference.rs:44:5 | LL | Err(From::from("foo")) | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr index 88e2520bf4b..30fbba16868 100644 --- a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr +++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr @@ -9,13 +9,6 @@ help: add `dyn` keyword before this trait LL | fn ice() -> impl AsRef<dyn Fn(&())> { | +++ -error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied - --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 - | -LL | fn ice() -> impl AsRef<Fn(&())> { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0277, E0782. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0782`. diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs index 5a922697f6f..bed81c4bca7 100644 --- a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs +++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -4,8 +4,8 @@ #![allow(warnings)] fn ice() -> impl AsRef<Fn(&())> { - //~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] - //[edition2021]~| ERROR: trait objects must include the `dyn` keyword [E0782] + //[edition2015]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] + //[edition2021]~^^ ERROR: trait objects must include the `dyn` keyword [E0782] todo!() } diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs index 3e760710797..61303a5b2cb 100644 --- a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs +++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; fn a() -> impl Fn(&u8) -> impl Debug + '_ { //~^ ERROR ambiguous `+` in a type - //~^^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~| ERROR higher kinded lifetime bounds on nested opaque types are not supported yet |x| x } diff --git a/src/test/ui/impl-trait/in-trait/generics-mismatch.rs b/src/test/ui/impl-trait/in-trait/generics-mismatch.rs new file mode 100644 index 00000000000..cc0fc720ebb --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/generics-mismatch.rs @@ -0,0 +1,17 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct U; + +trait Foo { + fn bar(&self) -> impl Sized; +} + +impl Foo for U { + fn bar<T>(&self) {} + //~^ ERROR method `bar` has 1 type parameter but its trait declaration has 0 type parameters +} + +fn main() { + U.bar(); +} diff --git a/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr b/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr new file mode 100644 index 00000000000..cd42683e022 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/generics-mismatch.rs:11:12 + | +LL | fn bar(&self) -> impl Sized; + | - expected 0 type parameters +... +LL | fn bar<T>(&self) {} + | ^ found 1 type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/src/test/ui/impl-trait/in-trait/method-signature-matches.rs b/src/test/ui/impl-trait/in-trait/method-signature-matches.rs new file mode 100644 index 00000000000..c848ee3f643 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/method-signature-matches.rs @@ -0,0 +1,51 @@ +// edition: 2021 + +#![feature(return_position_impl_trait_in_trait, async_fn_in_trait)] +#![allow(incomplete_features)] + +trait Uwu { + fn owo(x: ()) -> impl Sized; +} + +impl Uwu for () { + fn owo(_: u8) {} + //~^ ERROR method `owo` has an incompatible type for trait +} + +trait AsyncUwu { + async fn owo(x: ()) {} +} + +impl AsyncUwu for () { + async fn owo(_: u8) {} + //~^ ERROR method `owo` has an incompatible type for trait +} + +trait TooMuch { + fn calm_down_please() -> impl Sized; +} + +impl TooMuch for () { + fn calm_down_please(_: (), _: (), _: ()) {} + //~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 +} + +trait TooLittle { + fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; +} + +impl TooLittle for () { + fn come_on_a_little_more_effort() {} + //~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 +} + +trait Lifetimes { + fn early<'early, T>(x: &'early T) -> impl Sized; +} + +impl Lifetimes for () { + fn early<'late, T>(_: &'late ()) {} + //~^ ERROR method `early` has an incompatible type for trait +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr new file mode 100644 index 00000000000..2b32c52c829 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr @@ -0,0 +1,84 @@ +error[E0053]: method `owo` has an incompatible type for trait + --> $DIR/method-signature-matches.rs:11:15 + | +LL | fn owo(_: u8) {} + | ^^ + | | + | expected `()`, found `u8` + | help: change the parameter type to match the trait: `()` + | +note: type in trait + --> $DIR/method-signature-matches.rs:7:15 + | +LL | fn owo(x: ()) -> impl Sized; + | ^^ + = note: expected fn pointer `fn(())` + found fn pointer `fn(u8)` + +error[E0053]: method `owo` has an incompatible type for trait + --> $DIR/method-signature-matches.rs:20:21 + | +LL | async fn owo(_: u8) {} + | ^^ + | | + | expected `()`, found `u8` + | help: change the parameter type to match the trait: `()` + | +note: while checking the return type of the `async fn` + --> $DIR/method-signature-matches.rs:20:25 + | +LL | async fn owo(_: u8) {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/method-signature-matches.rs:20:25 + | +LL | async fn owo(_: u8) {} + | ^ checked the `Output` of this `async fn`, found opaque type +note: type in trait + --> $DIR/method-signature-matches.rs:16:21 + | +LL | async fn owo(x: ()) {} + | ^^ + = note: expected fn pointer `fn(()) -> _` + found fn pointer `fn(u8) -> _` + +error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 + --> $DIR/method-signature-matches.rs:29:28 + | +LL | fn calm_down_please() -> impl Sized; + | ------------------------------------ trait requires 0 parameters +... +LL | fn calm_down_please(_: (), _: (), _: ()) {} + | ^^^^^^^^^^^^^^^^ expected 0 parameters, found 3 + +error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 + --> $DIR/method-signature-matches.rs:38:5 + | +LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; + | ---------------- trait requires 3 parameters +... +LL | fn come_on_a_little_more_effort() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0 + +error[E0053]: method `early` has an incompatible type for trait + --> $DIR/method-signature-matches.rs:47:27 + | +LL | fn early<'late, T>(_: &'late ()) {} + | - ^^^^^^^^^ + | | | + | | expected type parameter `T`, found `()` + | | help: change the parameter type to match the trait: `&'early T` + | this type parameter + | +note: type in trait + --> $DIR/method-signature-matches.rs:43:28 + | +LL | fn early<'early, T>(x: &'early T) -> impl Sized; + | ^^^^^^^^^ + = note: expected fn pointer `fn(&'early T)` + found fn pointer `fn(&())` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0050, E0053. +For more information about an error, try `rustc --explain E0050`. diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.rs b/src/test/ui/impl-trait/in-trait/specialization-broken.rs new file mode 100644 index 00000000000..9d27d3710a6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/specialization-broken.rs @@ -0,0 +1,26 @@ +// FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not. +// But we fixed an ICE anyways. + +#![feature(specialization)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar(&self) -> impl Sized; +} + +default impl<U> Foo for U +where + U: Copy, +{ + fn bar(&self) -> U { + //~^ ERROR method `bar` has an incompatible type for trait + *self + } +} + +impl Foo for i32 {} + +fn main() { + 1i32.bar(); +} diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.stderr b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr new file mode 100644 index 00000000000..a30e6346b29 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr @@ -0,0 +1,23 @@ +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/specialization-broken.rs:16:22 + | +LL | default impl<U> Foo for U + | - this type parameter +... +LL | fn bar(&self) -> U { + | ^ + | | + | expected associated type, found type parameter `U` + | help: change the output type to match the trait: `impl Sized` + | +note: type in trait + --> $DIR/specialization-broken.rs:9:22 + | +LL | fn bar(&self) -> impl Sized; + | ^^^^^^^^^^ + = note: expected fn pointer `fn(&U) -> impl Sized` + found fn pointer `fn(&U) -> U` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs b/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs new file mode 100644 index 00000000000..c9ee877db8e --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(specialization)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar(&self) -> impl Sized; +} + +impl<U> Foo for U +where + U: Copy, +{ + fn bar(&self) -> U { + *self + } +} + +impl Foo for i32 {} + +fn main() { + let _: i32 = 1i32.bar(); +} diff --git a/src/test/ui/impl-trait/issues/issue-92305.rs b/src/test/ui/impl-trait/issues/issue-92305.rs index 1518c116b31..4a89238d07e 100644 --- a/src/test/ui/impl-trait/issues/issue-92305.rs +++ b/src/test/ui/impl-trait/issues/issue-92305.rs @@ -4,11 +4,10 @@ use std::iter; fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> { //~^ ERROR: missing generics for struct `Vec` [E0107] - iter::empty() //~ ERROR: type annotations needed [E0282] + iter::empty() } fn g<T>(data: &[T], target: T) -> impl Iterator<Item = Vec<T>> { - //~^ ERROR: type annotations needed [E0282] f(data).filter(|x| x == target) } diff --git a/src/test/ui/impl-trait/issues/issue-92305.stderr b/src/test/ui/impl-trait/issues/issue-92305.stderr index e8575b76b09..34d5c2d61dc 100644 --- a/src/test/ui/impl-trait/issues/issue-92305.stderr +++ b/src/test/ui/impl-trait/issues/issue-92305.stderr @@ -14,24 +14,6 @@ help: add missing generic argument LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> { | ~~~~~~ -error[E0282]: type annotations needed - --> $DIR/issue-92305.rs:7:5 - | -LL | iter::empty() - | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` - | -help: consider specifying the generic argument - | -LL | iter::empty::<T>() - | +++++ - -error[E0282]: type annotations needed - --> $DIR/issue-92305.rs:10:35 - | -LL | fn g<T>(data: &[T], target: T) -> impl Iterator<Item = Vec<T>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type - -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0107, E0282. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/impl-trait/nested-rpit-hrtb.rs b/src/test/ui/impl-trait/nested-rpit-hrtb.rs index abf6a7e956c..a5db10d3a22 100644 --- a/src/test/ui/impl-trait/nested-rpit-hrtb.rs +++ b/src/test/ui/impl-trait/nested-rpit-hrtb.rs @@ -35,26 +35,26 @@ fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet -// This should pass. +// This should resolve. fn one_hrtb_mention_fn_trait_param<'b>() -> impl for<'a> Foo<'a, Assoc = impl Qux<'b>> {} -// This should pass. +// This should resolve. fn one_hrtb_mention_fn_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'b> {} -// This should pass. +// This should resolve. fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {} -// This should pass. +// This should resolve. fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {} -// This should pass. +// This should resolve. fn two_htrb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> {} // `'b` is not in scope for the outlives bound. fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {} //~^ ERROR use of undeclared lifetime name `'b` [E0261] -// This should pass. +// This should resolve. fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {} // `'b` is not in scope for the outlives bound. diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs index e7fabd0ffbc..b5152d04f69 100644 --- a/src/test/ui/inference/cannot-infer-async.rs +++ b/src/test/ui/inference/cannot-infer-async.rs @@ -10,6 +10,7 @@ fn main() { let fut = async { make_unit()?; - Ok(()) //~ ERROR type annotations needed + Ok(()) + //~^ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs index 1c350b18f5a..bd5d10b4173 100644 --- a/src/test/ui/inference/cannot-infer-closure.rs +++ b/src/test/ui/inference/cannot-infer-closure.rs @@ -1,6 +1,7 @@ fn main() { let x = |a: (), b: ()| { Err(a)?; - Ok(b) //~ ERROR type annotations needed + Ok(b) + //~^ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/issue-103587.rs b/src/test/ui/inference/issue-103587.rs new file mode 100644 index 00000000000..11536f9f4cc --- /dev/null +++ b/src/test/ui/inference/issue-103587.rs @@ -0,0 +1,12 @@ +fn main() { + let x = Some(123); + + if let Some(_) == x {} + //~^ ERROR expected `=`, found `==` + + if Some(_) = x {} + //~^ ERROR mismatched types + + if None = x { } + //~^ ERROR mismatched types +} diff --git a/src/test/ui/inference/issue-103587.stderr b/src/test/ui/inference/issue-103587.stderr new file mode 100644 index 00000000000..b373fbfbb94 --- /dev/null +++ b/src/test/ui/inference/issue-103587.stderr @@ -0,0 +1,40 @@ +error: expected `=`, found `==` + --> $DIR/issue-103587.rs:4:20 + | +LL | if let Some(_) == x {} + | ^^ + | +help: consider using `=` here + | +LL | if let Some(_) = x {} + | ~ + +error[E0308]: mismatched types + --> $DIR/issue-103587.rs:7:8 + | +LL | if Some(_) = x {} + | ^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(_) = x {} + | +++ + +error[E0308]: mismatched types + --> $DIR/issue-103587.rs:10:8 + | +LL | if None = x { } + | ^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to use pattern matching + | +LL | if let None = x { } + | +++ +help: you might have meant to compare for equality + | +LL | if None == x { } + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/inference/issue-71732.rs b/src/test/ui/inference/issue-71732.rs index 30063a0957c..8a9d2b235f0 100644 --- a/src/test/ui/inference/issue-71732.rs +++ b/src/test/ui/inference/issue-71732.rs @@ -15,7 +15,8 @@ use std::collections::hash_map::HashMap; fn foo(parameters: &HashMap<String, String>) -> bool { parameters - .get(&"key".into()) //~ ERROR: type annotations needed + .get(&"key".into()) + //~^ ERROR type annotations needed .and_then(|found: &String| Some(false)) .unwrap_or(false) } diff --git a/src/test/ui/inference/issue-72616.rs b/src/test/ui/inference/issue-72616.rs index 5e5a3babfe0..69ade1a7515 100644 --- a/src/test/ui/inference/issue-72616.rs +++ b/src/test/ui/inference/issue-72616.rs @@ -1,3 +1,5 @@ +// ignore-wasm32 FIXME: ignoring wasm as it suggests slightly different impls + // Regression test for #72616, it used to emit incorrect diagnostics, like: // error[E0283]: type annotations needed for `String` // --> src/main.rs:8:30 @@ -18,7 +20,8 @@ pub fn main() { } { if String::from("a") == "a".try_into().unwrap() {} - //~^ ERROR: type annotations needed + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } { let _: String = match "_".try_into() { diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr index a71ce9a8ef2..6ee0626cab8 100644 --- a/src/test/ui/inference/issue-72616.stderr +++ b/src/test/ui/inference/issue-72616.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/issue-72616.rs:20:37 + --> $DIR/issue-72616.rs:22:37 | LL | if String::from("a") == "a".try_into().unwrap() {} | -- ^^^^^^^^ @@ -16,6 +16,22 @@ help: try using a fully qualified path to specify the expected types LL | if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {} | +++++++++++++++++++++++++++++++ ~ -error: aborting due to previous error +error[E0283]: type annotations needed + --> $DIR/issue-72616.rs:22:37 + | +LL | if String::from("a") == "a".try_into().unwrap() {} + | ^^^^^^^^ + | + = note: multiple `impl`s satisfying `_: TryFrom<&str>` found in the following crates: `core`, `std`: + - impl<> TryFrom<&str> for std::sys_common::net::LookupHost; + - impl<T, U> TryFrom<U> for T + where U: Into<T>; + = note: required for `&str` to implement `TryInto<_>` +help: try using a fully qualified path to specify the expected types + | +LL | if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {} + | +++++++++++++++++++++++++++++++ ~ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/inference/question-mark-type-infer.rs b/src/test/ui/inference/question-mark-type-infer.rs index 64333a29313..10560f85ed4 100644 --- a/src/test/ui/inference/question-mark-type-infer.rs +++ b/src/test/ui/inference/question-mark-type-infer.rs @@ -7,7 +7,8 @@ fn f(x: &i32) -> Result<i32, ()> { fn g() -> Result<Vec<i32>, ()> { let l = [1, 2, 3, 4]; - l.iter().map(f).collect()? //~ ERROR type annotations needed + l.iter().map(f).collect()? + //~^ ERROR type annotations needed } fn main() { diff --git a/src/test/ui/issues/issue-12127.rs b/src/test/ui/issues/issue-12127.rs index 8b30ddc2de6..199d542e816 100644 --- a/src/test/ui/issues/issue-12127.rs +++ b/src/test/ui/issues/issue-12127.rs @@ -1,6 +1,6 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f } +fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f } fn do_it(x: &isize) { } fn main() { diff --git a/src/test/ui/issues/issue-1460.stderr b/src/test/ui/issues/issue-1460.stderr index f0ff2cafd44..eb7661fad56 100644 --- a/src/test/ui/issues/issue-1460.stderr +++ b/src/test/ui/issues/issue-1460.stderr @@ -2,7 +2,7 @@ warning: unused closure that must be used --> $DIR/issue-1460.rs:6:5 | LL | {|i: u32| if 1 == i { }}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/issues/issue-16256.stderr b/src/test/ui/issues/issue-16256.stderr index ca8e9a1bed3..d920530b57c 100644 --- a/src/test/ui/issues/issue-16256.stderr +++ b/src/test/ui/issues/issue-16256.stderr @@ -2,7 +2,7 @@ warning: unused closure that must be used --> $DIR/issue-16256.rs:6:5 | LL | |c: u8| buf.push(c); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr index 73f93c51d34..dc8b34a70c3 100644 --- a/src/test/ui/issues/issue-23024.stderr +++ b/src/test/ui/issues/issue-23024.stderr @@ -16,7 +16,7 @@ LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); note: trait defined here, with 1 generic parameter: `Args` --> $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn<Args>: FnMut<Args> { +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { | ^^ ---- help: add missing generic argument | diff --git a/src/test/ui/issues/issue-28105.stderr b/src/test/ui/issues/issue-28105.stderr index 42ed838d7c0..f450256f3ec 100644 --- a/src/test/ui/issues/issue-28105.stderr +++ b/src/test/ui/issues/issue-28105.stderr @@ -4,11 +4,11 @@ error[E0268]: `continue` outside of a loop LL | continue | ^^^^^^^^ cannot `continue` outside of a loop -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/issue-28105.rs:6:5 | LL | break - | ^^^^^ cannot `break` outside of a loop + | ^^^^^ cannot `break` outside of a loop or labeled block error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr index 2d9ce430a46..5a758c7002b 100644 --- a/src/test/ui/issues/issue-32655.stderr +++ b/src/test/ui/issues/issue-32655.stderr @@ -2,18 +2,28 @@ error: cannot find attribute `derive_Clone` in this scope --> $DIR/issue-32655.rs:3:11 | LL | #[derive_Clone] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const` ... LL | foo!(); | ------ in this macro invocation | + ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL + | +LL | pub macro derive_const($item:item) { + | ---------------------- similarly named attribute macro `derive_const` defined here + | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot find attribute `derive_Clone` in this scope --> $DIR/issue-32655.rs:15:7 | LL | #[derive_Clone] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const` + | + ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL + | +LL | pub macro derive_const($item:item) { + | ---------------------- similarly named attribute macro `derive_const` defined here error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr index 6ca2deee377..07c8101cbc6 100644 --- a/src/test/ui/issues/issue-3707.stderr +++ b/src/test/ui/issues/issue-3707.stderr @@ -2,10 +2,10 @@ error[E0599]: no method named `boom` found for reference `&Obj` in the current s --> $DIR/issue-3707.rs:10:14 | LL | self.boom(); - | -----^^^^ + | -----^^^^-- | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `Obj::boom` + | help: use associated function syntax instead: `Obj::boom()` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `Obj` diff --git a/src/test/ui/issues/issue-43162.stderr b/src/test/ui/issues/issue-43162.stderr index a443db40732..40d9200058e 100644 --- a/src/test/ui/issues/issue-43162.stderr +++ b/src/test/ui/issues/issue-43162.stderr @@ -1,14 +1,14 @@ -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/issue-43162.rs:3:5 | LL | break true; - | ^^^^^^^^^^ cannot `break` outside of a loop + | ^^^^^^^^^^ cannot `break` outside of a loop or labeled block -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/issue-43162.rs:7:5 | LL | break {}; - | ^^^^^^^^ cannot `break` outside of a loop + | ^^^^^^^^ cannot `break` outside of a loop or labeled block error[E0308]: mismatched types --> $DIR/issue-43162.rs:1:13 diff --git a/src/test/ui/issues/issue-47184.stderr b/src/test/ui/issues/issue-47184.stderr index f97713b4ac4..c2c7df7a333 100644 --- a/src/test/ui/issues/issue-47184.stderr +++ b/src/test/ui/issues/issue-47184.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let _vec: Vec<&'static String> = vec![&String::new()]; | -------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47511.stderr b/src/test/ui/issues/issue-47511.stderr deleted file mode 100644 index 9998ee0e8d0..00000000000 --- a/src/test/ui/issues/issue-47511.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types - --> $DIR/issue-47511.rs:8:15 - | -LL | fn f(_: X) -> X { - | ^ - | - = note: lifetimes appearing in an associated or opaque type are not considered constrained - = note: consider introducing a named lifetime parameter - -error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types - --> $DIR/issue-47511.rs:12:23 - | -LL | fn g<'a>(_: X<'a>) -> X<'a> { - | ^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0581`. diff --git a/src/test/ui/issues/issue-50576.stderr b/src/test/ui/issues/issue-50576.stderr index 9fea1411080..4ec22fde910 100644 --- a/src/test/ui/issues/issue-50576.stderr +++ b/src/test/ui/issues/issue-50576.stderr @@ -4,17 +4,17 @@ error[E0426]: use of undeclared label `'L` LL | |bool: [u8; break 'L]| 0; | ^^ undeclared label `'L` -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/issue-50576.rs:2:17 | LL | |bool: [u8; break 'L]| 0; - | ^^^^^^^^ cannot `break` outside of a loop + | ^^^^^^^^ cannot `break` outside of a loop or labeled block -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/issue-50576.rs:5:16 | LL | Vec::<[u8; break]>::new(); - | ^^^^^ cannot `break` outside of a loop + | ^^^^^ cannot `break` outside of a loop or labeled block error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-50581.stderr b/src/test/ui/issues/issue-50581.stderr index 35d6fc49ced..07b6df072cb 100644 --- a/src/test/ui/issues/issue-50581.stderr +++ b/src/test/ui/issues/issue-50581.stderr @@ -1,8 +1,8 @@ -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/issue-50581.rs:2:14 | LL | |_: [u8; break]| (); - | ^^^^^ cannot `break` outside of a loop + | ^^^^^ cannot `break` outside of a loop or labeled block error: aborting due to previous error diff --git a/src/test/ui/issues/issue-52049.stderr b/src/test/ui/issues/issue-52049.stderr index 55929d85da4..b25dbd1cb8b 100644 --- a/src/test/ui/issues/issue-52049.stderr +++ b/src/test/ui/issues/issue-52049.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | foo(&unpromotable(5u32)); | -----^^^^^^^^^^^^^^^^^^- | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | argument requires that borrow lasts for `'static` LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr index f581429a281..89aeafebac4 100644 --- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr @@ -2,10 +2,7 @@ error[E0428]: the name `A` is defined multiple times --> $DIR/issue-69396-const-no-type-in-macro.rs:4:13 | LL | const A = "A".$fn(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | `A` redefined here - | previous definition of the value `A` here + | ^^^^^^^^^^^^^^^^^^^^ `A` redefined here ... LL | / suite! { LL | | len; diff --git a/src/test/ui/issues/issue-71584.rs b/src/test/ui/issues/issue-71584.rs index c96cd598f0c..7bf3ed60ec1 100644 --- a/src/test/ui/issues/issue-71584.rs +++ b/src/test/ui/issues/issue-71584.rs @@ -1,5 +1,6 @@ fn main() { let n: u32 = 1; let mut d: u64 = 2; - d = d % n.into(); //~ ERROR type annotations needed + d = d % n.into(); + //~^ ERROR type annotations needed } diff --git a/src/test/ui/issues/issue-7607-1.stderr b/src/test/ui/issues/issue-7607-1.stderr index ecff8b42b0e..f1ab0ad26d7 100644 --- a/src/test/ui/issues/issue-7607-1.stderr +++ b/src/test/ui/issues/issue-7607-1.stderr @@ -6,8 +6,8 @@ LL | impl Fo { | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn<Args>: FnMut<Args> { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | -------------------------------------- similarly named trait `Fn` defined here error: aborting due to previous error diff --git a/src/test/ui/issues/issue-83048.rs b/src/test/ui/issues/issue-83048.rs index 520ae974398..8e4fb6eae9d 100644 --- a/src/test/ui/issues/issue-83048.rs +++ b/src/test/ui/issues/issue-83048.rs @@ -1,5 +1,5 @@ // compile-flags: -Z unpretty=thir-tree pub fn main() { - break; //~ ERROR: `break` outside of a loop [E0268] + break; //~ ERROR: `break` outside of a loop or labeled block [E0268] } diff --git a/src/test/ui/issues/issue-83048.stderr b/src/test/ui/issues/issue-83048.stderr index 62d67d75844..dade9e46950 100644 --- a/src/test/ui/issues/issue-83048.stderr +++ b/src/test/ui/issues/issue-83048.stderr @@ -1,8 +1,8 @@ -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/issue-83048.rs:4:5 | LL | break; - | ^^^^^ cannot `break` outside of a loop + | ^^^^^ cannot `break` outside of a loop or labeled block error: aborting due to previous error diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs index 7d35da82532..4c424999b75 100644 --- a/src/test/ui/iterators/collect-into-array.rs +++ b/src/test/ui/iterators/collect-into-array.rs @@ -1,5 +1,4 @@ fn main() { - //~^ NOTE required by a bound in this let whatever: [u32; 10] = (0..10).collect(); //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()` diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr index 7fe9707e6d2..a23a36a88ab 100644 --- a/src/test/ui/iterators/collect-into-array.stderr +++ b/src/test/ui/iterators/collect-into-array.stderr @@ -1,5 +1,5 @@ error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator - --> $DIR/collect-into-array.rs:3:31 + --> $DIR/collect-into-array.rs:2:31 | LL | let whatever: [u32; 10] = (0..10).collect(); | ^^^^^^^ ------- required by a bound introduced by this call diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs index 5eade075613..09832c260d0 100644 --- a/src/test/ui/iterators/collect-into-slice.rs +++ b/src/test/ui/iterators/collect-into-slice.rs @@ -1,6 +1,4 @@ fn process_slice(data: &[i32]) { - //~^ NOTE required by a bound in this - //~| NOTE required by a bound in this todo!() } diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr index bce40118bdf..bc152467ce3 100644 --- a/src/test/ui/iterators/collect-into-slice.stderr +++ b/src/test/ui/iterators/collect-into-slice.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation time - --> $DIR/collect-into-slice.rs:8:9 + --> $DIR/collect-into-slice.rs:6:9 | LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -9,7 +9,7 @@ LL | let some_generated_vec = (0..10).collect(); = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `[i32]` cannot be known at compilation time - --> $DIR/collect-into-slice.rs:8:38 + --> $DIR/collect-into-slice.rs:6:38 | LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ doesn't have a size known at compile-time @@ -22,7 +22,7 @@ LL | fn collect<B: FromIterator<Self::Item>>(self) -> B | ^ required by this bound in `collect` error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size - --> $DIR/collect-into-slice.rs:8:30 + --> $DIR/collect-into-slice.rs:6:30 | LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ ------- required by a bound introduced by this call diff --git a/src/test/ui/lang-items/lang-item-missing-generator.rs b/src/test/ui/lang-items/lang-item-missing-generator.rs index 0c329542928..9b9aff38e52 100644 --- a/src/test/ui/lang-items/lang-item-missing-generator.rs +++ b/src/test/ui/lang-items/lang-item-missing-generator.rs @@ -1,12 +1,14 @@ // error-pattern: requires `generator` lang_item -#![feature(no_core, lang_items, unboxed_closures)] +#![feature(no_core, lang_items, unboxed_closures, tuple_trait)] #![no_core] #[lang = "sized"] pub trait Sized { } +#[lang = "tuple_trait"] pub trait Tuple { } + #[lang = "fn_once"] #[rustc_paren_sugar] -pub trait FnOnce<Args> { +pub trait FnOnce<Args: Tuple> { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; diff --git a/src/test/ui/lang-items/lang-item-missing-generator.stderr b/src/test/ui/lang-items/lang-item-missing-generator.stderr index fa13bf0b127..a24fdb5fb65 100644 --- a/src/test/ui/lang-items/lang-item-missing-generator.stderr +++ b/src/test/ui/lang-items/lang-item-missing-generator.stderr @@ -1,8 +1,15 @@ +error[E0635]: unknown feature `tuple_trait` + --> $DIR/lang-item-missing-generator.rs:2:51 + | +LL | #![feature(no_core, lang_items, unboxed_closures, tuple_trait)] + | ^^^^^^^^^^^ + error: requires `generator` lang_item - --> $DIR/lang-item-missing-generator.rs:15:17 + --> $DIR/lang-item-missing-generator.rs:17:17 | LL | pub fn abc() -> impl FnOnce(f32) { | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0635`. diff --git a/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs b/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs new file mode 100644 index 00000000000..5b9dc0e4308 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs @@ -0,0 +1,5 @@ +pub trait Trait<'a> { + type Assoc; +} + +pub type Alias<'a, T> = <T as Trait<'a>>::Assoc; diff --git a/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs b/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs new file mode 100644 index 00000000000..4154c279243 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs @@ -0,0 +1,10 @@ +// aux-build:upstream_alias.rs +// check-pass + +extern crate upstream_alias; + +fn foo<'a, T: for<'b> upstream_alias::Trait<'b>>(_: upstream_alias::Alias<'a, T>) -> &'a () { + todo!() +} + +fn main() {} diff --git a/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs b/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs new file mode 100644 index 00000000000..e56a34218e2 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs @@ -0,0 +1,24 @@ +// check-pass + +trait Gats<'a> { + type Assoc; + type Assoc2; +} + +trait Trait: for<'a> Gats<'a> { + fn foo<'a>(_: &mut <Self as Gats<'a>>::Assoc) -> <Self as Gats<'a>>::Assoc2; +} + +impl<'a> Gats<'a> for () { + type Assoc = &'a u32; + type Assoc2 = (); +} + +type GatsAssoc<'a, T> = <T as Gats<'a>>::Assoc; +type GatsAssoc2<'a, T> = <T as Gats<'a>>::Assoc2; + +impl Trait for () { + fn foo<'a>(_: &mut GatsAssoc<'a, Self>) -> GatsAssoc2<'a, Self> {} +} + +fn main() {} diff --git a/src/test/ui/issues/issue-47511.rs b/src/test/ui/late-bound-lifetimes/issue-47511.rs index eb4860e75d7..78944351540 100644 --- a/src/test/ui/issues/issue-47511.rs +++ b/src/test/ui/late-bound-lifetimes/issue-47511.rs @@ -1,9 +1,4 @@ -// check-fail -// known-bug: #47511 - -// Regression test for #47511: anonymous lifetimes can appear -// unconstrained in a return type, but only if they appear just once -// in the input, as the input to a projection. +// check-pass fn f(_: X) -> X { unimplemented!() diff --git a/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs b/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs new file mode 100644 index 00000000000..91839673c1f --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs @@ -0,0 +1,16 @@ +// check-pass + +fn f(_: X) -> X { + unimplemented!() +} + +fn g<'a>(_: X<'a>) -> X<'a> { + unimplemented!() +} + +type X<'a> = &'a (); + +fn main() { + let _: for<'a> fn(X<'a>) -> X<'a> = g; + let _: for<'a> fn(X<'a>) -> X<'a> = f; +} diff --git a/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs new file mode 100644 index 00000000000..0b331e2039f --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs @@ -0,0 +1,12 @@ +// ensures that we don't ICE when there are too many args supplied to the alias. + +trait Trait<'a> { + type Assoc; +} + +type Alias<'a, T> = <T as Trait<'a>>::Assoc; + +fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {} +//~^ error: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied + +fn main() {} diff --git a/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr new file mode 100644 index 00000000000..3704d9bb957 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr @@ -0,0 +1,17 @@ +error[E0107]: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/mismatched_arg_count.rs:9:29 + | +LL | fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {} + | ^^^^^ -- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: type alias defined here, with 1 lifetime parameter: `'a` + --> $DIR/mismatched_arg_count.rs:7:6 + | +LL | type Alias<'a, T> = <T as Trait<'a>>::Assoc; + | ^^^^^ -- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr index bbf04c98436..987b051b111 100644 --- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr +++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let mut x = vec![1].iter(); | ^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | LL | x.use_mut(); | ----------- borrow later used here diff --git a/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs b/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs index e3935cf9149..2003e1e293a 100644 --- a/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs +++ b/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs @@ -7,7 +7,7 @@ struct Bar { b: usize, //~ ERROR field `b` is never read #[deny(dead_code)] c: usize, //~ ERROR fields `c` and `e` are never read - d: usize, //~ WARN fields `d`, `f` and `g` are never read + d: usize, //~ WARN fields `d`, `f`, and `g` are never read #[deny(dead_code)] e: usize, f: usize, diff --git a/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr index c0f1ed38f6d..0e5c78a7167 100644 --- a/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr +++ b/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr @@ -1,4 +1,4 @@ -warning: fields `d`, `f` and `g` are never read +warning: fields `d`, `f`, and `g` are never read --> $DIR/multiple-dead-codes-in-the-same-struct.rs:10:5 | LL | struct Bar { diff --git a/src/test/ui/lint/dead-code/tuple-struct-field.rs b/src/test/ui/lint/dead-code/tuple-struct-field.rs index b15d7063686..14fb30be949 100644 --- a/src/test/ui/lint/dead-code/tuple-struct-field.rs +++ b/src/test/ui/lint/dead-code/tuple-struct-field.rs @@ -11,7 +11,7 @@ struct SingleUnused(i32, [u8; LEN], String); //~| HELP: consider changing the field to be of unit type struct MultipleUnused(i32, f32, String, u8); -//~^ ERROR: fields `0`, `1`, `2` and `3` are never read +//~^ ERROR: fields `0`, `1`, `2`, and `3` are never read //~| NOTE: fields in this struct //~| HELP: consider changing the fields to be of unit type diff --git a/src/test/ui/lint/dead-code/tuple-struct-field.stderr b/src/test/ui/lint/dead-code/tuple-struct-field.stderr index ca0989f5b98..b8ad5cbe4e9 100644 --- a/src/test/ui/lint/dead-code/tuple-struct-field.stderr +++ b/src/test/ui/lint/dead-code/tuple-struct-field.stderr @@ -16,7 +16,7 @@ help: consider changing the field to be of unit type to suppress this warning wh LL | struct SingleUnused(i32, (), String); | ~~ -error: fields `0`, `1`, `2` and `3` are never read +error: fields `0`, `1`, `2`, and `3` are never read --> $DIR/tuple-struct-field.rs:13:23 | LL | struct MultipleUnused(i32, f32, String, u8); diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr index 2805720f035..657f23c6085 100644 --- a/src/test/ui/lint/fn_must_use.stderr +++ b/src/test/ui/lint/fn_must_use.stderr @@ -2,7 +2,7 @@ warning: unused return value of `need_to_use_this_value` that must be used --> $DIR/fn_must_use.rs:55:5 | LL | need_to_use_this_value(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: it's important note: the lint level is defined here @@ -15,13 +15,13 @@ warning: unused return value of `MyStruct::need_to_use_this_method_value` that m --> $DIR/fn_must_use.rs:60:5 | LL | m.need_to_use_this_method_value(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused return value of `EvenNature::is_even` that must be used --> $DIR/fn_must_use.rs:61:5 | LL | m.is_even(); // trait method! - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: no side effects @@ -29,19 +29,19 @@ warning: unused return value of `MyStruct::need_to_use_this_associated_function_ --> $DIR/fn_must_use.rs:64:5 | LL | MyStruct::need_to_use_this_associated_function_value(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused return value of `std::cmp::PartialEq::eq` that must be used --> $DIR/fn_must_use.rs:70:5 | LL | 2.eq(&3); - | ^^^^^^^^^ + | ^^^^^^^^ warning: unused return value of `std::cmp::PartialEq::eq` that must be used --> $DIR/fn_must_use.rs:71:5 | LL | m.eq(&n); - | ^^^^^^^^^ + | ^^^^^^^^ warning: unused comparison that must be used --> $DIR/fn_must_use.rs:74:5 diff --git a/src/test/ui/lint/issue-103435-extra-parentheses.fixed b/src/test/ui/lint/issue-103435-extra-parentheses.fixed new file mode 100644 index 00000000000..2b01b414baa --- /dev/null +++ b/src/test/ui/lint/issue-103435-extra-parentheses.fixed @@ -0,0 +1,18 @@ +// run-rustfix +#![deny(unused_parens)] + +fn main() { + if let Some(_) = Some(1) {} + //~^ ERROR unnecessary parentheses around pattern + + for _x in 1..10 {} + //~^ ERROR unnecessary parentheses around pattern + + if 2 == 1 {} + //~^ ERROR unnecessary parentheses around `if` condition + + // reported by parser + for _x in 1..10 {} + //~^ ERROR expected one of + //~| ERROR unexpected parentheses surrounding +} diff --git a/src/test/ui/lint/issue-103435-extra-parentheses.rs b/src/test/ui/lint/issue-103435-extra-parentheses.rs new file mode 100644 index 00000000000..8261610cf56 --- /dev/null +++ b/src/test/ui/lint/issue-103435-extra-parentheses.rs @@ -0,0 +1,18 @@ +// run-rustfix +#![deny(unused_parens)] + +fn main() { + if let(Some(_))= Some(1) {} + //~^ ERROR unnecessary parentheses around pattern + + for(_x)in 1..10 {} + //~^ ERROR unnecessary parentheses around pattern + + if(2 == 1){} + //~^ ERROR unnecessary parentheses around `if` condition + + // reported by parser + for(_x in 1..10){} + //~^ ERROR expected one of + //~| ERROR unexpected parentheses surrounding +} diff --git a/src/test/ui/lint/issue-103435-extra-parentheses.stderr b/src/test/ui/lint/issue-103435-extra-parentheses.stderr new file mode 100644 index 00000000000..29c41c91050 --- /dev/null +++ b/src/test/ui/lint/issue-103435-extra-parentheses.stderr @@ -0,0 +1,61 @@ +error: expected one of `)`, `,`, `@`, or `|`, found keyword `in` + --> $DIR/issue-103435-extra-parentheses.rs:15:12 + | +LL | for(_x in 1..10){} + | ^^ expected one of `)`, `,`, `@`, or `|` + +error: unexpected parentheses surrounding `for` loop head + --> $DIR/issue-103435-extra-parentheses.rs:15:8 + | +LL | for(_x in 1..10){} + | ^ ^ + | +help: remove parentheses in `for` loop + | +LL - for(_x in 1..10){} +LL + for _x in 1..10 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-103435-extra-parentheses.rs:5:11 + | +LL | if let(Some(_))= Some(1) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-103435-extra-parentheses.rs:2:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - if let(Some(_))= Some(1) {} +LL + if let Some(_) = Some(1) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-103435-extra-parentheses.rs:8:8 + | +LL | for(_x)in 1..10 {} + | ^ ^ + | +help: remove these parentheses + | +LL - for(_x)in 1..10 {} +LL + for _x in 1..10 {} + | + +error: unnecessary parentheses around `if` condition + --> $DIR/issue-103435-extra-parentheses.rs:11:7 + | +LL | if(2 == 1){} + | ^ ^ + | +help: remove these parentheses + | +LL - if(2 == 1){} +LL + if 2 == 1 {} + | + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/lint/unused/must-use-box-from-raw.stderr b/src/test/ui/lint/unused/must-use-box-from-raw.stderr index 011acc3bf5d..72118275774 100644 --- a/src/test/ui/lint/unused/must-use-box-from-raw.stderr +++ b/src/test/ui/lint/unused/must-use-box-from-raw.stderr @@ -2,7 +2,7 @@ warning: unused return value of `Box::<T>::from_raw` that must be used --> $DIR/must-use-box-from-raw.rs:8:5 | LL | Box::from_raw(ptr); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: call `drop(from_raw(ptr))` if you intend to drop the `Box` note: the lint level is defined here diff --git a/src/test/ui/lint/unused/must_use-array.stderr b/src/test/ui/lint/unused/must_use-array.stderr index 45a5317fccc..bba2b1ba078 100644 --- a/src/test/ui/lint/unused/must_use-array.stderr +++ b/src/test/ui/lint/unused/must_use-array.stderr @@ -2,7 +2,7 @@ error: unused array of `S` that must be used --> $DIR/must_use-array.rs:39:5 | LL | singleton(); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/must_use-array.rs:1:9 @@ -14,7 +14,7 @@ error: unused array of `S` that must be used --> $DIR/must_use-array.rs:40:5 | LL | many(); - | ^^^^^^^ + | ^^^^^^ error: unused array of `S` in tuple element 0 that must be used --> $DIR/must_use-array.rs:41:6 @@ -26,7 +26,7 @@ error: unused array of implementers of `T` that must be used --> $DIR/must_use-array.rs:42:5 | LL | array_of_impl_trait(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: unused array of boxed `T` trait objects in tuple element 1 that must be used --> $DIR/must_use-array.rs:43:5 @@ -38,7 +38,7 @@ error: unused array of arrays of arrays of `S` that must be used --> $DIR/must_use-array.rs:45:5 | LL | array_of_arrays_of_arrays(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr b/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr index f5199f43c74..ef738708d5f 100644 --- a/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr +++ b/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr @@ -2,7 +2,7 @@ error: unused implementer of `Iterator` that must be used --> $DIR/must_use-in-stdlib-traits.rs:42:4 | LL | iterator(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^ | = note: iterators are lazy and do nothing unless consumed note: the lint level is defined here @@ -15,7 +15,7 @@ error: unused implementer of `Future` that must be used --> $DIR/must_use-in-stdlib-traits.rs:43:4 | LL | future(); - | ^^^^^^^^^ + | ^^^^^^^^ | = note: futures do nothing unless you `.await` or poll them @@ -23,7 +23,7 @@ error: unused implementer of `FnOnce` that must be used --> $DIR/must_use-in-stdlib-traits.rs:44:4 | LL | square_fn_once(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called @@ -31,7 +31,7 @@ error: unused implementer of `FnMut` that must be used --> $DIR/must_use-in-stdlib-traits.rs:45:4 | LL | square_fn_mut(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called @@ -39,7 +39,7 @@ error: unused implementer of `Fn` that must be used --> $DIR/must_use-in-stdlib-traits.rs:46:4 | LL | square_fn(); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called diff --git a/src/test/ui/lint/unused/must_use-trait.stderr b/src/test/ui/lint/unused/must_use-trait.stderr index a42eb884178..2f549648483 100644 --- a/src/test/ui/lint/unused/must_use-trait.stderr +++ b/src/test/ui/lint/unused/must_use-trait.stderr @@ -2,7 +2,7 @@ error: unused implementer of `Critical` that must be used --> $DIR/must_use-trait.rs:33:5 | LL | get_critical(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/must_use-trait.rs:1:9 @@ -14,13 +14,13 @@ error: unused boxed `Critical` trait object that must be used --> $DIR/must_use-trait.rs:34:5 | LL | get_boxed_critical(); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: unused boxed boxed `Critical` trait object that must be used --> $DIR/must_use-trait.rs:35:5 | LL | get_nested_boxed_critical(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unused boxed `Critical` trait object in tuple element 1 that must be used --> $DIR/must_use-trait.rs:37:5 diff --git a/src/test/ui/lint/unused/must_use-unit.stderr b/src/test/ui/lint/unused/must_use-unit.stderr index 7f25a193508..9fcbc5074ea 100644 --- a/src/test/ui/lint/unused/must_use-unit.stderr +++ b/src/test/ui/lint/unused/must_use-unit.stderr @@ -2,7 +2,7 @@ error: unused return value of `foo` that must be used --> $DIR/must_use-unit.rs:13:5 | LL | foo(); - | ^^^^^^ + | ^^^^^ | note: the lint level is defined here --> $DIR/must_use-unit.rs:2:9 @@ -14,7 +14,7 @@ error: unused return value of `bar` that must be used --> $DIR/must_use-unit.rs:15:5 | LL | bar(); - | ^^^^^^ + | ^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/unused/unused-async.rs b/src/test/ui/lint/unused/unused-async.rs index 7d17af11573..4be93aa155a 100644 --- a/src/test/ui/lint/unused/unused-async.rs +++ b/src/test/ui/lint/unused/unused-async.rs @@ -1,24 +1,43 @@ // edition:2018 -// run-pass -#![allow(dead_code)] +#![deny(unused_must_use)] + #[must_use] -//~^ WARNING `must_use` -async fn test() -> i32 { +async fn foo() -> i32 { 1 } +#[must_use] +fn bar() -> impl std::future::Future<Output=i32> { + async { + 42 + } +} + +async fn baz() -> i32 { + 0 +} struct Wowee {} impl Wowee { #[must_use] - //~^ WARNING `must_use` async fn test_method() -> i32 { 1 } } +async fn test() { + foo(); //~ ERROR unused return value of `foo` that must be used + //~^ ERROR unused implementer of `Future` that must be used + foo().await; //~ ERROR unused output of future returned by `foo` that must be used + bar(); //~ ERROR unused return value of `bar` that must be used + //~^ ERROR unused implementer of `Future` that must be used + bar().await; //~ ERROR unused output of future returned by `bar` that must be used + baz(); //~ ERROR unused implementer of `Future` that must be used + baz().await; // ok +} + /* FIXME(guswynn) update this test when async-fn-in-traits works trait Doer { #[must_use] diff --git a/src/test/ui/lint/unused/unused-async.stderr b/src/test/ui/lint/unused/unused-async.stderr index 6bbc9e2bf00..4bcb26dc165 100644 --- a/src/test/ui/lint/unused/unused-async.stderr +++ b/src/test/ui/lint/unused/unused-async.stderr @@ -1,26 +1,55 @@ -warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within - --> $DIR/unused-async.rs:5:1 - | -LL | #[must_use] - | ^^^^^^^^^^^ -LL | -LL | / async fn test() -> i32 { -LL | | 1 -LL | | } - | |_- this attribute does nothing, the `Future`s returned by async functions are already `must_use` - | - = note: `#[warn(unused_attributes)]` on by default - -warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within - --> $DIR/unused-async.rs:15:5 - | -LL | #[must_use] - | ^^^^^^^^^^^ -LL | -LL | / async fn test_method() -> i32 { -LL | | 1 -LL | | } - | |_____- this attribute does nothing, the `Future`s returned by async functions are already `must_use` - -warning: 2 warnings emitted +error: unused implementer of `Future` that must be used + --> $DIR/unused-async.rs:31:5 + | +LL | foo(); + | ^^^^^ + | + = note: futures do nothing unless you `.await` or poll them +note: the lint level is defined here + --> $DIR/unused-async.rs:2:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused return value of `foo` that must be used + --> $DIR/unused-async.rs:31:5 + | +LL | foo(); + | ^^^^^ + +error: unused output of future returned by `foo` that must be used + --> $DIR/unused-async.rs:33:5 + | +LL | foo().await; + | ^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/unused-async.rs:34:5 + | +LL | bar(); + | ^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: unused return value of `bar` that must be used + --> $DIR/unused-async.rs:34:5 + | +LL | bar(); + | ^^^^^ + +error: unused output of future returned by `bar` that must be used + --> $DIR/unused-async.rs:36:5 + | +LL | bar().await; + | ^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/unused-async.rs:37:5 + | +LL | baz(); + | ^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: aborting due to 7 previous errors diff --git a/src/test/ui/lint/unused/unused-closure.stderr b/src/test/ui/lint/unused/unused-closure.stderr index 4362abd2037..c3a82402e0a 100644 --- a/src/test/ui/lint/unused/unused-closure.stderr +++ b/src/test/ui/lint/unused/unused-closure.stderr @@ -4,7 +4,7 @@ error: unused closure that must be used LL | / || { LL | | println!("Hello!"); LL | | }; - | |______^ + | |_____^ | = note: closures are lazy and do nothing unless called note: the lint level is defined here @@ -17,7 +17,7 @@ error: unused implementer of `Future` that must be used --> $DIR/unused-closure.rs:13:5 | LL | async {}; - | ^^^^^^^^^ + | ^^^^^^^^ | = note: futures do nothing unless you `.await` or poll them @@ -25,7 +25,7 @@ error: unused closure that must be used --> $DIR/unused-closure.rs:14:5 | LL | || async {}; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called @@ -33,7 +33,7 @@ error: unused closure that must be used --> $DIR/unused-closure.rs:15:5 | LL | async || {}; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called @@ -41,7 +41,7 @@ error: unused array of boxed arrays of closures that must be used --> $DIR/unused-closure.rs:18:5 | LL | [Box::new([|| {}; 10]); 1]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called @@ -49,7 +49,7 @@ error: unused closure that must be used --> $DIR/unused-closure.rs:20:5 | LL | vec![|| "a"].pop().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called @@ -57,7 +57,7 @@ error: unused closure that must be used --> $DIR/unused-closure.rs:23:9 | LL | || true; - | ^^^^^^^^ + | ^^^^^^^ | = note: closures are lazy and do nothing unless called diff --git a/src/test/ui/lint/unused/unused-result.stderr b/src/test/ui/lint/unused/unused-result.stderr index 087e06341cd..4e1ba1fd959 100644 --- a/src/test/ui/lint/unused/unused-result.stderr +++ b/src/test/ui/lint/unused/unused-result.stderr @@ -2,7 +2,7 @@ error: unused `MustUse` that must be used --> $DIR/unused-result.rs:21:5 | LL | foo::<MustUse>(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/unused-result.rs:2:25 @@ -14,7 +14,7 @@ error: unused `MustUseMsg` that must be used --> $DIR/unused-result.rs:22:5 | LL | foo::<MustUseMsg>(); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = note: some message @@ -34,13 +34,13 @@ error: unused `MustUse` that must be used --> $DIR/unused-result.rs:35:5 | LL | foo::<MustUse>(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: unused `MustUseMsg` that must be used --> $DIR/unused-result.rs:36:5 | LL | foo::<MustUseMsg>(); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = note: some message diff --git a/src/test/ui/lint/unused/unused-supertrait.stderr b/src/test/ui/lint/unused/unused-supertrait.stderr index d2f8c007848..cb45add9c2b 100644 --- a/src/test/ui/lint/unused/unused-supertrait.stderr +++ b/src/test/ui/lint/unused/unused-supertrait.stderr @@ -2,7 +2,7 @@ error: unused implementer of `Iterator` that must be used --> $DIR/unused-supertrait.rs:9:5 | LL | it(); - | ^^^^^ + | ^^^^ | = note: iterators are lazy and do nothing unless consumed note: the lint level is defined here diff --git a/src/test/ui/lint/unused/unused_attributes-must_use.stderr b/src/test/ui/lint/unused/unused_attributes-must_use.stderr index ce959ddbc46..0f699429e02 100644 --- a/src/test/ui/lint/unused/unused_attributes-must_use.stderr +++ b/src/test/ui/lint/unused/unused_attributes-must_use.stderr @@ -139,7 +139,7 @@ error: unused `X` that must be used --> $DIR/unused_attributes-must_use.rs:103:5 | LL | X; - | ^^ + | ^ | note: the lint level is defined here --> $DIR/unused_attributes-must_use.rs:2:28 @@ -151,37 +151,37 @@ error: unused `Y` that must be used --> $DIR/unused_attributes-must_use.rs:104:5 | LL | Y::Z; - | ^^^^^ + | ^^^^ error: unused `U` that must be used --> $DIR/unused_attributes-must_use.rs:105:5 | LL | U { unit: () }; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: unused return value of `U::method` that must be used --> $DIR/unused_attributes-must_use.rs:106:5 | LL | U::method(); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: unused return value of `foo` that must be used --> $DIR/unused_attributes-must_use.rs:107:5 | LL | foo(); - | ^^^^^^ + | ^^^^^ error: unused return value of `foreign_foo` that must be used --> $DIR/unused_attributes-must_use.rs:110:9 | LL | foreign_foo(); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: unused return value of `Use::get_four` that must be used --> $DIR/unused_attributes-must_use.rs:118:5 | LL | ().get_four(); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 28 previous errors diff --git a/src/test/ui/attr-from-macro.rs b/src/test/ui/macros/attr-from-macro.rs index bb3a5c94d41..bb3a5c94d41 100644 --- a/src/test/ui/attr-from-macro.rs +++ b/src/test/ui/macros/attr-from-macro.rs diff --git a/src/test/ui/auxiliary/attr-from-macro.rs b/src/test/ui/macros/auxiliary/attr-from-macro.rs index 9b388675c80..9b388675c80 100644 --- a/src/test/ui/auxiliary/attr-from-macro.rs +++ b/src/test/ui/macros/auxiliary/attr-from-macro.rs diff --git a/src/test/ui/issues/issue-12552.rs b/src/test/ui/match/issue-12552.rs index b7f71dd1ce3..b7f71dd1ce3 100644 --- a/src/test/ui/issues/issue-12552.rs +++ b/src/test/ui/match/issue-12552.rs diff --git a/src/test/ui/issues/issue-12552.stderr b/src/test/ui/match/issue-12552.stderr index 4b027eba2c2..4b027eba2c2 100644 --- a/src/test/ui/issues/issue-12552.stderr +++ b/src/test/ui/match/issue-12552.stderr diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs index 8dbe3472ea8..307104e47a1 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs @@ -1,8 +1,8 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures,tuple_trait)] use std::ops::FnMut; -fn to_fn_mut<A, F: FnMut<A>>(f: F) -> F { f } +fn to_fn_mut<A:std::marker::Tuple, F:FnMut<A>>(f: F) -> F { f } fn call_it<F: FnMut(isize, isize) -> isize>(y: isize, mut f: F) -> isize { //~^ NOTE required by this bound in `call_it` diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs index 76b7aab542d..490d91ac118 100644 --- a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs +++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs @@ -1,6 +1,6 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn<A,F:Fn<A>>(f: F) -> F { f } +fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f } fn test(_x: Box<usize>) {} diff --git a/src/test/ui/nll/borrowed-temporary-error.stderr b/src/test/ui/nll/borrowed-temporary-error.stderr index 2c6bd92641f..89781d96fab 100644 --- a/src/test/ui/nll/borrowed-temporary-error.stderr +++ b/src/test/ui/nll/borrowed-temporary-error.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/borrowed-temporary-error.rs:8:10 | LL | &(v,) - | ^^^^ creates a temporary which is freed while still in use + | ^^^^ creates a temporary value which is freed while still in use LL | LL | }); | - temporary value is freed at the end of this statement diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs index 3bdb5433948..cda781d8e26 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs @@ -30,8 +30,6 @@ where T: Trait<'a>, { establish_relationships(value, |value| { - //~^ ERROR the parameter type `T` may not live long enough - // This function call requires that // // (a) T: Trait<'a> @@ -43,6 +41,7 @@ where // The latter does not hold. require(value); + //~^ ERROR the parameter type `T` may not live long enough }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index 750b08bbe85..038a5e11f88 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -23,17 +23,10 @@ LL | | T: Trait<'a>, = note: defining type: supply::<'_#1r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/propagate-from-trait-match.rs:32:36 + --> $DIR/propagate-from-trait-match.rs:43:9 | -LL | establish_relationships(value, |value| { - | ____________________________________^ -LL | | -LL | | -LL | | // This function call requires that -... | -LL | | require(value); -LL | | }); - | |_____^ ...so that the type `T` will meet its required lifetime bounds +LL | require(value); + | ^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/issue-48623-generator.stderr b/src/test/ui/nll/issue-48623-generator.stderr index 1b35165db45..bfdfca21004 100644 --- a/src/test/ui/nll/issue-48623-generator.stderr +++ b/src/test/ui/nll/issue-48623-generator.stderr @@ -2,7 +2,7 @@ warning: unused generator that must be used --> $DIR/issue-48623-generator.rs:15:5 | LL | move || { d; yield; &mut *r }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: generators are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/src/test/ui/issues/issue-54943.rs b/src/test/ui/nll/issue-54943.rs index 85722300bf0..85722300bf0 100644 --- a/src/test/ui/issues/issue-54943.rs +++ b/src/test/ui/nll/issue-54943.rs diff --git a/src/test/ui/issues/issue-54943.stderr b/src/test/ui/nll/issue-54943.stderr index 59be0f983b9..59be0f983b9 100644 --- a/src/test/ui/issues/issue-54943.stderr +++ b/src/test/ui/nll/issue-54943.stderr diff --git a/src/test/ui/nll/issue-57265-return-type-wf-check.stderr b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr index 20add62b91d..bb45575fa64 100644 --- a/src/test/ui/nll/issue-57265-return-type-wf-check.stderr +++ b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let (_, z) = foo(&"hello".to_string()); | -----^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | argument requires that borrow lasts for `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr index 6def5602e70..d8b26f0b017 100644 --- a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr +++ b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr @@ -35,10 +35,10 @@ LL | || { None::<&'a &'b ()>; }; = help: consider adding the following bound: `'b: 'a` error[E0309]: the parameter type `T` may not live long enough - --> $DIR/issue-98589-closures-relate-named-regions.rs:26:5 + --> $DIR/issue-98589-closures-relate-named-regions.rs:26:10 | LL | || { None::<&'a T>; }; - | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -46,10 +46,10 @@ LL | fn test_early_type<'a: 'a, T: 'a>() { | ++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/issue-98589-closures-relate-named-regions.rs:32:5 + --> $DIR/issue-98589-closures-relate-named-regions.rs:32:10 | LL | || { None::<&'a T>; }; - | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/issue-98693.rs b/src/test/ui/nll/issue-98693.rs index 18e6ec63046..7a325e2e998 100644 --- a/src/test/ui/nll/issue-98693.rs +++ b/src/test/ui/nll/issue-98693.rs @@ -13,8 +13,8 @@ where fn test<T>() { || { - //~^ ERROR the parameter type `T` may not live long enough assert_static::<T>(); + //~^ ERROR the parameter type `T` may not live long enough }; } diff --git a/src/test/ui/nll/issue-98693.stderr b/src/test/ui/nll/issue-98693.stderr index 31689620c64..15ca38aa25d 100644 --- a/src/test/ui/nll/issue-98693.stderr +++ b/src/test/ui/nll/issue-98693.stderr @@ -1,11 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/issue-98693.rs:15:5 + --> $DIR/issue-98693.rs:16:9 | -LL | / || { -LL | | -LL | | assert_static::<T>(); -LL | | }; - | |_____^ ...so that the type `T` will meet its required lifetime bounds +LL | assert_static::<T>(); + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr index 3b9b2956c51..d949e29b2b8 100644 --- a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr +++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr @@ -1,8 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/projection-implied-bounds.rs:30:18 + --> $DIR/projection-implied-bounds.rs:30:36 | LL | twice(value, |value_ref, item| invoke2(value_ref, item)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr index ee1f7b64bb2..4933b934868 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -23,10 +23,10 @@ LL | | T: Iterator, = note: defining type: no_region::<'_#1r, T> error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough - --> $DIR/projection-no-regions-closure.rs:25:23 + --> $DIR/projection-no-regions-closure.rs:25:31 | LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`... = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds @@ -80,10 +80,10 @@ LL | | T: 'b + Iterator, = note: defining type: wrong_region::<'_#1r, '_#2r, T> error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough - --> $DIR/projection-no-regions-closure.rs:42:23 + --> $DIR/projection-no-regions-closure.rs:42:31 | LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`... = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index 4e57dfad794..dbda04c42c5 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -25,10 +25,10 @@ LL | | T: Anything<'b>, = note: defining type: no_relationships_late::<'_#1r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:45:29 + --> $DIR/projection-one-region-closure.rs:45:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -75,10 +75,10 @@ LL | | 'a: 'a, = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:56:29 + --> $DIR/projection-one-region-closure.rs:56:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 0195a693e5f..90f04914286 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -24,10 +24,10 @@ LL | | T: Anything<'b, 'c>, = note: defining type: no_relationships_late::<'_#1r, '_#2r, T> error[E0309]: the associated type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:38:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:38:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`... = note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds @@ -58,10 +58,10 @@ LL | | 'a: 'a, = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T> error[E0309]: the associated type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:48:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`... = note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds @@ -167,7 +167,7 @@ LL | | T: Anything<'b, 'b>, = note: defining type: two_regions::<'_#1r, T> error: lifetime may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:87:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:87:5 | LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -175,9 +175,12 @@ LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Cell<&'_#8r ()>`, which makes the generic argument `&'_#8r ()` invariant + = note: the struct `Cell<T>` is invariant over the parameter `T` + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:97:29 diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 61c7d2550ca..f316a551cff 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -44,10 +44,10 @@ LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { = note: defining type: generic_fail::<T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:31 | LL | twice(cell, value, |a, b| invoke(a, b)); - | ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index 50d9e3aabe2..35979c8bf51 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -23,10 +23,10 @@ LL | | T: Debug, = note: defining type: no_region::<'_#1r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23 + --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:27 | LL | with_signature(x, |y| y) - | ^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs index d7702def32c..b8028761050 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs @@ -25,13 +25,12 @@ where #[rustc_regions] fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { with_signature(a, b, |x, y| { - //~^ ERROR the parameter type `T` may not live long enough - // // See `correct_region`, which explains the point of this // test. The only difference is that, in the case of this // function, there is no where clause *anywhere*, and hence we // get an error (but reported by the closure creator). require(&x, &y) + //~^ ERROR the parameter type `T` may not live long enough }) } @@ -62,9 +61,9 @@ where T: 'b, { with_signature(a, b, |x, y| { - //~^ ERROR the parameter type `T` may not live long enough // See `correct_region` require(&x, &y) + //~^ ERROR the parameter type `T` may not live long enough }) } diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index 14c55e32a3e..4c97db58c6c 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -22,17 +22,10 @@ LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { = note: defining type: no_region::<T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:32:9 | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | -LL | | // -LL | | // See `correct_region`, which explains the point of this -... | -LL | | require(&x, &y) -LL | | }) - | |_____^ ...so that the type `T` will meet its required lifetime bounds +LL | require(&x, &y) + | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -40,7 +33,7 @@ LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) { | ++++ note: external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:42:26 | LL | with_signature(a, b, |x, y| { | ^^^^^^ @@ -54,7 +47,7 @@ LL | with_signature(a, b, |x, y| { = note: where T: '_#2r note: no external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:39:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:1 | LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T) LL | | where @@ -64,7 +57,7 @@ LL | | T: 'a, = note: defining type: correct_region::<'_#1r, T> note: external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:63:26 | LL | with_signature(a, b, |x, y| { | ^^^^^^ @@ -79,7 +72,7 @@ LL | with_signature(a, b, |x, y| { = note: where T: '_#2r note: no external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:60:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:59:1 | LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) LL | | where @@ -89,15 +82,10 @@ LL | | T: 'b, = note: defining type: wrong_region::<'_#1r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:65:9 | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | -LL | | // See `correct_region` -LL | | require(&x, &y) -LL | | }) - | |_____^ ...so that the type `T` will meet its required lifetime bounds +LL | require(&x, &y) + | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -105,7 +93,7 @@ LL | T: 'b + 'a, | ++++ note: external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26 | LL | with_signature(a, b, |x, y| { | ^^^^^^ @@ -119,7 +107,7 @@ LL | with_signature(a, b, |x, y| { = note: where T: '_#3r note: no external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1 | LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) LL | | where diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr index 60d6e6db363..de6f8f80fe2 100644 --- a/src/test/ui/nll/user-annotations/patterns.stderr +++ b/src/test/ui/nll/user-annotations/patterns.stderr @@ -76,7 +76,7 @@ error[E0716]: temporary value dropped while borrowed LL | let _: Vec<&'static String> = vec![&String::new()]; | -------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -85,7 +85,7 @@ error[E0716]: temporary value dropped while borrowed LL | let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44); | ------------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -94,7 +94,7 @@ error[E0716]: temporary value dropped while borrowed LL | let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44); | ------------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error[E0597]: `x` does not live long enough diff --git a/src/test/ui/overloaded/overloaded-calls-nontuple.rs b/src/test/ui/overloaded/overloaded-calls-nontuple.rs index 07d44ff82b1..32a3b93e0a1 100644 --- a/src/test/ui/overloaded/overloaded-calls-nontuple.rs +++ b/src/test/ui/overloaded/overloaded-calls-nontuple.rs @@ -8,22 +8,23 @@ struct S { } impl FnMut<isize> for S { + //~^ ERROR type parameter to bare `FnMut` trait must be a tuple extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument self.x + self.y + z } - //~^^^ ERROR functions with the "rust-call" ABI must take a single non-self argument } impl FnOnce<isize> for S { + //~^ ERROR type parameter to bare `FnOnce` trait must be a tuple type Output = isize; - extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) } - //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument + extern "rust-call" fn call_once(mut self, z: isize) -> isize { + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument + self.call_mut(z) + } } fn main() { - let mut s = S { - x: 1, - y: 2, - }; - drop(s(3)) //~ ERROR cannot use call notation + let mut s = S { x: 1, y: 2 }; + drop(s(3)) } diff --git a/src/test/ui/overloaded/overloaded-calls-nontuple.stderr b/src/test/ui/overloaded/overloaded-calls-nontuple.stderr index 8f299bc9434..794535aeb11 100644 --- a/src/test/ui/overloaded/overloaded-calls-nontuple.stderr +++ b/src/test/ui/overloaded/overloaded-calls-nontuple.stderr @@ -1,21 +1,40 @@ -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/overloaded-calls-nontuple.rs:11:5 +error[E0059]: type parameter to bare `FnMut` trait must be a tuple + --> $DIR/overloaded-calls-nontuple.rs:10:6 | -LL | extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl FnMut<isize> for S { + | ^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + | +note: required by a bound in `FnMut` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait FnMut<Args: Tuple>: FnOnce<Args> { + | ^^^^^ required by this bound in `FnMut` + +error[E0059]: type parameter to bare `FnOnce` trait must be a tuple + --> $DIR/overloaded-calls-nontuple.rs:18:6 + | +LL | impl FnOnce<isize> for S { + | ^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + | +note: required by a bound in `FnOnce` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait FnOnce<Args: Tuple> { + | ^^^^^ required by this bound in `FnOnce` -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/overloaded-calls-nontuple.rs:19:5 +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/overloaded-calls-nontuple.rs:12:5 | -LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` -error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit - --> $DIR/overloaded-calls-nontuple.rs:28:10 +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/overloaded-calls-nontuple.rs:21:5 | -LL | drop(s(3)) - | ^^^^ +LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0059`. +Some errors have detailed explanations: E0059, E0277. +For more information about an error, try `rustc --explain E0059`. diff --git a/src/test/ui/parser/byte-literals.rs b/src/test/ui/parser/byte-literals.rs index 05a510b24a7..896dc1a1a5f 100644 --- a/src/test/ui/parser/byte-literals.rs +++ b/src/test/ui/parser/byte-literals.rs @@ -7,6 +7,6 @@ pub fn main() { b'\x0Z'; //~ ERROR invalid character in numeric character escape: `Z` b' '; //~ ERROR byte constant must be escaped b'''; //~ ERROR byte constant must be escaped - b'é'; //~ ERROR non-ASCII character in byte constant + b'é'; //~ ERROR non-ASCII character in byte literal b'a //~ ERROR unterminated byte constant [E0763] } diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr index c3d00061630..efa55ae05bd 100644 --- a/src/test/ui/parser/byte-literals.stderr +++ b/src/test/ui/parser/byte-literals.stderr @@ -32,11 +32,11 @@ error: byte constant must be escaped: `'` LL | b'''; | ^ help: escape the character: `\'` -error: non-ASCII character in byte constant +error: non-ASCII character in byte literal --> $DIR/byte-literals.rs:10:7 | LL | b'é'; - | ^ byte constant must be ASCII + | ^ must be ASCII | help: if you meant to use the unicode code point for 'é', use a \xHH escape | diff --git a/src/test/ui/parser/byte-string-literals.rs b/src/test/ui/parser/byte-string-literals.rs index b1f11024a7b..30a4f50c4e4 100644 --- a/src/test/ui/parser/byte-string-literals.rs +++ b/src/test/ui/parser/byte-string-literals.rs @@ -3,7 +3,7 @@ static FOO: &'static [u8] = b"\f"; //~ ERROR unknown byte escape pub fn main() { b"\f"; //~ ERROR unknown byte escape b"\x0Z"; //~ ERROR invalid character in numeric character escape: `Z` - b"é"; //~ ERROR non-ASCII character in byte constant - br##"é"##; //~ ERROR raw byte string must be ASCII + b"é"; //~ ERROR non-ASCII character in byte string literal + br##"é"##; //~ ERROR non-ASCII character in raw byte string literal b"a //~ ERROR unterminated double quote byte string } diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr index 3b8b3692e05..5b96cc3d18a 100644 --- a/src/test/ui/parser/byte-string-literals.stderr +++ b/src/test/ui/parser/byte-string-literals.stderr @@ -20,18 +20,18 @@ error: invalid character in numeric character escape: `Z` LL | b"\x0Z"; | ^ invalid character in numeric character escape -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/byte-string-literals.rs:6:7 | LL | b"é"; - | ^ byte constant must be ASCII + | ^ must be ASCII | help: if you meant to use the unicode code point for 'é', use a \xHH escape | LL | b"\xE9"; | ~~~~ -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/byte-string-literals.rs:7:10 | LL | br##"é"##; diff --git a/src/test/ui/parser/issue-102806.rs b/src/test/ui/parser/issue-102806.rs new file mode 100644 index 00000000000..ba297bdc967 --- /dev/null +++ b/src/test/ui/parser/issue-102806.rs @@ -0,0 +1,25 @@ +#![allow(dead_code)] + +#[derive(Default)] +struct V3 { + x: f32, + y: f32, + z: f32, +} + +fn pz(v: V3) { + let _ = V3 { z: 0.0, ...v}; + //~^ ERROR expected `..` + + let _ = V3 { z: 0.0, ...Default::default() }; + //~^ ERROR expected `..` + + let _ = V3 { z: 0.0, ... }; + //~^ expected identifier + //~| ERROR missing fields `x` and `y` in initializer of `V3` + + let V3 { z: val, ... } = v; + //~^ ERROR expected field pattern +} + +fn main() {} diff --git a/src/test/ui/parser/issue-102806.stderr b/src/test/ui/parser/issue-102806.stderr new file mode 100644 index 00000000000..6872b8bc0af --- /dev/null +++ b/src/test/ui/parser/issue-102806.stderr @@ -0,0 +1,45 @@ +error: expected `..`, found `...` + --> $DIR/issue-102806.rs:11:26 + | +LL | let _ = V3 { z: 0.0, ...v}; + | ^^^ + | +help: use `..` to fill in the rest of the fields + | +LL | let _ = V3 { z: 0.0, ..v}; + | ~~ + +error: expected `..`, found `...` + --> $DIR/issue-102806.rs:14:26 + | +LL | let _ = V3 { z: 0.0, ...Default::default() }; + | ^^^ + | +help: use `..` to fill in the rest of the fields + | +LL | let _ = V3 { z: 0.0, ..Default::default() }; + | ~~ + +error: expected identifier, found `...` + --> $DIR/issue-102806.rs:17:26 + | +LL | let _ = V3 { z: 0.0, ... }; + | -- ^^^ expected identifier + | | + | while parsing this struct + +error: expected field pattern, found `...` + --> $DIR/issue-102806.rs:21:22 + | +LL | let V3 { z: val, ... } = v; + | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + +error[E0063]: missing fields `x` and `y` in initializer of `V3` + --> $DIR/issue-102806.rs:17:13 + | +LL | let _ = V3 { z: 0.0, ... }; + | ^^ missing `x` and `y` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/src/test/ui/parser/issue-103451.rs b/src/test/ui/parser/issue-103451.rs new file mode 100644 index 00000000000..1fdb0014881 --- /dev/null +++ b/src/test/ui/parser/issue-103451.rs @@ -0,0 +1,5 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected value, found struct `R` +struct R { } +struct S { + x: [u8; R diff --git a/src/test/ui/parser/issue-103451.stderr b/src/test/ui/parser/issue-103451.stderr new file mode 100644 index 00000000000..eb3c92fb43d --- /dev/null +++ b/src/test/ui/parser/issue-103451.stderr @@ -0,0 +1,32 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-103451.rs:5:15 + | +LL | struct S { + | - unclosed delimiter +LL | x: [u8; R + | - ^ + | | + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-103451.rs:5:15 + | +LL | struct S { + | - unclosed delimiter +LL | x: [u8; R + | - ^ + | | + | unclosed delimiter + +error[E0423]: expected value, found struct `R` + --> $DIR/issue-103451.rs:5:13 + | +LL | struct R { } + | ------------ `R` defined here +LL | struct S { +LL | x: [u8; R + | ^ help: use struct literal syntax instead: `R {}` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/parser/issue-103748-ICE-wrong-braces.rs b/src/test/ui/parser/issue-103748-ICE-wrong-braces.rs new file mode 100644 index 00000000000..8012cb652bd --- /dev/null +++ b/src/test/ui/parser/issue-103748-ICE-wrong-braces.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] + +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 recursive type `Apple` has infinite size [E0072] diff --git a/src/test/ui/parser/issue-103748-ICE-wrong-braces.stderr b/src/test/ui/parser/issue-103748-ICE-wrong-braces.stderr new file mode 100644 index 00000000000..b0d8b03ae08 --- /dev/null +++ b/src/test/ui/parser/issue-103748-ICE-wrong-braces.stderr @@ -0,0 +1,51 @@ +error: invalid `?` in type + --> $DIR/issue-103748-ICE-wrong-braces.rs:3:36 + | +LL | struct Apple((Apple, Option(Banana ? Citron))); + | ^ `?` is only allowed on expressions, not types + | +help: if you meant to express that the type might not contain a value, use the `Option` wrapper type + | +LL | struct Apple((Apple, Option(Option<Banana > Citron))); + | +++++++ ~ + +error: expected one of `)` or `,`, found `Citron` + --> $DIR/issue-103748-ICE-wrong-braces.rs:3:38 + | +LL | struct Apple((Apple, Option(Banana ? Citron))); + | -^^^^^^ expected one of `)` or `,` + | | + | help: missing `,` + +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[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>)); + | ~ ~ + +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<Apple>, 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/src/test/ui/parser/item-kw-case-mismatch.fixed b/src/test/ui/parser/item-kw-case-mismatch.fixed new file mode 100644 index 00000000000..1794268f260 --- /dev/null +++ b/src/test/ui/parser/item-kw-case-mismatch.fixed @@ -0,0 +1,34 @@ +// run-rustfix +// edition:2018 +#![allow(unused_imports)] + +fn main() {} + +use std::ptr::read; //~ ERROR keyword `use` is written in a wrong case +use std::ptr::write; //~ ERROR keyword `use` is written in a wrong case + +async fn _a() {} +//~^ ERROR keyword `fn` is written in a wrong case + +fn _b() {} +//~^ ERROR keyword `fn` is written in a wrong case + +async fn _c() {} +//~^ ERROR keyword `async` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case + +async fn _d() {} +//~^ ERROR keyword `async` is written in a wrong case + +const unsafe fn _e() {} +//~^ ERROR keyword `const` is written in a wrong case +//~| ERROR keyword `unsafe` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case + +unsafe extern fn _f() {} +//~^ ERROR keyword `unsafe` is written in a wrong case +//~| ERROR keyword `extern` is written in a wrong case + +extern "C" fn _g() {} +//~^ ERROR keyword `extern` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case diff --git a/src/test/ui/parser/item-kw-case-mismatch.rs b/src/test/ui/parser/item-kw-case-mismatch.rs new file mode 100644 index 00000000000..ac8390efdb9 --- /dev/null +++ b/src/test/ui/parser/item-kw-case-mismatch.rs @@ -0,0 +1,34 @@ +// run-rustfix +// edition:2018 +#![allow(unused_imports)] + +fn main() {} + +Use std::ptr::read; //~ ERROR keyword `use` is written in a wrong case +USE std::ptr::write; //~ ERROR keyword `use` is written in a wrong case + +async Fn _a() {} +//~^ ERROR keyword `fn` is written in a wrong case + +Fn _b() {} +//~^ ERROR keyword `fn` is written in a wrong case + +aSYNC fN _c() {} +//~^ ERROR keyword `async` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case + +Async fn _d() {} +//~^ ERROR keyword `async` is written in a wrong case + +CONST UNSAFE FN _e() {} +//~^ ERROR keyword `const` is written in a wrong case +//~| ERROR keyword `unsafe` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case + +unSAFE EXTern fn _f() {} +//~^ ERROR keyword `unsafe` is written in a wrong case +//~| ERROR keyword `extern` is written in a wrong case + +EXTERN "C" FN _g() {} +//~^ ERROR keyword `extern` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case diff --git a/src/test/ui/parser/item-kw-case-mismatch.stderr b/src/test/ui/parser/item-kw-case-mismatch.stderr new file mode 100644 index 00000000000..e66dae825f9 --- /dev/null +++ b/src/test/ui/parser/item-kw-case-mismatch.stderr @@ -0,0 +1,86 @@ +error: keyword `use` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:7:1 + | +LL | Use std::ptr::read; + | ^^^ help: write it in the correct case (notice the capitalization): `use` + +error: keyword `use` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:8:1 + | +LL | USE std::ptr::write; + | ^^^ help: write it in the correct case: `use` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:10:7 + | +LL | async Fn _a() {} + | ^^ help: write it in the correct case (notice the capitalization): `fn` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:13:1 + | +LL | Fn _b() {} + | ^^ help: write it in the correct case (notice the capitalization): `fn` + +error: keyword `async` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:16:1 + | +LL | aSYNC fN _c() {} + | ^^^^^ help: write it in the correct case: `async` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:16:7 + | +LL | aSYNC fN _c() {} + | ^^ help: write it in the correct case: `fn` + +error: keyword `async` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:20:1 + | +LL | Async fn _d() {} + | ^^^^^ help: write it in the correct case: `async` + +error: keyword `const` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:23:1 + | +LL | CONST UNSAFE FN _e() {} + | ^^^^^ help: write it in the correct case: `const` + +error: keyword `unsafe` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:23:7 + | +LL | CONST UNSAFE FN _e() {} + | ^^^^^^ help: write it in the correct case: `unsafe` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:23:14 + | +LL | CONST UNSAFE FN _e() {} + | ^^ help: write it in the correct case: `fn` + +error: keyword `unsafe` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:28:1 + | +LL | unSAFE EXTern fn _f() {} + | ^^^^^^ help: write it in the correct case: `unsafe` + +error: keyword `extern` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:28:8 + | +LL | unSAFE EXTern fn _f() {} + | ^^^^^^ help: write it in the correct case: `extern` + +error: keyword `extern` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:32:1 + | +LL | EXTERN "C" FN _g() {} + | ^^^^^^ help: write it in the correct case: `extern` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:32:12 + | +LL | EXTERN "C" FN _g() {} + | ^^ help: write it in the correct case: `fn` + +error: aborting due to 14 previous errors + diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr index 28196c7ce2d..546ad84eeee 100644 --- a/src/test/ui/parser/kw-in-trait-bounds.stderr +++ b/src/test/ui/parser/kw-in-trait-bounds.stderr @@ -94,8 +94,8 @@ LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn<Args>: FnMut<Args> { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | -------------------------------------- similarly named trait `Fn` defined here error[E0405]: cannot find trait `r#fn` in this scope --> $DIR/kw-in-trait-bounds.rs:17:4 @@ -105,8 +105,8 @@ LL | G: fn(), | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn<Args>: FnMut<Args> { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | -------------------------------------- similarly named trait `Fn` defined here error[E0405]: cannot find trait `r#fn` in this scope --> $DIR/kw-in-trait-bounds.rs:3:27 @@ -116,8 +116,8 @@ LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn<Args>: FnMut<Args> { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | -------------------------------------- similarly named trait `Fn` defined here error[E0405]: cannot find trait `r#fn` in this scope --> $DIR/kw-in-trait-bounds.rs:3:41 @@ -127,8 +127,8 @@ LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn<Args>: FnMut<Args> { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | -------------------------------------- similarly named trait `Fn` defined here error[E0405]: cannot find trait `r#struct` in this scope --> $DIR/kw-in-trait-bounds.rs:24:10 diff --git a/src/test/ui/parser/label-after-block-like.rs b/src/test/ui/parser/label-after-block-like.rs new file mode 100644 index 00000000000..55f3f8f9f5f --- /dev/null +++ b/src/test/ui/parser/label-after-block-like.rs @@ -0,0 +1,43 @@ +fn a() { + if let () = () 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn b() { + if true 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn c() { + loop 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn d() { + while true 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn e() { + while let () = () 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn f() { + for _ in 0..0 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn g() { + unsafe 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn main() {} diff --git a/src/test/ui/parser/label-after-block-like.stderr b/src/test/ui/parser/label-after-block-like.stderr new file mode 100644 index 00000000000..8ff50b124b3 --- /dev/null +++ b/src/test/ui/parser/label-after-block-like.stderr @@ -0,0 +1,176 @@ +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:2:20 + | +LL | if let () = () 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:2:20 + | +LL | if let () = () 'a {} + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/label-after-block-like.rs:2:8 + | +LL | if let () = () 'a {} + | ^^^^^^^^^^^ +help: try placing this code inside a block + | +LL | if let () = () { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:8:13 + | +LL | if true 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:8:13 + | +LL | if true 'a {} + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/label-after-block-like.rs:8:8 + | +LL | if true 'a {} + | ^^^^ +help: try placing this code inside a block + | +LL | if true { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:14:10 + | +LL | loop 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:14:10 + | +LL | loop 'a {} + | ---- ^^ expected `{` + | | + | while parsing this `loop` expression + | +help: try placing this code inside a block + | +LL | loop { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:20:16 + | +LL | while true 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:20:16 + | +LL | while true 'a {} + | ----- ---- ^^ expected `{` + | | | + | | this `while` condition successfully parsed + | while parsing the body of this `while` expression + | +help: try placing this code inside a block + | +LL | while true { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:26:23 + | +LL | while let () = () 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:26:23 + | +LL | while let () = () 'a {} + | ----- ----------- ^^ expected `{` + | | | + | | this `while` condition successfully parsed + | while parsing the body of this `while` expression + | +help: try placing this code inside a block + | +LL | while let () = () { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:32:19 + | +LL | for _ in 0..0 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:32:19 + | +LL | for _ in 0..0 'a {} + | ^^ expected `{` + | +help: try placing this code inside a block + | +LL | for _ in 0..0 { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:38:12 + | +LL | unsafe 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:38:12 + | +LL | unsafe 'a {} + | ------ ^^ expected `{` + | | + | while parsing this `unsafe` expression + | +help: try placing this code inside a block + | +LL | unsafe { 'a {} } + | + + + +error: aborting due to 14 previous errors + diff --git a/src/test/ui/parser/raw/raw-byte-string-literals.rs b/src/test/ui/parser/raw/raw-byte-string-literals.rs index 163c8ac66b0..1b859fee596 100644 --- a/src/test/ui/parser/raw/raw-byte-string-literals.rs +++ b/src/test/ui/parser/raw/raw-byte-string-literals.rs @@ -2,6 +2,6 @@ pub fn main() { br"a "; //~ ERROR bare CR not allowed in raw string - br"é"; //~ ERROR raw byte string must be ASCII + br"é"; //~ ERROR non-ASCII character in raw byte string literal br##~"a"~##; //~ ERROR only `#` is allowed in raw string delimitation } diff --git a/src/test/ui/parser/raw/raw-byte-string-literals.stderr b/src/test/ui/parser/raw/raw-byte-string-literals.stderr index cfc877104bd..a2f27d1ed70 100644 --- a/src/test/ui/parser/raw/raw-byte-string-literals.stderr +++ b/src/test/ui/parser/raw/raw-byte-string-literals.stderr @@ -4,7 +4,7 @@ error: bare CR not allowed in raw string LL | br"a "; | ^ -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/raw-byte-string-literals.rs:5:8 | LL | br"é"; diff --git a/src/test/ui/parser/underscore-suffix-for-string.rs b/src/test/ui/parser/underscore-suffix-for-string.rs index 2e0ebe2cfa4..bd260752e04 100644 --- a/src/test/ui/parser/underscore-suffix-for-string.rs +++ b/src/test/ui/parser/underscore-suffix-for-string.rs @@ -1,8 +1,17 @@ -// check-pass +macro_rules! sink { + ($tt:tt) => {()} +} fn main() { let _ = "Foo"_; - //~^ WARNING underscore literal suffix is not allowed - //~| WARNING this was previously accepted - //~| NOTE issue #42326 + //~^ ERROR underscore literal suffix is not allowed + + // This is ok, because `__` is a valid identifier and the macro consumes it + // before proper parsing happens. + let _ = sink!("Foo"__); + + // This is not ok, even as an input to a macro, because the `_` suffix is + // never allowed. + sink!("Foo"_); + //~^ ERROR underscore literal suffix is not allowed } diff --git a/src/test/ui/parser/underscore-suffix-for-string.stderr b/src/test/ui/parser/underscore-suffix-for-string.stderr index 00c7657f17b..2fe2c130eb2 100644 --- a/src/test/ui/parser/underscore-suffix-for-string.stderr +++ b/src/test/ui/parser/underscore-suffix-for-string.stderr @@ -1,11 +1,14 @@ -warning: underscore literal suffix is not allowed - --> $DIR/underscore-suffix-for-string.rs:4:18 +error: underscore literal suffix is not allowed + --> $DIR/underscore-suffix-for-string.rs:6:18 | LL | let _ = "Foo"_; | ^ + +error: underscore literal suffix is not allowed + --> $DIR/underscore-suffix-for-string.rs:15:16 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: see issue #42326 <https://github.com/rust-lang/rust/issues/42326> for more information +LL | sink!("Foo"_); + | ^ -warning: 1 warning emitted +error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/unicode-control-codepoints.rs b/src/test/ui/parser/unicode-control-codepoints.rs index 5af0b585a12..df099bb62ad 100644 --- a/src/test/ui/parser/unicode-control-codepoints.rs +++ b/src/test/ui/parser/unicode-control-codepoints.rs @@ -14,15 +14,15 @@ fn main() { println!("{:?}", r##"/* } if isAdmin begin admins only "##); //~^ ERROR unicode codepoint changing visible direction of text present in literal println!("{:?}", b"/* } if isAdmin begin admins only "); - //~^ ERROR non-ASCII character in byte constant - //~| ERROR non-ASCII character in byte constant - //~| ERROR non-ASCII character in byte constant - //~| ERROR non-ASCII character in byte constant + //~^ ERROR non-ASCII character in byte string literal + //~| ERROR non-ASCII character in byte string literal + //~| ERROR non-ASCII character in byte string literal + //~| ERROR non-ASCII character in byte string literal println!("{:?}", br##"/* } if isAdmin begin admins only "##); - //~^ ERROR raw byte string must be ASCII - //~| ERROR raw byte string must be ASCII - //~| ERROR raw byte string must be ASCII - //~| ERROR raw byte string must be ASCII + //~^ ERROR non-ASCII character in raw byte string literal + //~| ERROR non-ASCII character in raw byte string literal + //~| ERROR non-ASCII character in raw byte string literal + //~| ERROR non-ASCII character in raw byte string literal println!("{:?}", ''); //~^ ERROR unicode codepoint changing visible direction of text present in literal } diff --git a/src/test/ui/parser/unicode-control-codepoints.stderr b/src/test/ui/parser/unicode-control-codepoints.stderr index 44548c72ff5..fc071a94191 100644 --- a/src/test/ui/parser/unicode-control-codepoints.stderr +++ b/src/test/ui/parser/unicode-control-codepoints.stderr @@ -14,69 +14,69 @@ LL | println!("{:?}", b"us\u{202B}e\u{202A}r"); | = help: unicode escape sequences cannot be used as a byte or in a byte string -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:26 | LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ byte constant must be ASCII but is '\u{202e}' + | ^ must be ASCII but is '\u{202e}' | help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes | LL | println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin begin admins only "); | ~~~~~~~~~~~~ -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:30 | LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ byte constant must be ASCII but is '\u{2066}' + | ^ must be ASCII but is '\u{2066}' | help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes | LL | println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin begin admins only "); | ~~~~~~~~~~~~ -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:41 | LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ byte constant must be ASCII but is '\u{2069}' + | ^ must be ASCII but is '\u{2069}' | help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes | LL | println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9 begin admins only "); | ~~~~~~~~~~~~ -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:43 | LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ byte constant must be ASCII but is '\u{2066}' + | ^ must be ASCII but is '\u{2066}' | help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes | LL | println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only "); | ~~~~~~~~~~~~ -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:29 | LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); | ^ must be ASCII but is '\u{202e}' -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:33 | LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); | ^ must be ASCII but is '\u{2066}' -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:44 | LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); | ^ must be ASCII but is '\u{2069}' -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:46 | LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); diff --git a/src/test/ui/parser/use-colon-as-mod-sep.rs b/src/test/ui/parser/use-colon-as-mod-sep.rs new file mode 100644 index 00000000000..e1e8756b03c --- /dev/null +++ b/src/test/ui/parser/use-colon-as-mod-sep.rs @@ -0,0 +1,11 @@ +// Recover from using a colon as a path separator. + +use std::process:Command; +//~^ ERROR expected `::`, found `:` +use std:fs::File; +//~^ ERROR expected `::`, found `:` +use std:collections:HashMap; +//~^ ERROR expected `::`, found `:` +//~| ERROR expected `::`, found `:` + +fn main() { } diff --git a/src/test/ui/parser/use-colon-as-mod-sep.stderr b/src/test/ui/parser/use-colon-as-mod-sep.stderr new file mode 100644 index 00000000000..e825dfed111 --- /dev/null +++ b/src/test/ui/parser/use-colon-as-mod-sep.stderr @@ -0,0 +1,28 @@ +error: expected `::`, found `:` + --> $DIR/use-colon-as-mod-sep.rs:3:17 + | +LL | use std::process:Command; + | ^ help: use double colon + | + = note: import paths are delimited using `::` + +error: expected `::`, found `:` + --> $DIR/use-colon-as-mod-sep.rs:5:8 + | +LL | use std:fs::File; + | ^ help: use double colon + +error: expected `::`, found `:` + --> $DIR/use-colon-as-mod-sep.rs:7:8 + | +LL | use std:collections:HashMap; + | ^ help: use double colon + +error: expected `::`, found `:` + --> $DIR/use-colon-as-mod-sep.rs:7:20 + | +LL | use std:collections:HashMap; + | ^ help: use double colon + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr index 4971263af08..fc1be052fb7 100644 --- a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr +++ b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let phantom_pinned = identity(pin!(PhantomPinned)); | ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | LL | stuff(phantom_pinned) | -------------- borrow later used here @@ -18,7 +18,7 @@ error[E0716]: temporary value dropped while borrowed LL | let phantom_pinned = { | -------------- borrow later stored here LL | let phantom_pinned = pin!(PhantomPinned); - | ^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use ... LL | }; | - temporary value is freed at the end of this statement diff --git a/src/test/ui/privacy/effective_visibilities.rs b/src/test/ui/privacy/effective_visibilities.rs index c1f9ee8dfdf..4479b0d8f61 100644 --- a/src/test/ui/privacy/effective_visibilities.rs +++ b/src/test/ui/privacy/effective_visibilities.rs @@ -6,7 +6,7 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub pub mod inner1 { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub #[rustc_effective_visibility] - extern "C" {} //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + extern "C" {} //~ ERROR not in the table #[rustc_effective_visibility] pub trait PubTrait { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub @@ -18,6 +18,7 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub #[rustc_effective_visibility] struct PrivStruct; //~ ERROR not in the table + //~| ERROR not in the table #[rustc_effective_visibility] pub union PubUnion { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub @@ -31,6 +32,7 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub pub enum Enum { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub #[rustc_effective_visibility] A( //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + //~| ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub #[rustc_effective_visibility] PubUnion, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub ), diff --git a/src/test/ui/privacy/effective_visibilities.stderr b/src/test/ui/privacy/effective_visibilities.stderr index 5a8f7db38fc..019aaf8086a 100644 --- a/src/test/ui/privacy/effective_visibilities.stderr +++ b/src/test/ui/privacy/effective_visibilities.stderr @@ -10,7 +10,7 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl LL | pub mod inner1 { | ^^^^^^^^^^^^^^ -error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub +error: not in the table --> $DIR/effective_visibilities.rs:9:9 | LL | extern "C" {} @@ -28,92 +28,104 @@ error: not in the table LL | struct PrivStruct; | ^^^^^^^^^^^^^^^^^ +error: not in the table + --> $DIR/effective_visibilities.rs:20:9 + | +LL | struct PrivStruct; + | ^^^^^^^^^^^^^^^^^ + error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:23:9 + --> $DIR/effective_visibilities.rs:24:9 | LL | pub union PubUnion { | ^^^^^^^^^^^^^^^^^^ error: not in the table - --> $DIR/effective_visibilities.rs:25:13 + --> $DIR/effective_visibilities.rs:26:13 | LL | a: u8, | ^^^^^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:27:13 + --> $DIR/effective_visibilities.rs:28:13 | LL | pub b: u8, | ^^^^^^^^^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:31:9 + --> $DIR/effective_visibilities.rs:32:9 | LL | pub enum Enum { | ^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:33:13 + --> $DIR/effective_visibilities.rs:34:13 + | +LL | A( + | ^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:34:13 | LL | A( | ^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:35:17 + --> $DIR/effective_visibilities.rs:37:17 | LL | PubUnion, | ^^^^^^^^ error: not in the table - --> $DIR/effective_visibilities.rs:41:5 + --> $DIR/effective_visibilities.rs:43:5 | LL | macro_rules! none_macro { | ^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub(self), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:47:5 + --> $DIR/effective_visibilities.rs:49:5 | LL | macro_rules! public_macro { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:52:5 + --> $DIR/effective_visibilities.rs:54:5 | LL | pub struct ReachableStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:54:9 + --> $DIR/effective_visibilities.rs:56:9 | LL | pub a: u8, | ^^^^^^^^^ error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:59:9 + --> $DIR/effective_visibilities.rs:61:9 | LL | pub use outer::inner1; | ^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:65:5 + --> $DIR/effective_visibilities.rs:67:5 | LL | pub type HalfPublicImport = u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) - --> $DIR/effective_visibilities.rs:68:5 + --> $DIR/effective_visibilities.rs:70:5 | LL | pub(crate) const HalfPublicImport: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:72:9 + --> $DIR/effective_visibilities.rs:74:9 | LL | pub use half_public_import::HalfPublicImport; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:72:9 + --> $DIR/effective_visibilities.rs:74:9 | LL | pub use half_public_import::HalfPublicImport; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,5 +142,5 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl LL | type B; | ^^^^^^ -error: aborting due to 22 previous errors +error: aborting due to 24 previous errors diff --git a/src/test/ui/privacy/effective_visibilities_glob.rs b/src/test/ui/privacy/effective_visibilities_glob.rs new file mode 100644 index 00000000000..eb9dcd6cd1f --- /dev/null +++ b/src/test/ui/privacy/effective_visibilities_glob.rs @@ -0,0 +1,21 @@ +// Effective visibility tracking for imports is fine-grained, so `S2` is not fully exported +// even if its parent import (`m::*`) is fully exported as a `use` item. + +#![feature(rustc_attrs)] + +mod m { + #[rustc_effective_visibility] + pub struct S1 {} //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + pub struct S2 {} //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) +} + +mod glob { + #[rustc_effective_visibility] + pub use crate::m::*; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub +} + +#[rustc_effective_visibility] +pub use glob::S1; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + +fn main() {} diff --git a/src/test/ui/privacy/effective_visibilities_glob.stderr b/src/test/ui/privacy/effective_visibilities_glob.stderr new file mode 100644 index 00000000000..0496cd5df8d --- /dev/null +++ b/src/test/ui/privacy/effective_visibilities_glob.stderr @@ -0,0 +1,26 @@ +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities_glob.rs:8:5 + | +LL | pub struct S1 {} + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities_glob.rs:10:5 + | +LL | pub struct S2 {} + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities_glob.rs:15:13 + | +LL | pub use crate::m::*; + | ^^^^^^^^ + +error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities_glob.rs:19:9 + | +LL | pub use glob::S1; + | ^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/proc-macro/expand-expr.rs b/src/test/ui/proc-macro/expand-expr.rs index d1146d97030..8d51b7e1718 100644 --- a/src/test/ui/proc-macro/expand-expr.rs +++ b/src/test/ui/proc-macro/expand-expr.rs @@ -1,5 +1,5 @@ // aux-build:expand-expr.rs - +#![feature(concat_bytes)] extern crate expand_expr; use expand_expr::{ @@ -23,6 +23,11 @@ expand_expr_is!( concat!("contents: ", include_str!("auxiliary/included-file.txt")) ); +expand_expr_is!( + b"contents: Included file contents\n", + concat_bytes!(b"contents: ", include_bytes!("auxiliary/included-file.txt")) +); + // Correct value is checked for multiple sources. check_expand_expr_file!(file!()); diff --git a/src/test/ui/proc-macro/expand-expr.stderr b/src/test/ui/proc-macro/expand-expr.stderr index 8dc2d0cfc2f..c6c4695fd9c 100644 --- a/src/test/ui/proc-macro/expand-expr.stderr +++ b/src/test/ui/proc-macro/expand-expr.stderr @@ -1,29 +1,29 @@ error: expected one of `.`, `?`, or an operator, found `;` - --> $DIR/expand-expr.rs:101:27 + --> $DIR/expand-expr.rs:106:27 | LL | expand_expr_fail!("string"; hello); | ^ expected one of `.`, `?`, or an operator error: expected expression, found `$` - --> $DIR/expand-expr.rs:104:19 + --> $DIR/expand-expr.rs:109:19 | LL | expand_expr_fail!($); | ^ expected expression error: expected expression, found `$` - --> $DIR/expand-expr.rs:33:23 + --> $DIR/expand-expr.rs:38:23 | LL | ($($t:tt)*) => { $($t)* }; | ^^^^ expected expression error: expected expression, found `$` - --> $DIR/expand-expr.rs:106:28 + --> $DIR/expand-expr.rs:111:28 | LL | expand_expr_fail!(echo_pm!($)); | ^ expected expression error: macro expansion ignores token `hello` and any following - --> $DIR/expand-expr.rs:110:47 + --> $DIR/expand-expr.rs:115:47 | LL | expand_expr_is!("string", echo_tts!("string"; hello)); | --------------------^^^^^-- help: you might be missing a semicolon here: `;` @@ -33,7 +33,7 @@ LL | expand_expr_is!("string", echo_tts!("string"; hello)); = note: the usage of `echo_tts!` is likely invalid in expression context error: macro expansion ignores token `;` and any following - --> $DIR/expand-expr.rs:111:44 + --> $DIR/expand-expr.rs:116:44 | LL | expand_expr_is!("string", echo_pm!("string"; hello)); | -----------------^-------- help: you might be missing a semicolon here: `;` @@ -43,7 +43,7 @@ LL | expand_expr_is!("string", echo_pm!("string"; hello)); = note: the usage of `echo_pm!` is likely invalid in expression context error: recursion limit reached while expanding `recursive_expand!` - --> $DIR/expand-expr.rs:119:16 + --> $DIR/expand-expr.rs:124:16 | LL | const _: u32 = recursive_expand!(); | ^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr index 8042b1740b1..8ef7e22536b 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller1.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr @@ -5,7 +5,7 @@ LL | fn call1<'a>(x: &'a usize) { | -- lifetime `'a` defined here ... LL | let z: &'a & usize = &(&y); - | ----------- ^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'a` ... diff --git a/src/test/ui/regions/regions-var-type-out-of-scope.stderr b/src/test/ui/regions/regions-var-type-out-of-scope.stderr index 476e82f046f..c32bbe0ee1f 100644 --- a/src/test/ui/regions/regions-var-type-out-of-scope.stderr +++ b/src/test/ui/regions/regions-var-type-out-of-scope.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | x = &id(3); | ^^^^^- temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | assert_eq!(*x, 3); | ----------------- borrow later used here | diff --git a/src/test/ui/align-with-extern-c-fn.rs b/src/test/ui/repr/align-with-extern-c-fn.rs index 9e490e27ad1..9e490e27ad1 100644 --- a/src/test/ui/align-with-extern-c-fn.rs +++ b/src/test/ui/repr/align-with-extern-c-fn.rs diff --git a/src/test/ui/aligned_enum_cast.rs b/src/test/ui/repr/aligned_enum_cast.rs index 1ddf127172e..1ddf127172e 100644 --- a/src/test/ui/aligned_enum_cast.rs +++ b/src/test/ui/repr/aligned_enum_cast.rs diff --git a/src/test/ui/repr_c_int_align.rs b/src/test/ui/repr/repr_c_int_align.rs index fdd14fc2dbe..fdd14fc2dbe 100644 --- a/src/test/ui/repr_c_int_align.rs +++ b/src/test/ui/repr/repr_c_int_align.rs diff --git a/src/test/ui/resolve/issue-103474.rs b/src/test/ui/resolve/issue-103474.rs new file mode 100644 index 00000000000..14f2259e1d4 --- /dev/null +++ b/src/test/ui/resolve/issue-103474.rs @@ -0,0 +1,28 @@ +struct S {} +impl S { + fn first(&self) {} + + fn second(&self) { + first() + //~^ ERROR cannot find function `first` in this scope + } + + fn third(&self) { + no_method_err() + //~^ ERROR cannot find function `no_method_err` in this scope + } +} + +// https://github.com/rust-lang/rust/pull/103531#discussion_r1004728080 +struct Foo { + i: i32, +} + +impl Foo { + fn needs_self() { + this.i + //~^ ERROR cannot find value `this` in this scope + } +} + +fn main() {} diff --git a/src/test/ui/resolve/issue-103474.stderr b/src/test/ui/resolve/issue-103474.stderr new file mode 100644 index 00000000000..415d231552a --- /dev/null +++ b/src/test/ui/resolve/issue-103474.stderr @@ -0,0 +1,35 @@ +error[E0425]: cannot find value `this` in this scope + --> $DIR/issue-103474.rs:23:9 + | +LL | this.i + | ^^^^ not found in this scope + | +help: you might have meant to use `self` here instead + | +LL | self.i + | ~~~~ +help: if you meant to use `self`, you are also missing a `self` receiver argument + | +LL | fn needs_self(&self) { + | +++++ + +error[E0425]: cannot find function `first` in this scope + --> $DIR/issue-103474.rs:6:9 + | +LL | first() + | ^^^^^ not found in this scope + | +help: consider using the associated function + | +LL | self.first() + | +++++ + +error[E0425]: cannot find function `no_method_err` in this scope + --> $DIR/issue-103474.rs:11:9 + | +LL | no_method_err() + | ^^^^^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index e7c53ff44e6..36f3da7c955 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -85,7 +85,7 @@ LL | static_method(); help: consider using the associated function | LL | Self::static_method(); - | ~~~~~~~~~~~~~~~~~~~ + | ++++++ error[E0425]: cannot find function `purr` in this scope --> $DIR/issue-2356.rs:54:9 @@ -114,7 +114,7 @@ LL | grow_older(); help: consider using the associated function | LL | Self::grow_older(); - | ~~~~~~~~~~~~~~~~ + | ++++++ error[E0425]: cannot find function `shave` in this scope --> $DIR/issue-2356.rs:74:5 diff --git a/src/test/ui/resolve/resolve-self-in-impl.stderr b/src/test/ui/resolve/resolve-self-in-impl.stderr index 9f9ed68898f..b3042d41346 100644 --- a/src/test/ui/resolve/resolve-self-in-impl.stderr +++ b/src/test/ui/resolve/resolve-self-in-impl.stderr @@ -1,40 +1,40 @@ error: `Self` is not valid in the self type of an impl block - --> $DIR/resolve-self-in-impl.rs:14:13 + --> $DIR/resolve-self-in-impl.rs:16:6 | -LL | impl Tr for Self {} - | ^^^^ +LL | impl Self {} + | ^^^^ | = note: replace `Self` with a different type error: `Self` is not valid in the self type of an impl block - --> $DIR/resolve-self-in-impl.rs:15:15 + --> $DIR/resolve-self-in-impl.rs:17:8 | -LL | impl Tr for S<Self> {} - | ^^^^ +LL | impl S<Self> {} + | ^^^^ | = note: replace `Self` with a different type error: `Self` is not valid in the self type of an impl block - --> $DIR/resolve-self-in-impl.rs:16:6 + --> $DIR/resolve-self-in-impl.rs:18:7 | -LL | impl Self {} - | ^^^^ +LL | impl (Self, Self) {} + | ^^^^ ^^^^ | = note: replace `Self` with a different type error: `Self` is not valid in the self type of an impl block - --> $DIR/resolve-self-in-impl.rs:17:8 + --> $DIR/resolve-self-in-impl.rs:14:13 | -LL | impl S<Self> {} - | ^^^^ +LL | impl Tr for Self {} + | ^^^^ | = note: replace `Self` with a different type error: `Self` is not valid in the self type of an impl block - --> $DIR/resolve-self-in-impl.rs:18:7 + --> $DIR/resolve-self-in-impl.rs:15:15 | -LL | impl (Self, Self) {} - | ^^^^ ^^^^ +LL | impl Tr for S<Self> {} + | ^^^^ | = note: replace `Self` with a different type diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index 6ee32314607..9577952119a 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -1,12 +1,10 @@ error[E0277]: the trait bound `f32: Termination` is not satisfied - --> $DIR/termination-trait-test-wrong-type.rs:6:1 + --> $DIR/termination-trait-test-wrong-type.rs:6:31 | -LL | #[test] - | ------- in this procedural macro expansion -LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> { -LL | | "0".parse() -LL | | } - | |_^ the trait `Termination` is not implemented for `f32` +LL | #[test] + | ------- in this procedural macro expansion +LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32` | = note: required for `Result<f32, ParseFloatError>` to implement `Termination` note: required by a bound in `assert_test_result` diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs new file mode 100644 index 00000000000..348ca0ab190 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs @@ -0,0 +1,4 @@ +#[derive_const(Default)] //~ ERROR use of unstable library feature +pub struct S; + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr new file mode 100644 index 00000000000..cc9bdd2715f --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'derive_const' + --> $DIR/derive-const-gate.rs:1:3 + | +LL | #[derive_const(Default)] + | ^^^^^^^^^^^^ + | + = help: add `#![feature(derive_const)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs new file mode 100644 index 00000000000..92843a8a2da --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs @@ -0,0 +1,13 @@ +#![feature(derive_const)] + +pub struct A; + +impl Default for A { + fn default() -> A { A } +} + +#[derive_const(Default)] +pub struct S(A); +//~^ cannot call non-const fn + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr new file mode 100644 index 00000000000..d463c774e28 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr @@ -0,0 +1,14 @@ +error[E0015]: cannot call non-const fn `<A as Default>::default` in constant functions + --> $DIR/derive-const-non-const-type.rs:10:14 + | +LL | #[derive_const(Default)] + | ------- in this derive macro expansion +LL | pub struct S(A); + | ^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs new file mode 100644 index 00000000000..d1fbeac8598 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)] + +pub struct A; + +impl const Default for A { + fn default() -> A { A } +} + +impl const PartialEq for A { + fn eq(&self, _: &A) -> bool { true } +} + +#[derive_const(Default, PartialEq)] +pub struct S((), A); + +const _: () = assert!(S((), A) == S::default()); + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs new file mode 100644 index 00000000000..3ac90992486 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs @@ -0,0 +1,46 @@ +// Tests that trait bounds on specializing trait impls must be `~const` if the +// same bound is present on the default impl and is `~const` there. + +#![feature(const_trait_impl)] +#![feature(rustc_attrs)] +#![feature(min_specialization)] + +#[rustc_specialization_trait] +trait Specialize {} + +#[const_trait] +trait Foo {} + +#[const_trait] +trait Bar {} + +// bgr360: I was only able to exercise the code path that raises the +// "missing ~const qualifier" error by making this base impl non-const, even +// though that doesn't really make sense to do. As seen below, if the base impl +// is made const, rustc fails earlier with an overlapping impl failure. +impl<T> Bar for T +where + T: ~const Foo, +{} + +impl<T> Bar for T +where + T: Foo, //~ ERROR missing `~const` qualifier + T: Specialize, +{} + +#[const_trait] +trait Baz {} + +impl<T> const Baz for T +where + T: ~const Foo, +{} + +impl<T> const Baz for T //~ ERROR conflicting implementations of trait `Baz` +where + T: Foo, + T: Specialize, +{} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr new file mode 100644 index 00000000000..4aea1979421 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr @@ -0,0 +1,18 @@ +error: missing `~const` qualifier for specialization + --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:8 + | +LL | T: Foo, + | ^^^ + +error[E0119]: conflicting implementations of trait `Baz` + --> $DIR/const-default-bound-non-const-specialized-bound.rs:40:1 + | +LL | impl<T> const Baz for T + | ----------------------- first implementation here +... +LL | impl<T> const Baz for T + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs new file mode 100644 index 00000000000..9ddea427cfd --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs @@ -0,0 +1,39 @@ +// Tests that a const default trait impl can be specialized by another const +// trait impl and that the specializing impl will be used during const-eval. + +// run-pass + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Value { + fn value() -> u32; +} + +const fn get_value<T: ~const Value>() -> u32 { + T::value() +} + +impl<T> const Value for T { + default fn value() -> u32 { + 0 + } +} + +struct FortyTwo; + +impl const Value for FortyTwo { + fn value() -> u32 { + 42 + } +} + +const ZERO: u32 = get_value::<()>(); + +const FORTY_TWO: u32 = get_value::<FortyTwo>(); + +fn main() { + assert_eq!(ZERO, 0); + assert_eq!(FORTY_TWO, 42); +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs new file mode 100644 index 00000000000..a3bb9b3f93e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs @@ -0,0 +1,26 @@ +// Tests that specializing trait impls must be at least as const as the default impl. + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Value { + fn value() -> u32; +} + +impl<T> const Value for T { + default fn value() -> u32 { + 0 + } +} + +struct FortyTwo; + +impl Value for FortyTwo { //~ ERROR cannot specialize on const impl with non-const impl + fn value() -> u32 { + println!("You can't do that (constly)"); + 42 + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr new file mode 100644 index 00000000000..24766804708 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on const impl with non-const impl + --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1 + | +LL | impl Value for FortyTwo { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs b/src/test/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs new file mode 100644 index 00000000000..2aac0a2b4d1 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Foo { + fn foo(); +} + +impl const Foo for u32 { + default fn foo() {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs b/src/test/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs new file mode 100644 index 00000000000..9c2c2cf1610 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs @@ -0,0 +1,37 @@ +// Tests that `~const` trait bounds can be used to specialize const trait impls. + +// check-pass + +#![feature(const_trait_impl)] +#![feature(rustc_attrs)] +#![feature(min_specialization)] + +#[const_trait] +#[rustc_specialization_trait] +trait Specialize {} + +#[const_trait] +trait Foo {} + +impl<T> const Foo for T {} + +impl<T> const Foo for T +where + T: ~const Specialize, +{} + +#[const_trait] +trait Bar {} + +impl<T> const Bar for T +where + T: ~const Foo, +{} + +impl<T> const Bar for T +where + T: ~const Foo, + T: ~const Specialize, +{} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs b/src/test/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs new file mode 100644 index 00000000000..1e6b1c6513b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs @@ -0,0 +1,45 @@ +// Tests that `T: ~const Foo` in a specializing impl is treated as equivalent to +// `T: Foo` in the default impl for the purposes of specialization (i.e., it +// does not think that the user is attempting to specialize on trait `Foo`). + +// check-pass + +#![feature(rustc_attrs)] +#![feature(min_specialization)] +#![feature(const_trait_impl)] + +#[rustc_specialization_trait] +trait Specialize {} + +#[const_trait] +trait Foo {} + +#[const_trait] +trait Bar {} + +impl<T> Bar for T +where + T: Foo, +{} + +impl<T> const Bar for T +where + T: ~const Foo, + T: Specialize, +{} + +#[const_trait] +trait Baz {} + +impl<T> const Baz for T +where + T: Foo, +{} + +impl<T> const Baz for T +where + T: ~const Foo, + T: Specialize, +{} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs b/src/test/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs new file mode 100644 index 00000000000..35aa52fbd4e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs @@ -0,0 +1,39 @@ +// Tests that a non-const default impl can be specialized by a const trait impl, +// but that the default impl cannot be used in a const context. + +// run-pass + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Value { + fn value() -> u32; +} + +const fn get_value<T: ~const Value>() -> u32 { + T::value() +} + +impl<T> Value for T { + default fn value() -> u32 { + println!("You can't do that (constly)"); + 0 + } +} + +struct FortyTwo; + +impl const Value for FortyTwo { + fn value() -> u32 { + 42 + } +} + +fn main() { + let zero = get_value::<()>(); + assert_eq!(zero, 0); + + const FORTY_TWO: u32 = get_value::<FortyTwo>(); + assert_eq!(FORTY_TWO, 42); +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs index ff0cd489d47..9ab170f0920 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs @@ -17,7 +17,9 @@ impl<T: ~const Default> const A for T { } } -impl<T: Default + Sup> A for T { //~ ERROR: cannot specialize +impl<T: Default + Sup> A for T { +//~^ ERROR: cannot specialize +//~| ERROR: missing `~const` qualifier fn a() -> u32 { 3 } diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr index 3296c109c4e..843fc6ce84d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr @@ -1,8 +1,14 @@ -error: cannot specialize on trait `Default` +error: cannot specialize on const impl with non-const impl + --> $DIR/specializing-constness.rs:20:1 + | +LL | impl<T: Default + Sup> A for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing `~const` qualifier for specialization --> $DIR/specializing-constness.rs:20:9 | LL | impl<T: Default + Sup> A for T { | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfcs/rfc1623-2.rs index c0e13a5f5f0..c0e13a5f5f0 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfcs/rfc1623-2.rs diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfcs/rfc1623-2.stderr index b15a4cb110b..d183eaaa623 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfcs/rfc1623-2.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/rfc1623.rs:28:8 + --> $DIR/rfc1623-2.rs:28:8 | LL | f: &id, | ^^^ one type is more general than the other @@ -8,7 +8,7 @@ LL | f: &id, found trait `Fn<(&Foo<'_>,)>` error[E0308]: mismatched types - --> $DIR/rfc1623.rs:28:8 + --> $DIR/rfc1623-2.rs:28:8 | LL | f: &id, | ^^^ one type is more general than the other @@ -17,7 +17,7 @@ LL | f: &id, found trait `Fn<(&Foo<'_>,)>` error: implementation of `FnOnce` is not general enough - --> $DIR/rfc1623.rs:28:8 + --> $DIR/rfc1623-2.rs:28:8 | LL | f: &id, | ^^^ implementation of `FnOnce` is not general enough @@ -26,7 +26,7 @@ LL | f: &id, = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough - --> $DIR/rfc1623.rs:28:8 + --> $DIR/rfc1623-2.rs:28:8 | LL | f: &id, | ^^^ implementation of `FnOnce` is not general enough diff --git a/src/test/ui/rfc1623-2.rs b/src/test/ui/rfcs/rfc1623-3.rs index 26fa6fdb57f..26fa6fdb57f 100644 --- a/src/test/ui/rfc1623-2.rs +++ b/src/test/ui/rfcs/rfc1623-3.rs diff --git a/src/test/ui/rfc1623-2.stderr b/src/test/ui/rfcs/rfc1623-3.stderr index 945c6533c79..77fc3f0412e 100644 --- a/src/test/ui/rfc1623-2.stderr +++ b/src/test/ui/rfcs/rfc1623-3.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/rfc1623-2.rs:8:42 + --> $DIR/rfc1623-3.rs:8:42 | LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = | --- --- ^ expected named lifetime parameter @@ -12,7 +12,7 @@ LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = | +++++++ ++ ++ ++ error[E0106]: missing lifetime specifier - --> $DIR/rfc1623-2.rs:10:39 + --> $DIR/rfc1623-3.rs:10:39 | LL | &(non_elidable as fn(&u8, &u8) -> &u8); | --- --- ^ expected named lifetime parameter @@ -24,7 +24,7 @@ LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); | +++++++ ++ ++ ++ error[E0605]: non-primitive cast: `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {non_elidable}` as `for<'a, 'b> fn(&'a u8, &'b u8) -> &u8` - --> $DIR/rfc1623-2.rs:10:6 + --> $DIR/rfc1623-3.rs:10:6 | LL | &(non_elidable as fn(&u8, &u8) -> &u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast diff --git a/src/test/ui/sanitize/memory-passing.rs b/src/test/ui/sanitize/memory-passing.rs new file mode 100644 index 00000000000..6d9b70ad6b1 --- /dev/null +++ b/src/test/ui/sanitize/memory-passing.rs @@ -0,0 +1,32 @@ +// needs-sanitizer-support +// needs-sanitizer-memory +// +// revisions: unoptimized optimized +// +// [optimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O +// [unoptimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins +// +// run-pass +// +// This test case intentionally limits the usage of the std, +// since it will be linked with an uninstrumented version of it. + +#![feature(core_intrinsics)] +#![feature(start)] +#![allow(invalid_value)] + +use std::hint::black_box; + +fn calling_black_box_on_zst_ok() { + // It's OK to call black_box on a value of a zero-sized type, even if its + // underlying the memory location is uninitialized. For non-zero-sized types, + // this would be an MSAN error. + let zst = (); + black_box(zst); +} + +#[start] +fn main(_: isize, _: *const *const u8) -> isize { + calling_black_box_on_zst_ok(); + 0 +} diff --git a/src/test/ui/self/class-missing-self.stderr b/src/test/ui/self/class-missing-self.stderr index d501200d73c..063c3f013c5 100644 --- a/src/test/ui/self/class-missing-self.stderr +++ b/src/test/ui/self/class-missing-self.stderr @@ -10,6 +10,10 @@ error[E0425]: cannot find function `sleep` in this scope LL | sleep(); | ^^^^^ not found in this scope | +help: consider using the associated function + | +LL | self.sleep(); + | +++++ help: consider importing this function | LL | use std::thread::sleep; diff --git a/src/test/ui/sized/coinductive-1-gat.rs b/src/test/ui/sized/coinductive-1-gat.rs new file mode 100644 index 00000000000..cdf70920f00 --- /dev/null +++ b/src/test/ui/sized/coinductive-1-gat.rs @@ -0,0 +1,14 @@ +// check-pass +struct Node<C: Trait>(C::Assoc::<Self>); + +trait Trait { + type Assoc<T>; +} + +impl Trait for Vec<()> { + type Assoc<T> = Vec<T>; +} + +fn main() { + let _ = Node::<Vec<()>>(Vec::new()); +} diff --git a/src/test/ui/sized/coinductive-1.rs b/src/test/ui/sized/coinductive-1.rs new file mode 100644 index 00000000000..7bcd0f1fdaf --- /dev/null +++ b/src/test/ui/sized/coinductive-1.rs @@ -0,0 +1,14 @@ +// check-pass +struct Node<C: Trait<Self>>(C::Assoc); + +trait Trait<T> { + type Assoc; +} + +impl<T> Trait<T> for Vec<()> { + type Assoc = Vec<T>; +} + +fn main() { + let _ = Node::<Vec<()>>(Vec::new()); +} diff --git a/src/test/ui/sized/coinductive-2.rs b/src/test/ui/sized/coinductive-2.rs new file mode 100644 index 00000000000..212274d2e4b --- /dev/null +++ b/src/test/ui/sized/coinductive-2.rs @@ -0,0 +1,28 @@ +// run-pass +struct Node<C: CollectionFactory<Self>> { + _children: C::Collection, +} + +trait CollectionFactory<T> { + type Collection; +} + +impl<T> CollectionFactory<T> for Vec<()> { + type Collection = Vec<T>; +} + +trait Collection<T>: Sized { + fn push(&mut self, v: T); +} + +impl<T> Collection<T> for Vec<T> { + fn push(&mut self, v: T) { + self.push(v) + } +} + +fn main() { + let _ = Node::<Vec<()>> { + _children: Vec::new(), + }; +} diff --git a/src/test/ui/sized/recursive-type-1.rs b/src/test/ui/sized/recursive-type-1.rs new file mode 100644 index 00000000000..cd6805967e5 --- /dev/null +++ b/src/test/ui/sized/recursive-type-1.rs @@ -0,0 +1,10 @@ +// check-pass +trait A { type Assoc; } + +impl A for () { + // FIXME: it would be nice for this to at least cause a warning. + type Assoc = Foo<()>; +} +struct Foo<T: A>(T::Assoc); + +fn main() {} diff --git a/src/test/ui/sized/recursive-type-2.rs b/src/test/ui/sized/recursive-type-2.rs new file mode 100644 index 00000000000..7d95417a6ff --- /dev/null +++ b/src/test/ui/sized/recursive-type-2.rs @@ -0,0 +1,13 @@ +// build-fail +//~^ ERROR cycle detected when computing layout of `Foo<()>` + +trait A { type Assoc: ?Sized; } + +impl A for () { + type Assoc = Foo<()>; +} +struct Foo<T: A>(T::Assoc); + +fn main() { + let x: Foo<()>; +} diff --git a/src/test/ui/sized/recursive-type-2.stderr b/src/test/ui/sized/recursive-type-2.stderr new file mode 100644 index 00000000000..d0e6e9db07e --- /dev/null +++ b/src/test/ui/sized/recursive-type-2.stderr @@ -0,0 +1,13 @@ +error[E0391]: cycle detected when computing layout of `Foo<()>` + | + = note: ...which requires computing layout of `<() as A>::Assoc`... + = note: ...which again requires computing layout of `Foo<()>`, completing the cycle +note: cycle used when elaborating drops for `main` + --> $DIR/recursive-type-2.rs:11:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs index 6240f103c99..18abfb5c3fb 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs @@ -18,7 +18,7 @@ fn f() { v3.push(&id('x')); // statement 6 //~^ ERROR temporary value dropped while borrowed - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| NOTE temporary value is freed at the end of this statement //~| HELP consider using a `let` binding to create a longer lived value @@ -28,7 +28,7 @@ fn f() { v4.push(&id('y')); //~^ ERROR temporary value dropped while borrowed - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| NOTE temporary value is freed at the end of this statement //~| NOTE consider using a `let` binding to create a longer lived value v4.use_ref(); @@ -39,7 +39,7 @@ fn f() { v5.push(&id('z')); //~^ ERROR temporary value dropped while borrowed - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| NOTE temporary value is freed at the end of this statement //~| HELP consider using a `let` binding to create a longer lived value diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr index a236dab3ae5..2dc29a78d20 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -16,7 +16,7 @@ error[E0716]: temporary value dropped while borrowed LL | v3.push(&id('x')); // statement 6 | ^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); | -- borrow later used here @@ -33,7 +33,7 @@ error[E0716]: temporary value dropped while borrowed LL | v4.push(&id('y')); | ^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | v4.use_ref(); | ------------ borrow later used here @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed LL | v5.push(&id('z')); | ^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); | -- borrow later used here diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.stderr index cb5289d24b4..25e344fedfb 100644 --- a/src/test/ui/span/borrowck-ref-into-rvalue.stderr +++ b/src/test/ui/span/borrowck-ref-into-rvalue.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/borrowck-ref-into-rvalue.rs:4:11 | LL | match Some("Hello".to_string()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use ... LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/span/issue-11925.rs b/src/test/ui/span/issue-11925.rs index d9c08fbdd0f..cac9fd5bfb6 100644 --- a/src/test/ui/span/issue-11925.rs +++ b/src/test/ui/span/issue-11925.rs @@ -1,6 +1,6 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f } +fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f } fn main() { let r = { diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr index 460ad9ac744..d9cce2254dd 100644 --- a/src/test/ui/span/issue-15480.stderr +++ b/src/test/ui/span/issue-15480.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/issue-15480.rs:6:10 | LL | &id(3) - | ^^^^^ creates a temporary which is freed while still in use + | ^^^^^ creates a temporary value which is freed while still in use LL | ]; | - temporary value is freed at the end of this statement ... diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr index ba0c45acf23..81e858fa0ce 100644 --- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr +++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:12:27 | LL | let ss: &isize = &id(1); - | ^^^^^ creates a temporary which is freed while still in use + | ^^^^^ creates a temporary value which is freed while still in use ... LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr index 27df25be3fa..b70bf69d688 100644 --- a/src/test/ui/span/slice-borrow.stderr +++ b/src/test/ui/span/slice-borrow.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/slice-borrow.rs:6:28 | LL | let x: &[isize] = &vec![1, 2, 3, 4, 5]; - | ^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use ... LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr index 112bfc00304..cedcb736794 100644 --- a/src/test/ui/static/static-drop-scope.stderr +++ b/src/test/ui/static/static-drop-scope.stderr @@ -13,7 +13,7 @@ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); | ------^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a static requires that borrow lasts for `'static` error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time @@ -31,7 +31,7 @@ LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); | ------^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time diff --git a/src/test/ui/static/static-reference-to-fn-2.stderr b/src/test/ui/static/static-reference-to-fn-2.stderr index ff15884bd44..133d8ec2e1e 100644 --- a/src/test/ui/static/static-reference-to-fn-2.stderr +++ b/src/test/ui/static/static-reference-to-fn-2.stderr @@ -6,7 +6,7 @@ LL | fn state1(self_: &mut StateMachineIter) -> Option<&'static str> { LL | self_.statefn = &id(state2 as StateMachineFunc); | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | assignment requires that borrow lasts for `'1` error[E0716]: temporary value dropped while borrowed @@ -17,7 +17,7 @@ LL | fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> { LL | self_.statefn = &id(state3 as StateMachineFunc); | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | assignment requires that borrow lasts for `'1` error[E0716]: temporary value dropped while borrowed @@ -28,7 +28,7 @@ LL | fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> { LL | self_.statefn = &id(finished as StateMachineFunc); | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | assignment requires that borrow lasts for `'1` error[E0515]: cannot return value referencing temporary value diff --git a/src/test/ui/static/static-region-bound.stderr b/src/test/ui/static/static-region-bound.stderr index 15261259ed4..1a607e3c014 100644 --- a/src/test/ui/static/static-region-bound.stderr +++ b/src/test/ui/static/static-region-bound.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/static-region-bound.rs:10:14 | LL | let x = &id(3); - | ^^^^^ creates a temporary which is freed while still in use + | ^^^^^ creates a temporary value which is freed while still in use LL | f(x); | ---- argument requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/statics/issue-44373.stderr b/src/test/ui/statics/issue-44373.stderr index 6f92fbb1eb6..2d29dec888e 100644 --- a/src/test/ui/statics/issue-44373.stderr +++ b/src/test/ui/statics/issue-44373.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/issue-44373.rs:4:42 | LL | let _val: &'static [&'static u32] = &[&FOO]; - | ----------------------- ^^^^^^ creates a temporary which is freed while still in use + | ----------------------- ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/suggestions/assoc_fn_without_self.stderr b/src/test/ui/suggestions/assoc_fn_without_self.stderr index 88920b85290..febdd67338c 100644 --- a/src/test/ui/suggestions/assoc_fn_without_self.stderr +++ b/src/test/ui/suggestions/assoc_fn_without_self.stderr @@ -7,13 +7,18 @@ LL | foo(); help: consider using the associated function | LL | Self::foo(); - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find function `bar` in this scope --> $DIR/assoc_fn_without_self.rs:17:9 | LL | bar(); | ^^^ not found in this scope + | +help: consider using the associated function + | +LL | self.bar(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/assoc_fn_without_self.rs:18:9 @@ -24,7 +29,7 @@ LL | baz(2, 3); help: consider using the associated function | LL | Self::baz(2, 3); - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find function `foo` in this scope --> $DIR/assoc_fn_without_self.rs:14:13 diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr index 3d9ac40ec36..02148b7f7ad 100644 --- a/src/test/ui/suggestions/if-let-typo.stderr +++ b/src/test/ui/suggestions/if-let-typo.stderr @@ -25,12 +25,22 @@ error[E0308]: mismatched types | LL | if Some(x) = foo {} | ^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(x) = foo {} + | +++ error[E0308]: mismatched types --> $DIR/if-let-typo.rs:6:8 | LL | if Some(foo) = bar {} | ^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(foo) = bar {} + | +++ error[E0308]: mismatched types --> $DIR/if-let-typo.rs:7:8 @@ -51,6 +61,11 @@ error[E0308]: mismatched types | LL | if Some(3) = foo {} | ^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(3) = foo {} + | +++ error: aborting due to 7 previous errors diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs index c56ea7c030d..fac68c053eb 100644 --- a/src/test/ui/suggestions/inner_type2.rs +++ b/src/test/ui/suggestions/inner_type2.rs @@ -22,5 +22,5 @@ fn main() { let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 }); item.method(); //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599] - //~| HELP if this `MaybeUninit::<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value + //~| HELP if this `MaybeUninit<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value } diff --git a/src/test/ui/suggestions/inner_type2.stderr b/src/test/ui/suggestions/inner_type2.stderr index eddfd9d6340..984366123c8 100644 --- a/src/test/ui/suggestions/inner_type2.stderr +++ b/src/test/ui/suggestions/inner_type2.stderr @@ -17,7 +17,7 @@ error[E0599]: no method named `method` found for union `MaybeUninit` in the curr LL | item.method(); | ^^^^^^ method not found in `MaybeUninit<Struct<u32>>` | - = help: if this `MaybeUninit::<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value + = help: if this `MaybeUninit<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value note: the method `method` exists on the type `Struct<u32>` --> $DIR/inner_type2.rs:6:5 | diff --git a/src/test/ui/suggestions/issue-102354.stderr b/src/test/ui/suggestions/issue-102354.stderr index 4f76c5f2e75..b17c4dc5dfb 100644 --- a/src/test/ui/suggestions/issue-102354.stderr +++ b/src/test/ui/suggestions/issue-102354.stderr @@ -13,7 +13,7 @@ LL | fn func() {} help: use associated function syntax instead | LL | i32::func(); - | ~~~~~~~~~ + | ~~~~~~~~~~~ help: disambiguate the associated function for the candidate | LL | <i32 as Trait>::func(x); diff --git a/src/test/ui/suggestions/issue-104086-suggest-let.rs b/src/test/ui/suggestions/issue-104086-suggest-let.rs new file mode 100644 index 00000000000..d22ad27d0e0 --- /dev/null +++ b/src/test/ui/suggestions/issue-104086-suggest-let.rs @@ -0,0 +1,30 @@ +fn main() { + x = x = x; + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `x` in this scope + + x = y = y = y; + //~^ ERROR cannot find value `y` in this scope + //~| ERROR cannot find value `y` in this scope + //~| ERROR cannot find value `y` in this scope + //~| ERROR cannot find value `x` in this scope + + x = y = y; + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `y` in this scope + //~| ERROR cannot find value `y` in this scope + + x = x = y; + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `y` in this scope + + x = x; // will suggest add `let` + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `x` in this scope + + x = y // will suggest add `let` + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `y` in this scope +} diff --git a/src/test/ui/suggestions/issue-104086-suggest-let.stderr b/src/test/ui/suggestions/issue-104086-suggest-let.stderr new file mode 100644 index 00000000000..fb4ea3121ac --- /dev/null +++ b/src/test/ui/suggestions/issue-104086-suggest-let.stderr @@ -0,0 +1,135 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:2:5 + | +LL | x = x = x; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = x = x; + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:2:9 + | +LL | x = x = x; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:2:13 + | +LL | x = x = x; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:7:5 + | +LL | x = y = y = y; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = y = y = y; + | +++ + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:7:9 + | +LL | x = y = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:7:13 + | +LL | x = y = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:7:17 + | +LL | x = y = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:13:5 + | +LL | x = y = y; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = y = y; + | +++ + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:13:9 + | +LL | x = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:13:13 + | +LL | x = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:18:5 + | +LL | x = x = y; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = x = y; + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:18:9 + | +LL | x = x = y; + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:18:13 + | +LL | x = x = y; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:23:5 + | +LL | x = x; // will suggest add `let` + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = x; // will suggest add `let` + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:23:9 + | +LL | x = x; // will suggest add `let` + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:27:5 + | +LL | x = y // will suggest add `let` + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = y // will suggest add `let` + | +++ + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:27:9 + | +LL | x = y // will suggest add `let` + | ^ not found in this scope + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/suggestions/multibyte-escapes.rs b/src/test/ui/suggestions/multibyte-escapes.rs index fd5d46a4e92..c4105186244 100644 --- a/src/test/ui/suggestions/multibyte-escapes.rs +++ b/src/test/ui/suggestions/multibyte-escapes.rs @@ -2,17 +2,17 @@ fn main() { b'µ'; - //~^ ERROR: non-ASCII character in byte constant + //~^ ERROR: non-ASCII character in byte literal //~| HELP: if you meant to use the unicode code point for 'µ', use a \xHH escape - //~| NOTE: byte constant must be ASCII + //~| NOTE: must be ASCII b'字'; - //~^ ERROR: non-ASCII character in byte constant + //~^ ERROR: non-ASCII character in byte literal //~| NOTE: this multibyte character does not fit into a single byte - //~| NOTE: byte constant must be ASCII + //~| NOTE: must be ASCII b"字"; - //~^ ERROR: non-ASCII character in byte constant + //~^ ERROR: non-ASCII character in byte string literal //~| HELP: if you meant to use the UTF-8 encoding of '字', use \xHH escapes - //~| NOTE: byte constant must be ASCII + //~| NOTE: must be ASCII } diff --git a/src/test/ui/suggestions/multibyte-escapes.stderr b/src/test/ui/suggestions/multibyte-escapes.stderr index 6e26bc1f01c..1e7c43e6538 100644 --- a/src/test/ui/suggestions/multibyte-escapes.stderr +++ b/src/test/ui/suggestions/multibyte-escapes.stderr @@ -1,28 +1,28 @@ -error: non-ASCII character in byte constant +error: non-ASCII character in byte literal --> $DIR/multibyte-escapes.rs:4:7 | LL | b'µ'; - | ^ byte constant must be ASCII + | ^ must be ASCII | help: if you meant to use the unicode code point for 'µ', use a \xHH escape | LL | b'\xB5'; | ~~~~ -error: non-ASCII character in byte constant +error: non-ASCII character in byte literal --> $DIR/multibyte-escapes.rs:9:7 | LL | b'字'; | ^^ | | - | byte constant must be ASCII + | must be ASCII | this multibyte character does not fit into a single byte -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/multibyte-escapes.rs:14:7 | LL | b"字"; - | ^^ byte constant must be ASCII + | ^^ must be ASCII | help: if you meant to use the UTF-8 encoding of '字', use \xHH escapes | diff --git a/src/test/ui/suggestions/option-to-bool.rs b/src/test/ui/suggestions/option-to-bool.rs new file mode 100644 index 00000000000..2a1823b15f5 --- /dev/null +++ b/src/test/ui/suggestions/option-to-bool.rs @@ -0,0 +1,9 @@ +#![cfg_attr(let_chains, feature(let_chains))] + +fn foo(x: Option<i32>) { + if true && x {} + //~^ ERROR mismatched types + //~| HELP use `Option::is_some` to test if the `Option` has a value +} + +fn main() {} diff --git a/src/test/ui/suggestions/option-to-bool.stderr b/src/test/ui/suggestions/option-to-bool.stderr new file mode 100644 index 00000000000..57a934b8342 --- /dev/null +++ b/src/test/ui/suggestions/option-to-bool.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/option-to-bool.rs:4:16 + | +LL | if true && x {} + | ^ expected `bool`, found enum `Option` + | + = note: expected type `bool` + found enum `Option<i32>` +help: use `Option::is_some` to test if the `Option` has a value + | +LL | if true && x.is_some() {} + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs new file mode 100644 index 00000000000..a39b8711dd8 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs @@ -0,0 +1,11 @@ +struct GenericAssocMethod<T>(T); + +impl<T> GenericAssocMethod<T> { + fn default_hello() {} +} + +fn main() { + let x = GenericAssocMethod(33); + x.default_hello(); + //~^ ERROR no method named `default_hello` found +} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr new file mode 100644 index 00000000000..c247e73b39c --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr @@ -0,0 +1,22 @@ +error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:9:7 + | +LL | struct GenericAssocMethod<T>(T); + | ---------------------------- method `default_hello` not found for this struct +... +LL | x.default_hello(); + | --^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<_>::default_hello()` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod<T>` + --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:4:5 + | +LL | fn default_hello() {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr index 996d5773118..7c9f0b6c212 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr @@ -2,10 +2,10 @@ error[E0599]: no method named `hello` found for struct `RefMut<'_, HasAssocMetho --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11 | LL | state.hello(); - | ------^^^^^ + | ------^^^^^-- | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `HasAssocMethod::hello` + | help: use associated function syntax instead: `HasAssocMethod::hello()` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `HasAssocMethod` diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed new file mode 100644 index 00000000000..02dd0715c80 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed @@ -0,0 +1,26 @@ +// run-rustfix + +struct GenericAssocMethod<T>(T); + +impl<T> GenericAssocMethod<T> { + fn default_hello() {} + fn self_ty_hello(_: Self) {} + fn self_ty_ref_hello(_: &Self) {} +} + +fn main() { + // Test for inferred types + let x = GenericAssocMethod(33); + GenericAssocMethod::<_>::self_ty_ref_hello(&x); + //~^ ERROR no method named `self_ty_ref_hello` found + GenericAssocMethod::<_>::self_ty_hello(x); + //~^ ERROR no method named `self_ty_hello` found + // Test for known types + let y = GenericAssocMethod(33i32); + GenericAssocMethod::<i32>::default_hello(); + //~^ ERROR no method named `default_hello` found + GenericAssocMethod::<i32>::self_ty_ref_hello(&y); + //~^ ERROR no method named `self_ty_ref_hello` found + GenericAssocMethod::<i32>::self_ty_hello(y); + //~^ ERROR no method named `self_ty_hello` found +} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs index 2a829db5383..1d0ca8e780a 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs @@ -1,11 +1,26 @@ +// run-rustfix + struct GenericAssocMethod<T>(T); impl<T> GenericAssocMethod<T> { fn default_hello() {} + fn self_ty_hello(_: Self) {} + fn self_ty_ref_hello(_: &Self) {} } fn main() { - let x = GenericAssocMethod(33i32); - x.default_hello(); + // Test for inferred types + let x = GenericAssocMethod(33); + x.self_ty_ref_hello(); + //~^ ERROR no method named `self_ty_ref_hello` found + x.self_ty_hello(); + //~^ ERROR no method named `self_ty_hello` found + // Test for known types + let y = GenericAssocMethod(33i32); + y.default_hello(); //~^ ERROR no method named `default_hello` found + y.self_ty_ref_hello(); + //~^ ERROR no method named `self_ty_ref_hello` found + y.self_ty_hello(); + //~^ ERROR no method named `self_ty_hello` found } diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr index 3fb418b1c0a..92b03fc7714 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -1,22 +1,98 @@ +error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:14:7 + | +LL | struct GenericAssocMethod<T>(T); + | ---------------------------- method `self_ty_ref_hello` not found for this struct +... +LL | x.self_ty_ref_hello(); + | --^^^^^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_ref_hello(&x)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod<T>` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5 + | +LL | fn self_ty_ref_hello(_: &Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:16:7 + | +LL | struct GenericAssocMethod<T>(T); + | ---------------------------- method `self_ty_hello` not found for this struct +... +LL | x.self_ty_hello(); + | --^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_hello(x)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod<T>` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5 + | +LL | fn self_ty_hello(_: Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<i32>` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:20:7 | LL | struct GenericAssocMethod<T>(T); | ---------------------------- method `default_hello` not found for this struct ... -LL | x.default_hello(); - | --^^^^^^^^^^^^^ +LL | y.default_hello(); + | --^^^^^^^^^^^^^-- | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::<i32>::default_hello` + | help: use associated function syntax instead: `GenericAssocMethod::<i32>::default_hello()` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `GenericAssocMethod<T>` - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:4:5 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:6:5 | LL | fn default_hello() {} | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<i32>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:22:7 + | +LL | struct GenericAssocMethod<T>(T); + | ---------------------------- method `self_ty_ref_hello` not found for this struct +... +LL | y.self_ty_ref_hello(); + | --^^^^^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<i32>::self_ty_ref_hello(&y)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod<T>` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5 + | +LL | fn self_ty_ref_hello(_: &Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<i32>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:24:7 + | +LL | struct GenericAssocMethod<T>(T); + | ---------------------------- method `self_ty_hello` not found for this struct +... +LL | y.self_ty_hello(); + | --^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<i32>::self_ty_hello(y)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod<T>` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5 + | +LL | fn self_ty_hello(_: Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs b/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs new file mode 100644 index 00000000000..c1a94456268 --- /dev/null +++ b/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs @@ -0,0 +1,6 @@ +fn main() { + let _: f64 = 0..10; //~ ERROR mismatched types + let _: f64 = 1..; //~ ERROR mismatched types + let _: f64 = ..10; //~ ERROR mismatched types + let _: f64 = std::ops::Range { start: 0, end: 1 }; //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr b/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr new file mode 100644 index 00000000000..773f1392ae7 --- /dev/null +++ b/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/unnecessary_dot_for_floating_point_literal.rs:2:18 + | +LL | let _: f64 = 0..10; + | --- ^^^^^ expected `f64`, found struct `std::ops::Range` + | | + | expected due to this + | + = note: expected type `f64` + found struct `std::ops::Range<{integer}>` +help: remove the unnecessary `.` operator for a floating point literal + | +LL | let _: f64 = 0.10; + | ~ + +error[E0308]: mismatched types + --> $DIR/unnecessary_dot_for_floating_point_literal.rs:3:18 + | +LL | let _: f64 = 1..; + | --- ^^^ expected `f64`, found struct `RangeFrom` + | | + | expected due to this + | + = note: expected type `f64` + found struct `RangeFrom<{integer}>` +help: remove the unnecessary `.` operator for a floating point literal + | +LL | let _: f64 = 1.; + | ~ + +error[E0308]: mismatched types + --> $DIR/unnecessary_dot_for_floating_point_literal.rs:4:18 + | +LL | let _: f64 = ..10; + | --- ^^^^ expected `f64`, found struct `RangeTo` + | | + | expected due to this + | + = note: expected type `f64` + found struct `RangeTo<{integer}>` +help: remove the unnecessary `.` operator and add an integer part for a floating point literal + | +LL | let _: f64 = 0.10; + | ~~ + +error[E0308]: mismatched types + --> $DIR/unnecessary_dot_for_floating_point_literal.rs:5:18 + | +LL | let _: f64 = std::ops::Range { start: 0, end: 1 }; + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `std::ops::Range` + | | + | expected due to this + | + = note: expected type `f64` + found struct `std::ops::Range<{integer}>` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/target-feature/tied-features-cli.one.stderr b/src/test/ui/target-feature/tied-features-cli.one.stderr index 0cc901eecaa..b4b50d98192 100644 --- a/src/test/ui/target-feature/tied-features-cli.one.stderr +++ b/src/test/ui/target-feature/tied-features-cli.one.stderr @@ -1,4 +1,4 @@ -error: target features paca, pacg must all be enabled or disabled together +error: the target features paca, pacg must all be either enabled or disabled together error: aborting due to previous error diff --git a/src/test/ui/target-feature/tied-features-cli.three.stderr b/src/test/ui/target-feature/tied-features-cli.three.stderr index 0cc901eecaa..b4b50d98192 100644 --- a/src/test/ui/target-feature/tied-features-cli.three.stderr +++ b/src/test/ui/target-feature/tied-features-cli.three.stderr @@ -1,4 +1,4 @@ -error: target features paca, pacg must all be enabled or disabled together +error: the target features paca, pacg must all be either enabled or disabled together error: aborting due to previous error diff --git a/src/test/ui/target-feature/tied-features-cli.two.stderr b/src/test/ui/target-feature/tied-features-cli.two.stderr index 0cc901eecaa..b4b50d98192 100644 --- a/src/test/ui/target-feature/tied-features-cli.two.stderr +++ b/src/test/ui/target-feature/tied-features-cli.two.stderr @@ -1,4 +1,4 @@ -error: target features paca, pacg must all be enabled or disabled together +error: the target features paca, pacg must all be either enabled or disabled together error: aborting due to previous error diff --git a/src/test/ui/test-attrs/test-thread-capture.run.stdout b/src/test/ui/test-attrs/test-thread-capture.run.stdout index c712a78afb0..513c8cf2add 100644 --- a/src/test/ui/test-attrs/test-thread-capture.run.stdout +++ b/src/test/ui/test-attrs/test-thread-capture.run.stdout @@ -10,7 +10,7 @@ fee fie foe fum -thread 'main' panicked at 'explicit panic', $DIR/test-thread-capture.rs:32:5 +thread 'thready_fail' panicked at 'explicit panic', $DIR/test-thread-capture.rs:32:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/test/ui/test-attrs/test-thread-nocapture.run.stderr b/src/test/ui/test-attrs/test-thread-nocapture.run.stderr index 0a12a052819..8c905d1af85 100644 --- a/src/test/ui/test-attrs/test-thread-nocapture.run.stderr +++ b/src/test/ui/test-attrs/test-thread-nocapture.run.stderr @@ -1,2 +1,2 @@ -thread 'main' panicked at 'explicit panic', $DIR/test-thread-nocapture.rs:32:5 +thread 'thready_fail' panicked at 'explicit panic', $DIR/test-thread-nocapture.rs:32:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/test/ui/track-diagnostics/track.stderr b/src/test/ui/track-diagnostics/track.stderr index ba26cf7c745..8256c1f5f0f 100644 --- a/src/test/ui/track-diagnostics/track.stderr +++ b/src/test/ui/track-diagnostics/track.stderr @@ -5,11 +5,11 @@ LL | break rust | ^^^^ not found in this scope -Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC -error[E0268]: `break` outside of a loop +error[E0268]: `break` outside of a loop or labeled block --> $DIR/track.rs:LL:CC | LL | break rust - | ^^^^^^^^^^ cannot `break` outside of a loop + | ^^^^^^^^^^ cannot `break` outside of a loop or labeled block -Ztrack-diagnostics: created at compiler/rustc_passes/src/loops.rs:LL:CC error: internal compiler error: It looks like you're trying to break rust; would you like some ICE? diff --git a/src/test/ui/traits/invalid_operator_trait.rs b/src/test/ui/traits/invalid_operator_trait.rs new file mode 100644 index 00000000000..7ea3b0d5bac --- /dev/null +++ b/src/test/ui/traits/invalid_operator_trait.rs @@ -0,0 +1,23 @@ +#![crate_type = "lib"] +#![feature(lang_items)] +#![feature(no_core)] +#![no_core] + +#[lang="sized"] +pub trait Sized { + // Empty. +} + +#[lang = "add"] +trait Add<RHS=Self> { + type Output; + + fn add<Y>(self, _: RHS) -> Self::Output; + //~^ ERROR `add` must not have any generic parameters +} + +#[allow(unreachable_code)] +fn ice(a: usize) { + let r = loop {}; + r = r + a; +} diff --git a/src/test/ui/traits/invalid_operator_trait.stderr b/src/test/ui/traits/invalid_operator_trait.stderr new file mode 100644 index 00000000000..8c6e3695905 --- /dev/null +++ b/src/test/ui/traits/invalid_operator_trait.stderr @@ -0,0 +1,8 @@ +error: `add` must not have any generic parameters + --> $DIR/invalid_operator_trait.rs:15:5 + | +LL | fn add<Y>(self, _: RHS) -> Self::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr index e210f11b3e0..b6a04585583 100644 --- a/src/test/ui/traits/issue-77982.stderr +++ b/src/test/ui/traits/issue-77982.stderr @@ -46,12 +46,7 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect( | | | required by a bound introduced by this call | - = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`: - - impl From<Ipv4Addr> for u32; - - impl From<NonZeroU32> for u32; - - impl From<bool> for u32; - - impl From<char> for u32; - and 3 more + = note: cannot satisfy `u32: From<_>` help: try using a fully qualified path to specify the expected types | LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect(); diff --git a/src/test/ui/traits/issue-82830.rs b/src/test/ui/traits/issue-82830.rs index c8289b2e30b..37bae2e90a5 100644 --- a/src/test/ui/traits/issue-82830.rs +++ b/src/test/ui/traits/issue-82830.rs @@ -1,10 +1,12 @@ +// check-pass + trait A<Y, N> { type B; } type MaybeBox<T> = <T as A<T, Box<T>>>::B; struct P { - t: MaybeBox<P>, //~ ERROR: overflow evaluating the requirement `P: Sized` + t: MaybeBox<P>, } impl<Y, N> A<Y, N> for P { diff --git a/src/test/ui/traits/issue-82830.stderr b/src/test/ui/traits/issue-82830.stderr deleted file mode 100644 index 6a597a40215..00000000000 --- a/src/test/ui/traits/issue-82830.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0275]: overflow evaluating the requirement `P: Sized` - --> $DIR/issue-82830.rs:7:8 - | -LL | t: MaybeBox<P>, - | ^^^^^^^^^^^ - | -note: required for `P` to implement `A<P, Box<P>>` - --> $DIR/issue-82830.rs:10:12 - | -LL | impl<Y, N> A<Y, N> for P { - | ^^^^^^^ ^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/traits/negative-impls/eager-mono.rs b/src/test/ui/traits/negative-impls/eager-mono.rs new file mode 100644 index 00000000000..ce770376c0b --- /dev/null +++ b/src/test/ui/traits/negative-impls/eager-mono.rs @@ -0,0 +1,12 @@ +// build-pass +// compile-flags:-C link-dead-code=y + +#![feature(negative_impls)] + +trait Foo { + fn foo() {} +} + +impl !Foo for () {} + +fn main() {} diff --git a/src/test/ui/traits/trait-upcasting/basic.rs b/src/test/ui/traits/trait-upcasting/basic.rs index 484a222bc01..570ec5160bf 100644 --- a/src/test/ui/traits/trait-upcasting/basic.rs +++ b/src/test/ui/traits/trait-upcasting/basic.rs @@ -1,7 +1,6 @@ // run-pass #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { diff --git a/src/test/ui/traits/trait-upcasting/correct-supertrait-substitution.rs b/src/test/ui/traits/trait-upcasting/correct-supertrait-substitution.rs index 8d0a9ef0ace..eae5cf8d58d 100644 --- a/src/test/ui/traits/trait-upcasting/correct-supertrait-substitution.rs +++ b/src/test/ui/traits/trait-upcasting/correct-supertrait-substitution.rs @@ -1,6 +1,5 @@ // run-pass #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {} trait Bar<T: Default + ToString> { diff --git a/src/test/ui/traits/trait-upcasting/diamond.rs b/src/test/ui/traits/trait-upcasting/diamond.rs index e4e23c1a26e..a4f81c464b4 100644 --- a/src/test/ui/traits/trait-upcasting/diamond.rs +++ b/src/test/ui/traits/trait-upcasting/diamond.rs @@ -1,7 +1,6 @@ // run-pass #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { diff --git a/src/test/ui/traits/trait-upcasting/invalid-upcast.rs b/src/test/ui/traits/trait-upcasting/invalid-upcast.rs index 24022450406..e634bbd5ac6 100644 --- a/src/test/ui/traits/trait-upcasting/invalid-upcast.rs +++ b/src/test/ui/traits/trait-upcasting/invalid-upcast.rs @@ -1,5 +1,4 @@ #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo { fn a(&self) -> i32 { diff --git a/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr b/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr index b4530ed0c3a..3aa21ee3ddd 100644 --- a/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr +++ b/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:54:35 + --> $DIR/invalid-upcast.rs:53:35 | LL | let _: &dyn std::fmt::Debug = baz; | -------------------- ^^^ expected trait `Debug`, found trait `Baz` @@ -10,7 +10,7 @@ LL | let _: &dyn std::fmt::Debug = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:56:24 + --> $DIR/invalid-upcast.rs:55:24 | LL | let _: &dyn Send = baz; | --------- ^^^ expected trait `Send`, found trait `Baz` @@ -21,7 +21,7 @@ LL | let _: &dyn Send = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:58:24 + --> $DIR/invalid-upcast.rs:57:24 | LL | let _: &dyn Sync = baz; | --------- ^^^ expected trait `Sync`, found trait `Baz` @@ -32,7 +32,7 @@ LL | let _: &dyn Sync = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:61:25 + --> $DIR/invalid-upcast.rs:60:25 | LL | let bar: &dyn Bar = baz; | -------- ^^^ expected trait `Bar`, found trait `Baz` @@ -43,7 +43,7 @@ LL | let bar: &dyn Bar = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:63:35 + --> $DIR/invalid-upcast.rs:62:35 | LL | let _: &dyn std::fmt::Debug = bar; | -------------------- ^^^ expected trait `Debug`, found trait `Bar` @@ -54,7 +54,7 @@ LL | let _: &dyn std::fmt::Debug = bar; found reference `&dyn Bar` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:65:24 + --> $DIR/invalid-upcast.rs:64:24 | LL | let _: &dyn Send = bar; | --------- ^^^ expected trait `Send`, found trait `Bar` @@ -65,7 +65,7 @@ LL | let _: &dyn Send = bar; found reference `&dyn Bar` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:67:24 + --> $DIR/invalid-upcast.rs:66:24 | LL | let _: &dyn Sync = bar; | --------- ^^^ expected trait `Sync`, found trait `Bar` @@ -76,7 +76,7 @@ LL | let _: &dyn Sync = bar; found reference `&dyn Bar` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:70:25 + --> $DIR/invalid-upcast.rs:69:25 | LL | let foo: &dyn Foo = baz; | -------- ^^^ expected trait `Foo`, found trait `Baz` @@ -87,7 +87,7 @@ LL | let foo: &dyn Foo = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:72:35 + --> $DIR/invalid-upcast.rs:71:35 | LL | let _: &dyn std::fmt::Debug = foo; | -------------------- ^^^ expected trait `Debug`, found trait `Foo` @@ -98,7 +98,7 @@ LL | let _: &dyn std::fmt::Debug = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:74:24 + --> $DIR/invalid-upcast.rs:73:24 | LL | let _: &dyn Send = foo; | --------- ^^^ expected trait `Send`, found trait `Foo` @@ -109,7 +109,7 @@ LL | let _: &dyn Send = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:76:24 + --> $DIR/invalid-upcast.rs:75:24 | LL | let _: &dyn Sync = foo; | --------- ^^^ expected trait `Sync`, found trait `Foo` @@ -120,7 +120,7 @@ LL | let _: &dyn Sync = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:79:25 + --> $DIR/invalid-upcast.rs:78:25 | LL | let foo: &dyn Foo = bar; | -------- ^^^ expected trait `Foo`, found trait `Bar` @@ -131,7 +131,7 @@ LL | let foo: &dyn Foo = bar; found reference `&dyn Bar` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:81:35 + --> $DIR/invalid-upcast.rs:80:35 | LL | let _: &dyn std::fmt::Debug = foo; | -------------------- ^^^ expected trait `Debug`, found trait `Foo` @@ -142,7 +142,7 @@ LL | let _: &dyn std::fmt::Debug = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:83:24 + --> $DIR/invalid-upcast.rs:82:24 | LL | let _: &dyn Send = foo; | --------- ^^^ expected trait `Send`, found trait `Foo` @@ -153,7 +153,7 @@ LL | let _: &dyn Send = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:85:24 + --> $DIR/invalid-upcast.rs:84:24 | LL | let _: &dyn Sync = foo; | --------- ^^^ expected trait `Sync`, found trait `Foo` diff --git a/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs index 6d88002540c..b672963ae98 100644 --- a/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs +++ b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs @@ -1,6 +1,5 @@ // run-pass #![feature(trait_upcasting)] -#![allow(incomplete_features)] struct Test { func: Box<dyn FnMut() + 'static>, diff --git a/src/test/ui/traits/trait-upcasting/lifetime.rs b/src/test/ui/traits/trait-upcasting/lifetime.rs index f029a6f081f..9825158c2dd 100644 --- a/src/test/ui/traits/trait-upcasting/lifetime.rs +++ b/src/test/ui/traits/trait-upcasting/lifetime.rs @@ -1,7 +1,6 @@ // run-pass #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { diff --git a/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs index 6986ad62172..2e53a00a90e 100644 --- a/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs +++ b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs @@ -1,12 +1,11 @@ // check-fail #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Bar<T> { fn bar(&self, _: T) {} } -trait Foo : Bar<i32> + Bar<u32> { +trait Foo: Bar<i32> + Bar<u32> { fn foo(&self, _: ()) {} } diff --git a/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr index 9564813512c..0ad18be03cd 100644 --- a/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr +++ b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/multiple-occurrence-ambiguousity.rs:21:26 + --> $DIR/multiple-occurrence-ambiguousity.rs:20:26 | LL | let t: &dyn Bar<_> = s; | ----------- ^ expected trait `Bar`, found trait `Foo` diff --git a/src/test/ui/traits/trait-upcasting/replace-vptr.rs b/src/test/ui/traits/trait-upcasting/replace-vptr.rs index 1164e43611a..9ccfc9306ac 100644 --- a/src/test/ui/traits/trait-upcasting/replace-vptr.rs +++ b/src/test/ui/traits/trait-upcasting/replace-vptr.rs @@ -1,7 +1,6 @@ // run-pass #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait A { fn foo_a(&self); diff --git a/src/test/ui/traits/trait-upcasting/struct.rs b/src/test/ui/traits/trait-upcasting/struct.rs index 0f3cb285bf4..a3e41696956 100644 --- a/src/test/ui/traits/trait-upcasting/struct.rs +++ b/src/test/ui/traits/trait-upcasting/struct.rs @@ -1,7 +1,6 @@ // run-pass #![feature(trait_upcasting)] -#![allow(incomplete_features)] use std::rc::Rc; use std::sync::Arc; diff --git a/src/test/ui/traits/trait-upcasting/subtrait-method.rs b/src/test/ui/traits/trait-upcasting/subtrait-method.rs index 3508e15284b..136d15af0e8 100644 --- a/src/test/ui/traits/trait-upcasting/subtrait-method.rs +++ b/src/test/ui/traits/trait-upcasting/subtrait-method.rs @@ -1,5 +1,4 @@ #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { diff --git a/src/test/ui/traits/trait-upcasting/subtrait-method.stderr b/src/test/ui/traits/trait-upcasting/subtrait-method.stderr index af7a410f6d9..918159e845b 100644 --- a/src/test/ui/traits/trait-upcasting/subtrait-method.stderr +++ b/src/test/ui/traits/trait-upcasting/subtrait-method.stderr @@ -1,64 +1,64 @@ error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope - --> $DIR/subtrait-method.rs:56:9 + --> $DIR/subtrait-method.rs:55:9 | LL | bar.c(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Baz` defines an item `c`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:28:1 + --> $DIR/subtrait-method.rs:27:1 | LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope - --> $DIR/subtrait-method.rs:60:9 + --> $DIR/subtrait-method.rs:59:9 | LL | foo.b(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `b`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:18:1 + --> $DIR/subtrait-method.rs:17:1 | LL | trait Bar: Foo { | ^^^^^^^^^^^^^^ error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope - --> $DIR/subtrait-method.rs:62:9 + --> $DIR/subtrait-method.rs:61:9 | LL | foo.c(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Baz` defines an item `c`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:28:1 + --> $DIR/subtrait-method.rs:27:1 | LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope - --> $DIR/subtrait-method.rs:66:9 + --> $DIR/subtrait-method.rs:65:9 | LL | foo.b(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `b`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:18:1 + --> $DIR/subtrait-method.rs:17:1 | LL | trait Bar: Foo { | ^^^^^^^^^^^^^^ error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope - --> $DIR/subtrait-method.rs:68:9 + --> $DIR/subtrait-method.rs:67:9 | LL | foo.c(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Baz` defines an item `c`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:28:1 + --> $DIR/subtrait-method.rs:27:1 | LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-1.rs b/src/test/ui/traits/trait-upcasting/type-checking-test-1.rs index 79ddedd4187..6bc9f4a75d3 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-1.rs +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-1.rs @@ -1,5 +1,4 @@ #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo: Bar<i32> + Bar<u32> {} trait Bar<T> { diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr index 3985372119e..fe269d8e99b 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` - --> $DIR/type-checking-test-1.rs:17:13 + --> $DIR/type-checking-test-1.rs:16:13 | LL | let _ = x as &dyn Bar<_>; // Ambiguous | ^^^^^^^^^^^^^^^^ invalid cast @@ -10,7 +10,7 @@ LL | let _ = &x as &dyn Bar<_>; // Ambiguous | + error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied - --> $DIR/type-checking-test-1.rs:17:13 + --> $DIR/type-checking-test-1.rs:16:13 | LL | let _ = x as &dyn Bar<_>; // Ambiguous | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-2.rs b/src/test/ui/traits/trait-upcasting/type-checking-test-2.rs index 32754c53803..36b11dffdb1 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-2.rs +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-2.rs @@ -1,5 +1,4 @@ #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo<T>: Bar<i32> + Bar<T> {} trait Bar<T> { diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr index 93c71f54eb5..ef007d5cb90 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>` - --> $DIR/type-checking-test-2.rs:20:13 + --> $DIR/type-checking-test-2.rs:19:13 | LL | let _ = x as &dyn Bar<u32>; // Error | ^^^^^^^^^^^^^^^^^^ invalid cast @@ -10,7 +10,7 @@ LL | let _ = &x as &dyn Bar<u32>; // Error | + error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied - --> $DIR/type-checking-test-2.rs:20:13 + --> $DIR/type-checking-test-2.rs:19:13 | LL | let _ = x as &dyn Bar<u32>; // Error | ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>` @@ -18,7 +18,7 @@ LL | let _ = x as &dyn Bar<u32>; // Error = note: required for the cast from `&dyn Foo<i32>` to the object type `dyn Bar<u32>` error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>` - --> $DIR/type-checking-test-2.rs:26:13 + --> $DIR/type-checking-test-2.rs:25:13 | LL | let a = x as &dyn Bar<_>; // Ambiguous | ^^^^^^^^^^^^^^^^ invalid cast @@ -29,7 +29,7 @@ LL | let a = &x as &dyn Bar<_>; // Ambiguous | + error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied - --> $DIR/type-checking-test-2.rs:26:13 + --> $DIR/type-checking-test-2.rs:25:13 | LL | let a = x as &dyn Bar<_>; // Ambiguous | ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>` diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr index e48ba709af1..e6cb6a75399 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr @@ -1,22 +1,18 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-3.rs:13:13 + --> $DIR/type-checking-test-3.rs:11:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here LL | let _ = x as &dyn Bar<'a>; // Error | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-3.rs:18:13 + --> $DIR/type-checking-test-3.rs:16:13 | LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) { | -- lifetime `'a` defined here LL | let _ = x as &dyn Bar<'static>; // Error | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-3.rs b/src/test/ui/traits/trait-upcasting/type-checking-test-3.rs index b3aa2279a30..b2db3a12797 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-3.rs +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-3.rs @@ -1,5 +1,4 @@ #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo<'a>: Bar<'a> {} trait Bar<'a> {} @@ -10,12 +9,12 @@ fn test_correct(x: &dyn Foo<'static>) { fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { let _ = x as &dyn Bar<'a>; // Error - //~^ ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn test_wrong2<'a>(x: &dyn Foo<'a>) { let _ = x as &dyn Bar<'static>; // Error - //~^ ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr index 5ad151b5092..e6cb6a75399 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-3.rs:12:13 + --> $DIR/type-checking-test-3.rs:11:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -7,7 +7,7 @@ LL | let _ = x as &dyn Bar<'a>; // Error | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-3.rs:17:13 + --> $DIR/type-checking-test-3.rs:16:13 | LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) { | -- lifetime `'a` defined here diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr index a3411f40ad0..8d506e5807e 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr @@ -1,33 +1,52 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:17:13 + --> $DIR/type-checking-test-4.rs:15:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here LL | let _ = x as &dyn Bar<'static, 'a>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:22:13 + --> $DIR/type-checking-test-4.rs:20:13 | LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here LL | let _ = x as &dyn Bar<'a, 'static>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:29:5 + --> $DIR/type-checking-test-4.rs:26:5 | LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here -... +LL | let y = x as &dyn Bar<'_, '_>; LL | y.get_b() // ERROR | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:31:5 + | +LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:36:5 + | +LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:44:5 | - = help: consider replacing `'a` with `'static` +LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +... +LL | z.get_b() // ERROR + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs b/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs index 70ccc87fc3e..f40c48f0d12 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs @@ -1,5 +1,4 @@ #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo<'a>: Bar<'a, 'a> {} trait Bar<'a, 'b> { @@ -14,28 +13,28 @@ fn test_correct(x: &dyn Foo<'static>) { fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { let _ = x as &dyn Bar<'static, 'a>; // Error - //~^ ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { let _ = x as &dyn Bar<'a, 'static>; // Error - //~^ ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { let y = x as &dyn Bar<'_, '_>; y.get_b() // ERROR - //~^ ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { <_ as Bar>::get_b(x) // ERROR - //~^ ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { <_ as Bar<'_, '_>>::get_b(x) // ERROR - //~^ ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { @@ -43,7 +42,7 @@ fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { y.get_b(); // ERROR let z = y; z.get_b() // ERROR - //~^ ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr index 436129d0bee..8d506e5807e 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:16:13 + --> $DIR/type-checking-test-4.rs:15:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -7,7 +7,7 @@ LL | let _ = x as &dyn Bar<'static, 'a>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:21:13 + --> $DIR/type-checking-test-4.rs:20:13 | LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -15,7 +15,7 @@ LL | let _ = x as &dyn Bar<'a, 'static>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:27:5 + --> $DIR/type-checking-test-4.rs:26:5 | LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -24,7 +24,7 @@ LL | y.get_b() // ERROR | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:32:5 + --> $DIR/type-checking-test-4.rs:31:5 | LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -32,7 +32,7 @@ LL | <_ as Bar>::get_b(x) // ERROR | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:37:5 + --> $DIR/type-checking-test-4.rs:36:5 | LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -40,7 +40,7 @@ LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:45:5 + --> $DIR/type-checking-test-4.rs:44:5 | LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here diff --git a/src/test/ui/transmute/transmute-padding-ice.rs b/src/test/ui/transmute/transmute-padding-ice.rs new file mode 100644 index 00000000000..a1be7075a8a --- /dev/null +++ b/src/test/ui/transmute/transmute-padding-ice.rs @@ -0,0 +1,29 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, + >, + { + } +} + +fn test() { + #[repr(C, align(2))] + struct A(u8, u8); + + #[repr(C)] + struct B(u8, u8); + + assert::is_maybe_transmutable::<B, A>(); + //~^ ERROR cannot be safely transmuted +} diff --git a/src/test/ui/transmute/transmute-padding-ice.stderr b/src/test/ui/transmute/transmute-padding-ice.stderr new file mode 100644 index 00000000000..c9233890f7a --- /dev/null +++ b/src/test/ui/transmute/transmute-padding-ice.stderr @@ -0,0 +1,24 @@ +error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + --> $DIR/transmute-padding-ice.rs:27:40 + | +LL | assert::is_maybe_transmutable::<B, A>(); + | ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `A` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/transmute-padding-ice.rs:11:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom< + | ______________^ +LL | | Src, +LL | | Context, +LL | | { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, +LL | | >, + | |_________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 067ed7ea1e5..cad3e0f6677 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -1,7 +1,6 @@ +// check-pass // Regression test for issue #57611 // Ensures that we don't ICE -// FIXME: This should compile, but it currently doesn't -// known-bug: unknown #![feature(trait_alias)] #![feature(type_alias_impl_trait)] diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr deleted file mode 100644 index 6344f114a91..00000000000 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-57611-trait-alias.rs:21:9 - | -LL | |x| x - | ^^^^^ one type is more general than the other - | - = note: expected trait `for<'a> Fn<(&'a X,)>` - found trait `Fn<(&X,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:21:9 - | -LL | |x| x - | ^^^ - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:21:9 - | -LL | |x| x - | ^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type/issue-103271.rs b/src/test/ui/type/issue-103271.rs new file mode 100644 index 00000000000..bd3254af3df --- /dev/null +++ b/src/test/ui/type/issue-103271.rs @@ -0,0 +1,10 @@ +fn main() { + let iter_fun = <&[u32]>::iter; + //~^ ERROR no function or associated item named `iter` found for reference `&[u32]` in the current scope [E0599] + //~| function or associated item not found in `&[u32]` + //~| HELP the function `iter` is implemented on `[u32]` + for item in iter_fun(&[1,1]) { + let x: &u32 = item; + assert_eq!(x, &1); + } +} diff --git a/src/test/ui/type/issue-103271.stderr b/src/test/ui/type/issue-103271.stderr new file mode 100644 index 00000000000..02a59d4b99c --- /dev/null +++ b/src/test/ui/type/issue-103271.stderr @@ -0,0 +1,14 @@ +error[E0599]: no function or associated item named `iter` found for reference `&[u32]` in the current scope + --> $DIR/issue-103271.rs:2:30 + | +LL | let iter_fun = <&[u32]>::iter; + | ^^^^ function or associated item not found in `&[u32]` + | +help: the function `iter` is implemented on `[u32]` + | +LL | let iter_fun = <[u32]>::iter; + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-10969.rs b/src/test/ui/typeck/issue-10969.rs index 0b78fc1bb7f..0b78fc1bb7f 100644 --- a/src/test/ui/issues/issue-10969.rs +++ b/src/test/ui/typeck/issue-10969.rs diff --git a/src/test/ui/issues/issue-10969.stderr b/src/test/ui/typeck/issue-10969.stderr index f64b61aaeb0..f64b61aaeb0 100644 --- a/src/test/ui/issues/issue-10969.stderr +++ b/src/test/ui/typeck/issue-10969.stderr diff --git a/src/test/ui/issues/issue-50687-ice-on-borrow.rs b/src/test/ui/typeck/issue-50687-ice-on-borrow.rs index 7a8a12c2a93..7a8a12c2a93 100644 --- a/src/test/ui/issues/issue-50687-ice-on-borrow.rs +++ b/src/test/ui/typeck/issue-50687-ice-on-borrow.rs diff --git a/src/test/ui/issues/issue-50687-ice-on-borrow.stderr b/src/test/ui/typeck/issue-50687-ice-on-borrow.stderr index e6a0edac4b1..e6a0edac4b1 100644 --- a/src/test/ui/issues/issue-50687-ice-on-borrow.stderr +++ b/src/test/ui/typeck/issue-50687-ice-on-borrow.stderr diff --git a/src/test/ui/typeck/issue-83693.stderr b/src/test/ui/typeck/issue-83693.stderr index 0d8bbf1ce98..1e45c2d35df 100644 --- a/src/test/ui/typeck/issue-83693.stderr +++ b/src/test/ui/typeck/issue-83693.stderr @@ -6,8 +6,8 @@ LL | impl F { | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn<Args>: FnMut<Args> { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | -------------------------------------- similarly named trait `Fn` defined here error[E0412]: cannot find type `TestResult` in this scope --> $DIR/issue-83693.rs:9:22 diff --git a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs index 925463d6dee..d2e48600227 100644 --- a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs +++ b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs @@ -1,8 +1,8 @@ #![feature(unboxed_closures)] fn a<F: Fn<usize>>(f: F) {} +//~^ ERROR type parameter to bare `Fn` trait must be a tuple fn main() { a(|_: usize| {}); - //~^ ERROR mismatched types } diff --git a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr index 9a24fb8c2be..1c18eb0fc49 100644 --- a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr +++ b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr @@ -1,17 +1,15 @@ -error[E0308]: mismatched types - --> $DIR/non-tupled-arg-mismatch.rs:6:5 - | -LL | a(|_: usize| {}); - | ^ types differ - | - = note: expected trait `Fn<usize>` - found trait `Fn<(usize,)>` -note: required by a bound in `a` +error[E0059]: type parameter to bare `Fn` trait must be a tuple --> $DIR/non-tupled-arg-mismatch.rs:3:9 | LL | fn a<F: Fn<usize>>(f: F) {} - | ^^^^^^^^^ required by this bound in `a` + | ^^^^^^^^^ the trait `Tuple` is not implemented for `usize` + | +note: required by a bound in `Fn` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn<Args: Tuple>: FnMut<Args> { + | ^^^^^ required by this bound in `Fn` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0059`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs index ed8d7211461..7377359b6b0 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs +++ b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs @@ -1,12 +1,12 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] // Tests that we can't move out of an unboxed closure environment // if the upvar is captured by ref or the closure takes self by // reference. -fn to_fn<A,F:Fn<A>>(f: F) -> F { f } -fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f } -fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f } +fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f } +fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f } +fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f } fn main() { // By-ref cases diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs index 57e6d30658c..c57312b4387 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs @@ -2,12 +2,12 @@ // as `mut` through a closure. Also test that we CAN mutate a moved copy, // unless this is a `Fn` closure. Issue #16749. -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] use std::mem; -fn to_fn<A,F:Fn<A>>(f: F) -> F { f } -fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f } +fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f } +fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f } fn a() { let n = 0; diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr index d6e74b5b8b9..26f97b51913 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr @@ -28,8 +28,8 @@ LL | n += 1; error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure --> $DIR/unboxed-closures-mutate-upvar.rs:53:9 | -LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... LL | let mut f = to_fn(move || { | ----- ------- in this closure diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs index 0e727b11cd2..7289d9322d0 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs @@ -1,6 +1,6 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f } +fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f } fn main() { let mut_ = to_fn_mut(|x| x); diff --git a/src/test/ui/unsafe/unsafe-not-inherited.rs b/src/test/ui/unsafe/unsafe-not-inherited.rs new file mode 100644 index 00000000000..6d797caa0f9 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-not-inherited.rs @@ -0,0 +1,26 @@ +#![allow(unused, dead_code)] + +static mut FOO: u64 = 0; + +fn static_mod() { + unsafe {static BAR: u64 = FOO;} + //~^ ERROR: use of mutable static is unsafe + //~| NOTE: use of mutable static + //~| NOTE: mutable statics can be mutated by multiple threads + //~| NOTE: items do not inherit unsafety +} + +unsafe fn unsafe_call() {} +fn foo() { + unsafe { + //~^ NOTE: items do not inherit unsafety + fn bar() { + unsafe_call(); + //~^ ERROR: call to unsafe function + //~| NOTE: call to unsafe function + //~| NOTE: consult the function's documentation + } + } +} + +fn main() {} diff --git a/src/test/ui/unsafe/unsafe-not-inherited.stderr b/src/test/ui/unsafe/unsafe-not-inherited.stderr new file mode 100644 index 00000000000..3bc5ca5c9d1 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-not-inherited.stderr @@ -0,0 +1,24 @@ +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/unsafe-not-inherited.rs:6:31 + | +LL | unsafe {static BAR: u64 = FOO;} + | ------ ^^^ use of mutable static + | | + | items do not inherit unsafety from separate enclosing items + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/unsafe-not-inherited.rs:18:13 + | +LL | unsafe { + | ------ items do not inherit unsafety from separate enclosing items +... +LL | unsafe_call(); + | ^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/weird-exprs.rs b/src/test/ui/weird-exprs.rs index 4066bcf3bad..d65703ef5ca 100644 --- a/src/test/ui/weird-exprs.rs +++ b/src/test/ui/weird-exprs.rs @@ -8,6 +8,7 @@ #![allow(unreachable_code)] #![allow(unused_braces, unused_must_use, unused_parens)] #![allow(uncommon_codepoints, confusable_idents)] +#![allow(unreachable_patterns)] #![recursion_limit = "256"] @@ -194,6 +195,15 @@ fn bathroom_stall() { assert_eq!(i, 13); } +fn closure_matching() { + let x = |_| Some(1); + let (|x| x) = match x(..) { + |_| Some(2) => |_| Some(3), + |_| _ => unreachable!(), + }; + assert!(matches!(x(..), |_| Some(4))); +} + pub fn main() { strange(); funny(); @@ -216,4 +226,5 @@ pub fn main() { 𝚌𝚘𝚗𝚝𝚒𝚗𝚞𝚎(); function(); bathroom_stall(); + closure_matching(); } diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md index 44c96f31d0b..9d30c554186 100644 --- a/src/tools/build-manifest/README.md +++ b/src/tools/build-manifest/README.md @@ -1,7 +1,16 @@ # build-manifest -This tool generates the manifests uploaded to static.rust-lang.org and used by -rustup. The tool is invoked by the bootstrap tool. +This tool generates the manifests uploaded to static.rust-lang.org and used by rustup. +You can see a full list of all manifests at <https://static.rust-lang.org/manifests.txt>. +This listing is updated by <https://github.com/rust-lang/generate-manifest-list> every 7 days. + +This gets called by `promote-release` <https://github.com/rust-lang/promote-release> via `x.py dist hash-and-sign`. + +## Adding a new component + +1. Add a new `Step` to `dist.rs`. This should usually be named after the filename of the uploaded tarball. See https://github.com/rust-lang/rust/pull/101799/files#diff-2c56335faa24486df09ba392d8900c57e2fac4633e1f7038469bcf9ed3feb871 for an example. + a. If appropriate, call `tarball.is_preview(true)` for the component. +2. Add a new `PkgType` to build-manifest. Fix all the compile errors as appropriate. ## Testing changes locally @@ -9,19 +18,16 @@ In order to test the changes locally you need to have a valid dist directory available locally. If you don't want to build all the compiler, you can easily create one from the nightly artifacts with: -``` -#!/bin/bash -for cmpn in rust rustc rust-std rust-docs cargo; do - wget https://static.rust-lang.org/dist/${cmpn}-nightly-x86_64-unknown-linux-gnu.tar.gz +```sh +for component in rust rustc rust-std rust-docs cargo; do + wget -P build/dist https://static.rust-lang.org/dist/${component}-nightly-x86_64-unknown-linux-gnu.tar.gz done ``` -Then, you can generate the manifest and all the packages from `path/to/dist` to -`path/to/output` with: +Then, you can generate the manifest and all the packages from `build/dist` to +`build/manifest` with: +```sh +mkdir -p build/manifest +cargo +nightly run --release -p build-manifest build/dist build/manifest 1970-01-01 http://example.com nightly ``` -$ cargo +nightly run path/to/dist path/to/output 1970-01-01 http://example.com CHANNEL -``` - -Remember to replace `CHANNEL` with the channel you produced dist artifacts of -and `VERSION` with the current Rust version. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index b0006cb90bd..0551e835bb0 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -1,8 +1,4 @@ -//! Build a dist manifest, hash and sign everything. -//! This gets called by `promote-release` -//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release) -//! via `x.py dist hash-and-sign`; the cmdline arguments are set up -//! by rustbuild (in `src/bootstrap/dist.rs`). +#![doc = include_str!("../README.md")] mod checksum; mod manifest; @@ -64,6 +60,7 @@ static TARGETS: &[&str] = &[ "aarch64-unknown-none", "aarch64-unknown-none-softfloat", "aarch64-unknown-redox", + "aarch64-unknown-uefi", "arm-linux-androideabi", "arm-unknown-linux-gnueabi", "arm-unknown-linux-gnueabihf", @@ -99,6 +96,7 @@ static TARGETS: &[&str] = &[ "i686-unknown-freebsd", "i686-unknown-linux-gnu", "i686-unknown-linux-musl", + "i686-unknown-uefi", "m68k-unknown-linux-gnu", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", @@ -155,6 +153,7 @@ static TARGETS: &[&str] = &[ "x86_64-unknown-none", "x86_64-unknown-redox", "x86_64-unknown-hermit", + "x86_64-unknown-uefi", ]; /// This allows the manifest to contain rust-docs for hosts that don't build @@ -184,7 +183,7 @@ static PKG_INSTALLERS: &[&str] = &["x86_64-apple-darwin", "aarch64-apple-darwin" static MINGW: &[&str] = &["i686-pc-windows-gnu", "x86_64-pc-windows-gnu"]; -static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview", "rust-docs-json-preview"]; +static NIGHTLY_ONLY_COMPONENTS: &[PkgType] = &[PkgType::Miri, PkgType::JsonDocs]; macro_rules! t { ($e:expr) => { @@ -287,28 +286,9 @@ impl Builder { } fn add_packages_to(&mut self, manifest: &mut Manifest) { - macro_rules! package { - ($name:expr, $targets:expr) => { - self.package($name, &mut manifest.pkg, $targets, &[]) - }; + for pkg in PkgType::all() { + self.package(pkg, &mut manifest.pkg); } - package!("rustc", HOSTS); - package!("rustc-dev", HOSTS); - package!("reproducible-artifacts", HOSTS); - package!("rustc-docs", HOSTS); - package!("cargo", HOSTS); - package!("rust-mingw", MINGW); - package!("rust-std", TARGETS); - self.package("rust-docs", &mut manifest.pkg, HOSTS, DOCS_FALLBACK); - self.package("rust-docs-json-preview", &mut manifest.pkg, HOSTS, DOCS_FALLBACK); - package!("rust-src", &["*"]); - package!("rls-preview", HOSTS); - package!("rust-analyzer-preview", HOSTS); - package!("clippy-preview", HOSTS); - package!("miri-preview", HOSTS); - package!("rustfmt-preview", HOSTS); - package!("rust-analysis", TARGETS); - package!("llvm-tools-preview", TARGETS); } fn add_artifacts_to(&mut self, manifest: &mut Manifest) { @@ -333,44 +313,28 @@ impl Builder { } fn add_profiles_to(&mut self, manifest: &mut Manifest) { - let mut profile = |name, pkgs| self.profile(name, &mut manifest.profiles, pkgs); - profile("minimal", &["rustc", "cargo", "rust-std", "rust-mingw"]); - profile( - "default", - &[ - "rustc", - "cargo", - "rust-std", - "rust-mingw", - "rust-docs", - "rustfmt-preview", - "clippy-preview", - ], - ); - profile( - "complete", - &[ - "rustc", - "cargo", - "rust-std", - "rust-mingw", - "rust-docs", - "rustfmt-preview", - "clippy-preview", - "rls-preview", - "rust-analyzer-preview", - "rust-src", - "llvm-tools-preview", - "rust-analysis", - "miri-preview", - ], - ); + use PkgType::*; + + let mut profile = |name, pkgs: &_| self.profile(name, &mut manifest.profiles, pkgs); + + // Use a Vec here to make sure we don't exclude any components in an earlier profile. + let minimal = vec![Rustc, Cargo, RustStd, RustMingw]; + profile("minimal", &minimal); + + let mut default = minimal; + default.extend([HtmlDocs, Rustfmt, Clippy]); + profile("default", &default); + + // NOTE: this profile is effectively deprecated; do not add new components to it. + let mut complete = default; + complete.extend([Rls, RustAnalyzer, RustSrc, LlvmTools, RustAnalysis, Miri]); + profile("complete", &complete); // The compiler libraries are not stable for end users, and they're also huge, so we only // `rustc-dev` for nightly users, and only in the "complete" profile. It's still possible // for users to install the additional component manually, if needed. if self.versions.channel() == "nightly" { - self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]); + self.extend_profile("complete", &mut manifest.profiles, &[RustcDev]); // Do not include the rustc-docs component for now, as it causes // conflicts with the rust-docs component when installed. See // #75833. @@ -382,12 +346,11 @@ impl Builder { let mut rename = |from: &str, to: &str| { manifest.renames.insert(from.to_owned(), Rename { to: to.to_owned() }) }; - rename("rls", "rls-preview"); - rename("rustfmt", "rustfmt-preview"); - rename("clippy", "clippy-preview"); - rename("miri", "miri-preview"); - rename("rust-docs-json", "rust-docs-json-preview"); - rename("rust-analyzer", "rust-analyzer-preview"); + for pkg in PkgType::all() { + if pkg.is_preview() { + rename(pkg.tarball_component_name(), &pkg.manifest_component_name()); + } + } } fn rust_package(&mut self, manifest: &Manifest) -> Package { @@ -419,42 +382,52 @@ impl Builder { let mut components = Vec::new(); let mut extensions = Vec::new(); - let host_component = |pkg| Component::from_str(pkg, host); - - // rustc/rust-std/cargo/docs are all required, - // and so is rust-mingw if it's available for the target. - components.extend(vec![ - host_component("rustc"), - host_component("rust-std"), - host_component("cargo"), - host_component("rust-docs"), - ]); - if host.contains("pc-windows-gnu") { - components.push(host_component("rust-mingw")); - } + let host_component = |pkg: &_| Component::from_pkg(pkg, host); - // Tools are always present in the manifest, - // but might be marked as unavailable if they weren't built. - extensions.extend(vec![ - host_component("clippy-preview"), - host_component("miri-preview"), - host_component("rls-preview"), - host_component("rust-analyzer-preview"), - host_component("rustfmt-preview"), - host_component("llvm-tools-preview"), - host_component("rust-analysis"), - host_component("rust-docs-json-preview"), - ]); - - extensions.extend( - TARGETS - .iter() - .filter(|&&target| target != host) - .map(|target| Component::from_str("rust-std", target)), - ); - extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-dev", target))); - extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-docs", target))); - extensions.push(Component::from_str("rust-src", "*")); + for pkg in PkgType::all() { + match pkg { + // rustc/rust-std/cargo/docs are all required + PkgType::Rustc | PkgType::Cargo | PkgType::HtmlDocs => { + components.push(host_component(pkg)); + } + PkgType::RustStd => { + components.push(host_component(pkg)); + extensions.extend( + TARGETS + .iter() + .filter(|&&target| target != host) + .map(|target| Component::from_pkg(pkg, target)), + ); + } + // so is rust-mingw if it's available for the target + PkgType::RustMingw => { + if host.contains("pc-windows-gnu") { + components.push(host_component(pkg)); + } + } + // Tools are always present in the manifest, + // but might be marked as unavailable if they weren't built. + PkgType::Clippy + | PkgType::Miri + | PkgType::Rls + | PkgType::RustAnalyzer + | PkgType::Rustfmt + | PkgType::LlvmTools + | PkgType::RustAnalysis + | PkgType::JsonDocs => { + extensions.push(host_component(pkg)); + } + PkgType::RustcDev | PkgType::RustcDocs => { + extensions.extend(HOSTS.iter().map(|target| Component::from_pkg(pkg, target))); + } + PkgType::RustSrc => { + extensions.push(Component::from_pkg(pkg, "*")); + } + PkgType::Rust => {} + // NOTE: this is intentional, these artifacts aren't intended to be used with rustup + PkgType::ReproducibleArtifacts => {} + } + } // If the components/extensions don't actually exist for this // particular host/target combination then nix it entirely from our @@ -481,43 +454,44 @@ impl Builder { &mut self, profile_name: &str, dst: &mut BTreeMap<String, Vec<String>>, - pkgs: &[&str], + pkgs: &[PkgType], ) { - dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect()); + dst.insert( + profile_name.to_owned(), + pkgs.iter().map(|s| s.manifest_component_name()).collect(), + ); } fn extend_profile( &mut self, profile_name: &str, dst: &mut BTreeMap<String, Vec<String>>, - pkgs: &[&str], + pkgs: &[PkgType], ) { dst.get_mut(profile_name) .expect("existing profile") - .extend(pkgs.iter().map(|s| (*s).to_owned())); + .extend(pkgs.iter().map(|s| s.manifest_component_name())); } - fn package( - &mut self, - pkgname: &str, - dst: &mut BTreeMap<String, Package>, - targets: &[&str], - fallback: &[(&str, &str)], - ) { - let version_info = self - .versions - .version(&PkgType::from_component(pkgname)) - .expect("failed to load package version"); + fn package(&mut self, pkg: &PkgType, dst: &mut BTreeMap<String, Package>) { + if *pkg == PkgType::Rust { + // This is handled specially by `rust_package` later. + // Order is important, so don't call `rust_package` here. + return; + } + + let fallback = if pkg.use_docs_fallback() { DOCS_FALLBACK } else { &[] }; + let version_info = self.versions.version(&pkg).expect("failed to load package version"); let mut is_present = version_info.present; // Never ship nightly-only components for other trains. - if self.versions.channel() != "nightly" && NIGHTLY_ONLY_COMPONENTS.contains(&pkgname) { + if self.versions.channel() != "nightly" && NIGHTLY_ONLY_COMPONENTS.contains(&pkg) { is_present = false; // Pretend the component is entirely missing. } macro_rules! tarball_name { ($target_name:expr) => { - self.versions.tarball_name(&PkgType::from_component(pkgname), $target_name).unwrap() + self.versions.tarball_name(pkg, $target_name).unwrap() }; } let mut target_from_compressed_tar = |target_name| { @@ -546,7 +520,8 @@ impl Builder { Target::unavailable() }; - let targets = targets + let targets = pkg + .targets() .iter() .map(|name| { let target = if is_present { @@ -561,7 +536,7 @@ impl Builder { .collect(); dst.insert( - pkgname.to_string(), + pkg.manifest_component_name(), Package { version: version_info.version.unwrap_or_default(), git_commit_hash: version_info.git_commit, diff --git a/src/tools/build-manifest/src/manifest.rs b/src/tools/build-manifest/src/manifest.rs index 547c270d89a..a9f19d8e565 100644 --- a/src/tools/build-manifest/src/manifest.rs +++ b/src/tools/build-manifest/src/manifest.rs @@ -1,3 +1,4 @@ +use crate::versions::PkgType; use crate::Builder; use serde::{Serialize, Serializer}; use std::collections::BTreeMap; @@ -116,8 +117,8 @@ pub(crate) struct Component { } impl Component { - pub(crate) fn from_str(pkg: &str, target: &str) -> Self { - Self { pkg: pkg.to_string(), target: target.to_string() } + pub(crate) fn from_pkg(pkg: &PkgType, target: &str) -> Self { + Self { pkg: pkg.manifest_component_name(), target: target.to_string() } } } diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs index 0186194a41f..dde9745afb7 100644 --- a/src/tools/build-manifest/src/versions.rs +++ b/src/tools/build-manifest/src/versions.rs @@ -8,55 +8,63 @@ use tar::Archive; const DEFAULT_TARGET: &str = "x86_64-unknown-linux-gnu"; -#[derive(Debug, Hash, Eq, PartialEq, Clone)] -pub(crate) enum PkgType { - Rust, - RustSrc, - Rustc, - Cargo, - Rls, - RustAnalyzer, - Clippy, - Rustfmt, - LlvmTools, - Miri, - JsonDocs, - Other(String), -} +macro_rules! pkg_type { + ( $($variant:ident = $component:literal $(; preview = true $(@$is_preview:tt)? )? ),+ $(,)? ) => { + #[derive(Debug, Hash, Eq, PartialEq, Clone)] + pub(crate) enum PkgType { + $($variant,)+ + } -impl PkgType { - pub(crate) fn from_component(component: &str) -> Self { - match component { - "rust" => PkgType::Rust, - "rust-src" => PkgType::RustSrc, - "rustc" => PkgType::Rustc, - "cargo" => PkgType::Cargo, - "rls" | "rls-preview" => PkgType::Rls, - "rust-analyzer" | "rust-analyzer-preview" => PkgType::RustAnalyzer, - "clippy" | "clippy-preview" => PkgType::Clippy, - "rustfmt" | "rustfmt-preview" => PkgType::Rustfmt, - "llvm-tools" | "llvm-tools-preview" => PkgType::LlvmTools, - "miri" | "miri-preview" => PkgType::Miri, - "rust-docs-json" | "rust-docs-json-preview" => PkgType::JsonDocs, - other => PkgType::Other(other.into()), + impl PkgType { + pub(crate) fn is_preview(&self) -> bool { + match self { + $( $( $($is_preview)? PkgType::$variant => true, )? )+ + _ => false, + } + } + + /// First part of the tarball name. + pub(crate) fn tarball_component_name(&self) -> &str { + match self { + $( PkgType::$variant => $component,)+ + } + } + + pub(crate) fn all() -> &'static [PkgType] { + &[ $(PkgType::$variant),+ ] + } } } +} - /// First part of the tarball name. - fn tarball_component_name(&self) -> &str { - match self { - PkgType::Rust => "rust", - PkgType::RustSrc => "rust-src", - PkgType::Rustc => "rustc", - PkgType::Cargo => "cargo", - PkgType::Rls => "rls", - PkgType::RustAnalyzer => "rust-analyzer", - PkgType::Clippy => "clippy", - PkgType::Rustfmt => "rustfmt", - PkgType::LlvmTools => "llvm-tools", - PkgType::Miri => "miri", - PkgType::JsonDocs => "rust-docs-json", - PkgType::Other(component) => component, +pkg_type! { + Rust = "rust", + RustSrc = "rust-src", + Rustc = "rustc", + RustcDev = "rustc-dev", + RustcDocs = "rustc-docs", + ReproducibleArtifacts = "reproducible-artifacts", + RustMingw = "rust-mingw", + RustStd = "rust-std", + Cargo = "cargo", + HtmlDocs = "rust-docs", + RustAnalysis = "rust-analysis", + Rls = "rls"; preview = true, + RustAnalyzer = "rust-analyzer"; preview = true, + Clippy = "clippy"; preview = true, + Rustfmt = "rustfmt"; preview = true, + LlvmTools = "llvm-tools"; preview = true, + Miri = "miri"; preview = true, + JsonDocs = "rust-docs-json"; preview = true, +} + +impl PkgType { + /// Component name in the manifest. In particular, this includes the `-preview` suffix where appropriate. + pub(crate) fn manifest_component_name(&self) -> String { + if self.is_preview() { + format!("{}-preview", self.tarball_component_name()) + } else { + self.tarball_component_name().to_string() } } @@ -73,10 +81,42 @@ impl PkgType { PkgType::Miri => false, PkgType::Rust => true, + PkgType::RustStd => true, PkgType::RustSrc => true, PkgType::Rustc => true, PkgType::JsonDocs => true, - PkgType::Other(_) => true, + PkgType::HtmlDocs => true, + PkgType::RustcDev => true, + PkgType::RustcDocs => true, + PkgType::ReproducibleArtifacts => true, + PkgType::RustMingw => true, + PkgType::RustAnalysis => true, + } + } + + pub(crate) fn targets(&self) -> &[&str] { + use crate::{HOSTS, MINGW, TARGETS}; + use PkgType::*; + + match self { + Rust => HOSTS, // doesn't matter in practice, but return something to avoid panicking + Rustc => HOSTS, + RustcDev => HOSTS, + ReproducibleArtifacts => HOSTS, + RustcDocs => HOSTS, + Cargo => HOSTS, + RustMingw => MINGW, + RustStd => TARGETS, + HtmlDocs => HOSTS, + JsonDocs => HOSTS, + RustSrc => &["*"], + Rls => HOSTS, + RustAnalyzer => HOSTS, + Clippy => HOSTS, + Miri => HOSTS, + Rustfmt => HOSTS, + RustAnalysis => TARGETS, + LlvmTools => TARGETS, } } @@ -84,6 +124,14 @@ impl PkgType { fn target_independent(&self) -> bool { *self == PkgType::RustSrc } + + /// Whether to package these target-specific docs for another similar target. + pub(crate) fn use_docs_fallback(&self) -> bool { + match self { + PkgType::JsonDocs | PkgType::HtmlDocs => true, + _ => false, + } + } } #[derive(Debug, Default, Clone)] diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 7e484fc1a766f56dbc95380f45719698e0c8274 +Subproject a3dfea71ca0c888a88111086898aa833c291d49 diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index aad7da61a8a..eefba8cd29c 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -207,6 +207,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::InlineAsm(..) | ast::ExprKind::ConstBlock(..) | ast::ExprKind::Lit(..) + | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::Loop(..) | ast::ExprKind::MacCall(..) | ast::ExprKind::MethodCall(..) diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index ae54b2078a6..f24d3507823 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -23,8 +23,8 @@ use std::borrow::Cow; use std::env; use std::ops::Deref; use std::panic; -use std::path::{Path, PathBuf}; -use std::process::{exit, Command}; +use std::path::Path; +use std::process::exit; use std::sync::LazyLock; /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If @@ -210,17 +210,6 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { interface::try_print_query_stack(&handler, num_frames); } -fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<PathBuf> { - home.and_then(|home| { - toolchain.map(|toolchain| { - let mut path = PathBuf::from(home); - path.push("toolchains"); - path.push(toolchain); - path - }) - }) -} - #[allow(clippy::too_many_lines)] pub fn main() { rustc_driver::init_rustc_env_logger(); @@ -228,51 +217,6 @@ pub fn main() { exit(rustc_driver::catch_with_exit_code(move || { let mut orig_args: Vec<String> = env::args().collect(); - // Get the sysroot, looking from most specific to this invocation to the least: - // - command line - // - runtime environment - // - SYSROOT - // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN - // - sysroot from rustc in the path - // - compile-time environment - // - SYSROOT - // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN - let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true); - let have_sys_root_arg = sys_root_arg.is_some(); - let sys_root = sys_root_arg - .map(PathBuf::from) - .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from)) - .or_else(|| { - let home = std::env::var("RUSTUP_HOME") - .or_else(|_| std::env::var("MULTIRUST_HOME")) - .ok(); - let toolchain = std::env::var("RUSTUP_TOOLCHAIN") - .or_else(|_| std::env::var("MULTIRUST_TOOLCHAIN")) - .ok(); - toolchain_path(home, toolchain) - }) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| PathBuf::from(s.trim())) - }) - .or_else(|| option_env!("SYSROOT").map(PathBuf::from)) - .or_else(|| { - let home = option_env!("RUSTUP_HOME") - .or(option_env!("MULTIRUST_HOME")) - .map(ToString::to_string); - let toolchain = option_env!("RUSTUP_TOOLCHAIN") - .or(option_env!("MULTIRUST_TOOLCHAIN")) - .map(ToString::to_string); - toolchain_path(home, toolchain) - }) - .map(|pb| pb.to_string_lossy().to_string()) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); - // make "clippy-driver --rustc" work like a subcommand that passes further args to "rustc" // for example `clippy-driver --rustc --version` will print the rustc version that clippy-driver // uses @@ -280,13 +224,7 @@ pub fn main() { orig_args.remove(pos); orig_args[0] = "rustc".to_string(); - // if we call "rustc", we need to pass --sysroot here as well - let mut args: Vec<String> = orig_args.clone(); - if !have_sys_root_arg { - args.extend(vec!["--sysroot".into(), sys_root]); - }; - - return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run(); + return rustc_driver::RunCompiler::new(&orig_args, &mut DefaultCallbacks).run(); } if orig_args.iter().any(|a| a == "--version" || a == "-V") { @@ -309,14 +247,6 @@ pub fn main() { exit(0); } - // this conditional check for the --sysroot flag is there so users can call - // `clippy_driver` directly - // without having to pass --sysroot or anything - let mut args: Vec<String> = orig_args.clone(); - if !have_sys_root_arg { - args.extend(vec!["--sysroot".into(), sys_root]); - }; - let mut no_deps = false; let clippy_args_var = env::var("CLIPPY_ARGS").ok(); let clippy_args = clippy_args_var @@ -345,10 +275,11 @@ pub fn main() { let clippy_enabled = !cap_lints_allow && (!no_deps || in_primary_package); if clippy_enabled { + let mut args: Vec<String> = orig_args.clone(); args.extend(clippy_args); rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var }).run() } else { - rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var }).run() + rustc_driver::RunCompiler::new(&orig_args, &mut RustcCallbacks { clippy_args_var }).run() } })) } diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr index 878897c410c..4506d1550bd 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr @@ -23,6 +23,11 @@ error[E0308]: mismatched types | LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | let Some(reference) = cache.data.get(key) { + | +++ error: aborting due to 3 previous errors diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index dee14405287..8d8ca101cd0 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -208,11 +208,13 @@ enum WillExecute { Disabled, } -/// Should `--emit metadata` be used? +/// What value should be passed to `--emit`? #[derive(Copy, Clone)] -enum EmitMetadata { - Yes, - No, +enum Emit { + None, + Metadata, + LlvmIr, + Asm, } impl<'test> TestCx<'test> { @@ -412,7 +414,7 @@ impl<'test> TestCx<'test> { } let should_run = self.run_if_enabled(); - let mut proc_res = self.compile_test(should_run, EmitMetadata::No); + let mut proc_res = self.compile_test(should_run, Emit::None); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); @@ -658,7 +660,7 @@ impl<'test> TestCx<'test> { // compile test file (it should have 'compile-flags:-g' in the header) let should_run = self.run_if_enabled(); - let compile_result = self.compile_test(should_run, EmitMetadata::No); + let compile_result = self.compile_test(should_run, Emit::None); if !compile_result.status.success() { self.fatal_proc_rec("compilation failed!", &compile_result); } @@ -778,7 +780,7 @@ impl<'test> TestCx<'test> { // compile test file (it should have 'compile-flags:-g' in the header) let should_run = self.run_if_enabled(); - let compiler_run_result = self.compile_test(should_run, EmitMetadata::No); + let compiler_run_result = self.compile_test(should_run, Emit::None); if !compiler_run_result.status.success() { self.fatal_proc_rec("compilation failed!", &compiler_run_result); } @@ -1010,7 +1012,7 @@ impl<'test> TestCx<'test> { fn run_debuginfo_lldb_test_no_opt(&self) { // compile test file (it should have 'compile-flags:-g' in the header) let should_run = self.run_if_enabled(); - let compile_result = self.compile_test(should_run, EmitMetadata::No); + let compile_result = self.compile_test(should_run, Emit::None); if !compile_result.status.success() { self.fatal_proc_rec("compilation failed!", &compile_result); } @@ -1426,21 +1428,21 @@ impl<'test> TestCx<'test> { } } - fn should_emit_metadata(&self, pm: Option<PassMode>) -> EmitMetadata { + fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit { match (pm, self.props.fail_mode, self.config.mode) { - (Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => EmitMetadata::Yes, - _ => EmitMetadata::No, + (Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => Emit::Metadata, + _ => Emit::None, } } - fn compile_test(&self, will_execute: WillExecute, emit_metadata: EmitMetadata) -> ProcRes { - self.compile_test_general(will_execute, emit_metadata, self.props.local_pass_mode()) + fn compile_test(&self, will_execute: WillExecute, emit: Emit) -> ProcRes { + self.compile_test_general(will_execute, emit, self.props.local_pass_mode()) } fn compile_test_general( &self, will_execute: WillExecute, - emit_metadata: EmitMetadata, + emit: Emit, local_pm: Option<PassMode>, ) -> ProcRes { // Only use `make_exe_name` when the test ends up being executed. @@ -1472,10 +1474,13 @@ impl<'test> TestCx<'test> { _ => AllowUnused::No, }; - let mut rustc = - self.make_compile_args(&self.testpaths.file, output_file, emit_metadata, allow_unused); - - rustc.arg("-L").arg(&self.aux_output_dir_name()); + let rustc = self.make_compile_args( + &self.testpaths.file, + output_file, + emit, + allow_unused, + LinkToAux::Yes, + ); self.compose_and_run_compiler(rustc, None) } @@ -1702,8 +1707,13 @@ impl<'test> TestCx<'test> { // Create the directory for the stdout/stderr files. create_dir_all(aux_cx.output_base_dir()).unwrap(); let input_file = &aux_testpaths.file; - let mut aux_rustc = - aux_cx.make_compile_args(input_file, aux_output, EmitMetadata::No, AllowUnused::No); + let mut aux_rustc = aux_cx.make_compile_args( + input_file, + aux_output, + Emit::None, + AllowUnused::No, + LinkToAux::No, + ); for key in &aux_props.unset_rustc_env { aux_rustc.env_remove(key); @@ -1831,8 +1841,9 @@ impl<'test> TestCx<'test> { &self, input_file: &Path, output_file: TargetLocation, - emit_metadata: EmitMetadata, + emit: Emit, allow_unused: AllowUnused, + link_to_aux: LinkToAux, ) -> Command { let is_aux = input_file.components().map(|c| c.as_os_str()).any(|c| c == "auxiliary"); let is_rustdoc = self.is_rustdoc() && !is_aux; @@ -1947,8 +1958,18 @@ impl<'test> TestCx<'test> { } } - if let (false, EmitMetadata::Yes) = (is_rustdoc, emit_metadata) { - rustc.args(&["--emit", "metadata"]); + match emit { + Emit::None => {} + Emit::Metadata if is_rustdoc => {} + Emit::Metadata => { + rustc.args(&["--emit", "metadata"]); + } + Emit::LlvmIr => { + rustc.args(&["--emit", "llvm-ir"]); + } + Emit::Asm => { + rustc.args(&["--emit", "asm"]); + } } if !is_rustdoc { @@ -2014,6 +2035,10 @@ impl<'test> TestCx<'test> { rustc.arg("-Ctarget-feature=-crt-static"); } + if let LinkToAux::Yes = link_to_aux { + rustc.arg("-L").arg(self.aux_output_dir_name()); + } + rustc.args(&self.props.compile_flags); rustc @@ -2205,13 +2230,15 @@ impl<'test> TestCx<'test> { // codegen tests (using FileCheck) fn compile_test_and_save_ir(&self) -> ProcRes { - let aux_dir = self.aux_output_dir_name(); - let output_file = TargetLocation::ThisDirectory(self.output_base_dir()); let input_file = &self.testpaths.file; - let mut rustc = - self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No); - rustc.arg("-L").arg(aux_dir).arg("--emit=llvm-ir"); + let rustc = self.make_compile_args( + input_file, + output_file, + Emit::LlvmIr, + AllowUnused::No, + LinkToAux::Yes, + ); self.compose_and_run_compiler(rustc, None) } @@ -2223,14 +2250,11 @@ impl<'test> TestCx<'test> { let output_file = TargetLocation::ThisFile(output_path.clone()); let input_file = &self.testpaths.file; - let mut rustc = - self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No); - - rustc.arg("-L").arg(self.aux_output_dir_name()); + let mut emit = Emit::None; match self.props.assembly_output.as_ref().map(AsRef::as_ref) { Some("emit-asm") => { - rustc.arg("--emit=asm"); + emit = Emit::Asm; } Some("ptx-linker") => { @@ -2241,6 +2265,9 @@ impl<'test> TestCx<'test> { None => self.fatal("missing 'assembly-output' header"), } + let rustc = + self.make_compile_args(input_file, output_file, emit, AllowUnused::No, LinkToAux::Yes); + (self.compose_and_run_compiler(rustc, None), output_path) } @@ -2365,10 +2392,10 @@ impl<'test> TestCx<'test> { let mut rustc = new_rustdoc.make_compile_args( &new_rustdoc.testpaths.file, output_file, - EmitMetadata::No, + Emit::None, AllowUnused::Yes, + LinkToAux::Yes, ); - rustc.arg("-L").arg(&new_rustdoc.aux_output_dir_name()); new_rustdoc.build_all_auxiliary(&mut rustc); let proc_res = new_rustdoc.document(&compare_dir); @@ -2641,7 +2668,7 @@ impl<'test> TestCx<'test> { fn run_codegen_units_test(&self) { assert!(self.revision.is_none(), "revisions not relevant here"); - let proc_res = self.compile_test(WillExecute::No, EmitMetadata::No); + let proc_res = self.compile_test(WillExecute::No, Emit::None); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); @@ -3154,7 +3181,7 @@ impl<'test> TestCx<'test> { if let Some(FailMode::Build) = self.props.fail_mode { // Make sure a build-fail test cannot fail due to failing analysis (e.g. typeck). let pm = Some(PassMode::Check); - let proc_res = self.compile_test_general(WillExecute::No, EmitMetadata::Yes, pm); + let proc_res = self.compile_test_general(WillExecute::No, Emit::Metadata, pm); self.check_if_test_should_compile(&proc_res, pm); } @@ -3312,13 +3339,13 @@ impl<'test> TestCx<'test> { if self.props.run_rustfix && self.config.compare_mode.is_none() { // And finally, compile the fixed code and make sure it both // succeeds and has no diagnostics. - let mut rustc = self.make_compile_args( + let rustc = self.make_compile_args( &self.testpaths.file.with_extension(UI_FIXED), TargetLocation::ThisFile(self.make_exe_name()), emit_metadata, AllowUnused::No, + LinkToAux::Yes, ); - rustc.arg("-L").arg(&self.aux_output_dir_name()); let res = self.compose_and_run_compiler(rustc, None); if !res.status.success() { self.fatal_proc_rec("failed to compile fixed code", &res); @@ -3852,3 +3879,8 @@ enum AllowUnused { Yes, No, } + +enum LinkToAux { + Yes, + No, +} diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 7842611bd4f..4170c32f1fe 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -55,30 +55,6 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[ #[rustfmt::skip] const INTRA_DOC_LINK_EXCEPTIONS: &[(&str, &[&str])] = &[ - // This will never have links that are not in other pages. - // To avoid repeating the exceptions twice, an empty list means all broken links are allowed. - ("reference/print.html", &[]), - // All the reference 'links' are actually ENBF highlighted as code - ("reference/comments.html", &[ - "/</code> <code>!", - "*</code> <code>!", - ]), - ("reference/identifiers.html", &[ - "a</code>-<code>z</code> <code>A</code>-<code>Z", - "a</code>-<code>z</code> <code>A</code>-<code>Z</code> <code>0</code>-<code>9</code> <code>_", - "a</code>-<code>z</code> <code>A</code>-<code>Z</code>] [<code>a</code>-<code>z</code> <code>A</code>-<code>Z</code> <code>0</code>-<code>9</code> <code>_", - ]), - ("reference/tokens.html", &[ - "0</code>-<code>1", - "0</code>-<code>7", - "0</code>-<code>9", - "0</code>-<code>9", - "0</code>-<code>9</code> <code>a</code>-<code>f</code> <code>A</code>-<code>F", - ]), - ("reference/notation.html", &[ - "b</code> <code>B", - "a</code>-<code>z", - ]), // This is being used in the sense of 'inclusive range', not a markdown link ("core/ops/struct.RangeInclusive.html", &["begin</code>, <code>end"]), ("std/ops/struct.RangeInclusive.html", &["begin</code>, <code>end"]), @@ -365,6 +341,33 @@ impl Checker { } }); + self.check_intra_doc_links(file, &pretty_path, &source, report); + + // we don't need the source anymore, + // so drop to reduce memory-usage + match self.cache.get_mut(&pretty_path).unwrap() { + FileEntry::HtmlFile { source, .. } => *source = Rc::new(String::new()), + _ => unreachable!("must be html file"), + } + } + + fn check_intra_doc_links( + &mut self, + file: &Path, + pretty_path: &str, + source: &str, + report: &mut Report, + ) { + let relative = file.strip_prefix(&self.root).expect("should always be relative to root"); + // Don't check the reference. It has several legitimate things that + // look like [<code>…</code>]. The reference has its own broken link + // checker in its CI which handles this using pulldown_cmark. + // + // This checks both the end of the root (when checking just the + // reference directory) or the beginning (when checking all docs). + if self.root.ends_with("reference") || relative.starts_with("reference") { + return; + } // Search for intra-doc links that rustdoc didn't warn about // FIXME(#77199, 77200) Rustdoc should just warn about these directly. // NOTE: only looks at one line at a time; in practice this should find most links @@ -379,12 +382,6 @@ impl Checker { } } } - // we don't need the source anymore, - // so drop to reduce memory-usage - match self.cache.get_mut(&pretty_path).unwrap() { - FileEntry::HtmlFile { source, .. } => *source = Rc::new(String::new()), - _ => unreachable!("must be html file"), - } } /// Load a file from disk, or from the cache if available. diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 3efb2d733d4..607ffe0cc59 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -67,9 +67,9 @@ jobs: shell: bash run: | if [[ ${{ github.event_name }} == 'schedule' ]]; then - ./rustup-toolchain HEAD --host ${{ matrix.host_target }} + ./miri toolchain HEAD --host ${{ matrix.host_target }} else - ./rustup-toolchain "" --host ${{ matrix.host_target }} + ./miri toolchain "" --host ${{ matrix.host_target }} fi - name: Show Rust version @@ -118,7 +118,7 @@ jobs: - name: Install "master" toolchain shell: bash run: | - ./rustup-toolchain "" -c clippy + ./miri toolchain - name: Show Rust version run: | diff --git a/src/tools/miri/.gitpod.yml b/src/tools/miri/.gitpod.yml index 36bd991740a..724cf26df2b 100644 --- a/src/tools/miri/.gitpod.yml +++ b/src/tools/miri/.gitpod.yml @@ -4,6 +4,6 @@ tasks: - before: echo "..." init: | cargo install rustup-toolchain-install-master - ./rustup-toolchain + ./miri toolchain ./miri build - command: echo "Run tests with ./miri test" \ No newline at end of file + command: echo "Run tests with ./miri test" diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index b1e6b9c69d3..5c41547616e 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -23,13 +23,13 @@ tested against. Other versions will likely not work. After installing [`rustup-toolchain-install-master`], you can run the following command to install that exact version of rustc as a toolchain: ``` -./rustup-toolchain +./miri toolchain ``` This will set up a rustup toolchain called `miri` and set it as an override for the current directory. You can also create a `.auto-everything` file (contents don't matter, can be empty), which -will cause any `./miri` command to automatically call `rustup-toolchain`, `clippy` and `rustfmt` +will cause any `./miri` command to automatically call `./miri toolchain`, `clippy` and `rustfmt` for you. If you don't want all of these to happen, you can add individual `.auto-toolchain`, `.auto-clippy` and `.auto-fmt` files respectively. @@ -132,12 +132,15 @@ development version of Miri using and then you can use it as if it was installed by `rustup`. Make sure you use the same toolchain when calling `cargo miri` that you used when installing Miri! Usually this means you have to write `cargo +miri miri ...` to select the `miri` -toolchain that was installed by `./rustup-toolchain`. +toolchain that was installed by `./miri toolchain`. There's a test for the cargo wrapper in the `test-cargo-miri` directory; run `./run-test.py` in there to execute it. Like `./miri test`, this respects the `MIRI_TEST_TARGET` environment variable to execute the test for another target. +Note that installing Miri like this will "take away" Miri management from `rustup`. +If you want to later go back to a rustup-installed Miri, run `rustup update`. + ### Using a modified standard library Miri re-builds the standard library into a custom sysroot, so it is fairly easy @@ -214,7 +217,7 @@ for changes in rustc. In both cases, `rustc-version` needs updating. To update the `rustc-version` file and install the latest rustc, you can run: ``` -./rustup-toolchain HEAD +./miri toolchain HEAD ``` Now edit Miri until `./miri test` passes, and submit a PR. Generally, it is @@ -290,16 +293,14 @@ cargo run --release -p josh-proxy -- --local=$(pwd)/local --remote=https://githu ### Importing changes from the rustc repo +Josh needs to be running, as described above. We assume we start on an up-to-date master branch in the Miri repo. ```sh -# Fetch rustc side of the history. Takes ca 5 min the first time. -# Do NOT change that commit ID, it needs to be exactly this! -git fetch http://localhost:8000/rust-lang/rust.git:at_commit=75dd959a3a40eb5b4574f8d2e23aa6efbeb33573[:prefix=src/tools/miri]:/src/tools/miri.git master -# Include that history into ours. -git merge FETCH_HEAD -m "merge rustc history" +# Fetch and merge rustc side of the history. Takes ca 5 min the first time. +./miri rustc-pull # Update toolchain reference and apply formatting. -./rustup-toolchain HEAD && ./miri fmt +./miri toolchain HEAD && ./miri fmt git commit -am "rustup" ``` @@ -310,16 +311,15 @@ needed. ### Exporting changes to the rustc repo -We will use the josh proxy to push to your fork of rustc. You need to make sure -that the master branch of your fork is up-to-date. Also make sure that there -exists no branch called `miri` in your fork. Then run the following in the Miri -repo, assuming we are on an up-to-date master branch: +Josh needs to be running, as described above. We will use the josh proxy to push +to your fork of rustc. Run the following in the Miri repo, assuming we are on an +up-to-date master branch: ```sh # Push the Miri changes to your rustc fork (substitute your github handle for YOUR_NAME). -# Do NOT change that commit ID, it needs to be exactly this! -git push http://localhost:8000/YOUR_NAME/rust.git:at_commit=75dd959a3a40eb5b4574f8d2e23aa6efbeb33573[:prefix=src/tools/miri]:/src/tools/miri.git -o base=master HEAD:miri +./miri rustc-push YOUR_NAME miri ``` -This will create a new branch in your fork, and the output should include a link -to create a rustc PR that will integrate those changes into the main repository. +This will create a new branch called 'miri' in your fork, and the output should +include a link to create a rustc PR that will integrate those changes into the +main repository. diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 5803a88c0e7..1185525f686 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -374,14 +374,15 @@ to Miri failing to detect cases of undefined behavior in a program. application instead of raising an error within the context of Miri (and halting execution). Note that code might not expect these operations to ever panic, so this flag can lead to strange (mis)behavior. -* `-Zmiri-retag-fields` changes Stacked Borrows retagging to recurse into fields. +* `-Zmiri-retag-fields` changes Stacked Borrows retagging to recurse into *all* fields. This means that references in fields of structs/enums/tuples/arrays/... are retagged, and in particular, they are protected when passed as function arguments. + (The default is to recurse only in cases where rustc would actually emit a `noalias` attribute.) * `-Zmiri-retag-fields=<all|none|scalar>` controls when Stacked Borrows retagging recurses into fields. `all` means it always recurses (like `-Zmiri-retag-fields`), `none` means it never - recurses (the default), `scalar` means it only recurses for types where we would also emit + recurses, `scalar` (the default) means it only recurses for types where we would also emit `noalias` annotations in the generated LLVM IR (types passed as indivudal scalars or pairs of - scalars). + scalars). Setting this to `none` is **unsound**. * `-Zmiri-tag-gc=<blocks>` configures how often the pointer tag garbage collector runs. The default is to search for and remove unreachable tags once every `10000` basic blocks. Setting this to `0` disables the garbage collector, which causes some programs to have explosive memory usage @@ -419,9 +420,9 @@ Some native rustc `-Z` flags are also very relevant for Miri: Moreover, Miri recognizes some environment variables: -* `MIRI_AUTO_OPS` indicates whether the automatic execution of rustfmt, clippy and rustup-toolchain - should be skipped. If it is set to any value, they are skipped. This is used for avoiding - infinite recursion in `./miri` and to allow automated IDE actions to avoid the auto ops. +* `MIRI_AUTO_OPS` indicates whether the automatic execution of rustfmt, clippy and toolchain setup + should be skipped. If it is set to any value, they are skipped. This is used for avoiding infinite + recursion in `./miri` and to allow automated IDE actions to avoid the auto ops. * `MIRI_LOG`, `MIRI_BACKTRACE` control logging and backtrace printing during Miri executions, also [see "Testing the Miri driver" in `CONTRIBUTING.md`][testing-miri]. * `MIRIFLAGS` (recognized by `cargo miri` and the test suite) defines extra @@ -433,8 +434,10 @@ Moreover, Miri recognizes some environment variables: trigger a re-build of the standard library; you have to clear the Miri build cache manually (on Linux, `rm -rf ~/.cache/miri`). * `MIRI_SYSROOT` (recognized by `cargo miri` and the Miri driver) indicates the sysroot to use. When - using `cargo miri`, only set this if you do not want to use the automatically created sysroot. For - directly invoking the Miri driver, this variable (or a `--sysroot` flag) is mandatory. + using `cargo miri`, this skips the automatic setup -- only set this if you do not want to use the + automatically created sysroot. For directly invoking the Miri driver, this variable (or a + `--sysroot` flag) is mandatory. When invoking `cargo miri setup`, this indicates where the sysroot + will be put. * `MIRI_TEST_TARGET` (recognized by the test suite and the `./miri` script) indicates which target architecture to test against. `miri` and `cargo miri` accept the `--target` flag for the same purpose. diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 22da80be902..df36041c75e 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -528,7 +528,7 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner cmd.args(binary_args); // Make sure we use the build-time working directory for interpreting Miri/rustc arguments. - // But then we need to switch to the run-time one, which we instruct Miri do do by setting `MIRI_CWD`. + // But then we need to switch to the run-time one, which we instruct Miri to do by setting `MIRI_CWD`. cmd.current_dir(info.current_dir); cmd.env("MIRI_CWD", env::current_dir().unwrap()); diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index 72d8ef2f752..f3841a61408 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -17,10 +17,8 @@ pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta let only_setup = matches!(subcommand, MiriCommand::Setup); let ask_user = !only_setup; let print_sysroot = only_setup && has_arg_flag("--print-sysroot"); // whether we just print the sysroot path - if std::env::var_os("MIRI_SYSROOT").is_some() { - if only_setup { - println!("WARNING: MIRI_SYSROOT already set, not doing anything.") - } + if !only_setup && std::env::var_os("MIRI_SYSROOT").is_some() { + // Skip setup step if MIRI_SYSROOT is explicitly set, *unless* we are `cargo miri setup`. return; } @@ -61,8 +59,13 @@ pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta } // Determine where to put the sysroot. - let user_dirs = directories::ProjectDirs::from("org", "rust-lang", "miri").unwrap(); - let sysroot_dir = user_dirs.cache_dir(); + let sysroot_dir = match std::env::var_os("MIRI_SYSROOT") { + Some(dir) => PathBuf::from(dir), + None => { + let user_dirs = directories::ProjectDirs::from("org", "rust-lang", "miri").unwrap(); + user_dirs.cache_dir().to_owned() + } + }; // Sysroot configuration and build details. let sysroot_config = if std::env::var_os("MIRI_NO_STD").is_some() { SysrootConfig::NoStd @@ -111,7 +114,7 @@ pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta (command, rustflags) }; // Make sure all target-level Miri invocations know their sysroot. - std::env::set_var("MIRI_SYSROOT", sysroot_dir); + std::env::set_var("MIRI_SYSROOT", &sysroot_dir); // Do the build. if only_setup { @@ -121,7 +124,7 @@ pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta // We want to be quiet, but still let the user know that something is happening. eprint!("Preparing a sysroot for Miri (target: {target})... "); } - Sysroot::new(sysroot_dir, target) + Sysroot::new(&sysroot_dir, target) .build_from_source(&rust_src, BuildMode::Check, sysroot_config, rustc_version, cargo_cmd) .unwrap_or_else(|_| { if only_setup { diff --git a/src/tools/miri/miri b/src/tools/miri/miri index e492308a62e..f0986bfb1cd 100755 --- a/src/tools/miri/miri +++ b/src/tools/miri/miri @@ -42,6 +42,22 @@ many different seeds. Runs the benchmarks from bench-cargo-miri in hyperfine. hyperfine needs to be installed. <benches> can explicitly list the benchmarks to run; by default, all of them are run. +./miri rustc-pull: +Pull and merge Miri changes from the rustc repo. + +./miri rustc-push <github user> <branch>: +Push Miri changes back to the rustc repo. This will update the 'master' branch +in the Rust fork of the given user to upstream. It will also pull a copy of the +rustc history into the Miri repo, unless you set the RUSTC_GIT env var to an +existing clone of the rustc repo. + +./miri toolchain <commit> <flags>: +Update and activate the rustup toolchain 'miri'. If no commit is given, updates +to the commit given in the `rust-version` file. If the commit is `HEAD`, updates +to the latest upstream rustc commit. +`rustup-toolchain-install-master` must be installed for this to work. Any extra +flags are passed to `rustup-toolchain-install-master`. + ENVIRONMENT VARIABLES MIRI_SYSROOT: @@ -52,37 +68,98 @@ Pass extra flags to all cargo invocations. (Ignored by `./miri cargo`.) EOF ) -## We need to know where we are. +## We need to know which command to run and some global constants. +COMMAND="$1" +if [ -z "$COMMAND" ]; then + echo "$USAGE" + exit 1 +fi +shift # macOS does not have a useful readlink/realpath so we have to use Python instead... MIRIDIR=$(python3 -c 'import os, sys; print(os.path.dirname(os.path.realpath(sys.argv[1])))' "$0") +# Used for rustc syncs. +JOSH_FILTER=":at_commit=75dd959a3a40eb5b4574f8d2e23aa6efbeb33573[:prefix=src/tools/miri]:/src/tools/miri" +# Needed for `./miri bench`. +TOOLCHAIN=$(cd "$MIRIDIR"; rustup show active-toolchain | head -n 1 | cut -d ' ' -f 1) -## Run the auto-things. -if [ -z "$MIRI_AUTO_OPS" ]; then - export MIRI_AUTO_OPS=42 - - # Run this first, so that the toolchain doesn't change after - # other code has run. - if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-toolchain" ] ; then - (cd "$MIRIDIR" && ./rustup-toolchain) +## Early commands, that don't do auto-things and don't want the environment-altering things happening below. +case "$COMMAND" in +toolchain) + cd "$MIRIDIR" + # Make sure rustup-toolchain-install-master is installed. + if ! which rustup-toolchain-install-master >/dev/null; then + echo "Please install rustup-toolchain-install-master by running 'cargo install rustup-toolchain-install-master'" + exit 1 fi - - if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-fmt" ] ; then - $0 fmt + # Determine new commit. + if [[ "$1" == "" ]]; then + NEW_COMMIT=$(cat rust-version) + elif [[ "$1" == "HEAD" ]]; then + NEW_COMMIT=$(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1) + else + NEW_COMMIT="$1" fi - - if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-clippy" ] ; then - $0 clippy -- -D warnings + echo "$NEW_COMMIT" > rust-version + shift || true # don't fail if shifting fails because no commit was given + # Check if we already are at that commit. + CUR_COMMIT=$(rustc +miri --version -v 2>/dev/null | grep "^commit-hash: " | cut -d " " -f 2) + if [[ "$CUR_COMMIT" == "$NEW_COMMIT" ]]; then + echo "miri toolchain is already at commit $CUR_COMMIT." + rustup override set miri + exit 0 fi -fi - -## Determine command and toolchain. -COMMAND="$1" -[ $# -gt 0 ] && shift -# Doing this *after* auto-toolchain logic above, since that might change the toolchain. -TOOLCHAIN=$(cd "$MIRIDIR"; rustup show active-toolchain | head -n 1 | cut -d ' ' -f 1) - -## Handle some commands early, since they should *not* alter the environment. -case "$COMMAND" in + # Install and setup new toolchain. + rustup toolchain uninstall miri + rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy "$@" -- "$NEW_COMMIT" + rustup override set miri + # Cleanup. + cargo clean + # Call 'cargo metadata' on the sources in case that changes the lockfile + # (which fails under some setups when it is done from inside vscode). + cargo metadata --format-version 1 --manifest-path "$(rustc --print sysroot)/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml" >/dev/null + # Done! + exit 0 + ;; +rustc-pull) + cd "$MIRIDIR" + git fetch http://localhost:8000/rust-lang/rust.git$JOSH_FILTER.git master + git merge FETCH_HEAD --no-ff -m "Merge from rustc" + exit 0 + ;; +rustc-push) + USER="$1" + BRANCH="$2" + if [ -z "$USER" ] || [ -z "$BRANCH" ]; then + echo "Usage: $0 rustc-push <github user> <branch>" + exit 1 + fi + if [ -n "$RUSTC_GIT" ]; then + # Use an existing fork for the branch updates. + cd "$RUSTC_GIT" + else + # Do this in the local Miri repo. + echo "This will pull a copy of the rust-lang/rust history into this Miri checkout, growing it by about 1GB." + read -r -p "To avoid that, abort now and set the RUSTC_GIT environment variable to an existing rustc checkout. Proceed? [y/N] " + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi + cd "$MIRIDIR" + fi + # Prepare the branches. For reliable pushing we need to push to a non-existent branch + # and set `-o base` to a branch that holds current rustc master. + echo "Preparing $USER/rust..." + if git fetch https://github.com/$USER/rust $BRANCH &>/dev/null; then + echo "The '$BRANCH' seems to already exist in $USER/rust. Please delete it and try again." + exit 1 + fi + git fetch https://github.com/rust-lang/rust master + git push https://github.com/$USER/rust FETCH_HEAD:master + # Do the actual push. + cd "$MIRIDIR" + echo "Pushing Miri changes..." + git push http://localhost:8000/$USER/rust.git$JOSH_FILTER.git HEAD:$BRANCH -o base=master + exit 0 + ;; many-seeds) for SEED in $({ echo obase=16; seq 0 255; } | bc); do echo "Trying seed: $SEED" @@ -106,9 +183,29 @@ bench) ;; esac +## Run the auto-things. +if [ -z "$MIRI_AUTO_OPS" ]; then + export MIRI_AUTO_OPS=42 + + # Run this first, so that the toolchain doesn't change after + # other code has run. + if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-toolchain" ] ; then + $0 toolchain + # Let's make sure to actually use that toolchain, too. + TOOLCHAIN=miri + fi + + if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-fmt" ] ; then + $0 fmt + fi + + if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-clippy" ] ; then + $0 clippy -- -D warnings + fi +fi + ## Prepare the environment # Determine some toolchain properties -# export the target so its available in miri TARGET=$(rustc +$TOOLCHAIN --version --verbose | grep "^host:" | cut -d ' ' -f 2) SYSROOT=$(rustc +$TOOLCHAIN --print sysroot) LIBDIR=$SYSROOT/lib/rustlib/$TARGET/lib @@ -227,10 +324,7 @@ cargo) $CARGO "$@" ;; *) - if [ -n "$COMMAND" ]; then - echo "Unknown command: $COMMAND" - echo - fi - echo "$USAGE" + echo "Unknown command: $COMMAND" exit 1 + ;; esac diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index d0e98a8b0db..13492d183c9 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -85d089b41e2a0c0f07ab34f6c5a7c451389f25e6 +b03502b35d111bef0399a66ab3cc765f0802e8ba diff --git a/src/tools/miri/rustup-toolchain b/src/tools/miri/rustup-toolchain deleted file mode 100755 index d7730f2b06d..00000000000 --- a/src/tools/miri/rustup-toolchain +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -set -e -# Manages a rustup toolchain called "miri". -# -# All commands set "miri" as the override toolchain for the current directory, -# and make the `rust-version` file match that toolchain. -# -# USAGE: -# -# ./rustup-toolchain: Update "miri" toolchain to match `rust-version` (the known-good version for this commit). -# -# ./rustup-toolchain HEAD: Update "miri" toolchain and `rust-version` file to latest rustc HEAD. -# -# ./rustup-toolchain $COMMIT: Update "miri" toolchain and `rust-version` file to match that commit. -# -# Any extra parameters are passed to `rustup-toolchain-install-master`. - -# Make sure rustup-toolchain-install-master is installed. -if ! which rustup-toolchain-install-master >/dev/null; then - echo "Please install rustup-toolchain-install-master by running 'cargo install rustup-toolchain-install-master'" - exit 1 -fi - -# Determine new commit. -if [[ "$1" == "" ]]; then - NEW_COMMIT=$(cat rust-version) -elif [[ "$1" == "HEAD" ]]; then - NEW_COMMIT=$(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1) -else - NEW_COMMIT="$1" -fi -echo "$NEW_COMMIT" > rust-version -shift || true # don't fail if shifting fails - -# Check if we already are at that commit. -CUR_COMMIT=$(rustc +miri --version -v 2>/dev/null | grep "^commit-hash: " | cut -d " " -f 2) -if [[ "$CUR_COMMIT" == "$NEW_COMMIT" ]]; then - echo "miri toolchain is already at commit $CUR_COMMIT." - rustup override set miri - exit 0 -fi - -# Install and setup new toolchain. -rustup toolchain uninstall miri -rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy "$@" -- "$NEW_COMMIT" -rustup override set miri - -# Cleanup. -cargo clean - -# Call 'cargo metadata' on the sources in case that changes the lockfile -# (which fails under some setups when it is done from inside vscode). -cargo metadata --format-version 1 --manifest-path "$(rustc --print sysroot)/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml" >/dev/null diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index bd01ea655dd..e673ea67dbc 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -216,76 +216,28 @@ fn init_late_loggers(tcx: TyCtxt<'_>) { } } -/// Returns the "default sysroot" that Miri will use for host things if no `--sysroot` flag is set. -/// Should be a compile-time constant. -fn host_sysroot() -> Option<String> { - if option_env!("RUSTC_STAGE").is_some() { - // This is being built as part of rustc, and gets shipped with rustup. - // We can rely on the sysroot computation in librustc_session. - return None; - } - // For builds outside rustc, we need to ensure that we got a sysroot - // that gets used as a default. The sysroot computation in librustc_session would - // end up somewhere in the build dir (see `get_or_default_sysroot`). - // Taken from PR <https://github.com/Manishearth/rust-clippy/pull/911>. - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - Some(match (home, toolchain) { - (Some(home), Some(toolchain)) => { - // Check that at runtime, we are still in this toolchain (if there is any toolchain). - if let Some(toolchain_runtime) = - env::var_os("RUSTUP_TOOLCHAIN").or_else(|| env::var_os("MULTIRUST_TOOLCHAIN")) - { - if toolchain_runtime != toolchain { - show_error!( - "This Miri got built with local toolchain `{toolchain}`, but now is being run under a different toolchain. \n\ - Make sure to run Miri in the toolchain it got built with, e.g. via `cargo +{toolchain} miri`." - ) - } - } - format!("{home}/toolchains/{toolchain}") - } - _ => option_env!("RUST_SYSROOT") - .unwrap_or_else(|| { - show_error!( - "To build Miri without rustup, set the `RUST_SYSROOT` env var at build time", - ) - }) - .to_owned(), - }) -} - /// Execute a compiler with the given CLI arguments and callbacks. fn run_compiler( mut args: Vec<String>, target_crate: bool, callbacks: &mut (dyn rustc_driver::Callbacks + Send), ) -> ! { - // Make sure we use the right default sysroot. The default sysroot is wrong, - // because `get_or_default_sysroot` in `librustc_session` bases that on `current_exe`. - // - // Make sure we always call `host_sysroot` as that also does some sanity-checks - // of the environment we were built in and whether it matches what we are running in. - let host_default_sysroot = host_sysroot(); - // Now see if we even need to set something. - let sysroot_flag = "--sysroot"; - if !args.iter().any(|e| e == sysroot_flag) { - // No sysroot was set, let's see if we have a custom default we want to configure. - let default_sysroot = if target_crate { + if target_crate { + // Miri needs a custom sysroot for target crates. + // If no `--sysroot` is given, the `MIRI_SYSROOT` env var is consulted to find where + // that sysroot lives, and that is passed to rustc. + let sysroot_flag = "--sysroot"; + if !args.iter().any(|e| e == sysroot_flag) { // Using the built-in default here would be plain wrong, so we *require* // the env var to make sure things make sense. - Some(env::var("MIRI_SYSROOT").unwrap_or_else(|_| { + let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| { show_error!( "Miri was invoked in 'target' mode without `MIRI_SYSROOT` or `--sysroot` being set" - ) - })) - } else { - host_default_sysroot - }; - if let Some(sysroot) = default_sysroot { - // We need to overwrite the default that librustc_session would compute. + ) + }); + args.push(sysroot_flag.to_owned()); - args.push(sysroot); + args.push(miri_sysroot); } } diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index 791931901e2..eb42cdf80ab 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -3,7 +3,7 @@ use std::num::NonZeroU32; use rustc_index::vec::Idx; -use super::sync::EvalContextExtPriv; +use super::sync::EvalContextExtPriv as _; use super::thread::MachineCallback; use super::vector_clock::VClock; use crate::*; @@ -52,6 +52,43 @@ impl<'mir, 'tcx> VisitTags for InitOnce<'mir, 'tcx> { } } +impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { + /// Synchronize with the previous initialization attempt of an InitOnce. + #[inline] + fn init_once_observe_attempt(&mut self, id: InitOnceId) { + let this = self.eval_context_mut(); + let current_thread = this.get_active_thread(); + + if let Some(data_race) = &this.machine.data_race { + data_race.validate_lock_acquire( + &this.machine.threads.sync.init_onces[id].data_race, + current_thread, + ); + } + } + + #[inline] + fn init_once_wake_waiter( + &mut self, + id: InitOnceId, + waiter: InitOnceWaiter<'mir, 'tcx>, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + let current_thread = this.get_active_thread(); + + this.unblock_thread(waiter.thread); + + // Call callback, with the woken-up thread as `current`. + this.set_active_thread(waiter.thread); + this.init_once_observe_attempt(id); + waiter.callback.call(this)?; + this.set_active_thread(current_thread); + + Ok(()) + } +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn init_once_get_or_create_id( @@ -141,20 +178,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Wake up everyone. // need to take the queue to avoid having `this` be borrowed multiple times for waiter in std::mem::take(&mut init_once.waiters) { - // End of the wait happens-before woken-up thread. - if let Some(data_race) = &this.machine.data_race { - data_race.validate_lock_acquire( - &this.machine.threads.sync.init_onces[id].data_race, - waiter.thread, - ); - } - - this.unblock_thread(waiter.thread); - - // Call callback, with the woken-up thread as `current`. - this.set_active_thread(waiter.thread); - waiter.callback.call(this)?; - this.set_active_thread(current_thread); + this.init_once_wake_waiter(id, waiter)?; } Ok(()) @@ -172,28 +196,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ); // Each complete happens-before the end of the wait - // FIXME: should this really induce synchronization? If we think of it as a lock, then yes, - // but the docs don't talk about such details. if let Some(data_race) = &this.machine.data_race { data_race.validate_lock_release(&mut init_once.data_race, current_thread); } // Wake up one waiting thread, so they can go ahead and try to init this. if let Some(waiter) = init_once.waiters.pop_front() { - // End of the wait happens-before woken-up thread. - if let Some(data_race) = &this.machine.data_race { - data_race.validate_lock_acquire( - &this.machine.threads.sync.init_onces[id].data_race, - waiter.thread, - ); - } - - this.unblock_thread(waiter.thread); - - // Call callback, with the woken-up thread as `current`. - this.set_active_thread(waiter.thread); - waiter.callback.call(this)?; - this.set_active_thread(current_thread); + this.init_once_wake_waiter(id, waiter)?; } else { // Nobody there to take this, so go back to 'uninit' init_once.status = InitOnceStatus::Uninitialized; @@ -201,4 +210,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(()) } + + /// Synchronize with the previous completion of an InitOnce. + /// Must only be called after checking that it is complete. + #[inline] + fn init_once_observe_completed(&mut self, id: InitOnceId) { + let this = self.eval_context_mut(); + + assert_eq!( + this.init_once_status(id), + InitOnceStatus::Complete, + "observing the completion of incomplete init once" + ); + + this.init_once_observe_attempt(id); + } } diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index e76610e7302..ba5ae852c5a 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -116,13 +116,25 @@ struct RwLock { declare_id!(CondvarId); +#[derive(Debug, Copy, Clone)] +pub enum RwLockMode { + Read, + Write, +} + +#[derive(Debug)] +pub enum CondvarLock { + Mutex(MutexId), + RwLock { id: RwLockId, mode: RwLockMode }, +} + /// A thread waiting on a conditional variable. #[derive(Debug)] struct CondvarWaiter { /// The thread that is waiting on this variable. thread: ThreadId, - /// The mutex on which the thread is waiting. - mutex: MutexId, + /// The mutex or rwlock on which the thread is waiting. + lock: CondvarLock, } /// The conditional variable state. @@ -569,16 +581,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } /// Mark that the thread is waiting on the conditional variable. - fn condvar_wait(&mut self, id: CondvarId, thread: ThreadId, mutex: MutexId) { + fn condvar_wait(&mut self, id: CondvarId, thread: ThreadId, lock: CondvarLock) { let this = self.eval_context_mut(); let waiters = &mut this.machine.threads.sync.condvars[id].waiters; assert!(waiters.iter().all(|waiter| waiter.thread != thread), "thread is already waiting"); - waiters.push_back(CondvarWaiter { thread, mutex }); + waiters.push_back(CondvarWaiter { thread, lock }); } /// Wake up some thread (if there is any) sleeping on the conditional /// variable. - fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, MutexId)> { + fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, CondvarLock)> { let this = self.eval_context_mut(); let current_thread = this.get_active_thread(); let condvar = &mut this.machine.threads.sync.condvars[id]; @@ -592,7 +604,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if let Some(data_race) = data_race { data_race.validate_lock_acquire(&condvar.data_race, waiter.thread); } - (waiter.thread, waiter.mutex) + (waiter.thread, waiter.lock) }) } diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index a3fc343f8b6..81132db94cf 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -163,7 +163,7 @@ impl Default for MiriConfig { mute_stdout_stderr: false, preemption_rate: 0.01, // 1% report_progress: None, - retag_fields: RetagFields::No, + retag_fields: RetagFields::OnlyScalar, external_so_file: None, gc_interval: 10_000, num_cpus: 1, diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 3b73d05907b..8028ce75354 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -3,7 +3,6 @@ #![feature(never_type)] #![feature(try_blocks)] #![feature(io_error_more)] -#![feature(int_log)] #![feature(variant_count)] #![feature(yeet_expr)] #![feature(is_some_and)] diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index fcb00692079..a7275646847 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -3,6 +3,7 @@ use std::time::SystemTime; use rustc_hir::LangItem; use rustc_middle::ty::{layout::TyAndLayout, query::TyCtxtAt, Ty}; +use crate::concurrency::sync::CondvarLock; use crate::concurrency::thread::{MachineCallback, Time}; use crate::*; @@ -696,8 +697,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?; - if let Some((thread, mutex)) = this.condvar_signal(id) { - post_cond_signal(this, thread, mutex)?; + if let Some((thread, lock)) = this.condvar_signal(id) { + if let CondvarLock::Mutex(mutex) = lock { + post_cond_signal(this, thread, mutex)?; + } else { + panic!("condvar should not have an rwlock on unix"); + } } Ok(0) @@ -710,8 +715,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?; - while let Some((thread, mutex)) = this.condvar_signal(id) { - post_cond_signal(this, thread, mutex)?; + while let Some((thread, lock)) = this.condvar_signal(id) { + if let CondvarLock::Mutex(mutex) = lock { + post_cond_signal(this, thread, mutex)?; + } else { + panic!("condvar should not have an rwlock on unix"); + } } Ok(0) @@ -729,7 +738,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let active_thread = this.get_active_thread(); release_cond_mutex_and_block(this, active_thread, mutex_id)?; - this.condvar_wait(id, active_thread, mutex_id); + this.condvar_wait(id, active_thread, CondvarLock::Mutex(mutex_id)); Ok(0) } @@ -768,7 +777,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; release_cond_mutex_and_block(this, active_thread, mutex_id)?; - this.condvar_wait(id, active_thread, mutex_id); + this.condvar_wait(id, active_thread, CondvarLock::Mutex(mutex_id)); // We return success for now and override it in the timeout callback. this.write_scalar(Scalar::from_i32(0), dest)?; diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 2a34a3a47bb..e16749c986b 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -273,6 +273,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let result = this.InitOnceComplete(ptr, flags, context)?; this.write_scalar(result, dest)?; } + "SleepConditionVariableSRW" => { + let [condvar, lock, timeout, flags] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let result = this.SleepConditionVariableSRW(condvar, lock, timeout, flags, dest)?; + this.write_scalar(result, dest)?; + } + "WakeConditionVariable" => { + let [condvar] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.WakeConditionVariable(condvar)?; + } + "WakeAllConditionVariable" => { + let [condvar] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.WakeAllConditionVariable(condvar)?; + } // Dynamic symbol loading "GetProcAddress" => { diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 8156ae8af1e..8f414d98dba 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -3,11 +3,45 @@ use std::time::Duration; use rustc_target::abi::Size; use crate::concurrency::init_once::InitOnceStatus; +use crate::concurrency::sync::{CondvarLock, RwLockMode}; use crate::concurrency::thread::MachineCallback; use crate::*; const SRWLOCK_ID_OFFSET: u64 = 0; const INIT_ONCE_ID_OFFSET: u64 = 0; +const CONDVAR_ID_OFFSET: u64 = 0; + +impl<'mir, 'tcx> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { + /// Try to reacquire the lock associated with the condition variable after we + /// were signaled. + fn reacquire_cond_lock( + &mut self, + thread: ThreadId, + lock: RwLockId, + mode: RwLockMode, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + this.unblock_thread(thread); + + match mode { + RwLockMode::Read => + if this.rwlock_is_write_locked(lock) { + this.rwlock_enqueue_and_block_reader(lock, thread); + } else { + this.rwlock_reader_lock(lock, thread); + }, + RwLockMode::Write => + if this.rwlock_is_locked(lock) { + this.rwlock_enqueue_and_block_writer(lock, thread); + } else { + this.rwlock_writer_lock(lock, thread); + }, + } + + Ok(()) + } +} impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} #[allow(non_snake_case)] @@ -177,8 +211,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Box::new(Callback { init_once_id: id, pending_place }), ) } - InitOnceStatus::Complete => - this.write_scalar(this.eval_windows("c", "FALSE")?, &pending_place)?, + InitOnceStatus::Complete => { + this.init_once_observe_completed(id); + this.write_scalar(this.eval_windows("c", "FALSE")?, &pending_place)?; + } } // This always succeeds (even if the thread is blocked, we will succeed if we ever unblock). @@ -325,4 +361,131 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(()) } + + fn SleepConditionVariableSRW( + &mut self, + condvar_op: &OpTy<'tcx, Provenance>, + lock_op: &OpTy<'tcx, Provenance>, + timeout_op: &OpTy<'tcx, Provenance>, + flags_op: &OpTy<'tcx, Provenance>, + dest: &PlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, Scalar<Provenance>> { + let this = self.eval_context_mut(); + + let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?; + let lock_id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?; + let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?; + let flags = this.read_scalar(flags_op)?.to_u32()?; + + let timeout_time = if timeout_ms == this.eval_windows("c", "INFINITE")?.to_u32()? { + None + } else { + let duration = Duration::from_millis(timeout_ms.into()); + Some(this.machine.clock.now().checked_add(duration).unwrap()) + }; + + let shared_mode = 0x1; // CONDITION_VARIABLE_LOCKMODE_SHARED is not in std + let mode = if flags == 0 { + RwLockMode::Write + } else if flags == shared_mode { + RwLockMode::Read + } else { + throw_unsup_format!("unsupported `Flags` {flags} in `SleepConditionVariableSRW`"); + }; + + let active_thread = this.get_active_thread(); + + let was_locked = match mode { + RwLockMode::Read => this.rwlock_reader_unlock(lock_id, active_thread), + RwLockMode::Write => this.rwlock_writer_unlock(lock_id, active_thread), + }; + + if !was_locked { + throw_ub_format!( + "calling SleepConditionVariableSRW with an SRWLock that is not locked by the current thread" + ); + } + + this.block_thread(active_thread); + this.condvar_wait(condvar_id, active_thread, CondvarLock::RwLock { id: lock_id, mode }); + + if let Some(timeout_time) = timeout_time { + struct Callback<'tcx> { + thread: ThreadId, + condvar_id: CondvarId, + lock_id: RwLockId, + mode: RwLockMode, + dest: PlaceTy<'tcx, Provenance>, + } + + impl<'tcx> VisitTags for Callback<'tcx> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let Callback { thread: _, condvar_id: _, lock_id: _, mode: _, dest } = self; + dest.visit_tags(visit); + } + } + + impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { + fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + this.reacquire_cond_lock(self.thread, self.lock_id, self.mode)?; + + this.condvar_remove_waiter(self.condvar_id, self.thread); + + let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT")?; + this.set_last_error(error_timeout)?; + this.write_scalar(this.eval_windows("c", "FALSE")?, &self.dest)?; + Ok(()) + } + } + + this.register_timeout_callback( + active_thread, + Time::Monotonic(timeout_time), + Box::new(Callback { + thread: active_thread, + condvar_id, + lock_id, + mode, + dest: dest.clone(), + }), + ); + } + + this.eval_windows("c", "TRUE") + } + + fn WakeConditionVariable(&mut self, condvar_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?; + + if let Some((thread, lock)) = this.condvar_signal(condvar_id) { + if let CondvarLock::RwLock { id, mode } = lock { + this.reacquire_cond_lock(thread, id, mode)?; + this.unregister_timeout_callback_if_exists(thread); + } else { + panic!("mutexes should not exist on windows"); + } + } + + Ok(()) + } + + fn WakeAllConditionVariable( + &mut self, + condvar_op: &OpTy<'tcx, Provenance>, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?; + + while let Some((thread, lock)) = this.condvar_signal(condvar_id) { + if let CondvarLock::RwLock { id, mode } = lock { + this.reacquire_cond_lock(thread, id, mode)?; + this.unregister_timeout_callback_if_exists(thread); + } else { + panic!("mutexes should not exist on windows"); + } + } + + Ok(()) + } } diff --git a/src/tools/miri/src/stacked_borrows/mod.rs b/src/tools/miri/src/stacked_borrows/mod.rs index 5ec787dd441..7f18e5dbae0 100644 --- a/src/tools/miri/src/stacked_borrows/mod.rs +++ b/src/tools/miri/src/stacked_borrows/mod.rs @@ -252,7 +252,7 @@ pub fn err_sb_ub<'tcx>( /// We need to make at least the following things true: /// /// U1: After creating a `Uniq`, it is at the top. -/// U2: If the top is `Uniq`, accesses must be through that `Uniq` or remove it it. +/// U2: If the top is `Uniq`, accesses must be through that `Uniq` or remove it. /// U3: If an access happens with a `Uniq`, it requires the `Uniq` to be in the stack. /// /// F1: After creating a `&`, the parts outside `UnsafeCell` have our `SharedReadOnly` on top. diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.rs b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.rs index 5cefdb08e78..cc774500a3c 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.rs @@ -1,4 +1,3 @@ -//@compile-flags: -Zmiri-retag-fields=scalar //@error-pattern: which is protected struct Newtype<'a>(&'a mut i32, i32); diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.rs b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.rs index bc3883575c3..1aa6e240e30 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.rs @@ -1,4 +1,3 @@ -//@compile-flags: -Zmiri-retag-fields=scalar //@error-pattern: which is protected struct Newtype<'a>(&'a mut i32); diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.rs b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.rs index 7fa9cf77d44..5a9dc6afba8 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.rs @@ -1,16 +1,15 @@ // Make sure that we cannot return a `&mut` that got already invalidated, not even in an `Option`. -// Due to shallow reborrowing, the error only surfaces when we look into the `Option`. fn foo(x: &mut (i32, i32)) -> Option<&mut i32> { let xraw = x as *mut (i32, i32); let ret = unsafe { &mut (*xraw).1 }; // let-bind to avoid 2phase let ret = Some(ret); let _val = unsafe { *xraw }; // invalidate xref - ret + ret //~ ERROR: /retag .* tag does not exist in the borrow stack/ } fn main() { match foo(&mut (1, 2)) { - Some(_x) => {} //~ ERROR: /retag .* tag does not exist in the borrow stack/ + Some(_x) => {} None => {} } } diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr index 1068c286c62..c0ff35ebcde 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr @@ -1,11 +1,11 @@ error: Undefined Behavior: trying to retag from <TAG> for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_mut_option.rs:LL:CC | -LL | Some(_x) => {} - | ^^ - | | - | trying to retag from <TAG> for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of retag at ALLOC[0x4..0x8] +LL | ret + | ^^^ + | | + | trying to retag from <TAG> for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information @@ -13,14 +13,19 @@ help: <TAG> was created by a Unique retag at offsets [0x4..0x8] --> $DIR/return_invalid_mut_option.rs:LL:CC | LL | let ret = Some(ret); - | ^^^ + | ^^^^^^^^^ help: <TAG> was later invalidated at offsets [0x0..0x8] by a read access --> $DIR/return_invalid_mut_option.rs:LL:CC | LL | let _val = unsafe { *xraw }; // invalidate xref | ^^^^^ = note: BACKTRACE: - = note: inside `main` at $DIR/return_invalid_mut_option.rs:LL:CC + = note: inside `foo` at $DIR/return_invalid_mut_option.rs:LL:CC +note: inside `main` at $DIR/return_invalid_mut_option.rs:LL:CC + --> $DIR/return_invalid_mut_option.rs:LL:CC + | +LL | match foo(&mut (1, 2)) { + | ^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.rs b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.rs index c94fef90542..8fe7f15cab0 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.rs @@ -1,12 +1,11 @@ // Make sure that we cannot return a `&mut` that got already invalidated, not even in a tuple. -// Due to shallow reborrowing, the error only surfaces when we look into the tuple. fn foo(x: &mut (i32, i32)) -> (&mut i32,) { let xraw = x as *mut (i32, i32); let ret = (unsafe { &mut (*xraw).1 },); let _val = unsafe { *xraw }; // invalidate xref - ret + ret //~ ERROR: /retag .* tag does not exist in the borrow stack/ } fn main() { - foo(&mut (1, 2)).0; //~ ERROR: /retag .* tag does not exist in the borrow stack/ + foo(&mut (1, 2)).0; } diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr index 79de9b668cf..9abf43c29f0 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: trying to retag from <TAG> for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_mut_tuple.rs:LL:CC | -LL | foo(&mut (1, 2)).0; - | ^^^^^^^^^^^^^^^^^^ +LL | ret + | ^^^ | | | trying to retag from <TAG> for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location | this error occurs as part of retag at ALLOC[0x4..0x8] @@ -13,14 +13,19 @@ help: <TAG> was created by a Unique retag at offsets [0x4..0x8] --> $DIR/return_invalid_mut_tuple.rs:LL:CC | LL | let ret = (unsafe { &mut (*xraw).1 },); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: <TAG> was later invalidated at offsets [0x0..0x8] by a read access --> $DIR/return_invalid_mut_tuple.rs:LL:CC | LL | let _val = unsafe { *xraw }; // invalidate xref | ^^^^^ = note: BACKTRACE: - = note: inside `main` at $DIR/return_invalid_mut_tuple.rs:LL:CC + = note: inside `foo` at $DIR/return_invalid_mut_tuple.rs:LL:CC +note: inside `main` at $DIR/return_invalid_mut_tuple.rs:LL:CC + --> $DIR/return_invalid_mut_tuple.rs:LL:CC + | +LL | foo(&mut (1, 2)).0; + | ^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.rs b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.rs index 3a028ceed86..094ce33b9c1 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.rs @@ -1,15 +1,14 @@ // Make sure that we cannot return a `&` that got already invalidated, not even in an `Option`. -// Due to shallow reborrowing, the error only surfaces when we look into the `Option`. fn foo(x: &mut (i32, i32)) -> Option<&i32> { let xraw = x as *mut (i32, i32); let ret = Some(unsafe { &(*xraw).1 }); unsafe { *xraw = (42, 23) }; // unfreeze - ret + ret //~ ERROR: /retag .* tag does not exist in the borrow stack/ } fn main() { match foo(&mut (1, 2)) { - Some(_x) => {} //~ ERROR: /retag .* tag does not exist in the borrow stack/ + Some(_x) => {} None => {} } } diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr index f45456305db..6066bf89f5d 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr @@ -1,11 +1,11 @@ error: Undefined Behavior: trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_shr_option.rs:LL:CC | -LL | Some(_x) => {} - | ^^ - | | - | trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of retag at ALLOC[0x4..0x8] +LL | ret + | ^^^ + | | + | trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information @@ -13,14 +13,19 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0x8] --> $DIR/return_invalid_shr_option.rs:LL:CC | LL | let ret = Some(unsafe { &(*xraw).1 }); - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access --> $DIR/return_invalid_shr_option.rs:LL:CC | LL | unsafe { *xraw = (42, 23) }; // unfreeze | ^^^^^^^^^^^^^^^^ = note: BACKTRACE: - = note: inside `main` at $DIR/return_invalid_shr_option.rs:LL:CC + = note: inside `foo` at $DIR/return_invalid_shr_option.rs:LL:CC +note: inside `main` at $DIR/return_invalid_shr_option.rs:LL:CC + --> $DIR/return_invalid_shr_option.rs:LL:CC + | +LL | match foo(&mut (1, 2)) { + | ^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.rs b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.rs index e4536626dbf..d0fd53e06aa 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.rs @@ -1,12 +1,11 @@ // Make sure that we cannot return a `&` that got already invalidated, not even in a tuple. -// Due to shallow reborrowing, the error only surfaces when we look into the tuple. fn foo(x: &mut (i32, i32)) -> (&i32,) { let xraw = x as *mut (i32, i32); let ret = (unsafe { &(*xraw).1 },); unsafe { *xraw = (42, 23) }; // unfreeze - ret + ret //~ ERROR: /retag .* tag does not exist in the borrow stack/ } fn main() { - foo(&mut (1, 2)).0; //~ ERROR: /retag .* tag does not exist in the borrow stack/ + foo(&mut (1, 2)).0; } diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr index 2e41f505bb9..52d365246a7 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_shr_tuple.rs:LL:CC | -LL | foo(&mut (1, 2)).0; - | ^^^^^^^^^^^^^^^^^^ +LL | ret + | ^^^ | | | trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location | this error occurs as part of retag at ALLOC[0x4..0x8] @@ -13,14 +13,19 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0x8] --> $DIR/return_invalid_shr_tuple.rs:LL:CC | LL | let ret = (unsafe { &(*xraw).1 },); - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access --> $DIR/return_invalid_shr_tuple.rs:LL:CC | LL | unsafe { *xraw = (42, 23) }; // unfreeze | ^^^^^^^^^^^^^^^^ = note: BACKTRACE: - = note: inside `main` at $DIR/return_invalid_shr_tuple.rs:LL:CC + = note: inside `foo` at $DIR/return_invalid_shr_tuple.rs:LL:CC +note: inside `main` at $DIR/return_invalid_shr_tuple.rs:LL:CC + --> $DIR/return_invalid_shr_tuple.rs:LL:CC + | +LL | foo(&mut (1, 2)).0; + | ^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/pass/concurrency/sync.rs b/src/tools/miri/tests/pass/concurrency/sync.rs index b1518a49fbb..19ea6c130bd 100644 --- a/src/tools/miri/tests/pass/concurrency/sync.rs +++ b/src/tools/miri/tests/pass/concurrency/sync.rs @@ -230,20 +230,8 @@ fn main() { check_once(); park_timeout(); park_unpark(); - - if !cfg!(windows) { - // ignore-target-windows: Condvars on Windows are not supported yet - check_barriers(); - check_conditional_variables_notify_one(); - check_conditional_variables_timed_wait_timeout(); - check_conditional_variables_timed_wait_notimeout(); - } else { - // We need to fake the same output... - for _ in 0..10 { - println!("before wait"); - } - for _ in 0..10 { - println!("after wait"); - } - } + check_barriers(); + check_conditional_variables_notify_one(); + check_conditional_variables_timed_wait_timeout(); + check_conditional_variables_timed_wait_notimeout(); } diff --git a/src/tools/miri/tests/pass/concurrency/sync_nopreempt.rs b/src/tools/miri/tests/pass/concurrency/sync_nopreempt.rs index 55206f4bfc5..c6cff038f81 100644 --- a/src/tools/miri/tests/pass/concurrency/sync_nopreempt.rs +++ b/src/tools/miri/tests/pass/concurrency/sync_nopreempt.rs @@ -1,4 +1,3 @@ -//@ignore-target-windows: Condvars on Windows are not supported yet. // We are making scheduler assumptions here. //@compile-flags: -Zmiri-strict-provenance -Zmiri-preemption-rate=0 diff --git a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs b/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs new file mode 100644 index 00000000000..d89320bfe59 --- /dev/null +++ b/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs @@ -0,0 +1,227 @@ +//@only-target-windows: Uses win32 api functions +// We are making scheduler assumptions here. +//@compile-flags: -Zmiri-preemption-rate=0 + +use std::ffi::c_void; +use std::ptr::null_mut; +use std::thread; + +#[derive(Copy, Clone)] +struct SendPtr<T>(*mut T); + +unsafe impl<T> Send for SendPtr<T> {} + +extern "system" { + fn SleepConditionVariableSRW( + condvar: *mut *mut c_void, + lock: *mut *mut c_void, + timeout: u32, + flags: u32, + ) -> i32; + fn WakeAllConditionVariable(condvar: *mut *mut c_void); + + fn AcquireSRWLockExclusive(lock: *mut *mut c_void); + fn AcquireSRWLockShared(lock: *mut *mut c_void); + fn ReleaseSRWLockExclusive(lock: *mut *mut c_void); + fn ReleaseSRWLockShared(lock: *mut *mut c_void); +} + +const CONDITION_VARIABLE_LOCKMODE_SHARED: u32 = 1; +const INFINITE: u32 = u32::MAX; + +/// threads should be able to reacquire the lock while it is locked by multiple other threads in shared mode +fn all_shared() { + println!("all_shared"); + + let mut lock = null_mut(); + let mut condvar = null_mut(); + + let lock_ptr = SendPtr(&mut lock); + let condvar_ptr = SendPtr(&mut condvar); + + let mut handles = Vec::with_capacity(10); + + // waiters + for i in 0..5 { + handles.push(thread::spawn(move || { + unsafe { + AcquireSRWLockShared(lock_ptr.0); + } + println!("exclusive waiter {i} locked"); + + let r = unsafe { + SleepConditionVariableSRW( + condvar_ptr.0, + lock_ptr.0, + INFINITE, + CONDITION_VARIABLE_LOCKMODE_SHARED, + ) + }; + assert_ne!(r, 0); + + println!("exclusive waiter {i} reacquired lock"); + + // unlocking is unnecessary because the lock is never used again + })); + } + + // ensures each waiter is waiting by this point + thread::yield_now(); + + // readers + for i in 0..5 { + handles.push(thread::spawn(move || { + unsafe { + AcquireSRWLockShared(lock_ptr.0); + } + println!("reader {i} locked"); + + // switch to next reader or main thread + thread::yield_now(); + + unsafe { + ReleaseSRWLockShared(lock_ptr.0); + } + println!("reader {i} unlocked"); + })); + } + + // ensures each reader has acquired the lock + thread::yield_now(); + + unsafe { + WakeAllConditionVariable(condvar_ptr.0); + } + + for handle in handles { + handle.join().unwrap(); + } +} + +// reacquiring a lock should wait until the lock is not exclusively locked +fn shared_sleep_and_exclusive_lock() { + println!("shared_sleep_and_exclusive_lock"); + + let mut lock = null_mut(); + let mut condvar = null_mut(); + + let lock_ptr = SendPtr(&mut lock); + let condvar_ptr = SendPtr(&mut condvar); + + let mut waiters = Vec::with_capacity(5); + for i in 0..5 { + waiters.push(thread::spawn(move || { + unsafe { + AcquireSRWLockShared(lock_ptr.0); + } + println!("shared waiter {i} locked"); + + let r = unsafe { + SleepConditionVariableSRW( + condvar_ptr.0, + lock_ptr.0, + INFINITE, + CONDITION_VARIABLE_LOCKMODE_SHARED, + ) + }; + assert_ne!(r, 0); + + println!("shared waiter {i} reacquired lock"); + + // unlocking is unnecessary because the lock is never used again + })); + } + + // ensures each waiter is waiting by this point + thread::yield_now(); + + unsafe { + AcquireSRWLockExclusive(lock_ptr.0); + } + println!("main locked"); + + unsafe { + WakeAllConditionVariable(condvar_ptr.0); + } + + // waiters are now waiting for the lock to be unlocked + thread::yield_now(); + + unsafe { + ReleaseSRWLockExclusive(lock_ptr.0); + } + println!("main unlocked"); + + for handle in waiters { + handle.join().unwrap(); + } +} + +// threads reacquiring locks should wait for all locks to be released first +fn exclusive_sleep_and_shared_lock() { + println!("exclusive_sleep_and_shared_lock"); + + let mut lock = null_mut(); + let mut condvar = null_mut(); + + let lock_ptr = SendPtr(&mut lock); + let condvar_ptr = SendPtr(&mut condvar); + + let mut handles = Vec::with_capacity(10); + for i in 0..5 { + handles.push(thread::spawn(move || { + unsafe { + AcquireSRWLockExclusive(lock_ptr.0); + } + + println!("exclusive waiter {i} locked"); + + let r = unsafe { SleepConditionVariableSRW(condvar_ptr.0, lock_ptr.0, INFINITE, 0) }; + assert_ne!(r, 0); + + println!("exclusive waiter {i} reacquired lock"); + + // switch to next waiter or main thread + thread::yield_now(); + + unsafe { + ReleaseSRWLockExclusive(lock_ptr.0); + } + println!("exclusive waiter {i} unlocked"); + })); + } + + for i in 0..5 { + handles.push(thread::spawn(move || { + unsafe { + AcquireSRWLockShared(lock_ptr.0); + } + println!("reader {i} locked"); + + // switch to next reader or main thread + thread::yield_now(); + + unsafe { + ReleaseSRWLockShared(lock_ptr.0); + } + println!("reader {i} unlocked"); + })); + } + + // ensures each reader has acquired the lock + thread::yield_now(); + + unsafe { + WakeAllConditionVariable(condvar_ptr.0); + } + + for handle in handles { + handle.join().unwrap(); + } +} + +fn main() { + all_shared(); + shared_sleep_and_exclusive_lock(); + exclusive_sleep_and_shared_lock(); +} diff --git a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.stdout b/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.stdout new file mode 100644 index 00000000000..918b54668f2 --- /dev/null +++ b/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.stdout @@ -0,0 +1,60 @@ +all_shared +exclusive waiter 0 locked +exclusive waiter 1 locked +exclusive waiter 2 locked +exclusive waiter 3 locked +exclusive waiter 4 locked +reader 0 locked +reader 1 locked +reader 2 locked +reader 3 locked +reader 4 locked +exclusive waiter 0 reacquired lock +exclusive waiter 1 reacquired lock +exclusive waiter 2 reacquired lock +exclusive waiter 3 reacquired lock +exclusive waiter 4 reacquired lock +reader 0 unlocked +reader 1 unlocked +reader 2 unlocked +reader 3 unlocked +reader 4 unlocked +shared_sleep_and_exclusive_lock +shared waiter 0 locked +shared waiter 1 locked +shared waiter 2 locked +shared waiter 3 locked +shared waiter 4 locked +main locked +main unlocked +shared waiter 0 reacquired lock +shared waiter 1 reacquired lock +shared waiter 2 reacquired lock +shared waiter 3 reacquired lock +shared waiter 4 reacquired lock +exclusive_sleep_and_shared_lock +exclusive waiter 0 locked +exclusive waiter 1 locked +exclusive waiter 2 locked +exclusive waiter 3 locked +exclusive waiter 4 locked +reader 0 locked +reader 1 locked +reader 2 locked +reader 3 locked +reader 4 locked +reader 0 unlocked +reader 1 unlocked +reader 2 unlocked +reader 3 unlocked +reader 4 unlocked +exclusive waiter 0 reacquired lock +exclusive waiter 0 unlocked +exclusive waiter 1 reacquired lock +exclusive waiter 1 unlocked +exclusive waiter 2 reacquired lock +exclusive waiter 2 unlocked +exclusive waiter 3 reacquired lock +exclusive waiter 3 unlocked +exclusive waiter 4 reacquired lock +exclusive waiter 4 unlocked diff --git a/src/tools/miri/tests/pass/concurrency/windows_init_once.rs b/src/tools/miri/tests/pass/concurrency/windows_init_once.rs index d3c72c3d028..4eb88379620 100644 --- a/src/tools/miri/tests/pass/concurrency/windows_init_once.rs +++ b/src/tools/miri/tests/pass/concurrency/windows_init_once.rs @@ -131,8 +131,46 @@ fn retry_on_fail() { waiter2.join().unwrap(); } +fn no_data_race_after_complete() { + let mut init_once = null_mut(); + let mut pending = 0; + + unsafe { + assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); + assert_eq!(pending, TRUE); + } + + let init_once_ptr = SendPtr(&mut init_once); + + let mut place = 0; + let place_ptr = SendPtr(&mut place); + + let reader = thread::spawn(move || unsafe { + let mut pending = 0; + + // this doesn't block because reader only executes after `InitOnceComplete` is called + assert_eq!(InitOnceBeginInitialize(init_once_ptr.0, 0, &mut pending, null_mut()), TRUE); + assert_eq!(pending, FALSE); + // this should not data race + place_ptr.0.read() + }); + + unsafe { + // this should not data race + place_ptr.0.write(1); + } + + unsafe { + assert_eq!(InitOnceComplete(init_once_ptr.0, 0, null_mut()), TRUE); + } + + // run reader (without preemption, it has not taken a step yet) + assert_eq!(reader.join().unwrap(), 1); +} + fn main() { single_thread(); block_until_complete(); retry_on_fail(); + no_data_race_after_complete(); } diff --git a/src/tools/miri/tests/pass/integer-ops.rs b/src/tools/miri/tests/pass/integer-ops.rs index 724be9efc9f..0ec1f8e9c69 100644 --- a/src/tools/miri/tests/pass/integer-ops.rs +++ b/src/tools/miri/tests/pass/integer-ops.rs @@ -1,5 +1,4 @@ //@compile-flags: -Coverflow-checks=off -#![feature(int_log)] #![allow(arithmetic_overflow)] pub fn main() { diff --git a/src/tools/miri/tests/pass/panic/concurrent-panic.rs b/src/tools/miri/tests/pass/panic/concurrent-panic.rs index 342269c6acb..776bc2057f3 100644 --- a/src/tools/miri/tests/pass/panic/concurrent-panic.rs +++ b/src/tools/miri/tests/pass/panic/concurrent-panic.rs @@ -1,4 +1,3 @@ -//@ignore-target-windows: Condvars on Windows are not supported yet. // We are making scheduler assumptions here. //@compile-flags: -Zmiri-preemption-rate=0 diff --git a/src/tools/miri/tests/pass/stacked-borrows/no_field_retagging.rs b/src/tools/miri/tests/pass/stacked-borrows/no_field_retagging.rs new file mode 100644 index 00000000000..48fc8e8668c --- /dev/null +++ b/src/tools/miri/tests/pass/stacked-borrows/no_field_retagging.rs @@ -0,0 +1,19 @@ +//@compile-flags: -Zmiri-retag-fields=none + +struct Newtype<'a>(&'a mut i32); + +fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) { + dealloc(); +} + +// Make sure that we do *not* retag the fields of `Newtype`. +fn main() { + let ptr = Box::into_raw(Box::new(0i32)); + #[rustfmt::skip] // I like my newlines + unsafe { + dealloc_while_running( + Newtype(&mut *ptr), + || drop(Box::from_raw(ptr)), + ) + }; +} diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout index 83873307820..296339e7384 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout +++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout @@ -1,6 +1,6 @@ 0..1: [ SharedReadWrite<TAG> ] 0..1: [ SharedReadWrite<TAG> ] 0..1: [ SharedReadWrite<TAG> ] -0..1: [ SharedReadWrite<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> ] -0..1: [ SharedReadWrite<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> SharedReadOnly<TAG> ] +0..1: [ SharedReadWrite<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> ] +0..1: [ SharedReadWrite<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> SharedReadOnly<TAG> ] 0..1: [ unknown-bottom(..<TAG>) ] diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs index ec992da6812..8e7c39e72b6 100644 --- a/src/tools/remote-test-server/src/main.rs +++ b/src/tools/remote-test-server/src/main.rs @@ -39,6 +39,8 @@ macro_rules! t { } static TEST: AtomicUsize = AtomicUsize::new(0); +const RETRY_INTERVAL: u64 = 1; +const NUMBER_OF_RETRIES: usize = 5; #[derive(Copy, Clone)] struct Config { @@ -115,7 +117,7 @@ fn main() { let config = Config::parse_args(); println!("starting test server"); - let listener = t!(TcpListener::bind(config.bind)); + let listener = bind_socket(config.bind); let (work, tmp): (PathBuf, PathBuf) = if cfg!(target_os = "android") { ("/data/local/tmp/work".into(), "/data/local/tmp/work/tmp".into()) } else { @@ -159,6 +161,16 @@ fn main() { } } +fn bind_socket(addr: SocketAddr) -> TcpListener { + for _ in 0..(NUMBER_OF_RETRIES - 1) { + if let Ok(x) = TcpListener::bind(addr) { + return x; + } + std::thread::sleep(std::time::Duration::from_secs(RETRY_INTERVAL)); + } + TcpListener::bind(addr).unwrap() +} + fn handle_push(socket: TcpStream, work: &Path, config: Config) { let mut reader = BufReader::new(socket); let dst = recv(&work, &mut reader); diff --git a/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/bug_report.md b/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/bug_report.md index a038dce3248..c2e21933c9a 100644 --- a/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/bug_report.md +++ b/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/bug_report.md @@ -13,8 +13,7 @@ Forum for questions: https://users.rust-lang.org/c/ide/14 Before submitting, please make sure that you're not running into one of these known issues: - 1. extension doesn't load in VSCodium: #11080 - 2. on-the-fly diagnostics are mostly unimplemented (`cargo check` diagnostics will be shown when saving a file): #3107 + 1. on-the-fly diagnostics are mostly unimplemented (`cargo check` diagnostics will be shown when saving a file): #3107 Otherwise please try to provide information which will help us to fix the issue faster. Minimal reproducible examples with few dependencies are especially lovely <3. --> diff --git a/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md b/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md index a0b1627d7e2..ad220ff65ca 100644 --- a/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md +++ b/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md @@ -2,8 +2,8 @@ name: Critical Nightly Regression about: You are using nightly rust-analyzer and the latest version is unusable. title: '' -labels: '' -assignees: 'matklad' +labels: 'Broken Window' +assignees: '' --- @@ -14,4 +14,3 @@ Please try to provide information which will help us to fix the issue faster. Mi --> This is a serious regression in nightly and it's important to fix it before the next release. -@matklad, please take a look. diff --git a/src/tools/rust-analyzer/.github/workflows/release.yaml b/src/tools/rust-analyzer/.github/workflows/release.yaml index 422fe29f9d5..b070dd3406f 100644 --- a/src/tools/rust-analyzer/.github/workflows/release.yaml +++ b/src/tools/rust-analyzer/.github/workflows/release.yaml @@ -257,8 +257,7 @@ jobs: - name: Publish Extension (OpenVSX, release) if: github.ref == 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer') working-directory: ./editors/code - # token from https://dev.azure.com/rust-analyzer/ - run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix || true + run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix timeout-minutes: 2 - name: Publish Extension (Code Marketplace, nightly) @@ -269,5 +268,5 @@ jobs: - name: Publish Extension (OpenVSX, nightly) if: github.ref != 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer') working-directory: ./editors/code - run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix || true + run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix timeout-minutes: 2 diff --git a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs index 6636c8a23ca..933970d10e4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs @@ -143,9 +143,12 @@ pub(crate) fn print_type_ref(type_ref: &TypeRef, buf: &mut dyn Write) -> fmt::Re print_type_ref(elem, buf)?; write!(buf, "]")?; } - TypeRef::Fn(args_and_ret, varargs) => { + TypeRef::Fn(args_and_ret, varargs, is_unsafe) => { let ((_, return_type), args) = args_and_ret.split_last().expect("TypeRef::Fn is missing return type"); + if *is_unsafe { + write!(buf, "unsafe ")?; + } write!(buf, "fn(")?; for (i, (_, typeref)) in args.iter().enumerate() { if i != 0 { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs index 5b4c71be7fb..f8bb78ddcfe 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs @@ -119,7 +119,7 @@ pub enum TypeRef { Array(Box<TypeRef>, ConstScalarOrPath), Slice(Box<TypeRef>), /// A fn pointer. Last element of the vector is the return type. - Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/), + Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/, bool /*is_unsafe*/), ImplTrait(Vec<Interned<TypeBound>>), DynTrait(Vec<Interned<TypeBound>>), Macro(AstId<ast::MacroCall>), @@ -229,7 +229,7 @@ impl TypeRef { Vec::new() }; params.push((None, ret_ty)); - TypeRef::Fn(params, is_varargs) + TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some()) } // for types are close enough for our purposes to the inner type for now... ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()), @@ -263,7 +263,7 @@ impl TypeRef { fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) { f(type_ref); match type_ref { - TypeRef::Fn(params, _) => { + TypeRef::Fn(params, _, _) => { params.iter().for_each(|(_, param_type)| go(param_type, f)) } TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)), 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 5ad66132635..a22a4b170f6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -1187,8 +1187,11 @@ impl HirDisplay for TypeRef { inner.hir_fmt(f)?; write!(f, "]")?; } - TypeRef::Fn(parameters, is_varargs) => { + &TypeRef::Fn(ref parameters, is_varargs, is_unsafe) => { // FIXME: Function pointer qualifiers. + if is_unsafe { + write!(f, "unsafe ")?; + } write!(f, "fn(")?; if let Some(((_, return_type), function_parameters)) = parameters.split_last() { for index in 0..function_parameters.len() { @@ -1203,7 +1206,7 @@ impl HirDisplay for TypeRef { write!(f, ", ")?; } } - if *is_varargs { + if is_varargs { write!(f, "{}...", if parameters.len() == 1 { "" } else { ", " })?; } write!(f, ")")?; 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 0efff651cc1..0b3c23f5747 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1020,7 +1020,7 @@ impl Expectation { /// The primary use case is where the expected type is a fat pointer, /// like `&[isize]`. For example, consider the following statement: /// - /// let x: &[isize] = &[1, 2, 3]; + /// let x: &[isize] = &[1, 2, 3]; /// /// In this case, the expected type for the `&[1, 2, 3]` expression is /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the 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 f56108b26c4..b1f4de82607 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 @@ -85,6 +85,7 @@ impl<'a> InferenceContext<'a> { let ty = match &self.body[tgt_expr] { Expr::Missing => self.err_ty(), &Expr::If { condition, then_branch, else_branch } => { + let expected = &expected.adjust_for_branches(&mut self.table); self.infer_expr( condition, &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 42c3b58d5ad..b68c764bdca 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -38,10 +38,12 @@ use std::sync::Arc; use chalk_ir::{ fold::{Shift, TypeFoldable}, interner::HasInterner, - NoSolution, + NoSolution, UniverseIndex, }; use hir_def::{expr::ExprId, type_ref::Rawness, TypeOrConstParamId}; +use hir_expand::name; use itertools::Either; +use traits::FnTrait; use utils::Generics; use crate::{consteval::unknown_const, db::HirDatabase, utils::generics}; @@ -208,6 +210,7 @@ pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>( pub struct CallableSig { params_and_return: Arc<[Ty]>, is_varargs: bool, + safety: Safety, } has_interner!(CallableSig); @@ -216,9 +219,14 @@ has_interner!(CallableSig); pub type PolyFnSig = Binders<CallableSig>; impl CallableSig { - pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig { + pub fn from_params_and_return( + mut params: Vec<Ty>, + ret: Ty, + is_varargs: bool, + safety: Safety, + ) -> CallableSig { params.push(ret); - CallableSig { params_and_return: params.into(), is_varargs } + CallableSig { params_and_return: params.into(), is_varargs, safety } } pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { @@ -235,13 +243,14 @@ impl CallableSig { .map(|arg| arg.assert_ty_ref(Interner).clone()) .collect(), is_varargs: fn_ptr.sig.variadic, + safety: fn_ptr.sig.safety, } } pub fn to_fn_ptr(&self) -> FnPointer { FnPointer { num_binders: 0, - sig: FnSig { abi: (), safety: Safety::Safe, variadic: self.is_varargs }, + sig: FnSig { abi: (), safety: self.safety, variadic: self.is_varargs }, substitution: FnSubst(Substitution::from_iter( Interner, self.params_and_return.iter().cloned(), @@ -266,7 +275,11 @@ impl TypeFoldable<Interner> for CallableSig { ) -> Result<Self, E> { let vec = self.params_and_return.to_vec(); let folded = vec.try_fold_with(folder, outer_binder)?; - Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs }) + Ok(CallableSig { + params_and_return: folded.into(), + is_varargs: self.is_varargs, + safety: self.safety, + }) } } @@ -508,3 +521,68 @@ where }); Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) } } + +pub fn callable_sig_from_fnonce( + self_ty: &Canonical<Ty>, + env: Arc<TraitEnvironment>, + db: &dyn HirDatabase, +) -> Option<CallableSig> { + let krate = env.krate; + let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?; + let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; + + let mut kinds = self_ty.binders.interned().to_vec(); + let b = TyBuilder::trait_ref(db, fn_once_trait); + if b.remaining() != 2 { + return None; + } + let fn_once = b + .push(self_ty.value.clone()) + .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) + .build(); + kinds.extend(fn_once.substitution.iter(Interner).skip(1).map(|x| { + let vk = match x.data(Interner) { + chalk_ir::GenericArgData::Ty(_) => { + chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General) + } + chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime, + chalk_ir::GenericArgData::Const(c) => { + chalk_ir::VariableKind::Const(c.data(Interner).ty.clone()) + } + }; + chalk_ir::WithKind::new(vk, UniverseIndex::ROOT) + })); + + // FIXME: chalk refuses to solve `<Self as FnOnce<^0.0>>::Output == ^0.1`, so we first solve + // `<Self as FnOnce<^0.0>>` and then replace `^0.0` with the concrete argument tuple. + let trait_env = env.env.clone(); + let obligation = InEnvironment { goal: fn_once.cast(Interner), environment: trait_env }; + let canonical = + Canonical { binders: CanonicalVarKinds::from_iter(Interner, kinds), value: obligation }; + let subst = match db.trait_solve(krate, canonical) { + Some(Solution::Unique(vars)) => vars.value.subst, + _ => return None, + }; + let args = subst.at(Interner, self_ty.binders.interned().len()).ty(Interner)?; + let params = match args.kind(Interner) { + chalk_ir::TyKind::Tuple(_, subst) => { + subst.iter(Interner).filter_map(|arg| arg.ty(Interner).cloned()).collect::<Vec<_>>() + } + _ => return None, + }; + if params.iter().any(|ty| ty.is_unknown()) { + return None; + } + + let fn_once = TyBuilder::trait_ref(db, fn_once_trait) + .push(self_ty.value.clone()) + .push(args.clone()) + .build(); + let projection = + TyBuilder::assoc_type_projection(db, output_assoc_type, Some(fn_once.substitution.clone())) + .build(); + + let ret_ty = db.normalize_projection(projection, env); + + Some(CallableSig::from_params_and_return(params, ret_ty.clone(), false, Safety::Safe)) +} 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 22a85cf1545..baf9842d5fb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -227,13 +227,17 @@ impl<'a> TyLoweringContext<'a> { .intern(Interner) } TypeRef::Placeholder => TyKind::Error.intern(Interner), - TypeRef::Fn(params, is_varargs) => { + &TypeRef::Fn(ref params, variadic, is_unsafe) => { let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr))) }); TyKind::Function(FnPointer { num_binders: 0, // FIXME lower `for<'a> fn()` correctly - sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs }, + sig: FnSig { + abi: (), + safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe }, + variadic, + }, substitution: FnSubst(substs), }) .intern(Interner) @@ -1573,7 +1577,12 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { .with_type_param_mode(ParamLoweringMode::Variable); let ret = ctx_ret.lower_ty(&data.ret_type); let generics = generics(db.upcast(), def.into()); - let sig = CallableSig::from_params_and_return(params, ret, data.is_varargs()); + let sig = CallableSig::from_params_and_return( + params, + ret, + data.is_varargs(), + if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe }, + ); make_binders(db, &generics, sig) } @@ -1617,7 +1626,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>(); let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders(); - Binders::new(binders, CallableSig::from_params_and_return(params, ret, false)) + Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe)) } /// Build the type of a tuple struct constructor. @@ -1644,7 +1653,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>(); let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders(); - Binders::new(binders, CallableSig::from_params_and_return(params, ret, false)) + Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe)) } /// Build the type of a tuple enum variant constructor. 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 d301595bcd9..7e3aecc2ae0 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 @@ -123,6 +123,23 @@ fn test() { } #[test] +fn if_else_adjust_for_branches_discard_type_var() { + check_no_mismatches( + r#" +fn test() { + let f = || { + if true { + &"" + } else { + "" + } + }; +} +"#, + ); +} + +#[test] fn match_first_coerce() { check_no_mismatches( r#" @@ -183,6 +200,22 @@ fn test() { } #[test] +fn match_adjust_for_branches_discard_type_var() { + check_no_mismatches( + r#" +fn test() { + let f = || { + match 0i32 { + 0i32 => &"", + _ => "", + } + }; +} +"#, + ); +} + +#[test] fn return_coerce_unknown() { check_types( r" @@ -357,7 +390,7 @@ fn test() { let f: fn(u32) -> isize = foo; // ^^^ adjustments: Pointer(ReifyFnPointer) let f: unsafe fn(u32) -> isize = foo; - // ^^^ adjustments: Pointer(ReifyFnPointer) + // ^^^ adjustments: Pointer(ReifyFnPointer), Pointer(UnsafeFnPointer) }", ); } @@ -388,7 +421,10 @@ fn coerce_closure_to_fn_ptr() { check_no_mismatches( r" fn test() { - let f: fn(u32) -> isize = |x| { 1 }; + let f: fn(u32) -> u32 = |x| x; + // ^^^^^ adjustments: Pointer(ClosureFnPointer(Safe)) + let f: unsafe fn(u32) -> u32 = |x| x; + // ^^^^^ adjustments: Pointer(ClosureFnPointer(Unsafe)) }", ); } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index f5324208c9a..cbd9bf32a54 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -2995,7 +2995,17 @@ impl Type { let callee = match self.ty.kind(Interner) { TyKind::Closure(id, _) => Callee::Closure(*id), TyKind::Function(_) => Callee::FnPtr, - _ => Callee::Def(self.ty.callable_def(db)?), + TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?), + _ => { + let ty = hir_ty::replace_errors_with_variables(&self.ty); + let sig = hir_ty::callable_sig_from_fnonce(&ty, self.env.clone(), db)?; + return Some(Callable { + ty: self.clone(), + sig, + callee: Callee::Other, + is_bound_method: false, + }); + } }; let sig = self.ty.callable_sig(db)?; @@ -3464,6 +3474,7 @@ enum Callee { Def(CallableDefId), Closure(ClosureId), FnPtr, + Other, } pub enum CallableKind { @@ -3472,6 +3483,8 @@ pub enum CallableKind { TupleEnumVariant(Variant), Closure, FnPtr, + /// Some other type that implements `FnOnce`. + Other, } impl Callable { @@ -3483,6 +3496,7 @@ impl Callable { Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()), Closure(_) => CallableKind::Closure, FnPtr => CallableKind::FnPtr, + Other => CallableKind::Other, } } pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> { 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 60d1588a44e..b273ebc85a5 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 @@ -14,4 +14,5 @@ pub struct AssistConfig { pub allowed: Option<Vec<AssistKind>>, pub insert_use: InsertUseConfig, pub prefer_no_std: bool, + pub assist_emit_must_use: bool, } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_type.rs index bfa9759ec84..b5f99726fe1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_type.rs @@ -69,14 +69,14 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> O let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?; acc.add( AssistId("add_explicit_type", AssistKind::RefactorRewrite), - format!("Insert explicit type `{}`", inferred_type), + format!("Insert explicit type `{inferred_type}`"), pat_range, |builder| match ascribed_ty { Some(ascribed_ty) => { builder.replace(ascribed_ty.syntax().text_range(), inferred_type); } None => { - builder.insert(pat_range.end(), format!(": {}", inferred_type)); + builder.insert(pat_range.end(), format!(": {inferred_type}")); } }, ) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_return_type.rs index f858d7a15c2..89040a8569e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_return_type.rs @@ -35,16 +35,16 @@ pub(crate) fn add_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt match builder_edit_pos { InsertOrReplace::Insert(insert_pos, needs_whitespace) => { let preceeding_whitespace = if needs_whitespace { " " } else { "" }; - builder.insert(insert_pos, &format!("{}-> {} ", preceeding_whitespace, ty)) + builder.insert(insert_pos, &format!("{preceeding_whitespace}-> {ty} ")) } InsertOrReplace::Replace(text_range) => { - builder.replace(text_range, &format!("-> {}", ty)) + builder.replace(text_range, &format!("-> {ty}")) } } if let FnType::Closure { wrap_expr: true } = fn_type { cov_mark::hit!(wrap_closure_non_block_expr); // `|x| x` becomes `|x| -> T x` which is invalid, so wrap it in a block - builder.replace(tail_expr.syntax().text_range(), &format!("{{{}}}", tail_expr)); + builder.replace(tail_expr.syntax().text_range(), &format!("{{{tail_expr}}}")); } }, ) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs index c0bf238db73..acf82e4b257 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs @@ -93,12 +93,13 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti builder.trigger_signature_help(); match ctx.config.snippet_cap { Some(cap) => { - let snip = format!("::<{}>", get_snippet_fish_head(number_of_arguments)); + let fish_head = get_snippet_fish_head(number_of_arguments); + let snip = format!("::<{fish_head}>"); builder.insert_snippet(cap, ident.text_range().end(), snip) } None => { let fish_head = std::iter::repeat("_").take(number_of_arguments).format(", "); - let snip = format!("::<{}>", fish_head); + let snip = format!("::<{fish_head}>"); builder.insert(ident.text_range().end(), snip); } } @@ -109,7 +110,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti /// This will create a snippet string with tabstops marked fn get_snippet_fish_head(number_of_arguments: usize) -> String { let mut fish_head = (1..number_of_arguments) - .format_with("", |i, f| f(&format_args!("${{{}:_}}, ", i))) + .format_with("", |i, f| f(&format_args!("${{{i}:_}}, "))) .to_string(); // tabstop 0 is a special case and always the last one diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs index 2853d1d1be3..57cfa17cc8e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -123,20 +123,20 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let lhs_range = lhs.syntax().text_range(); let not_lhs = invert_boolean_expression(lhs); - edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); + edit.replace(lhs_range, format!("!({not_lhs}")); } if let Some(rhs) = terms.pop_back() { let rhs_range = rhs.syntax().text_range(); let not_rhs = invert_boolean_expression(rhs); - edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); + edit.replace(rhs_range, format!("{not_rhs})")); } for term in terms { let term_range = term.syntax().text_range(); let not_term = invert_boolean_expression(term); - edit.replace(term_range, not_term.syntax().text()); + edit.replace(term_range, not_term.to_string()); } } }, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs index 678dc877d13..a689270bc09 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs @@ -127,10 +127,12 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< .sort_by_key(|import| Reverse(relevance_score(ctx, import, current_module.as_ref()))); for import in proposed_imports { + let import_path = import.import_path; + acc.add_group( &group_label, AssistId("auto_import", AssistKind::QuickFix), - format!("Import `{}`", import.import_path), + format!("Import `{import_path}`"), range, |builder| { let scope = match scope.clone() { @@ -138,7 +140,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)), ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)), }; - insert_use(&scope, mod_path_to_ast(&import.import_path), &ctx.config.insert_use); + insert_use(&scope, mod_path_to_ast(&import_path), &ctx.config.insert_use); }, ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs index f171dd81a81..312cb65abd2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -54,16 +54,17 @@ fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { let indent_spaces = indentation.to_string(); let output = lines - .map(|l| l.trim_start_matches(&indent_spaces)) - .map(|l| { + .map(|line| { + let line = line.trim_start_matches(&indent_spaces); + // Don't introduce trailing whitespace - if l.is_empty() { + if line.is_empty() { line_prefix.to_string() } else { - format!("{} {}", line_prefix, l.trim_start_matches(&indent_spaces)) + format!("{line_prefix} {line}") } }) - .join(&format!("\n{}", indent_spaces)); + .join(&format!("\n{indent_spaces}")); edit.replace(target, output) }, @@ -96,7 +97,7 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { let block_prefix = CommentKind { shape: CommentShape::Block, ..comment.kind() }.prefix(); - let output = format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation); + let output = format!("{block_prefix}\n{block_comment_body}\n{indentation}*/"); edit.replace(target, output) }, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs index 9060696cdc8..ff2195f7e6c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_integer_literal.rs @@ -32,19 +32,19 @@ pub(crate) fn convert_integer_literal(acc: &mut Assists, ctx: &AssistContext<'_> } let mut converted = match target_radix { - Radix::Binary => format!("0b{:b}", value), - Radix::Octal => format!("0o{:o}", value), + Radix::Binary => format!("0b{value:b}"), + Radix::Octal => format!("0o{value:o}"), Radix::Decimal => value.to_string(), - Radix::Hexadecimal => format!("0x{:X}", value), + Radix::Hexadecimal => format!("0x{value:X}"), }; - let label = format!("Convert {} to {}{}", literal, converted, suffix.unwrap_or_default()); - // Appends the type suffix back into the new literal if it exists. if let Some(suffix) = suffix { converted.push_str(suffix); } + let label = format!("Convert {literal} to {converted}"); + acc.add_group( &group_id, AssistId("convert_integer_literal", AssistKind::RefactorInline), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs index 95d11abe8bc..872b52c98ff 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs @@ -86,9 +86,9 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext<'_>) - impl_.syntax().text_range(), |builder| { builder.replace(src_type.syntax().text_range(), dest_type.to_string()); - builder.replace(ast_trait.syntax().text_range(), format!("From<{}>", src_type)); + builder.replace(ast_trait.syntax().text_range(), format!("From<{src_type}>")); builder.replace(into_fn_return.syntax().text_range(), "-> Self"); - builder.replace(into_fn_params.syntax().text_range(), format!("(val: {})", src_type)); + builder.replace(into_fn_params.syntax().text_range(), format!("(val: {src_type})")); builder.replace(into_fn_name.syntax().text_range(), "from"); for s in selfs { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs index 2cf370c0907..80eecf4a098 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs @@ -119,19 +119,19 @@ pub(crate) fn convert_for_loop_with_for_each( { // We have either "for x in &col" and col implements a method called iter // or "for x in &mut col" and col implements a method called iter_mut - format_to!(buf, "{}.{}()", expr_behind_ref, method); + format_to!(buf, "{expr_behind_ref}.{method}()"); } else if let ast::Expr::RangeExpr(..) = iterable { // range expressions need to be parenthesized for the syntax to be correct - format_to!(buf, "({})", iterable); + format_to!(buf, "({iterable})"); } else if impls_core_iter(&ctx.sema, &iterable) { - format_to!(buf, "{}", iterable); + format_to!(buf, "{iterable}"); } else if let ast::Expr::RefExpr(_) = iterable { - format_to!(buf, "({}).into_iter()", iterable); + format_to!(buf, "({iterable}).into_iter()"); } else { - format_to!(buf, "{}.into_iter()", iterable); + format_to!(buf, "{iterable}.into_iter()"); } - format_to!(buf, ".for_each(|{}| {});", pat, body); + format_to!(buf, ".for_each(|{pat}| {body});"); builder.replace(for_loop.syntax().text_range(), buf) }, 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 00095de257d..c82a3b53032 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 @@ -80,7 +80,7 @@ fn binders_to_str(binders: &[(Name, bool)], addmut: bool) -> String { .map( |(ident, ismut)| { if *ismut && addmut { - format!("mut {}", ident) + format!("mut {ident}") } else { ident.to_string() } @@ -93,7 +93,7 @@ fn binders_to_str(binders: &[(Name, bool)], addmut: bool) -> String { } else if binders.len() == 1 { vars } else { - format!("({})", vars) + format!("({vars})") } } @@ -153,7 +153,7 @@ pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<' 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.syntax().text()), + Some(tail) if only_expr => format!("{tail},"), _ => let_else_block.syntax().text().to_string(), }; let replace = if binders.is_empty() { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs new file mode 100644 index 00000000000..5bf04a3ad37 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs @@ -0,0 +1,413 @@ +use ide_db::defs::{Definition, NameRefClass}; +use syntax::{ + ast::{self, HasName}, + ted, AstNode, SyntaxNode, +}; + +use crate::{ + assist_context::{AssistContext, Assists}, + AssistId, AssistKind, +}; + +// Assist: convert_match_to_let_else +// +// Converts let statement with match initializer to let-else statement. +// +// ``` +// # //- minicore: option +// fn foo(opt: Option<()>) { +// let val = $0match opt { +// Some(it) => it, +// None => return, +// }; +// } +// ``` +// -> +// ``` +// fn foo(opt: Option<()>) { +// let Some(val) = opt else { return }; +// } +// ``` +pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let let_stmt: ast::LetStmt = ctx.find_node_at_offset()?; + let binding = find_binding(let_stmt.pat()?)?; + + let initializer = match let_stmt.initializer() { + Some(ast::Expr::MatchExpr(it)) => it, + _ => return None, + }; + let initializer_expr = initializer.expr()?; + + let (extracting_arm, diverging_arm) = match find_arms(ctx, &initializer) { + Some(it) => it, + None => return None, + }; + if extracting_arm.guard().is_some() { + cov_mark::hit!(extracting_arm_has_guard); + return None; + } + + let diverging_arm_expr = diverging_arm.expr()?; + let extracting_arm_pat = extracting_arm.pat()?; + let extracted_variable = find_extracted_variable(ctx, &extracting_arm)?; + + acc.add( + AssistId("convert_match_to_let_else", AssistKind::RefactorRewrite), + "Convert match to let-else", + let_stmt.syntax().text_range(), + |builder| { + let extracting_arm_pat = rename_variable(&extracting_arm_pat, extracted_variable, binding); + builder.replace( + let_stmt.syntax().text_range(), + format!("let {extracting_arm_pat} = {initializer_expr} else {{ {diverging_arm_expr} }};") + ) + }, + ) +} + +// Given a pattern, find the name introduced to the surrounding scope. +fn find_binding(pat: ast::Pat) -> Option<ast::IdentPat> { + if let ast::Pat::IdentPat(ident) = pat { + Some(ident) + } else { + None + } +} + +// Given a match expression, find extracting and diverging arms. +fn find_arms( + ctx: &AssistContext<'_>, + match_expr: &ast::MatchExpr, +) -> Option<(ast::MatchArm, ast::MatchArm)> { + let arms = match_expr.match_arm_list()?.arms().collect::<Vec<_>>(); + if arms.len() != 2 { + return None; + } + + let mut extracting = None; + let mut diverging = None; + for arm in arms { + if ctx.sema.type_of_expr(&arm.expr().unwrap()).unwrap().original().is_never() { + diverging = Some(arm); + } else { + extracting = Some(arm); + } + } + + match (extracting, diverging) { + (Some(extracting), Some(diverging)) => Some((extracting, diverging)), + _ => { + cov_mark::hit!(non_diverging_match); + None + } + } +} + +// Given an extracting arm, find the extracted variable. +fn find_extracted_variable(ctx: &AssistContext<'_>, arm: &ast::MatchArm) -> Option<ast::Name> { + match arm.expr()? { + ast::Expr::PathExpr(path) => { + let name_ref = path.syntax().descendants().find_map(ast::NameRef::cast)?; + match NameRefClass::classify(&ctx.sema, &name_ref)? { + NameRefClass::Definition(Definition::Local(local)) => { + let source = local.source(ctx.db()).value.left()?; + Some(source.name()?) + } + _ => None, + } + } + _ => { + cov_mark::hit!(extracting_arm_is_not_an_identity_expr); + return None; + } + } +} + +// Rename `extracted` with `binding` in `pat`. +fn rename_variable(pat: &ast::Pat, extracted: ast::Name, binding: ast::IdentPat) -> SyntaxNode { + let syntax = pat.syntax().clone_for_update(); + let extracted_syntax = syntax.covering_element(extracted.syntax().text_range()); + + // If `extracted` variable is a record field, we should rename it to `binding`, + // otherwise we just need to replace `extracted` with `binding`. + + if let Some(record_pat_field) = extracted_syntax.ancestors().find_map(ast::RecordPatField::cast) + { + if let Some(name_ref) = record_pat_field.field_name() { + ted::replace( + record_pat_field.syntax(), + ast::make::record_pat_field(ast::make::name_ref(&name_ref.text()), binding.into()) + .syntax() + .clone_for_update(), + ); + } + } else { + ted::replace(extracted_syntax, binding.syntax().clone_for_update()); + } + + syntax +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn should_not_be_applicable_for_non_diverging_match() { + cov_mark::check!(non_diverging_match); + check_assist_not_applicable( + convert_match_to_let_else, + r#" +//- minicore: option +fn foo(opt: Option<()>) { + let val = $0match opt { + Some(it) => it, + None => (), + }; +} +"#, + ); + } + + #[test] + fn should_not_be_applicable_if_extracting_arm_is_not_an_identity_expr() { + cov_mark::check_count!(extracting_arm_is_not_an_identity_expr, 2); + check_assist_not_applicable( + convert_match_to_let_else, + r#" +//- minicore: option +fn foo(opt: Option<i32>) { + let val = $0match opt { + Some(it) => it + 1, + None => return, + }; +} +"#, + ); + + check_assist_not_applicable( + convert_match_to_let_else, + r#" +//- minicore: option +fn foo(opt: Option<()>) { + let val = $0match opt { + Some(it) => { + let _ = 1 + 1; + it + }, + None => return, + }; +} +"#, + ); + } + + #[test] + fn should_not_be_applicable_if_extracting_arm_has_guard() { + cov_mark::check!(extracting_arm_has_guard); + check_assist_not_applicable( + convert_match_to_let_else, + r#" +//- minicore: option +fn foo(opt: Option<()>) { + let val = $0match opt { + Some(it) if 2 > 1 => it, + None => return, + }; +} +"#, + ); + } + + #[test] + fn basic_pattern() { + check_assist( + convert_match_to_let_else, + r#" +//- minicore: option +fn foo(opt: Option<()>) { + let val = $0match opt { + Some(it) => it, + None => return, + }; +} + "#, + r#" +fn foo(opt: Option<()>) { + let Some(val) = opt else { return }; +} + "#, + ); + } + + #[test] + fn keeps_modifiers() { + check_assist( + convert_match_to_let_else, + r#" +//- minicore: option +fn foo(opt: Option<()>) { + let ref mut val = $0match opt { + Some(it) => it, + None => return, + }; +} + "#, + r#" +fn foo(opt: Option<()>) { + let Some(ref mut val) = opt else { return }; +} + "#, + ); + } + + #[test] + fn nested_pattern() { + check_assist( + convert_match_to_let_else, + r#" +//- minicore: option, result +fn foo(opt: Option<Result<()>>) { + let val = $0match opt { + Some(Ok(it)) => it, + _ => return, + }; +} + "#, + r#" +fn foo(opt: Option<Result<()>>) { + let Some(Ok(val)) = opt else { return }; +} + "#, + ); + } + + #[test] + fn works_with_any_diverging_block() { + check_assist( + convert_match_to_let_else, + r#" +//- minicore: option +fn foo(opt: Option<()>) { + loop { + let val = $0match opt { + Some(it) => it, + None => break, + }; + } +} + "#, + r#" +fn foo(opt: Option<()>) { + loop { + let Some(val) = opt else { break }; + } +} + "#, + ); + + check_assist( + convert_match_to_let_else, + r#" +//- minicore: option +fn foo(opt: Option<()>) { + loop { + let val = $0match opt { + Some(it) => it, + None => continue, + }; + } +} + "#, + r#" +fn foo(opt: Option<()>) { + loop { + let Some(val) = opt else { continue }; + } +} + "#, + ); + + check_assist( + convert_match_to_let_else, + r#" +//- minicore: option +fn panic() -> ! {} + +fn foo(opt: Option<()>) { + loop { + let val = $0match opt { + Some(it) => it, + None => panic(), + }; + } +} + "#, + r#" +fn panic() -> ! {} + +fn foo(opt: Option<()>) { + loop { + let Some(val) = opt else { panic() }; + } +} + "#, + ); + } + + #[test] + fn struct_pattern() { + check_assist( + convert_match_to_let_else, + r#" +//- minicore: option +struct Point { + x: i32, + y: i32, +} + +fn foo(opt: Option<Point>) { + let val = $0match opt { + Some(Point { x: 0, y }) => y, + _ => return, + }; +} + "#, + r#" +struct Point { + x: i32, + y: i32, +} + +fn foo(opt: Option<Point>) { + let Some(Point { x: 0, y: val }) = opt else { return }; +} + "#, + ); + } + + #[test] + fn renames_whole_binding() { + check_assist( + convert_match_to_let_else, + r#" +//- minicore: option +fn foo(opt: Option<i32>) -> Option<i32> { + let val = $0match opt { + it @ Some(42) => it, + _ => return None, + }; + val +} + "#, + r#" +fn foo(opt: Option<i32>) -> Option<i32> { + let val @ Some(42) = opt else { return None }; + val +} + "#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs index cb75619ced9..b97be34c5f7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs @@ -129,32 +129,15 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' } Some((path, bound_ident)) => { // If-let. - let match_expr = { - let happy_arm = { - let pat = make::tuple_struct_pat( - path, - once(make::ext::simple_ident_pat(make::name("it")).into()), - ); - let expr = { - let path = make::ext::ident_path("it"); - make::expr_path(path) - }; - make::match_arm(once(pat.into()), None, expr) - }; - - let sad_arm = make::match_arm( - // FIXME: would be cool to use `None` or `Err(_)` if appropriate - once(make::wildcard_pat().into()), - None, - early_expression, - ); - - make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) - }; - - let let_stmt = make::let_stmt(bound_ident, None, Some(match_expr)); - let let_stmt = let_stmt.indent(if_indent_level); - let_stmt.syntax().clone_for_update() + let pat = make::tuple_struct_pat(path, once(bound_ident)); + let let_else_stmt = make::let_else_stmt( + pat.into(), + None, + cond_expr, + ast::make::tail_only_block_expr(early_expression), + ); + let let_else_stmt = let_else_stmt.indent(if_indent_level); + let_else_stmt.syntax().clone_for_update() } }; @@ -238,10 +221,7 @@ fn main(n: Option<String>) { r#" fn main(n: Option<String>) { bar(); - let n = match n { - Some(it) => it, - _ => return, - }; + let Some(n) = n else { return }; foo(n); // comment @@ -264,10 +244,7 @@ fn main() { "#, r#" fn main() { - let x = match Err(92) { - Ok(it) => it, - _ => return, - }; + let Ok(x) = Err(92) else { return }; foo(x); } "#, @@ -292,10 +269,7 @@ fn main(n: Option<String>) { r#" fn main(n: Option<String>) { bar(); - let n = match n { - Some(it) => it, - _ => return, - }; + let Some(n) = n else { return }; foo(n); // comment @@ -323,10 +297,7 @@ fn main(n: Option<String>) { r#" fn main(n: Option<String>) { bar(); - let mut n = match n { - Some(it) => it, - _ => return, - }; + let Some(mut n) = n else { return }; foo(n); // comment @@ -354,10 +325,7 @@ fn main(n: Option<&str>) { r#" fn main(n: Option<&str>) { bar(); - let ref n = match n { - Some(it) => it, - _ => return, - }; + let Some(ref n) = n else { return }; foo(n); // comment @@ -412,10 +380,7 @@ fn main() { r#" fn main() { while true { - let n = match n { - Some(it) => it, - _ => continue, - }; + let Some(n) = n else { continue }; foo(n); bar(); } @@ -469,10 +434,7 @@ fn main() { r#" fn main() { loop { - let n = match n { - Some(it) => it, - _ => continue, - }; + let Some(n) = n else { continue }; foo(n); bar(); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs index d8f52270846..92e091fca12 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs @@ -226,7 +226,13 @@ fn edit_field_references( } fn generate_names(fields: impl Iterator<Item = ast::TupleField>) -> Vec<ast::Name> { - fields.enumerate().map(|(i, _)| ast::make::name(&format!("field{}", i + 1))).collect() + fields + .enumerate() + .map(|(i, _)| { + let idx = i + 1; + ast::make::name(&format!("field{idx}")) + }) + .collect() } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs index 54a7f480a4e..b1b0f587cd3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs @@ -58,16 +58,16 @@ pub(crate) fn convert_two_arm_bool_match_to_matches_macro( target_range, |builder| { let mut arm_str = String::new(); - if let Some(ref pat) = first_arm.pat() { + if let Some(pat) = &first_arm.pat() { arm_str += &pat.to_string(); } - if let Some(ref guard) = first_arm.guard() { - arm_str += &format!(" {}", &guard.to_string()); + if let Some(guard) = &first_arm.guard() { + arm_str += &format!(" {guard}"); } if invert_matches { - builder.replace(target_range, format!("!matches!({}, {})", expr, arm_str)); + builder.replace(target_range, format!("!matches!({expr}, {arm_str})")); } else { - builder.replace(target_range, format!("matches!({}, {})", expr, arm_str)); + builder.replace(target_range, format!("matches!({expr}, {arm_str})")); } }, ) 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 dc581ff3bd2..31c2ce7c1b5 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 @@ -133,7 +133,7 @@ fn generate_name( _usages: &Option<UsageSearchResult>, ) -> String { // FIXME: detect if name already used - format!("_{}", index) + format!("_{index}") } enum RefType { @@ -168,12 +168,12 @@ fn edit_tuple_assignment( let add_cursor = |text: &str| { // place cursor on first tuple item let first_tuple = &data.field_names[0]; - text.replacen(first_tuple, &format!("$0{}", first_tuple), 1) + text.replacen(first_tuple, &format!("$0{first_tuple}"), 1) }; // with sub_pattern: keep original tuple and add subpattern: `tup @ (_0, _1)` if in_sub_pattern { - let text = format!(" @ {}", tuple_pat); + let text = format!(" @ {tuple_pat}"); match ctx.config.snippet_cap { Some(cap) => { let snip = add_cursor(&text); @@ -314,9 +314,9 @@ struct RefData { impl RefData { fn format(&self, field_name: &str) -> String { match (self.needs_deref, self.needs_parentheses) { - (true, true) => format!("(*{})", field_name), - (true, false) => format!("*{}", field_name), - (false, true) => format!("({})", field_name), + (true, true) => format!("(*{field_name})"), + (true, false) => format!("*{field_name}"), + (false, true) => format!("({field_name})"), (false, false) => field_name.to_string(), } } 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 d6c8ea785f8..06058835849 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 @@ -181,7 +181,7 @@ fn make_function_name(semantics_scope: &hir::SemanticsScope<'_>) -> ast::NameRef let mut counter = 0; while names_in_scope.contains(&name) { counter += 1; - name = format!("{}{}", &default_name, counter) + name = format!("{default_name}{counter}") } make::name_ref(&name) } @@ -1291,19 +1291,23 @@ fn make_call(ctx: &AssistContext<'_>, fun: &Function, indent: IndentLevel) -> St match fun.outliving_locals.as_slice() { [] => {} [var] => { - format_to!(buf, "let {}{} = ", mut_modifier(var), var.local.name(ctx.db())) + let modifier = mut_modifier(var); + let name = var.local.name(ctx.db()); + format_to!(buf, "let {modifier}{name} = ") } vars => { buf.push_str("let ("); let bindings = vars.iter().format_with(", ", |local, f| { - f(&format_args!("{}{}", mut_modifier(local), local.local.name(ctx.db()))) + let modifier = mut_modifier(local); + let name = local.local.name(ctx.db()); + f(&format_args!("{modifier}{name}")) }); - format_to!(buf, "{}", bindings); + format_to!(buf, "{bindings}"); buf.push_str(") = "); } } - format_to!(buf, "{}", expr); + format_to!(buf, "{expr}"); let insert_comma = fun .body .parent() @@ -1447,6 +1451,8 @@ fn format_function( new_indent: IndentLevel, ) -> String { let mut fn_def = String::new(); + + let fun_name = &fun.name; let params = fun.make_param_list(ctx, module); let ret_ty = fun.make_ret_ty(ctx, module); let body = make_body(ctx, old_indent, new_indent, fun); @@ -1454,42 +1460,28 @@ fn format_function( let async_kw = if fun.control_flow.is_async { "async " } else { "" }; let unsafe_kw = if fun.control_flow.is_unsafe { "unsafe " } else { "" }; let (generic_params, where_clause) = make_generic_params_and_where_clause(ctx, fun); + + format_to!(fn_def, "\n\n{new_indent}{const_kw}{async_kw}{unsafe_kw}"); match ctx.config.snippet_cap { - Some(_) => format_to!( - fn_def, - "\n\n{}{}{}{}fn $0{}", - new_indent, - const_kw, - async_kw, - unsafe_kw, - fun.name, - ), - None => format_to!( - fn_def, - "\n\n{}{}{}{}fn {}", - new_indent, - const_kw, - async_kw, - unsafe_kw, - fun.name, - ), + Some(_) => format_to!(fn_def, "fn $0{fun_name}"), + None => format_to!(fn_def, "fn {fun_name}"), } if let Some(generic_params) = generic_params { - format_to!(fn_def, "{}", generic_params); + format_to!(fn_def, "{generic_params}"); } - format_to!(fn_def, "{}", params); + format_to!(fn_def, "{params}"); if let Some(ret_ty) = ret_ty { - format_to!(fn_def, " {}", ret_ty); + format_to!(fn_def, " {ret_ty}"); } if let Some(where_clause) = where_clause { - format_to!(fn_def, " {}", where_clause); + format_to!(fn_def, " {where_clause}"); } - format_to!(fn_def, " {}", body); + format_to!(fn_def, " {body}"); fn_def } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs index 897980c6650..56834394aeb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs @@ -127,7 +127,7 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti for item in items_to_be_processed { let item = item.indent(IndentLevel(1)); let mut indented_item = String::new(); - format_to!(indented_item, "{}{}", new_item_indent, item.to_string()); + format_to!(indented_item, "{new_item_indent}{item}"); body_items.push(indented_item); } @@ -137,30 +137,28 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let mut impl_body_def = String::new(); if let Some(self_ty) = impl_.self_ty() { - format_to!( - impl_body_def, - "{}impl {} {{\n{}\n{}}}", - old_item_indent + 1, - self_ty.to_string(), - body, - old_item_indent + 1 - ); - + { + let impl_indent = old_item_indent + 1; + format_to!( + impl_body_def, + "{impl_indent}impl {self_ty} {{\n{body}\n{impl_indent}}}", + ); + } body = impl_body_def; // Add the import for enum/struct corresponding to given impl block module.make_use_stmt_of_node_with_super(self_ty.syntax()); for item in module.use_items { - let mut indented_item = String::new(); - format_to!(indented_item, "{}{}", old_item_indent + 1, item.to_string()); - body = format!("{}\n\n{}", indented_item, body); + let item_indent = old_item_indent + 1; + body = format!("{item_indent}{item}\n\n{body}"); } } } let mut module_def = String::new(); - format_to!(module_def, "mod {} {{\n{}\n{}}}", module.name, body, old_item_indent); + let module_name = module.name; + format_to!(module_def, "mod {module_name} {{\n{body}\n{old_item_indent}}}"); let mut usages_to_be_updated_for_curr_file = vec![]; for usages_to_be_updated_for_file in usages_to_be_processed { @@ -199,7 +197,7 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti builder.delete(range); } - builder.insert(impl_.syntax().text_range().end(), format!("\n\n{}", module_def)); + builder.insert(impl_.syntax().text_range().end(), format!("\n\n{module_def}")); } else { builder.replace(module.text_range, module_def) } @@ -343,9 +341,10 @@ impl Module { && !self.text_range.contains_range(desc.text_range()) { if let Some(name_ref) = ast::NameRef::cast(desc) { + let mod_name = self.name; return Some(( name_ref.syntax().text_range(), - format!("{}::{}", self.name, name_ref), + format!("{mod_name}::{name_ref}"), )); } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs index 970e948dfd9..b4e10667b07 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs @@ -296,10 +296,14 @@ fn create_struct_def( fn update_variant(variant: &ast::Variant, generics: Option<ast::GenericParamList>) -> Option<()> { let name = variant.name()?; - let ty = generics + let generic_args = generics .filter(|generics| generics.generic_params().count() > 0) - .map(|generics| make::ty(&format!("{}{}", &name.text(), generics.to_generic_args()))) - .unwrap_or_else(|| make::ty(&name.text())); + .map(|generics| generics.to_generic_args()); + // FIXME: replace with a `ast::make` constructor + let ty = match generic_args { + Some(generic_args) => make::ty(&format!("{name}{generic_args}")), + None => make::ty(&name.text()), + }; // change from a record to a tuple field list let tuple_field = make::tuple_field(None, ty); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs index 03aa8601d14..3116935fc5e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs @@ -1,8 +1,7 @@ use either::Either; use ide_db::syntax_helpers::node_ext::walk_ty; -use itertools::Itertools; use syntax::{ - ast::{self, edit::IndentLevel, AstNode, HasGenericParams, HasName}, + ast::{self, edit::IndentLevel, make, AstNode, HasGenericParams, HasName}, match_ast, }; @@ -64,41 +63,29 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> known_generics.extend(it.generic_params()); } let generics = collect_used_generics(&ty, &known_generics); + let generic_params = + generics.map(|it| make::generic_param_list(it.into_iter().cloned())); - let replacement = if !generics.is_empty() { - format!( - "Type<{}>", - generics.iter().format_with(", ", |generic, f| { - match generic { - ast::GenericParam::ConstParam(cp) => f(&cp.name().unwrap()), - ast::GenericParam::LifetimeParam(lp) => f(&lp.lifetime().unwrap()), - ast::GenericParam::TypeParam(tp) => f(&tp.name().unwrap()), - } - }) - ) - } else { - String::from("Type") - }; + let ty_args = generic_params + .as_ref() + .map_or(String::new(), |it| it.to_generic_args().to_string()); + let replacement = format!("Type{ty_args}"); builder.replace(target, replacement); let indent = IndentLevel::from_node(node); - let generics = if !generics.is_empty() { - format!("<{}>", generics.iter().format(", ")) - } else { - String::new() - }; + let generic_params = generic_params.map_or(String::new(), |it| it.to_string()); match ctx.config.snippet_cap { Some(cap) => { builder.insert_snippet( cap, insert_pos, - format!("type $0Type{} = {};\n\n{}", generics, ty, indent), + format!("type $0Type{generic_params} = {ty};\n\n{indent}"), ); } None => { builder.insert( insert_pos, - format!("type Type{} = {};\n\n{}", generics, ty, indent), + format!("type Type{generic_params} = {ty};\n\n{indent}"), ); } } @@ -109,7 +96,7 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> fn collect_used_generics<'gp>( ty: &ast::Type, known_generics: &'gp [ast::GenericParam], -) -> Vec<&'gp ast::GenericParam> { +) -> Option<Vec<&'gp ast::GenericParam>> { // can't use a closure -> closure here cause lifetime inference fails for that fn find_lifetime(text: &str) -> impl Fn(&&ast::GenericParam) -> bool + '_ { move |gp: &&ast::GenericParam| match gp { @@ -198,7 +185,8 @@ fn collect_used_generics<'gp>( ast::GenericParam::LifetimeParam(_) => 0, ast::GenericParam::TypeParam(_) => 1, }); - generics + + Some(generics).filter(|it| it.len() > 0) } #[cfg(test)] 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 3596b6f8238..a738deffb95 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 @@ -91,13 +91,13 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op match anchor { Anchor::Before(_) | Anchor::Replace(_) => { - format_to!(buf, "let {}{} = {}", var_modifier, var_name, reference_modifier) + format_to!(buf, "let {var_modifier}{var_name} = {reference_modifier}") } Anchor::WrapInBlock(_) => { - format_to!(buf, "{{ let {} = {}", var_name, reference_modifier) + format_to!(buf, "{{ let {var_name} = {reference_modifier}") } }; - format_to!(buf, "{}", to_extract.syntax()); + format_to!(buf, "{to_extract}"); if let Anchor::Replace(stmt) = anchor { cov_mark::hit!(test_extract_var_expr_stmt); @@ -107,8 +107,8 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op match ctx.config.snippet_cap { Some(cap) => { let snip = buf.replace( - &format!("let {}{}", var_modifier, var_name), - &format!("let {}$0{}", var_modifier, var_name), + &format!("let {var_modifier}{var_name}"), + &format!("let {var_modifier}$0{var_name}"), ); edit.replace_snippet(cap, expr_range, snip) } @@ -135,8 +135,8 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op match ctx.config.snippet_cap { Some(cap) => { let snip = buf.replace( - &format!("let {}{}", var_modifier, var_name), - &format!("let {}$0{}", var_modifier, var_name), + &format!("let {var_modifier}{var_name}"), + &format!("let {var_modifier}$0{var_name}"), ); edit.insert_snippet(cap, offset, snip) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs index b33846f5466..87645430287 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs @@ -57,8 +57,8 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>) if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" }; let assist_label = match target_name { - None => format!("Change visibility to {}", missing_visibility), - Some(name) => format!("Change visibility of {} to {}", name, missing_visibility), + None => format!("Change visibility to {missing_visibility}"), + Some(name) => format!("Change visibility of {name} to {missing_visibility}"), }; acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { @@ -68,15 +68,15 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>) Some(current_visibility) => builder.replace_snippet( cap, current_visibility.syntax().text_range(), - format!("$0{}", missing_visibility), + format!("$0{missing_visibility}"), ), - None => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), + None => builder.insert_snippet(cap, offset, format!("$0{missing_visibility} ")), }, None => match current_visibility { Some(current_visibility) => { builder.replace(current_visibility.syntax().text_range(), missing_visibility) } - None => builder.insert(offset, format!("{} ", missing_visibility)), + None => builder.insert(offset, format!("{missing_visibility} ")), }, } }) @@ -114,7 +114,7 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_> let target_name = record_field_def.name(ctx.db()); let assist_label = - format!("Change visibility of {}.{} to {}", parent_name, target_name, missing_visibility); + format!("Change visibility of {parent_name}.{target_name} to {missing_visibility}"); acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { builder.edit_file(target_file); @@ -123,15 +123,15 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_> Some(current_visibility) => builder.replace_snippet( cap, current_visibility.syntax().text_range(), - format!("$0{}", missing_visibility), + format!("$0{missing_visibility}"), ), - None => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), + None => builder.insert_snippet(cap, offset, format!("$0{missing_visibility} ")), }, None => match current_visibility { Some(current_visibility) => { builder.replace(current_visibility.syntax().text_range(), missing_visibility) } - None => builder.insert(offset, format!("{} ", missing_visibility)), + None => builder.insert(offset, format!("{missing_visibility} ")), }, } }) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs index bdd3cf4f06c..c9aa41c845a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs @@ -124,6 +124,7 @@ fn generate_enum_projection_method( happy_case, sad_case, } = props; + let variant = ctx.find_node_at_offset::<ast::Variant>()?; let variant_name = variant.name()?; let parent_enum = ast::Adt::Enum(variant.parent_enum()); @@ -144,7 +145,7 @@ fn generate_enum_projection_method( ast::StructKind::Unit => return None, }; - let fn_name = format!("{}_{}", fn_name_prefix, &to_lower_snake_case(&variant_name.text())); + let fn_name = format!("{fn_name_prefix}_{}", &to_lower_snake_case(&variant_name.text())); // Return early if we've found an existing new fn let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?; @@ -156,15 +157,25 @@ fn generate_enum_projection_method( assist_description, target, |builder| { - let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{v} ")); + let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v)); + + let field_type_syntax = field_type.syntax(); + + let must_use = if ctx.config.assist_emit_must_use { + "#[must_use]\n " + } else { + "" + }; + let method = format!( - " {vis}fn {fn_name}({self_param}) -> {return_prefix}{field_type}{return_suffix} {{ + " {must_use}{vis}fn {fn_name}({self_param}) -> {return_prefix}{field_type_syntax}{return_suffix} {{ if let Self::{variant_name}{pattern_suffix} = self {{ {happy_case}({bound_name}) }} else {{ {sad_case} }} - }}"); + }}" + ); add_method_to_adt(builder, &parent_enum, impl_def, &method); }, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index 9f51cdaf8b1..0c546ce5d41 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeSet; + use ast::make; use either::Either; use hir::{db::HirDatabase, PathResolution, Semantics, TypeInfo}; @@ -190,10 +192,10 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< PathResolution::Def(hir::ModuleDef::Function(f)) => f, _ => return None, }; - (function, format!("Inline `{}`", path)) + (function, format!("Inline `{path}`")) } ast::CallableExpr::MethodCall(call) => { - (ctx.sema.resolve_method_call(call)?, format!("Inline `{}`", name_ref)) + (ctx.sema.resolve_method_call(call)?, format!("Inline `{name_ref}`")) } }; @@ -373,8 +375,44 @@ fn inline( }) } } + + let mut func_let_vars: BTreeSet<String> = BTreeSet::new(); + + // grab all of the local variable declarations in the function + for stmt in fn_body.statements() { + if let Some(let_stmt) = ast::LetStmt::cast(stmt.syntax().to_owned()) { + for has_token in let_stmt.syntax().children_with_tokens() { + if let Some(node) = has_token.as_node() { + if let Some(ident_pat) = ast::IdentPat::cast(node.to_owned()) { + func_let_vars.insert(ident_pat.syntax().text().to_string()); + } + } + } + } + } + // Inline parameter expressions or generate `let` statements depending on whether inlining works or not. for ((pat, param_ty, _), usages, expr) in izip!(params, param_use_nodes, arguments).rev() { + // izip confuses RA due to our lack of hygiene info currently losing us type info causing incorrect errors + let usages: &[ast::PathExpr] = &*usages; + let expr: &ast::Expr = expr; + + let insert_let_stmt = || { + let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty.clone()); + if let Some(stmt_list) = body.stmt_list() { + stmt_list.push_front( + make::let_stmt(pat.clone(), ty, Some(expr.clone())).clone_for_update().into(), + ) + } + }; + + // check if there is a local var in the function that conflicts with parameter + // if it does then emit a let statement and continue + if func_let_vars.contains(&expr.syntax().text().to_string()) { + insert_let_stmt(); + continue; + } + let inline_direct = |usage, replacement: &ast::Expr| { if let Some(field) = path_expr_as_record_field(usage) { cov_mark::hit!(inline_call_inline_direct_field); @@ -383,9 +421,7 @@ fn inline( ted::replace(usage.syntax(), &replacement.syntax().clone_for_update()); } }; - // izip confuses RA due to our lack of hygiene info currently losing us type info causing incorrect errors - let usages: &[ast::PathExpr] = &*usages; - let expr: &ast::Expr = expr; + match usages { // inline single use closure arguments [usage] @@ -408,18 +444,11 @@ fn inline( } // can't inline, emit a let statement _ => { - let ty = - sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty.clone()); - if let Some(stmt_list) = body.stmt_list() { - stmt_list.push_front( - make::let_stmt(pat.clone(), ty, Some(expr.clone())) - .clone_for_update() - .into(), - ) - } + insert_let_stmt(); } } } + if let Some(generic_arg_list) = generic_arg_list.clone() { if let Some((target, source)) = &sema.scope(node.syntax()).zip(sema.scope(fn_body.syntax())) { @@ -1256,4 +1285,37 @@ impl A { "#, ) } + + #[test] + fn local_variable_shadowing_callers_argument() { + check_assist( + inline_call, + r#" +fn foo(bar: u32, baz: u32) -> u32 { + let a = 1; + bar * baz * a * 6 +} +fn main() { + let a = 7; + let b = 1; + let res = foo$0(a, b); +} +"#, + r#" +fn foo(bar: u32, baz: u32) -> u32 { + let a = 1; + bar * baz * a * 6 +} +fn main() { + let a = 7; + let b = 1; + let res = { + let bar = a; + let a = 1; + bar * b * a * 6 + }; +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs index 7259d678194..ce44100e34b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -113,7 +113,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) .collect::<Option<Vec<_>>>()?; let init_str = initializer_expr.syntax().text().to_string(); - let init_in_paren = format!("({})", &init_str); + let init_in_paren = format!("({init_str})"); let target = match target { ast::NameOrNameRef::Name(it) => it.syntax().text_range(), @@ -132,7 +132,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) let replacement = if should_wrap { &init_in_paren } else { &init_str }; if ast::RecordExprField::for_field_name(&name).is_some() { cov_mark::hit!(inline_field_shorthand); - builder.insert(range.end(), format!(": {}", replacement)); + builder.insert(range.end(), format!(": {replacement}")); } else { builder.replace(range, replacement.clone()) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs index 2fc754e3e50..a54dc4f96de 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_lifetime.rs @@ -127,7 +127,7 @@ fn generate_unique_lifetime_param_name( Some(type_params) => { let used_lifetime_params: FxHashSet<_> = type_params.lifetime_params().map(|p| p.syntax().text().to_string()).collect(); - ('a'..='z').map(|it| format!("'{}", it)).find(|it| !used_lifetime_params.contains(it)) + ('a'..='z').map(|it| format!("'{it}")).find(|it| !used_lifetime_params.contains(it)) } None => Some("'a".to_string()), } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs index c24015b1c51..641c90885bf 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs @@ -78,7 +78,7 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op .join(" | ") }; - let arm = format!("{} => {},", pats, current_expr.syntax().text()); + let arm = format!("{pats} => {current_expr},"); if let [first, .., last] = &*arms_to_merge { let start = first.syntax().text_range().start(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs index a6c85a2b18b..1728c03cd03 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs @@ -40,11 +40,11 @@ pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let target = source_file.syntax().text_range(); let module_name = module.name(ctx.db())?.to_string(); - let path = format!("../{}.rs", module_name); + let path = format!("../{module_name}.rs"); let dst = AnchoredPathBuf { anchor: ctx.file_id(), path }; acc.add( AssistId("move_from_mod_rs", AssistKind::Refactor), - format!("Convert {}/mod.rs to {}.rs", module_name, module_name), + format!("Convert {module_name}/mod.rs to {module_name}.rs"), target, |builder| { builder.move_file(ctx.file_id(), dst); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs index b8f1b36deb9..ec3281619cc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs @@ -133,16 +133,16 @@ pub(crate) fn move_arm_cond_to_match_guard( }; let then_arm_end = match_arm.syntax().text_range().end(); let indent_level = match_arm.indent_level(); - let spaces = " ".repeat(indent_level.0 as _); + let spaces = indent_level; let mut first = true; for (cond, block) in conds_blocks { if !first { - edit.insert(then_arm_end, format!("\n{}", spaces)); + edit.insert(then_arm_end, format!("\n{spaces}")); } else { first = false; } - let guard = format!("{} if {} => ", match_pat, cond.syntax().text()); + let guard = format!("{match_pat} if {cond} => "); edit.insert(then_arm_end, guard); let only_expr = block.statements().next().is_none(); match &block.tail_expr() { @@ -158,7 +158,7 @@ pub(crate) fn move_arm_cond_to_match_guard( } if let Some(e) = tail { cov_mark::hit!(move_guard_ifelse_else_tail); - let guard = format!("\n{}{} => ", spaces, match_pat); + let guard = format!("\n{spaces}{match_pat} => "); edit.insert(then_arm_end, guard); let only_expr = e.statements().next().is_none(); match &e.tail_expr() { @@ -183,7 +183,7 @@ pub(crate) fn move_arm_cond_to_match_guard( { cov_mark::hit!(move_guard_ifelse_has_wildcard); } - _ => edit.insert(then_arm_end, format!("\n{}{} => {{}}", spaces, match_pat)), + _ => edit.insert(then_arm_end, format!("\n{spaces}{match_pat} => {{}}")), } } }, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs index 7468318a594..a7c605325ea 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs @@ -52,7 +52,7 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) -> let mut buf = String::from("./"); match parent_module.name(ctx.db()) { Some(name) if !parent_module.is_mod_rs(ctx.db()) => { - format_to!(buf, "{}/", name) + format_to!(buf, "{name}/") } _ => (), } @@ -82,7 +82,7 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) -> items }; - let buf = format!("mod {};", module_name); + let buf = format!("mod {module_name};"); let replacement_start = match module_ast.mod_token() { Some(mod_token) => mod_token.text_range(), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs index a909ce8b267..076d25411a8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs @@ -40,11 +40,11 @@ pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let target = source_file.syntax().text_range(); let module_name = module.name(ctx.db())?.to_string(); - let path = format!("./{}/mod.rs", module_name); + let path = format!("./{module_name}/mod.rs"); let dst = AnchoredPathBuf { anchor: ctx.file_id(), path }; acc.add( AssistId("move_to_mod_rs", AssistKind::Refactor), - format!("Convert {}.rs to {}/mod.rs", module_name, module_name), + format!("Convert {module_name}.rs to {module_name}/mod.rs"), target, |builder| { builder.move_file(ctx.file_id(), dst); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs index 424db7437a7..7e3fef516bf 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs @@ -38,7 +38,7 @@ pub(crate) fn reformat_number_literal(acc: &mut Assists, ctx: &AssistContext<'_> converted.push_str(suffix); let group_id = GroupLabel("Reformat number literal".into()); - let label = format!("Convert {} to {}", literal, converted); + let label = format!("Convert {literal} to {converted}"); let range = literal.syntax().text_range(); acc.add_group( &group_id, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs index e57d1d065d6..1ea87429c50 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs @@ -54,7 +54,7 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> acc.add( AssistId("qualify_method_call", AssistKind::RefactorInline), - format!("Qualify `{}` method call", ident.text()), + format!("Qualify `{ident}` method call"), range, |builder| { qualify_candidate.qualify( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs index 4b2af550bc5..e759e1561cb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs @@ -118,14 +118,14 @@ impl QualifyCandidate<'_> { match self { QualifyCandidate::QualifierStart(segment, generics) => { let generics = generics.as_ref().map_or_else(String::new, ToString::to_string); - replacer(format!("{}{}::{}", import, generics, segment)); + replacer(format!("{import}{generics}::{segment}")); } QualifyCandidate::UnqualifiedName(generics) => { let generics = generics.as_ref().map_or_else(String::new, ToString::to_string); - replacer(format!("{}{}", import, generics)); + replacer(format!("{import}{generics}")); } QualifyCandidate::TraitAssocItem(qualifier, segment) => { - replacer(format!("<{} as {}>::{}", qualifier, import, segment)); + replacer(format!("<{qualifier} as {import}>::{segment}")); } QualifyCandidate::TraitMethod(db, mcall_expr) => { Self::qualify_trait_method(db, mcall_expr, replacer, import, item); @@ -155,16 +155,11 @@ impl QualifyCandidate<'_> { hir::Access::Exclusive => make::expr_ref(receiver, true), hir::Access::Owned => receiver, }; - replacer(format!( - "{}::{}{}{}", - import, - method_name, - generics, - match arg_list { - Some(args) => make::arg_list(iter::once(receiver).chain(args)), - None => make::arg_list(iter::once(receiver)), - } - )); + let arg_list = match arg_list { + Some(args) => make::arg_list(iter::once(receiver).chain(args)), + None => make::arg_list(iter::once(receiver)), + }; + replacer(format!("{import}::{method_name}{generics}{arg_list}")); } Some(()) } @@ -218,15 +213,17 @@ fn group_label(candidate: &ImportCandidate) -> GroupLabel { } } .text(); - GroupLabel(format!("Qualify {}", name)) + GroupLabel(format!("Qualify {name}")) } fn label(candidate: &ImportCandidate, import: &LocatedImport) -> String { + let import_path = &import.import_path; + match candidate { ImportCandidate::Path(candidate) if candidate.qualifier.is_none() => { - format!("Qualify as `{}`", import.import_path) + format!("Qualify as `{import_path}`") } - _ => format!("Qualify with `{}`", import.import_path), + _ => format!("Qualify with `{import_path}`"), } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs index dbe8cb7bf03..c9bc25b27a5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs @@ -34,13 +34,10 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt let hashes = "#".repeat(required_hashes(&value).max(1)); if matches!(value, Cow::Borrowed(_)) { // Avoid replacing the whole string to better position the cursor. - edit.insert(token.syntax().text_range().start(), format!("r{}", hashes)); + edit.insert(token.syntax().text_range().start(), format!("r{hashes}")); edit.insert(token.syntax().text_range().end(), hashes); } else { - edit.replace( - token.syntax().text_range(), - format!("r{}\"{}\"{}", hashes, value, hashes), - ); + edit.replace(token.syntax().text_range(), format!("r{hashes}\"{value}\"{hashes}")); } }, ) @@ -83,7 +80,7 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> O } } - edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); + edit.replace(token.syntax().text_range(), format!("\"{escaped}\"")); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs index afaa7c933c7..3d9cbff177b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs @@ -102,7 +102,7 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( }; ( macro_call.syntax().text_range(), - if wrap { format!("({})", expr) } else { expr.to_string() }, + if wrap { format!("({expr})") } else { expr.to_string() }, ) } // dbg!(expr0, expr1, ...) @@ -127,8 +127,8 @@ mod tests { fn check(ra_fixture_before: &str, ra_fixture_after: &str) { check_assist( remove_dbg, - &format!("fn main() {{\n{}\n}}", ra_fixture_before), - &format!("fn main() {{\n{}\n}}", ra_fixture_after), + &format!("fn main() {{\n{ra_fixture_before}\n}}"), + &format!("fn main() {{\n{ra_fixture_after}\n}}"), ); } 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 9fd5e1886d2..f9ba289ee17 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 @@ -124,7 +124,7 @@ fn add_assist( ) -> Option<()> { let target = attr.syntax().text_range(); let annotated_name = adt.name()?; - let label = format!("Convert to manual `impl {} for {}`", replace_trait_path, annotated_name); + let label = format!("Convert to manual `impl {replace_trait_path} for {annotated_name}`"); acc.add( AssistId("replace_derive_with_manual_impl", AssistKind::Refactor), @@ -158,11 +158,8 @@ fn add_assist( } } - builder.insert_snippet( - cap, - insert_pos, - format!("\n\n{}", render_snippet(cap, impl_def.syntax(), cursor)), - ) + let rendered = render_snippet(cap, impl_def.syntax(), cursor); + builder.insert_snippet(cap, insert_pos, format!("\n\n{rendered}")) } }; }, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_or_with_or_else.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_or_with_or_else.rs index 7d91be62101..77382056c18 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_or_with_or_else.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_or_with_or_else.rs @@ -62,7 +62,7 @@ pub(crate) fn replace_or_with_or_else(acc: &mut Assists, ctx: &AssistContext<'_> acc.add( AssistId("replace_or_with_or_else", AssistKind::RefactorRewrite), - format!("Replace {} with {}", name.text(), replace), + format!("Replace {name} with {replace}"), call.syntax().text_range(), |builder| { builder.replace(name.syntax().text_range(), replace); @@ -138,7 +138,7 @@ pub(crate) fn replace_or_else_with_or(acc: &mut Assists, ctx: &AssistContext<'_> acc.add( AssistId("replace_or_else_with_or", AssistKind::RefactorRewrite), - format!("Replace {} with {}", name.text(), replace), + format!("Replace {name} with {replace}"), call.syntax().text_range(), |builder| { builder.replace(name.syntax().text_range(), replace); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs index 521447c26df..c177adc7a10 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs @@ -79,7 +79,7 @@ pub(crate) fn replace_turbofish_with_explicit_type( "Replace turbofish with explicit type", TextRange::new(initializer_start, turbofish_range.end()), |builder| { - builder.insert(ident_range.end(), format!(": {}", returned_type)); + builder.insert(ident_range.end(), format!(": {returned_type}")); builder.delete(turbofish_range); }, ); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs index d5cd2d55134..04398832253 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unnecessary_async.rs @@ -44,6 +44,12 @@ pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> O if function.body()?.syntax().descendants().find_map(ast::AwaitExpr::cast).is_some() { return None; } + // Do nothing if the method is a member of trait. + if let Some(impl_) = function.syntax().ancestors().nth(2).and_then(ast::Impl::cast) { + if let Some(_) = impl_.trait_() { + return None; + } + } // Remove the `async` keyword plus whitespace after it, if any. let async_range = { @@ -254,4 +260,18 @@ pub async fn f(s: &S) { s.f2() }"#, fn does_not_apply_when_not_on_prototype() { check_assist_not_applicable(unnecessary_async, "pub async fn f() { $0f2() }") } + + #[test] + fn does_not_apply_on_async_trait_method() { + check_assist_not_applicable( + unnecessary_async, + r#" +trait Trait { + async fn foo(); +} +impl Trait for () { + $0async fn foo() {} +}"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs index 25c58d086e9..d09614c5112 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs @@ -69,13 +69,13 @@ pub(crate) fn unwrap_tuple(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option for (pat, ty, expr) in itertools::izip!(tuple_pat.fields(), tys.fields(), tuple_init.fields()) { - zipped_decls.push_str(&format!("{}let {pat}: {ty} = {expr};\n", indents)) + zipped_decls.push_str(&format!("{indents}let {pat}: {ty} = {expr};\n")) } edit.replace(parent.text_range(), zipped_decls.trim()); } else { let mut zipped_decls = String::new(); for (pat, expr) in itertools::izip!(tuple_pat.fields(), tuple_init.fields()) { - zipped_decls.push_str(&format!("{}let {pat} = {expr};\n", indents)); + zipped_decls.push_str(&format!("{indents}let {pat} = {expr};\n")); } edit.replace(parent.text_range(), zipped_decls.trim()); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs index 83446387db1..b6c489eb62e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs @@ -76,11 +76,11 @@ pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext< match ctx.config.snippet_cap { Some(cap) => { - let snippet = format!("Result<{}, ${{0:_}}>", type_ref); + let snippet = format!("Result<{type_ref}, ${{0:_}}>"); builder.replace_snippet(cap, type_ref.syntax().text_range(), snippet) } None => builder - .replace(type_ref.syntax().text_range(), format!("Result<{}, _>", type_ref)), + .replace(type_ref.syntax().text_range(), format!("Result<{type_ref}, _>")), } }, ) 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 a07318cefad..387cc631428 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -120,6 +120,7 @@ mod handlers { mod convert_into_to_from; mod convert_iter_for_each_to_for; mod convert_let_else_to_match; + mod convert_match_to_let_else; mod convert_tuple_struct_to_named_struct; mod convert_named_struct_to_tuple_struct; mod convert_to_guarded_return; @@ -220,6 +221,7 @@ mod handlers { convert_iter_for_each_to_for::convert_for_loop_with_for_each, convert_let_else_to_match::convert_let_else_to_match, convert_named_struct_to_tuple_struct::convert_named_struct_to_tuple_struct, + convert_match_to_let_else::convert_match_to_let_else, convert_to_guarded_return::convert_to_guarded_return, convert_tuple_struct_to_named_struct::convert_tuple_struct_to_named_struct, convert_two_arm_bool_match_to_matches_macro::convert_two_arm_bool_match_to_matches_macro, 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 f7f2417d074..92ced27c78a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -30,6 +30,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { skip_glob_imports: true, }, prefer_no_std: false, + assist_emit_must_use: false, }; pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { 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 2c4000efe0f..029d169899b 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 @@ -408,6 +408,27 @@ fn main() { } #[test] +fn doctest_convert_match_to_let_else() { + check_doc_test( + "convert_match_to_let_else", + r#####" +//- minicore: option +fn foo(opt: Option<()>) { + let val = $0match opt { + Some(it) => it, + None => return, + }; +} +"#####, + r#####" +fn foo(opt: Option<()>) { + let Some(val) = opt else { return }; +} +"#####, + ) +} + +#[test] fn doctest_convert_named_struct_to_tuple_struct() { check_doc_test( "convert_named_struct_to_tuple_struct", 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 db32e7182c4..307e6792705 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -189,8 +189,8 @@ pub(crate) fn render_snippet(_cap: SnippetCap, node: &SyntaxNode, cursor: Cursor let mut placeholder = cursor.node().to_string(); escape(&mut placeholder); let tab_stop = match cursor { - Cursor::Replace(placeholder) => format!("${{0:{}}}", placeholder), - Cursor::Before(placeholder) => format!("$0{}", placeholder), + Cursor::Replace(placeholder) => format!("${{0:{placeholder}}}"), + Cursor::Before(placeholder) => format!("$0{placeholder}"), }; let mut buf = node.to_string(); @@ -539,17 +539,17 @@ impl ReferenceConversion { ReferenceConversionType::AsRefSlice => { let type_argument_name = self.ty.type_arguments().next().unwrap().display(db).to_string(); - format!("&[{}]", type_argument_name) + format!("&[{type_argument_name}]") } ReferenceConversionType::Dereferenced => { let type_argument_name = self.ty.type_arguments().next().unwrap().display(db).to_string(); - format!("&{}", type_argument_name) + format!("&{type_argument_name}") } ReferenceConversionType::Option => { let type_argument_name = self.ty.type_arguments().next().unwrap().display(db).to_string(); - format!("Option<&{}>", type_argument_name) + format!("Option<&{type_argument_name}>") } ReferenceConversionType::Result => { let mut type_arguments = self.ty.type_arguments(); @@ -557,19 +557,19 @@ impl ReferenceConversion { type_arguments.next().unwrap().display(db).to_string(); let second_type_argument_name = type_arguments.next().unwrap().display(db).to_string(); - format!("Result<&{}, &{}>", first_type_argument_name, second_type_argument_name) + format!("Result<&{first_type_argument_name}, &{second_type_argument_name}>") } } } pub(crate) fn getter(&self, field_name: String) -> String { match self.conversion { - ReferenceConversionType::Copy => format!("self.{}", field_name), + ReferenceConversionType::Copy => format!("self.{field_name}"), ReferenceConversionType::AsRefStr | ReferenceConversionType::AsRefSlice | ReferenceConversionType::Dereferenced | ReferenceConversionType::Option - | ReferenceConversionType::Result => format!("self.{}.as_ref()", field_name), + | ReferenceConversionType::Result => format!("self.{field_name}.as_ref()"), } } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs index 7a0c912959a..6c87e66c134 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs @@ -41,7 +41,7 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let mut arms = vec![]; for variant in list.variants() { let name = variant.name()?; - let variant_name = make::ext::path_from_idents(["Self", &format!("{}", name)])?; + let variant_name = make::ext::path_from_idents(["Self", &format!("{name}")])?; match variant.field_list() { // => match self { Self::Name { x } => Self::Name { x: x.clone() } } @@ -70,7 +70,7 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let mut pats = vec![]; let mut fields = vec![]; for (i, _) in list.fields().enumerate() { - let field_name = format!("arg{}", i); + let field_name = format!("arg{i}"); let pat = make::ident_pat(false, false, make::name(&field_name)); pats.push(pat.into()); @@ -118,7 +118,7 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let mut fields = vec![]; for (i, _) in field_list.fields().enumerate() { let f_path = make::expr_path(make::ext::ident_path("self")); - let target = make::expr_field(f_path, &format!("{}", i)); + let target = make::expr_field(f_path, &format!("{i}")); fields.push(gen_clone_call(target)); } let struct_name = make::expr_path(make::ext::ident_path("Self")); @@ -151,7 +151,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let mut arms = vec![]; for variant in list.variants() { let name = variant.name()?; - let variant_name = make::ext::path_from_idents(["Self", &format!("{}", name)])?; + let variant_name = make::ext::path_from_idents(["Self", &format!("{name}")])?; let target = make::expr_path(make::ext::ident_path("f")); match variant.field_list() { @@ -159,7 +159,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { // => f.debug_struct(name) let target = make::expr_path(make::ext::ident_path("f")); let method = make::name_ref("debug_struct"); - let struct_name = format!("\"{}\"", name); + let struct_name = format!("\"{name}\""); let args = make::arg_list(Some(make::expr_literal(&struct_name).into())); let mut expr = make::expr_method_call(target, method, args); @@ -173,8 +173,8 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { // => <expr>.field("field_name", field) let method_name = make::name_ref("field"); - let name = make::expr_literal(&(format!("\"{}\"", field_name))).into(); - let path = &format!("{}", field_name); + let name = make::expr_literal(&(format!("\"{field_name}\""))).into(); + let path = &format!("{field_name}"); let path = make::expr_path(make::ext::ident_path(path)); let args = make::arg_list(vec![name, path]); expr = make::expr_method_call(expr, method_name, args); @@ -192,13 +192,13 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { // => f.debug_tuple(name) let target = make::expr_path(make::ext::ident_path("f")); let method = make::name_ref("debug_tuple"); - let struct_name = format!("\"{}\"", name); + let struct_name = format!("\"{name}\""); let args = make::arg_list(Some(make::expr_literal(&struct_name).into())); let mut expr = make::expr_method_call(target, method, args); let mut pats = vec![]; for (i, _) in list.fields().enumerate() { - let name = format!("arg{}", i); + let name = format!("arg{i}"); // create a field pattern for use in `MyStruct(fields..)` let field_name = make::name(&name); @@ -222,7 +222,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { arms.push(make::match_arm(Some(pat.into()), None, expr)); } None => { - let fmt_string = make::expr_literal(&(format!("\"{}\"", name))).into(); + let fmt_string = make::expr_literal(&(format!("\"{name}\""))).into(); let args = make::arg_list([target, fmt_string]); let macro_name = make::expr_path(make::ext::ident_path("write")); let macro_call = make::expr_macro_call(macro_name, args); @@ -244,7 +244,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { } ast::Adt::Struct(strukt) => { - let name = format!("\"{}\"", annotated_name); + let name = format!("\"{annotated_name}\""); let args = make::arg_list(Some(make::expr_literal(&name).into())); let target = make::expr_path(make::ext::ident_path("f")); @@ -258,10 +258,10 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let mut expr = make::expr_method_call(target, method, args); for field in field_list.fields() { let name = field.name()?; - let f_name = make::expr_literal(&(format!("\"{}\"", name))).into(); + let f_name = make::expr_literal(&(format!("\"{name}\""))).into(); let f_path = make::expr_path(make::ext::ident_path("self")); let f_path = make::expr_ref(f_path, false); - let f_path = make::expr_field(f_path, &format!("{}", name)); + let f_path = make::expr_field(f_path, &format!("{name}")); let args = make::arg_list([f_name, f_path]); expr = make::expr_method_call(expr, make::name_ref("field"), args); } @@ -275,7 +275,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { for (i, _) in field_list.fields().enumerate() { let f_path = make::expr_path(make::ext::ident_path("self")); let f_path = make::expr_ref(f_path, false); - let f_path = make::expr_field(f_path, &format!("{}", i)); + let f_path = make::expr_field(f_path, &format!("{i}")); let method = make::name_ref("field"); expr = make::expr_method_call(expr, method, make::arg_list(Some(f_path))); } @@ -379,7 +379,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let mut stmts = vec![]; for (i, _) in field_list.fields().enumerate() { let base = make::expr_path(make::ext::ident_path("self")); - let target = make::expr_field(base, &format!("{}", i)); + let target = make::expr_field(base, &format!("{i}")); stmts.push(gen_hash_call(target)); } make::block_expr(stmts, None).indent(ast::edit::IndentLevel(1)) @@ -453,10 +453,10 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { for field in list.fields() { let field_name = field.name()?.to_string(); - let l_name = &format!("l_{}", field_name); + let l_name = &format!("l_{field_name}"); l_fields.push(gen_record_pat_field(&field_name, l_name)); - let r_name = &format!("r_{}", field_name); + let r_name = &format!("r_{field_name}"); r_fields.push(gen_record_pat_field(&field_name, r_name)); let lhs = make::expr_path(make::ext::ident_path(l_name)); @@ -484,12 +484,12 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let mut r_fields = vec![]; for (i, _) in list.fields().enumerate() { - let field_name = format!("{}", i); + let field_name = format!("{i}"); - let l_name = format!("l{}", field_name); + let l_name = format!("l{field_name}"); l_fields.push(gen_tuple_field(&l_name)); - let r_name = format!("r{}", field_name); + let r_name = format!("r{field_name}"); r_fields.push(gen_tuple_field(&r_name)); let lhs = make::expr_path(make::ext::ident_path(&l_name)); @@ -548,7 +548,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { Some(ast::FieldList::TupleFieldList(field_list)) => { let mut expr = None; for (i, _) in field_list.fields().enumerate() { - let idx = format!("{}", i); + let idx = format!("{i}"); let lhs = make::expr_path(make::ext::ident_path("self")); let lhs = make::expr_field(lhs, &idx); let rhs = make::expr_path(make::ext::ident_path("other")); @@ -628,7 +628,7 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { Some(ast::FieldList::TupleFieldList(field_list)) => { let mut exprs = vec![]; for (i, _) in field_list.fields().enumerate() { - let idx = format!("{}", i); + let idx = format!("{i}"); let lhs = make::expr_path(make::ext::ident_path("self")); let lhs = make::expr_field(lhs, &idx); let rhs = make::expr_path(make::ext::ident_path("other")); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs index 9a891cea2d4..b9bd47f7da5 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs @@ -69,10 +69,6 @@ pub(crate) fn complete_postfix( } } - if !ctx.config.snippets.is_empty() { - add_custom_postfix_completions(acc, ctx, &postfix_snippet, &receiver_text); - } - let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty.strip_references()); if let Some(try_enum) = &try_enum { match try_enum { @@ -140,6 +136,10 @@ pub(crate) fn complete_postfix( None => return, }; + if !ctx.config.snippets.is_empty() { + add_custom_postfix_completions(acc, ctx, &postfix_snippet, &receiver_text); + } + match try_enum { Some(try_enum) => match try_enum { TryEnum::Result => { @@ -613,4 +613,25 @@ fn main() { r#"fn main() { log::error!("{}", 2+2) }"#, ); } + + #[test] + fn postfix_custom_snippets_completion_for_references() { + check_edit_with_config( + CompletionConfig { + snippets: vec![Snippet::new( + &[], + &["ok".into()], + &["Ok(${receiver})".into()], + "", + &[], + crate::SnippetScope::Expr, + ) + .unwrap()], + ..TEST_CONFIG + }, + "ok", + r#"fn main() { &&42.$0 }"#, + r#"fn main() { Ok(&&42) }"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 82b85f2fa5e..aa5d7e9beb5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -446,33 +446,47 @@ impl<'a> FindUsages<'a> { }) } - // FIXME: There should be optimization potential here - // Currently we try to descend everything we find which - // means we call `Semantics::descend_into_macros` on - // every textual hit. That function is notoriously - // expensive even for things that do not get down mapped - // into macros. + let find_nodes = move |name: &str, node: &syntax::SyntaxNode, offset: TextSize| { + node.token_at_offset(offset).find(|it| it.text() == name).map(|token| { + // FIXME: There should be optimization potential here + // Currently we try to descend everything we find which + // means we call `Semantics::descend_into_macros` on + // every textual hit. That function is notoriously + // expensive even for things that do not get down mapped + // into macros. + sema.descend_into_macros(token).into_iter().filter_map(|it| it.parent()) + }) + }; + for (text, file_id, search_range) in scope_files(sema, &search_scope) { let tree = Lazy::new(move || sema.parse(file_id).syntax().clone()); // Search for occurrences of the items name for offset in match_indices(&text, finder, search_range) { - for name in sema.find_nodes_at_offset_with_descend(&tree, offset) { - if match name { - ast::NameLike::NameRef(name_ref) => self.found_name_ref(&name_ref, sink), - ast::NameLike::Name(name) => self.found_name(&name, sink), - ast::NameLike::Lifetime(lifetime) => self.found_lifetime(&lifetime, sink), - } { - return; + if let Some(iter) = find_nodes(name, &tree, offset) { + for name in iter.filter_map(ast::NameLike::cast) { + if match name { + ast::NameLike::NameRef(name_ref) => { + self.found_name_ref(&name_ref, sink) + } + ast::NameLike::Name(name) => self.found_name(&name, sink), + ast::NameLike::Lifetime(lifetime) => { + self.found_lifetime(&lifetime, sink) + } + } { + return; + } } } } // Search for occurrences of the `Self` referring to our type if let Some((self_ty, finder)) = &include_self_kw_refs { for offset in match_indices(&text, finder, search_range) { - for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) { - if self.found_self_ty_name_ref(self_ty, &name_ref, sink) { - return; + if let Some(iter) = find_nodes("Self", &tree, offset) { + for name_ref in iter.filter_map(ast::NameRef::cast) { + if self.found_self_ty_name_ref(self_ty, &name_ref, sink) { + return; + } } } } @@ -493,17 +507,21 @@ impl<'a> FindUsages<'a> { let tree = Lazy::new(move || sema.parse(file_id).syntax().clone()); for offset in match_indices(&text, finder, search_range) { - for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) { - if self.found_name_ref(&name_ref, sink) { - return; + if let Some(iter) = find_nodes("super", &tree, offset) { + for name_ref in iter.filter_map(ast::NameRef::cast) { + if self.found_name_ref(&name_ref, sink) { + return; + } } } } if let Some(finder) = &is_crate_root { for offset in match_indices(&text, finder, search_range) { - for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) { - if self.found_name_ref(&name_ref, sink) { - return; + if let Some(iter) = find_nodes("crate", &tree, offset) { + for name_ref in iter.filter_map(ast::NameRef::cast) { + if self.found_name_ref(&name_ref, sink) { + return; + } } } } @@ -544,9 +562,11 @@ impl<'a> FindUsages<'a> { let finder = &Finder::new("self"); for offset in match_indices(&text, finder, search_range) { - for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) { - if self.found_self_module_name_ref(&name_ref, sink) { - return; + if let Some(iter) = find_nodes("self", &tree, offset) { + for name_ref in iter.filter_map(ast::NameRef::cast) { + if self.found_self_module_name_ref(&name_ref, sink) { + return; + } } } } diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs index 852a8fd8376..07d117aff10 100644 --- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs +++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs @@ -73,8 +73,8 @@ impl MonikerResult { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PackageInformation { pub name: String, - pub repo: String, - pub version: String, + pub repo: Option<String>, + pub version: Option<String>, } pub(crate) fn crate_for_file(db: &RootDatabase, file_id: FileId) -> Option<Crate> { @@ -256,18 +256,18 @@ pub(crate) fn def_to_moniker( let (name, repo, version) = match krate.origin(db) { CrateOrigin::CratesIo { repo, name } => ( name.unwrap_or(krate.display_name(db)?.canonical_name().to_string()), - repo?, - krate.version(db)?, + repo, + krate.version(db), ), CrateOrigin::Lang(lang) => ( krate.display_name(db)?.canonical_name().to_string(), - "https://github.com/rust-lang/rust/".to_string(), - match lang { + Some("https://github.com/rust-lang/rust/".to_string()), + Some(match lang { LangCrateOrigin::Other => { "https://github.com/rust-lang/rust/library/".into() } lang => format!("https://github.com/rust-lang/rust/library/{lang}",), - }, + }), ), }; PackageInformation { name, repo, version } @@ -315,7 +315,7 @@ pub mod module { } "#, "foo::module::func", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Import, ); check_moniker( @@ -331,7 +331,7 @@ pub mod module { } "#, "foo::module::func", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -348,7 +348,7 @@ pub mod module { } "#, "foo::module::MyTrait::func", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -365,7 +365,7 @@ pub mod module { } "#, "foo::module::MyTrait::MY_CONST", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -382,7 +382,7 @@ pub mod module { } "#, "foo::module::MyTrait::MyType", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -405,7 +405,7 @@ pub mod module { } "#, "foo::module::MyStruct::MyTrait::func", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -425,7 +425,7 @@ pub struct St { } "#, "foo::St::a", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Import, ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index fe44856dcad..b4df0437050 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -40,7 +40,9 @@ pub(crate) fn prepare_rename( if def.range_for_rename(&sema).is_none() { bail!("No references found at position") } - let frange = sema.original_range(name_like.syntax()); + let Some(frange) = sema.original_range_opt(name_like.syntax()) else { + bail!("No references found at position"); + }; always!( frange.range.contains_inclusive(position.offset) @@ -51,7 +53,7 @@ pub(crate) fn prepare_rename( .reduce(|acc, cur| match (acc, cur) { // ensure all ranges are the same (Ok(acc_inner), Ok(cur_inner)) if acc_inner == cur_inner => Ok(acc_inner), - (Err(e), _) => Err(e), + (e @ Err(_), _) | (_, e @ Err(_)) => e, _ => bail!("inconsistent text range"), }); @@ -2249,4 +2251,33 @@ fn foo((bar | bar | bar): ()) { "#, ); } + + #[test] + fn regression_13498() { + check( + "Testing", + r" +mod foo { + pub struct Test$0; +} + +use foo::Test as Tester; + +fn main() { + let t = Tester; +} +", + r" +mod foo { + pub struct Testing; +} + +use foo::Testing as Tester; + +fn main() { + let t = Tester; +} +", + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs index fedc1a43582..7486b20293a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs +++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs @@ -149,7 +149,7 @@ fn signature_help_for_call( variant.name(db) ); } - hir::CallableKind::Closure | hir::CallableKind::FnPtr => (), + hir::CallableKind::Closure | hir::CallableKind::FnPtr | hir::CallableKind::Other => (), } res.signature.push('('); @@ -189,9 +189,10 @@ fn signature_help_for_call( hir::CallableKind::Function(func) if callable.return_type().contains_unknown() => { render(func.ret_type(db)) } - hir::CallableKind::Function(_) | hir::CallableKind::Closure | hir::CallableKind::FnPtr => { - render(callable.return_type()) - } + hir::CallableKind::Function(_) + | hir::CallableKind::Closure + | hir::CallableKind::FnPtr + | hir::CallableKind::Other => render(callable.return_type()), hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {} } Some(res) @@ -387,10 +388,9 @@ mod tests { } fn check(ra_fixture: &str, expect: Expect) { - // Implicitly add `Sized` to avoid noisy `T: ?Sized` in the results. let fixture = format!( r#" -#[lang = "sized"] trait Sized {{}} +//- minicore: sized, fn {ra_fixture} "# ); @@ -1331,4 +1331,19 @@ fn f() { "#]], ); } + + #[test] + fn help_for_generic_call() { + check( + r#" +fn f<F: FnOnce(u8, u16) -> i32>(f: F) { + f($0) +} +"#, + expect![[r#" + (u8, u16) -> i32 + ^^ --- + "#]], + ); + } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs index 5ff347b9bd7..c74ddabb177 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs @@ -106,12 +106,12 @@ impl LsifManager<'_> { manager: "cargo".to_string(), uri: None, content: None, - repository: Some(lsif::Repository { - url: pi.repo, + repository: pi.repo.map(|url| lsif::Repository { + url, r#type: "git".to_string(), commit_id: None, }), - version: Some(pi.version), + version: pi.version, })); self.package_map.insert(package_information, result_set_id); result_set_id 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 16298862b50..ca7ba896b67 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 @@ -231,7 +231,7 @@ fn token_to_symbol(token: &TokenStaticData) -> Option<scip_types::Symbol> { package: Some(scip_types::Package { manager: "cargo".to_string(), name: package_name, - version, + version: version.unwrap_or_else(|| ".".to_string()), ..Default::default() }) .into(), @@ -415,4 +415,42 @@ pub mod module { "", ); } + + #[test] + fn global_symbol_for_pub_struct() { + check_symbol( + r#" + //- /lib.rs crate:main + mod foo; + + fn main() { + let _bar = foo::Bar { i: 0 }; + } + //- /foo.rs + pub struct Bar$0 { + pub i: i32, + } + "#, + "rust-analyzer cargo main . foo/Bar#", + ); + } + + #[test] + fn global_symbol_for_pub_struct_reference() { + check_symbol( + r#" + //- /lib.rs crate:main + mod foo; + + fn main() { + let _bar = foo::Bar$0 { i: 0 }; + } + //- /foo.rs + pub struct Bar { + pub i: i32, + } + "#, + "rust-analyzer cargo main . foo/Bar#", + ); + } } 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 1ed8f2bb5f3..4072ae585db 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -56,6 +56,9 @@ mod patch_old_style; // parsing the old name. config_data! { struct ConfigData { + /// Whether to insert #[must_use] when generating `as_` methods + /// for enum variants. + assist_emitMustUse: bool = "false", /// Placeholder expression to use for missing expressions in assists. assist_expressionFillDefault: ExprFillDefaultDef = "\"todo\"", @@ -1276,6 +1279,7 @@ impl Config { allowed: None, insert_use: self.insert_use_config(), prefer_no_std: self.data.imports_prefer_no_std, + assist_emit_must_use: self.data.assist_emitMustUse, } } 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 4057a75e7c1..8c26009add2 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -334,6 +334,10 @@ pub fn block_expr( ast_from_text(&format!("fn f() {buf}")) } +pub fn tail_only_block_expr(tail_expr: ast::Expr) -> ast::BlockExpr { + ast_from_text(&format!("fn f() {{ {tail_expr} }}")) +} + /// Ideally this function wouldn't exist since it involves manual indenting. /// It differs from `make::block_expr` by also supporting comments. /// @@ -656,6 +660,22 @@ pub fn let_stmt( }; ast_from_text(&format!("fn f() {{ {text} }}")) } + +pub fn let_else_stmt( + pattern: ast::Pat, + ty: Option<ast::Type>, + expr: ast::Expr, + diverging: ast::BlockExpr, +) -> ast::LetStmt { + let mut text = String::new(); + format_to!(text, "let {pattern}"); + if let Some(ty) = ty { + format_to!(text, ": {ty}"); + } + format_to!(text, " = {expr} else {diverging};"); + ast_from_text(&format!("fn f() {{ {text} }}")) +} + pub fn expr_stmt(expr: ast::Expr) -> ast::ExprStmt { let semi = if expr.is_block_like() { "" } else { ";" }; ast_from_text(&format!("fn f() {{ {expr}{semi} (); }}")) diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index b9f2b513235..1eea2346451 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -5,9 +5,7 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{ - self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode, -}; +use rustc_lexer::unescape::{self, unescape_byte, unescape_char, unescape_literal, Mode}; use crate::{ algo, @@ -143,7 +141,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) { ast::LiteralKind::ByteString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| { + unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| { if let Err(err) = char { push_err(2, (range.start, err)); } diff --git a/src/tools/rust-analyzer/docs/dev/guide.md b/src/tools/rust-analyzer/docs/dev/guide.md index 52a13da31c5..56a68ef0437 100644 --- a/src/tools/rust-analyzer/docs/dev/guide.md +++ b/src/tools/rust-analyzer/docs/dev/guide.md @@ -338,7 +338,7 @@ The algorithm for building a tree of modules is to start with a crate root declarations and recursively process child modules. This is handled by the [`module_tree_query`], with two slight variations. -[`module_tree_query`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/module_tree.rs#L116-L123 +[`module_tree_query`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L115-L133 First, rust-analyzer builds a module tree for all crates in a source root simultaneously. The main reason for this is historical (`module_tree` predates @@ -361,7 +361,7 @@ the same, we don't have to re-execute [`module_tree_query`]. In fact, we only need to re-execute it when we add/remove new files or when we change mod declarations. -[`submodules_query`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/module_tree.rs#L41 +[`submodules_query`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L41 We store the resulting modules in a `Vec`-based indexed arena. The indices in the arena becomes module IDs. And this brings us to the next topic: @@ -389,8 +389,8 @@ integers which can "intern" a location and return an integer ID back. The salsa database we use includes a couple of [interners]. How to "garbage collect" unused locations is an open question. -[`LocationInterner`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/base_db/src/loc2id.rs#L65-L71 -[interners]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/db.rs#L22-L23 +[`LocationInterner`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_db/src/loc2id.rs#L65-L71 +[interners]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/db.rs#L22-L23 For example, we use `LocationInterner` to assign IDs to definitions of functions, structs, enums, etc. The location, [`DefLoc`] contains two bits of information: @@ -404,7 +404,7 @@ using offsets, text ranges or syntax trees as keys and values for queries. What we do instead is we store "index" of the item among all of the items of a file (so, a positional based ID, but localized to a single file). -[`DefLoc`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/ids.rs#L127-L139 +[`DefLoc`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L129-L139 One thing we've glossed over for the time being is support for macros. We have only proof of concept handling of macros at the moment, but they are extremely @@ -437,7 +437,7 @@ terms of `HirFileId`! This does not recur infinitely though: any chain of `HirFileId`s bottoms out in `HirFileId::FileId`, that is, some source file actually written by the user. -[`HirFileId`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/ids.rs#L18-L125 +[`HirFileId`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L31-L93 Now that we understand how to identify a definition, in a source or in a macro-generated file, we can discuss name resolution a bit. @@ -451,14 +451,13 @@ each module into a position-independent representation which does not change if we modify bodies of the items. After that we [loop] resolving all imports until we've reached a fixed point. -[lower]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/lower.rs#L113-L117 -[loop]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres.rs#L186-L196 - +[lower]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L113-L147 +[loop]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres.rs#L186-L196 And, given all our preparation with IDs and a position-independent representation, it is satisfying to [test] that typing inside function body does not invalidate name resolution results. -[test]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/tests.rs#L376 +[test]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/tests.rs#L376 An interesting fact about name resolution is that it "erases" all of the intermediate paths from the imports: in the end, we know which items are defined @@ -493,10 +492,10 @@ there's an intermediate [projection query] which returns only the first position-independent part of the lowering. The result of this query is stable. Naturally, name resolution [uses] this stable projection query. -[imports]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/lower.rs#L52-L59 -[`SourceMap`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/lower.rs#L52-L59 -[projection query]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/lower.rs#L97-L103 -[uses]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/query_definitions.rs#L49 +[imports]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59 +[`SourceMap`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59 +[projection query]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L97-L103 +[uses]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/query_definitions.rs#L49 ## Type inference @@ -518,10 +517,10 @@ construct a mapping from `ExprId`s to types. [@flodiebold]: https://github.com/flodiebold [#327]: https://github.com/rust-lang/rust-analyzer/pull/327 -[lower the AST]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/expr.rs -[positional ID]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/expr.rs#L13-L15 -[a source map]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/expr.rs#L41-L44 -[type inference]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/ty.rs#L1208-L1223 +[lower the AST]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs +[positional ID]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs#L13-L15 +[a source map]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs#L41-L44 +[type inference]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ty.rs#L1208-L1223 ## Tying it all together: completion @@ -563,10 +562,11 @@ the type to completion. [catch]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L436-L442 [the handler]: https://salsa.zulipchat.com/#narrow/stream/181542-rfcs.2Fsalsa-query-group/topic/design.20next.20steps [ask analysis for completion]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/lib.rs#L439-L444 -[completion implementation]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion.rs#L46-L62 -[`CompletionContext`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/completion_context.rs#L14-L37 -["IntelliJ Trick"]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/completion_context.rs#L72-L75 -[find an ancestor `fn` node]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/completion_context.rs#L116-L120 -[semantic model]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/completion_context.rs#L123 -[series of independent completion routines]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion.rs#L52-L59 -[`complete_dot`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/complete_dot.rs#L6-L22 +[ask analysis for completion]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L439-L444 +[completion implementation]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion.rs#L46-L62 +[`CompletionContext`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L14-L37 +["IntelliJ Trick"]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L72-L75 +[find an ancestor `fn` node]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L116-L120 +[semantic model]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L123 +[series of independent completion routines]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion.rs#L52-L59 +[`complete_dot`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/complete_dot.rs#L6-L22 diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index 502833de72c..36794efe427 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -1,3 +1,9 @@ +[[rust-analyzer.assist.emitMustUse]]rust-analyzer.assist.emitMustUse (default: `false`):: ++ +-- +Whether to insert #[must_use] when generating `as_` methods +for enum variants. +-- [[rust-analyzer.assist.expressionFillDefault]]rust-analyzer.assist.expressionFillDefault (default: `"todo"`):: + -- diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc index c30838e5f5e..49500e390a5 100644 --- a/src/tools/rust-analyzer/docs/user/manual.adoc +++ b/src/tools/rust-analyzer/docs/user/manual.adoc @@ -487,6 +487,12 @@ https://docs.helix-editor.com/[Helix] supports LSP by default. However, it won't install `rust-analyzer` automatically. You can follow instructions for installing <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. +=== Crates + +There is a package named `ra_ap_rust_analyzer` available on https://crates.io/crates/ra_ap_rust-analyzer[crates.io], for someone who wants to use it programmatically. + +For more details, see https://github.com/rust-lang/rust-analyzer/blob/master/.github/workflows/publish.yml[the publish workflow]. + == Troubleshooting Start with looking at the rust-analyzer version. diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json index a72865d4fe4..0b25564e28d 100644 --- a/src/tools/rust-analyzer/editors/code/package-lock.json +++ b/src/tools/rust-analyzer/editors/code/package-lock.json @@ -23,7 +23,7 @@ "esbuild": "^0.14.48", "eslint": "^8.19.0", "eslint-config-prettier": "^8.5.0", - "ovsx": "^0.5.1", + "ovsx": "^0.5.2", "prettier": "^2.7.1", "tslib": "^2.4.0", "typescript": "^4.7.4", @@ -2874,9 +2874,9 @@ } }, "node_modules/ovsx": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.5.1.tgz", - "integrity": "sha512-3OWq0l7DuVHi2bd2aQe5+QVQlFIqvrcw3/2vGXL404L6Tr+R4QHtzfnYYghv8CCa85xJHjU0RhcaC7pyXkAUbg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.5.2.tgz", + "integrity": "sha512-UbLultRCk46WddeA0Cly4hoRhzBJUiLgbIEViXlgOvV54LbsppClDkMLoCevUUBHoiNdMX2NuiSgURAEXgCZdw==", "dev": true, "dependencies": { "commander": "^6.1.0", @@ -5958,9 +5958,9 @@ } }, "ovsx": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.5.1.tgz", - "integrity": "sha512-3OWq0l7DuVHi2bd2aQe5+QVQlFIqvrcw3/2vGXL404L6Tr+R4QHtzfnYYghv8CCa85xJHjU0RhcaC7pyXkAUbg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.5.2.tgz", + "integrity": "sha512-UbLultRCk46WddeA0Cly4hoRhzBJUiLgbIEViXlgOvV54LbsppClDkMLoCevUUBHoiNdMX2NuiSgURAEXgCZdw==", "dev": true, "requires": { "commander": "^6.1.0", diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 6771cad28a7..1a97a9c0893 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -49,7 +49,7 @@ "esbuild": "^0.14.48", "eslint": "^8.19.0", "eslint-config-prettier": "^8.5.0", - "ovsx": "^0.5.1", + "ovsx": "^0.5.2", "prettier": "^2.7.1", "tslib": "^2.4.0", "typescript": "^4.7.4", @@ -100,22 +100,32 @@ { "command": "rust-analyzer.syntaxTree", "title": "Show Syntax Tree", - "category": "rust-analyzer" + "category": "rust-analyzer (debug command)" }, { "command": "rust-analyzer.viewHir", "title": "View Hir", - "category": "rust-analyzer" + "category": "rust-analyzer (debug command)" }, { "command": "rust-analyzer.viewFileText", "title": "View File Text (as seen by the server)", - "category": "rust-analyzer" + "category": "rust-analyzer (debug command)" }, { "command": "rust-analyzer.viewItemTree", "title": "Debug ItemTree", - "category": "rust-analyzer" + "category": "rust-analyzer (debug command)" + }, + { + "command": "rust-analyzer.shuffleCrateGraph", + "title": "Shuffle Crate Graph", + "category": "rust-analyzer (debug command)" + }, + { + "command": "rust-analyzer.memoryUsage", + "title": "Memory Usage (Clears Database)", + "category": "rust-analyzer (debug command)" }, { "command": "rust-analyzer.viewCrateGraph", @@ -173,16 +183,6 @@ "category": "rust-analyzer" }, { - "command": "rust-analyzer.memoryUsage", - "title": "Memory Usage (Clears Database)", - "category": "rust-analyzer" - }, - { - "command": "rust-analyzer.shuffleCrateGraph", - "title": "Shuffle Crate Graph", - "category": "rust-analyzer" - }, - { "command": "rust-analyzer.reloadWorkspace", "title": "Reload workspace", "category": "rust-analyzer" @@ -397,6 +397,11 @@ "type": "boolean" }, "$generated-start": {}, + "rust-analyzer.assist.emitMustUse": { + "markdownDescription": "Whether to insert #[must_use] when generating `as_` methods\nfor enum variants.", + "default": false, + "type": "boolean" + }, "rust-analyzer.assist.expressionFillDefault": { "markdownDescription": "Placeholder expression to use for missing expressions in assists.", "default": "todo", diff --git a/src/tools/rust-analyzer/triagebot.toml b/src/tools/rust-analyzer/triagebot.toml index fa0824ac53c..a910e012b73 100644 --- a/src/tools/rust-analyzer/triagebot.toml +++ b/src/tools/rust-analyzer/triagebot.toml @@ -1 +1,11 @@ [assign] + +[shortcut] + +[relabel] +allow-unauthenticated = [ + "S-*", +] + +[autolabel."S-waiting-on-review"] +new_pr = true diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index 70d5f94472f..d40d9a3cb54 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -149,6 +149,7 @@ async function main(argv) { // This is more convenient that setting fields one by one. let args = [ "--variable", "DOC_PATH", opts["doc_folder"], "--enable-fail-on-js-error", + "--allow-file-access-from-files", ]; if (opts["debug"]) { debug = true; diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index df3185758bf..3da4fed33e1 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -307,10 +307,13 @@ function runChecks(testFile, doSearch, parseQuery) { * `parseQuery` function exported from the search module. */ function loadSearchJS(doc_folder, resource_suffix) { - const searchJs = path.join(doc_folder, "search" + resource_suffix + ".js"); const searchIndexJs = path.join(doc_folder, "search-index" + resource_suffix + ".js"); const searchIndex = require(searchIndexJs); - const searchModule = require(searchJs); + + const staticFiles = path.join(doc_folder, "static.files"); + const searchJs = fs.readdirSync(staticFiles).find( + f => f.match(/search.*\.js$/)); + const searchModule = require(path.join(staticFiles, searchJs)); const searchWords = searchModule.initSearch(searchIndex.searchIndex); return { diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 3105882e2d3..7750df0fff3 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -399,6 +399,7 @@ pub(crate) fn format_expr( } } ast::ExprKind::Underscore => Some("_".to_owned()), + ast::ExprKind::IncludedBytes(..) => unreachable!(), ast::ExprKind::Err => None, }; diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index cd852855602..c47b3b314dd 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -496,6 +496,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Continue(..) | ast::ExprKind::Err | ast::ExprKind::Field(..) + | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::InlineAsm(..) | ast::ExprKind::Let(..) | ast::ExprKind::Path(..) diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 774c97b7777..97d038da702 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -10,6 +10,7 @@ regex = "1" miropt-test-tools = { path = "../miropt-test-tools" } lazy_static = "1" walkdir = "2" +ignore = "0.4.18" [[bin]] name = "rust-tidy" diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index ee883777c31..b0b11cafca5 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -31,6 +31,7 @@ fn main() { let args: Vec<String> = env::args().skip(1).collect(); let verbose = args.iter().any(|s| *s == "--verbose"); + let bless = args.iter().any(|s| *s == "--bless"); let bad = std::sync::Arc::new(AtomicBool::new(false)); @@ -64,7 +65,7 @@ fn main() { // Checks over tests. check!(debug_artifacts, &src_path); check!(ui_tests, &src_path); - check!(mir_opt_tests, &src_path); + check!(mir_opt_tests, &src_path, bless); // Checks that only make sense for the compiler. check!(errors, &compiler_path); diff --git a/src/tools/tidy/src/mir_opt_tests.rs b/src/tools/tidy/src/mir_opt_tests.rs index f9e8b55497b..018573284ea 100644 --- a/src/tools/tidy/src/mir_opt_tests.rs +++ b/src/tools/tidy/src/mir_opt_tests.rs @@ -1,9 +1,9 @@ -//! Tidy check to ensure that mir opt directories do not have stale files. +//! Tidy check to ensure that mir opt directories do not have stale files or dashes in file names use std::collections::HashSet; use std::path::{Path, PathBuf}; -pub fn check(path: &Path, bad: &mut bool) { +fn check_unused_files(path: &Path, bless: bool, bad: &mut bool) { let mut rs_files = Vec::<PathBuf>::new(); let mut output_files = HashSet::<PathBuf>::new(); let files = walkdir::WalkDir::new(&path.join("test/mir-opt")).into_iter(); @@ -27,11 +27,48 @@ pub fn check(path: &Path, bad: &mut bool) { for extra in output_files { if extra.file_name() != Some("README.md".as_ref()) { - tidy_error!( - bad, - "the following output file is not associated with any mir-opt test, you can remove it: {}", - extra.display() - ); + if !bless { + tidy_error!( + bad, + "the following output file is not associated with any mir-opt test, you can remove it: {}", + extra.display() + ); + } else { + let _ = std::fs::remove_file(extra); + } + } + } +} + +fn check_dash_files(path: &Path, bless: bool, bad: &mut bool) { + for file in walkdir::WalkDir::new(&path.join("test/mir-opt")) + .into_iter() + .filter_map(Result::ok) + .filter(|e| e.file_type().is_file()) + { + let path = file.path(); + if path.extension() == Some("rs".as_ref()) { + if let Some(name) = path.file_name().and_then(|s| s.to_str()) { + if name.contains('-') { + if !bless { + tidy_error!( + bad, + "mir-opt test files should not have dashes in them: {}", + path.display() + ); + } else { + let new_name = name.replace('-', "_"); + let mut new_path = path.to_owned(); + new_path.set_file_name(new_name); + let _ = std::fs::rename(path, new_path); + } + } + } } } } + +pub fn check(path: &Path, bless: bool, bad: &mut bool) { + check_unused_files(path, bless, bad); + check_dash_files(path, bless, bad); +} diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index c600f99c2c4..2b82e9b3f99 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -2,43 +2,50 @@ //! - the number of entries in each directory must be less than `ENTRY_LIMIT` //! - there are no stray `.stderr` files +use ignore::Walk; +use ignore::WalkBuilder; use std::fs; use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. -const ROOT_ENTRY_LIMIT: usize = 948; -const ISSUES_ENTRY_LIMIT: usize = 2117; +const ROOT_ENTRY_LIMIT: usize = 939; +const ISSUES_ENTRY_LIMIT: usize = 2105; fn check_entries(path: &Path, bad: &mut bool) { - let dirs = walkdir::WalkDir::new(&path.join("test/ui")) - .into_iter() - .filter_entry(|e| e.file_type().is_dir()); - for dir in dirs { - if let Ok(dir) = dir { - let dir_path = dir.path(); + for dir in Walk::new(&path.join("test/ui")) { + if let Ok(entry) = dir { + if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) { + let dir_path = entry.path(); + // Use special values for these dirs. + let is_root = path.join("test/ui") == dir_path; + let is_issues_dir = path.join("test/ui/issues") == dir_path; + let limit = if is_root { + ROOT_ENTRY_LIMIT + } else if is_issues_dir { + ISSUES_ENTRY_LIMIT + } else { + ENTRY_LIMIT + }; - // Use special values for these dirs. - let is_root = path.join("test/ui") == dir_path; - let is_issues_dir = path.join("test/ui/issues") == dir_path; - let limit = if is_root { - ROOT_ENTRY_LIMIT - } else if is_issues_dir { - ISSUES_ENTRY_LIMIT - } else { - ENTRY_LIMIT - }; + let count = WalkBuilder::new(&dir_path) + .max_depth(Some(1)) + .build() + .into_iter() + .collect::<Vec<_>>() + .len() + - 1; // remove the dir itself - let count = std::fs::read_dir(dir_path).unwrap().count(); - if count > limit { - tidy_error!( - bad, - "following path contains more than {} entries, \ - you should move the test to some relevant subdirectory (current: {}): {}", - limit, - count, - dir_path.display() - ); + if count > limit { + tidy_error!( + bad, + "following path contains more than {} entries, \ + you should move the test to some relevant subdirectory (current: {}): {}", + limit, + count, + dir_path.display() + ); + } } } } diff --git a/triagebot.toml b/triagebot.toml index 202f9cad57a..8efd9af41a4 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -12,6 +12,7 @@ allow-unauthenticated = [ "T-*", "WG-*", "const-hack", + "llvm-main", "needs-fcp", "relnotes", "requires-nightly", @@ -572,6 +573,7 @@ fallback = [ "/src/llvm-project" = ["@cuviper"] "/src/rustdoc-json-types" = ["rustdoc"] "/src/stage0.json" = ["bootstrap"] +"/src/test/ui" = ["compiler"] "/src/tools/cargo" = ["@ehuss", "@joshtriplett"] "/src/tools/compiletest" = ["bootstrap"] "/src/tools/linkchecker" = ["@ehuss"] |
